MCPcopy Create free account
hub / github.com/BohemiaInteractive/CWR / query_server

Function query_server

mserver/Client/src/query.rs:22–74  ·  view source on GitHub ↗

Probe one server. `Ok(Some(_))` if it answered with a well-formed status within `timeout`; `Ok(None)` if it did not respond (unreachable / wrong protocol).

(
    addr: A,
    timeout: Duration,
)

Source from the content-addressed store, hash-verified

20/// Probe one server. `Ok(Some(_))` if it answered with a well-formed status within
21/// `timeout`; `Ok(None)` if it did not respond (unreachable / wrong protocol).
22pub fn query_server<A: ToSocketAddrs>(
23 addr: A,
24 timeout: Duration,
25) -> io::Result<Option<ServerStatus>> {
26 let target = addr
27 .to_socket_addrs()?
28 .next()
29 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "no address resolved"))?;
30
31 let bind_any: SocketAddr = if target.is_ipv6() {
32 "[::]:0".parse()
33 } else {
34 "0.0.0.0:0".parse()
35 }
36 .expect("static bind address");
37 let socket = UdpSocket::bind(bind_any)?;
38 socket.set_read_timeout(Some(timeout))?;
39
40 let request = framing::frame_request(&codec::encode_enum_request(codec::MAGIC_APP), 1);
41 let sent = Instant::now();
42 socket.send_to(&request, target)?;
43
44 let deadline = sent + timeout;
45 let mut buf = [0u8; MSG_HEADER_LEN + SESSION_PACKET_4];
46 loop {
47 match socket.recv_from(&mut buf) {
48 Ok((n, from)) => {
49 // Ignore datagrams from a different host (basic anti-spoofing) or that
50 // are not a valid response; keep waiting until the deadline.
51 if from.ip() == target.ip() {
52 if let Some(session) = framing::unframe_response(&buf[..n])
53 .and_then(codec::decode_session_response)
54 {
55 let ping_ms = u32::try_from(sent.elapsed().as_millis()).unwrap_or(u32::MAX);
56 return Ok(Some(ServerStatus { session, ping_ms }));
57 }
58 }
59 match deadline.checked_duration_since(Instant::now()) {
60 Some(remaining) if !remaining.is_zero() => {
61 socket.set_read_timeout(Some(remaining))?;
62 }
63 _ => return Ok(None),
64 }
65 }
66 Err(e)
67 if e.kind() == io::ErrorKind::WouldBlock || e.kind() == io::ErrorKind::TimedOut =>
68 {
69 return Ok(None);
70 }
71 Err(e) => return Err(e),
72 }
73 }
74}
75
76#[cfg(test)]
77mod tests {

Callers 4

run_queryFunction · 0.85
mainFunction · 0.85

Calls 4

frame_requestFunction · 0.85
encode_enum_requestFunction · 0.85
unframe_responseFunction · 0.85
parseMethod · 0.45