minecraft_pinger/bedrock/
pinger.rs1use std::time::Instant;
2use bytes::Bytes;
3use log::debug;
4use tokio::net::UdpSocket;
5use tokio::time::timeout;
6use crate::bedrock::model::BedrockPing;
7use crate::bedrock::protocol::{create_ping, read_response};
8use crate::common::dns::resolve_filtered_addrs;
9use crate::config::PingConfig;
10use crate::error::PingError;
11use crate::MinecraftPinger;
12
13impl MinecraftPinger {
14 pub async fn ping_bedrock_server(self: &Self,
15 ip: &str,
16 port: u16,
17 config: &PingConfig) -> Result<BedrockPing, PingError> {
18 let rs = timeout(config.timeout(), self.ping_bedrock_server_internal(ip, port, config)).await??;
19 Ok(rs)
20 }
21
22 async fn ping_bedrock_server_internal(self: &Self, ip: &str, port: u16, config: &PingConfig) -> Result<BedrockPing, PingError> {
23 debug!("Pinging bedrock server {}:{}", ip, port);
24
25 let addrs = resolve_filtered_addrs(self, ip, port, "udp", config.ip_filter()).await?;
26 let start_time = Instant::now();
27
28 let socket = UdpSocket::bind("0.0.0.0:0").await?;
29 timeout(config.timeout(), socket.connect(&addrs[..]))
30 .await?
31 .map_err(|e| {
32 debug!("Connection error: {}", e);
33 PingError::ConnectionRefused
34 })?;
35
36 let _ = socket.send(&create_ping()?).await;
37
38 let mut buffer = [0u8; 1024];
39 let len = timeout(config.timeout(), socket.recv(&mut buffer))
40 .await?
41 .map_err(|_| PingError::ConnectionRefused)?;
42
43 let mut response_bytes = Bytes::copy_from_slice(&buffer[..len]);
44 let latency = start_time.elapsed().as_millis() as u32;
45
46 let mut rs = read_response(&mut response_bytes)?;
47 rs.latency = latency;
48
49 Ok(rs)
50 }
51}
52