aboutsummaryrefslogtreecommitdiff
path: root/minecraft-protocol/src/server_status_pinger.rs
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2021-12-06 00:28:40 -0600
committermat <github@matdoes.dev>2021-12-06 00:28:40 -0600
commit5029a09963b5753c1f9b7f777f28e1c0951343e7 (patch)
tree2e0e37029bf031adc3e28713828e7d4be7336ccb /minecraft-protocol/src/server_status_pinger.rs
downloadazalea-drasl-5029a09963b5753c1f9b7f777f28e1c0951343e7.tar.xz
Initial commit
Diffstat (limited to 'minecraft-protocol/src/server_status_pinger.rs')
-rw-r--r--minecraft-protocol/src/server_status_pinger.rs100
1 files changed, 100 insertions, 0 deletions
diff --git a/minecraft-protocol/src/server_status_pinger.rs b/minecraft-protocol/src/server_status_pinger.rs
new file mode 100644
index 00000000..86d0cae9
--- /dev/null
+++ b/minecraft-protocol/src/server_status_pinger.rs
@@ -0,0 +1,100 @@
+use crate::{connection::Connection, resolver, ServerAddress};
+use tokio::{
+ io::{AsyncReadExt, AsyncWriteExt, BufWriter},
+ net::TcpStream,
+};
+
+struct ServerStatus {}
+
+async fn write_byte(buf: &mut Vec<u8>, n: u8) {
+ buf.write_u8(n).await.unwrap();
+ println!("write_byte: {}", n);
+}
+
+async fn write_bytes(buf: &mut Vec<u8>, bytes: &[u8]) {
+ buf.write_all(bytes).await.unwrap();
+ println!("write_bytes: {:?}", buf);
+}
+
+async fn write_varint(buf: &mut Vec<u8>, mut n: u32) {
+ loop {
+ if (n & 0xFFFFFF80) == 0 {
+ write_byte(buf, n as u8).await;
+ return ();
+ }
+ write_byte(buf, (n & 0x7F | 0x80) as u8).await;
+ n >>= 7;
+ }
+}
+
+async fn write_utf(buf: &mut Vec<u8>, string: &[u8], len: usize) {
+ if string.len() > len {
+ panic!(
+ "String too big (was {} bytes encoded, max {})",
+ string.len(),
+ len
+ );
+ }
+ write_varint(buf, string.len() as u32).await;
+ write_bytes(buf, string).await;
+}
+
+async fn write_short(buf: &mut Vec<u8>, n: u16) {
+ buf.write_u16(n).await.unwrap();
+ println!("write_short: {}", n);
+}
+
+pub async fn ping_server(address: &ServerAddress) -> Result<(), String> {
+ let resolved_address = resolver::resolve_address(&address).await?;
+
+ let mut conn = Connection::new(&resolved_address).await?;
+
+ // protocol version is 757
+
+ // client intention packet
+ // friendlyByteBuf.writeVarInt(this.protocolVersion);
+ // friendlyByteBuf.writeUtf(this.hostName);
+ // friendlyByteBuf.writeShort(this.port);
+ // friendlyByteBuf.writeVarInt(this.intention.getId());
+
+ println!("resolved_address {}", &resolved_address.ip);
+ println!("writing intention packet {}", address.host);
+
+ let mut buf: Vec<u8> = vec![0x00]; // 0 is the packet id for handshake
+ write_varint(&mut buf, 757).await;
+ write_utf(&mut buf, address.host.as_bytes(), 32767).await;
+ write_short(&mut buf, address.port).await;
+ write_varint(&mut buf, 1).await;
+
+ let mut full_buffer = vec![];
+ write_varint(&mut full_buffer, buf.len() as u32).await; // length of 1st packet id + data as VarInt
+ full_buffer.append(&mut buf);
+ full_buffer.extend_from_slice(&[
+ 1, // length of 2nd packet id + data as VarInt
+ 0x00, // 2nd packet id: 0 for request as VarInt
+ ]);
+
+ conn.stream.write_all(&full_buffer).await.unwrap();
+ conn.stream.flush().await.unwrap();
+
+ // log what the server sends back
+ loop {
+ if 0 == conn.stream.read_buf(&mut conn.buffer).await.unwrap() {
+ // The remote closed the connection. For this to be a clean
+ // shutdown, there should be no data in the read buffer. If
+ // there is, this means that the peer closed the socket while
+ // sending a frame.
+
+ // log conn.buffer
+ println!("{:?}", conn.buffer);
+ if conn.buffer.is_empty() {
+ println!("buffer is empty ok");
+ return Ok(());
+ } else {
+ return Err("connection reset by peer".into());
+ }
+ }
+ }
+
+ Ok(())
+}