fn blocking_query_loop()

in chrony-candm/src/net.rs [130:180]


fn blocking_query_loop<Sock: DgramSocket>(
    sock: &Sock,
    request_body: RequestBody,
    options: ClientOptions,
) -> std::io::Result<Reply> {
    let request = Request {
        sequence: rand::thread_rng().gen(),
        attempt: 0,
        body: request_body,
    };

    let mut send_buf = BytesMut::with_capacity(request.length());
    request.serialize(&mut send_buf);
    let mut recv_buf = [0; 1500];
    let mut attempt = 0;

    loop {
        sock.send(send_buf.as_ref())?;
        match sock.recv(&mut recv_buf) {
            Ok(len) => {
                let mut msg = &recv_buf[0..len];
                match Reply::deserialize(&mut msg) {
                    Ok(reply) => {
                        if reply.sequence == request.sequence {
                            return Ok(reply);
                        } else {
                            return Err(std::io::Error::new(
                                std::io::ErrorKind::InvalidData,
                                "Bad sequence number",
                            ));
                        }
                    }
                    Err(e) => return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, e)),
                }
            }
            Err(e) => {
                if e.kind() == std::io::ErrorKind::TimedOut
                    || e.kind() == std::io::ErrorKind::WouldBlock
                {
                    attempt += 1;
                    if attempt == options.n_tries {
                        return Err(e);
                    }
                    increment_attempt(send_buf.as_mut());
                } else {
                    return Err(e);
                }
            }
        }
    }
}