11use crate :: analyze:: { MotdInfo , PlayerInfo , StatusPayload } ;
2+ use crate :: mode:: QueryMode :: JAVA ;
23use crate :: mode:: QueryModeHandler ;
34use crate :: network:: resolve:: { resolve_addr, resolve_server_srv} ;
45use crate :: network:: schema:: { read_string, read_var_int_stream, write_var_int} ;
5- use crate :: network:: util;
6+ use crate :: network:: util:: { io_timeout, now_timestamp} ;
7+ use crate :: util:: make_tcp_socket;
68use async_trait:: async_trait;
79use bytes:: { Buf , BufMut , BytesMut } ;
810use clap:: Args ;
@@ -11,22 +13,14 @@ use std::io::ErrorKind;
1113use std:: net:: SocketAddr ;
1214use std:: time:: Duration ;
1315use tokio:: io:: { AsyncReadExt , AsyncWriteExt } ;
14- use tokio:: net:: TcpSocket ;
15- use tokio:: time:: timeout;
16- use crate :: mode:: QueryMode :: JAVA ;
16+ use tokio:: task:: JoinSet ;
1717
1818async fn single_ip_check ( addr : & SocketAddr , protocol : i32 ) -> std:: io:: Result < StatusPayload > {
19- let timeout_time = Duration :: from_secs ( 5 ) ;
19+ let time = Duration :: from_secs ( 5 ) ;
2020 let ip_str = addr. ip ( ) . to_string ( ) ;
2121
22- let socket = if addr. is_ipv4 ( ) {
23- log:: trace!( "Using IPv4 socket to {}" , addr) ;
24- TcpSocket :: new_v4 ( ) ?
25- } else {
26- log:: trace!( "Using IPv6 socket to {}" , addr) ;
27- TcpSocket :: new_v6 ( ) ?
28- } ;
29- let mut stream = timeout ( timeout_time, socket. connect ( * addr) ) . await ??;
22+ let socket = make_tcp_socket ( addr) ?;
23+ let mut stream = io_timeout ( time, socket. connect ( * addr) , "Connection" ) . await ??;
3024
3125 let mut handshake = vec ! [ 0 ] ;
3226 write_var_int ( & mut handshake, protocol) ; // protocol_version
@@ -44,9 +38,9 @@ async fn single_ip_check(addr: &SocketAddr, protocol: i32) -> std::io::Result<St
4438
4539 let handshake_recv_len = read_var_int_stream ( & mut stream) . await ?;
4640 let mut handshake_recv = vec ! [ 0 ; handshake_recv_len as usize ] ;
47- timeout ( timeout_time , stream. read_exact ( & mut handshake_recv) ) . await ??;
41+ io_timeout ( time , stream. read_exact ( & mut handshake_recv) , "Handshake" ) . await ??;
4842 let mut recv_buf = BytesMut :: from ( handshake_recv. as_slice ( ) ) ;
49- log:: trace!( "Handshake received, length: {}" , handshake_recv. len( ) ) ;
43+ log:: trace!( "Handshake received from {} , length: {}" , addr , handshake_recv. len( ) ) ;
5044
5145 if recv_buf. remaining ( ) == 0 || recv_buf. get_u8 ( ) != 0 {
5246 return Err ( std:: io:: Error :: new (
@@ -68,20 +62,20 @@ async fn single_ip_check(addr: &SocketAddr, protocol: i32) -> std::io::Result<St
6862 let mut decoded: Value = from_str ( & json_str) . map_err ( crate :: util:: wrap_invalid) ?;
6963
7064 stream. write ( & [ 9 , 1 ] ) . await ?; // ping_request
71- stream. write_i64 ( util :: now_timestamp ( ) ) . await ?;
65+ stream. write_i64 ( now_timestamp ( ) ) . await ?;
7266 stream. flush ( ) . await ?;
7367 log:: trace!( "Ping request sent" ) ;
7468
7569 let recv_pong = & mut [ 0 ; 10 ] ;
76- timeout ( timeout_time , stream. read_exact ( recv_pong) ) . await ??;
70+ io_timeout ( time , stream. read_exact ( recv_pong) , "Ping receiving" ) . await ??;
7771 if recv_pong[ 0 ] != 9 || recv_pong[ 1 ] != 1 {
7872 return Err ( std:: io:: Error :: new (
7973 ErrorKind :: InvalidData ,
8074 "Invalid pong packet" ,
8175 ) ) ;
8276 }
8377 let server_clock = i64:: from_be_bytes ( recv_pong[ 2 ..10 ] . try_into ( ) . expect ( "Recv failed" ) ) ;
84- let diff = util :: now_timestamp ( ) - server_clock;
78+ let diff = now_timestamp ( ) - server_clock;
8579 log:: trace!( "Got ping time: {}" , diff) ;
8680
8781 let players = decoded[ "players" ] . take ( ) ;
@@ -123,21 +117,34 @@ async fn single_ip_check(addr: &SocketAddr, protocol: i32) -> std::io::Result<St
123117 } )
124118}
125119
120+ async fn safe_ip_check ( addr : SocketAddr , protocol : i32 ) -> std:: io:: Result < StatusPayload > {
121+ match single_ip_check ( & addr, protocol) . await {
122+ Ok ( r) => Ok ( r) ,
123+ Err ( e) => {
124+ log:: warn!( "Failed to check available server ip {}: {}" , addr, e) ;
125+ Err ( e)
126+ }
127+ }
128+ }
129+
126130async fn check_java_server (
127- addr_vec : & Vec < SocketAddr > ,
131+ addr_vec : Vec < SocketAddr > ,
128132 protocol : i32 ,
129133) -> std:: io:: Result < StatusPayload > {
134+ let mut set = JoinSet :: new ( ) ;
135+
130136 for addr in addr_vec {
131- match single_ip_check ( & addr, protocol) . await {
132- Ok ( r ) => {
133- return Ok ( r ) ;
134- }
135- Err ( e ) => {
136- log :: warn! ( "Failed to check available server ip {}: {}" , addr , e ) ;
137- continue ;
138- }
137+ set . spawn ( safe_ip_check ( addr, protocol) ) ;
138+ }
139+
140+ while let Some ( join_res ) = set . join_next ( ) . await {
141+ if let Ok ( res ) = join_res
142+ && res . is_ok ( )
143+ {
144+ return res ;
139145 }
140146 }
147+
141148 Err ( std:: io:: Error :: new ( ErrorKind :: NotFound , "No server found" ) )
142149}
143150
@@ -155,19 +162,23 @@ pub struct JavaQuery<'a> {
155162 args : & ' a JavaModeArgs ,
156163}
157164
165+ pub async fn add_srv ( addr : & str , addresses : & mut Vec < SocketAddr > ) {
166+ let srv_res = resolve_server_srv ( addr) . await ;
167+ let srv = srv_res
168+ . iter ( )
169+ . filter_map ( |addr| resolve_addr ( addr, 25565 ) )
170+ . flatten ( ) ;
171+ addresses. splice ( 0 ..0 , srv) ;
172+ }
173+
158174#[ async_trait]
159175impl QueryModeHandler for JavaQuery < ' _ > {
160176 async fn do_query ( & self , addr : & str ) -> std:: io:: Result < StatusPayload > {
161- let mut je_res = resolve_addr ( addr, 25565 ) ;
162- let je_address = je_res. get_or_insert_default ( ) ;
177+ let je_res = resolve_addr ( addr, 25565 ) ;
178+ let mut je_address = je_res. unwrap_or ( vec ! [ ] ) ;
163179
164180 if !self . args . no_srv {
165- let srv_res = resolve_server_srv ( addr) . await ;
166- let srv = srv_res
167- . iter ( )
168- . filter_map ( |addr| resolve_addr ( addr, 25565 ) )
169- . flatten ( ) ;
170- je_address. splice ( 0 ..0 , srv) ;
181+ add_srv ( addr, & mut je_address) . await ;
171182 }
172183
173184 check_java_server ( je_address, self . args . protocol ) . await
0 commit comments