fn parse_server_response()

in mini-sntp/src/lib.rs [155:218]


fn parse_server_response(
    buf: [u8; 48],
    request_transmit_timestamp: chrono::DateTime<chrono::Utc>,
) -> Result<SntpTimeQueryResult, Error> {
    let sntp_epoch = sntp_epoch();

    let destination_timestamp = chrono::Utc::now();

    #[cfg(test)]
    let destination_timestamp = destination_timestamp - chrono::Duration::seconds(30); // simulate unsynced local clock

    let packet = Packet::parse(buf, sntp_epoch);
    #[cfg(test)]
    let packet = dbg!(packet);

    match packet.leap_indicator {
        0..=2 => (),
        leap_indicator => {
            return Err(Error::BadServerResponse(
                BadServerResponseReason::LeapIndicator(leap_indicator),
            ));
        }
    };

    // RFC 2030 says:
    //
    // >Version 4 servers are required to
    // >reply in the same version as the request, so the VN field of the
    // >request also specifies the version of the reply.
    //
    // But at least one pool.ntp.org server does not respect this and responds with VN=4
    // even though our client requests have VN=3.
    //
    // So allow both VN=3 and VN=4 in the server response. The response body format is identical for both anyway.
    if packet.version_number != 3 && packet.version_number != 4 {
        return Err(Error::BadServerResponse(
            BadServerResponseReason::VersionNumber(packet.version_number),
        ));
    }

    if packet.mode != 4 {
        return Err(Error::BadServerResponse(BadServerResponseReason::Mode(
            packet.mode,
        )));
    }

    if packet.originate_timestamp != request_transmit_timestamp {
        return Err(Error::BadServerResponse(
            BadServerResponseReason::OriginateTimestamp {
                expected: request_transmit_timestamp,
                actual: packet.originate_timestamp,
            },
        ));
    }

    Ok(SntpTimeQueryResult {
        local_clock_offset: ((packet.receive_timestamp - request_transmit_timestamp)
            + (packet.transmit_timestamp - destination_timestamp))
            / 2,

        round_trip_delay: (destination_timestamp - request_transmit_timestamp)
            - (packet.receive_timestamp - packet.transmit_timestamp),
    })
}