11use crate :: analyze:: { MotdInfo , StatusPayload } ;
22use crate :: mode:: QueryMode :: BEDROCK ;
33use crate :: mode:: QueryModeHandler ;
4- use crate :: network:: resolve :: { resolve_addr , sanitize_addr } ;
5- use crate :: network:: util ;
6- use crate :: network:: util:: io_timeout ;
4+ use crate :: network:: connection :: { ProxyableUdpSocket , UdpTarget , udp_socket } ;
5+ use crate :: network:: resolve :: sanitize_addr ;
6+ use crate :: network:: util:: { generic_timeout , now_timestamp } ;
77use anyhow:: { Result , anyhow} ;
88use async_trait:: async_trait;
99use bytes:: { Buf , BufMut , BytesMut } ;
1010use serde_json:: json;
11- use std:: net:: SocketAddr ;
1211use std:: time:: Duration ;
13- use tokio:: net:: UdpSocket ;
1412use tokio:: task:: JoinSet ;
1513
1614const MAGIC_HIGH : u64 = 0x00ffff00fefefefeu64 ;
1715const MAGIC_LOW : u64 = 0xfdfdfdfd12345678u64 ;
1816
19- async fn single_ip_check ( addr : SocketAddr ) -> Result < StatusPayload > {
17+ async fn single_ip_check ( addr : & UdpTarget , socket : ProxyableUdpSocket ) -> Result < StatusPayload > {
2018 let timeout_time = Duration :: from_secs ( 5 ) ;
21- let socket = UdpSocket :: bind ( "0.0.0.0:0" ) . await ?;
22- socket. connect ( addr) . await ?;
23- log:: trace!( "Connected to {}" , addr) ;
2419
25- let timestamp = util :: now_timestamp ( ) ;
20+ let timestamp = now_timestamp ( ) ;
2621 let mut packet = Vec :: from ( [ 1u8 ] ) ;
2722 packet. put_i64 ( timestamp) ;
2823 packet. put_u64 ( MAGIC_HIGH ) ;
@@ -32,10 +27,10 @@ async fn single_ip_check(addr: SocketAddr) -> Result<StatusPayload> {
3227 log:: trace!( "Sent Unconnected Ping packet" ) ;
3328
3429 let mut recv_buf = [ 0u8 ; 1024 ] ;
35- let recv = io_timeout ( timeout_time, socket. recv_from ( & mut recv_buf) , "Recv" ) . await ?;
30+ let recv = generic_timeout ( timeout_time, socket. recv_from ( & mut recv_buf) , "Recv" ) . await ?;
3631 log:: trace!( "Received response from {}" , addr) ;
3732
38- let mut bytes = BytesMut :: from ( & recv_buf[ ..recv. 0 ] ) ;
33+ let mut bytes = BytesMut :: from ( & recv_buf[ ..recv] ) ;
3934 if bytes. get_u8 ( ) != 0x1C {
4035 return Err ( anyhow ! ( "Unexpected response byte" ) ) ;
4136 }
@@ -49,11 +44,11 @@ async fn single_ip_check(addr: SocketAddr) -> Result<StatusPayload> {
4944 if magic_high != MAGIC_HIGH || magic_low != MAGIC_LOW {
5045 return Err ( anyhow ! ( "Invalid magic number" ) ) ;
5146 }
52- if str_len as usize != recv. 0 - 35 {
53- return Err ( anyhow ! ( "Invalid string length" , ) ) ;
47+ if str_len as usize != recv - 35 {
48+ return Err ( anyhow ! ( "Invalid string length" ) ) ;
5449 }
5550
56- let ping = util :: now_timestamp ( ) - server_clock;
51+ let ping = now_timestamp ( ) - server_clock;
5752 let resp = String :: from_utf8 ( bytes. to_vec ( ) ) ?;
5853 log:: trace!( "Ping response: {}" , resp) ;
5954
@@ -65,55 +60,47 @@ async fn single_ip_check(addr: SocketAddr) -> Result<StatusPayload> {
6560 Ok ( StatusPayload {
6661 mode : BEDROCK ,
6762 ping,
68- max_players : Some ( util :: parse_i64 ( parts[ 5 ] ) ?) ,
69- player_count : Some ( util :: parse_i64 ( parts[ 4 ] ) ?) ,
63+ max_players : Some ( parts[ 5 ] . parse ( ) ?) ,
64+ player_count : Some ( parts[ 4 ] . parse ( ) ?) ,
7065 players : None ,
7166 motd : Some ( MotdInfo :: String ( format ! ( "{}\n {}" , parts[ 1 ] , parts[ 7 ] ) ) ) ,
72- protocol : Some ( util :: parse_i64 ( parts[ 2 ] ) ?) ,
67+ protocol : Some ( parts[ 2 ] . parse ( ) ?) ,
7368 version_name : Some ( parts[ 3 ] . to_string ( ) ) ,
7469 favicon : None ,
7570 full_extra : Some ( json ! ( { "server_guid" : server_guid, "game_mode" : parts[ 8 ] . to_string( ) } ) ) ,
7671 } )
7772}
7873
79- async fn safe_ip_check ( addr : SocketAddr ) -> Result < StatusPayload > {
80- match single_ip_check ( addr) . await {
74+ async fn safe_ip_check ( addr : UdpTarget , socket : ProxyableUdpSocket ) -> Result < StatusPayload > {
75+ match single_ip_check ( & addr, socket ) . await {
8176 Ok ( status) => Ok ( status) ,
82- Err ( e) => Err ( anyhow ! (
83- "Protocol error in <{}:{}>: {}" ,
84- addr. ip( ) ,
85- addr. port( ) ,
86- e
87- ) ) ,
77+ Err ( e) => Err ( anyhow ! ( "Protocol error in <{}>: {}" , addr, e) ) ,
8878 }
8979}
9080
91- async fn check_bedrock_server ( addr_vec : Vec < SocketAddr > ) -> Result < StatusPayload > {
92- let mut set = JoinSet :: new ( ) ;
93-
94- for addr in addr_vec {
95- set. spawn ( safe_ip_check ( addr) ) ;
96- }
97-
98- while let Some ( join_res) = set. join_next ( ) . await {
99- if let Ok ( res) = join_res {
100- match res {
101- Ok ( res) => return Ok ( res) ,
102- Err ( e) => log:: warn!( "{}" , e) ,
103- }
104- }
105- }
106-
107- Err ( anyhow ! ( "No server found" ) )
108- }
109-
11081pub struct BedrockQuery ;
11182
11283#[ async_trait]
11384impl QueryModeHandler for BedrockQuery {
11485 async fn do_query ( & self , addr : & str ) -> Result < StatusPayload > {
11586 let ( host, port) = sanitize_addr ( addr, 19132 ) ?;
116- check_bedrock_server ( resolve_addr ( & host, port) ) . await
87+ let socks = udp_socket ( & host, port, Duration :: new ( 5 , 0 ) ) . await ?;
88+ let mut set = JoinSet :: new ( ) ;
89+
90+ for sock in socks {
91+ set. spawn ( safe_ip_check ( sock. 0 , sock. 1 ) ) ;
92+ }
93+
94+ while let Some ( join_res) = set. join_next ( ) . await {
95+ if let Ok ( res) = join_res {
96+ match res {
97+ Ok ( res) => return Ok ( res) ,
98+ Err ( e) => log:: warn!( "{}" , e) ,
99+ }
100+ }
101+ }
102+
103+ Err ( anyhow ! ( "No server found" ) )
117104 }
118105}
119106
0 commit comments