minecraft_pinger/java/
pinger.rs1use std::time::Instant;
2use bytes::BytesMut;
3use log::debug;
4use tokio::io::{AsyncWriteExt, BufReader};
5use tokio::net::TcpStream;
6use tokio::time::timeout;
7use crate::common::dns::resolve_filtered_addrs;
8use crate::common::protocol::read_string;
9use crate::error::PingError;
10use crate::java::config::JavaPingConfig;
11use crate::java::model::JavaPing;
12use crate::java::protocol::{read_packet, write_ping_handshake, write_ping_request};
13use crate::MinecraftPinger;
14
15impl MinecraftPinger {
16 pub async fn ping_java_server(self: &Self,
17 ip: &str,
18 port: u16,
19 config: &JavaPingConfig) -> Result<JavaPing, PingError> {
20 let rs = timeout(config.common().timeout(), self.ping_java_server_internal(ip, port, &config)).await??;
21 Ok(rs)
22 }
23
24 async fn ping_java_server_internal(self: &Self, ip: &str, port: u16, config: &JavaPingConfig) -> Result<JavaPing, PingError> {
25 debug!("Pinging server {}:{}", ip, port);
26
27 let addrs = resolve_filtered_addrs(self, ip, port, "tcp", config.common().ip_filter()).await?;
28
29 let stream_future = TcpStream::connect(&addrs[..]);
30 let mut stream = timeout(config.common().timeout(), stream_future)
31 .await?
32 .map_err(|e| {
33 debug!("Connection error: {}", e);
34 PingError::ConnectionRefused
35 })?;
36
37 stream.set_nodelay(true).unwrap_or_default();
38
39 debug!("Stream connected to {}", stream.peer_addr().map(|a| a.to_string()).unwrap_or_else(|_| "unknown".to_string()));
40
41 let start_time = Instant::now();
42
43 let mut buffer = BytesMut::with_capacity(256);
44
45 let handshake_host = config.hostname().as_deref().unwrap_or(ip);
46 write_ping_handshake(&mut buffer, handshake_host, &port, &config.protocol_version());
47 write_ping_request(&mut buffer);
48
49 stream.write_all(&buffer.freeze())
50 .await
51 .map_err(|_| PingError::SendPacket)?;
52 debug!("Stream all packets !");
53
54 let mut buffered_reader = BufReader::new(&mut stream);
55 let mut packet = read_packet(&mut buffered_reader).await?;
56 debug!("Received Packet ID: {}", packet.id());
57
58 let json = read_string(&mut packet.data)?;
59 let latency = start_time.elapsed().as_millis() as u32;
60
61 let mut as_res = serde_json::from_str::<JavaPing>(&json)?;
62
63 as_res.latency = latency;
64 Ok(as_res)
65 }
66}