Skip to content

Commit

Permalink
Expose typed poll interval and listen to server min poll interval
Browse files Browse the repository at this point in the history
  • Loading branch information
tdittr committed Oct 31, 2023
1 parent 6598597 commit 1c2bc15
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 16 deletions.
24 changes: 16 additions & 8 deletions ntp-proto/src/packet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ struct NtpHeaderV3V4 {
leap: NtpLeapIndicator,
mode: NtpAssociationMode,
stratum: u8,
poll: i8,
poll: PollInterval,
precision: i8,
root_delay: NtpDuration,
root_dispersion: NtpDuration,
Expand Down Expand Up @@ -159,7 +159,7 @@ impl NtpHeaderV3V4 {
leap: NtpLeapIndicator::NoWarning,
mode: NtpAssociationMode::Client,
stratum: 0,
poll: 0,
poll: PollInterval::from_byte(0),
precision: 0,
root_delay: NtpDuration::default(),
root_dispersion: NtpDuration::default(),
Expand All @@ -181,7 +181,7 @@ impl NtpHeaderV3V4 {
leap: NtpLeapIndicator::from_bits((data[0] & 0xC0) >> 6),
mode: NtpAssociationMode::from_bits(data[0] & 0x07),
stratum: data[1],
poll: data[2] as i8,
poll: PollInterval::from_byte(data[2]),
precision: data[3] as i8,
root_delay: NtpDuration::from_bits_short(data[4..8].try_into().unwrap()),
root_dispersion: NtpDuration::from_bits_short(data[8..12].try_into().unwrap()),
Expand All @@ -197,7 +197,7 @@ impl NtpHeaderV3V4 {

fn serialize<W: std::io::Write>(&self, w: &mut W, version: u8) -> std::io::Result<()> {
w.write_all(&[(self.leap.to_bits() << 6) | (version << 3) | self.mode.to_bits()])?;
w.write_all(&[self.stratum, self.poll as u8, self.precision as u8])?;
w.write_all(&[self.stratum, self.poll.as_byte(), self.precision as u8])?;
w.write_all(&self.root_delay.to_bits_short())?;
w.write_all(&self.root_dispersion.to_bits_short())?;
w.write_all(&self.reference_id.to_bytes())?;
Expand All @@ -210,7 +210,7 @@ impl NtpHeaderV3V4 {

fn poll_message(poll_interval: PollInterval) -> (Self, RequestIdentifier) {
let mut packet = Self::new();
packet.poll = poll_interval.as_log();
packet.poll = poll_interval;
packet.mode = NtpAssociationMode::Client;

// In order to increase the entropy of the transmit timestamp
Expand Down Expand Up @@ -875,6 +875,14 @@ impl<'a> NtpPacket<'a> {
}
}

pub fn poll(&self) -> PollInterval {
match self.header {
NtpHeader::V3(h) | NtpHeader::V4(h) => h.poll,
#[cfg(feature = "ntpv5")]
NtpHeader::V5(h) => h.poll,
}
}

pub fn stratum(&self) -> u8 {
match self.header {
NtpHeader::V3(header) => header.stratum,
Expand Down Expand Up @@ -1240,7 +1248,7 @@ mod tests {
leap: NtpLeapIndicator::NoWarning,
mode: NtpAssociationMode::Client,
stratum: 2,
poll: 6,
poll: PollInterval::from_byte(6),
precision: -24,
root_delay: NtpDuration::from_fixed_int(1023 << 16),
root_dispersion: NtpDuration::from_fixed_int(893 << 16),
Expand Down Expand Up @@ -1269,7 +1277,7 @@ mod tests {
leap: NtpLeapIndicator::NoWarning,
mode: NtpAssociationMode::Client,
stratum: 2,
poll: 6,
poll: PollInterval::from_byte(6),
precision: -24,
root_delay: NtpDuration::from_fixed_int(1023 << 16),
root_dispersion: NtpDuration::from_fixed_int(893 << 16),
Expand Down Expand Up @@ -1301,7 +1309,7 @@ mod tests {
leap: NtpLeapIndicator::NoWarning,
mode: NtpAssociationMode::Server,
stratum: 2,
poll: 6,
poll: PollInterval::from_byte(6),
precision: -23,
root_delay: NtpDuration::from_fixed_int(566 << 16),
root_dispersion: NtpDuration::from_fixed_int(951 << 16),
Expand Down
16 changes: 8 additions & 8 deletions ntp-proto/src/packet/v5/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ pub struct NtpHeaderV5 {
pub leap: NtpLeapIndicator,
pub mode: NtpMode,
pub stratum: u8,
pub poll: i8,
pub poll: PollInterval,
pub precision: i8,
pub timescale: NtpTimescale,
pub era: NtpEra,
Expand All @@ -161,7 +161,7 @@ impl NtpHeaderV5 {
leap: NtpLeapIndicator::NoWarning,
mode: NtpMode::Request,
stratum: 0,
poll: 0,
poll: PollInterval::from_byte(0),
precision: 0,
root_delay: NtpDuration::default(),
root_dispersion: NtpDuration::default(),
Expand Down Expand Up @@ -229,7 +229,7 @@ impl NtpHeaderV5 {
leap: NtpLeapIndicator::from_bits((data[0] & 0xC0) >> 6),
mode: NtpMode::from_bits(data[0] & 0x07)?,
stratum: data[1],
poll: data[2] as i8,
poll: PollInterval::from_byte(data[2]),
precision: data[3] as i8,
timescale: NtpTimescale::from_bits(data[4])?,
era: NtpEra(data[5]),
Expand All @@ -248,7 +248,7 @@ impl NtpHeaderV5 {
#[allow(dead_code)]
pub(crate) fn serialize<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
w.write_all(&[(self.leap.to_bits() << 6) | (Self::VERSION << 3) | self.mode.to_bits()])?;
w.write_all(&[self.stratum, self.poll as u8, self.precision as u8])?;
w.write_all(&[self.stratum, self.poll.as_byte(), self.precision as u8])?;
w.write_all(&[self.timescale.to_bits()])?;
w.write_all(&[self.era.0])?;
w.write_all(&self.flags.as_bits())?;
Expand All @@ -263,7 +263,7 @@ impl NtpHeaderV5 {

pub fn poll_message(poll_interval: PollInterval) -> (Self, RequestIdentifier) {
let mut packet = Self::new();
packet.poll = poll_interval.as_log();
packet.poll = poll_interval;
packet.mode = NtpMode::Request;

let client_cookie = NtpClientCookie::new_random();
Expand Down Expand Up @@ -358,7 +358,7 @@ mod tests {
assert_eq!(parsed.leap, NtpLeapIndicator::NoWarning);
assert!(parsed.mode.is_request());
assert_eq!(parsed.stratum, 0);
assert_eq!(parsed.poll, 5);
assert_eq!(parsed.poll, PollInterval::from_byte(5));
assert_eq!(parsed.precision, 0);
assert_eq!(parsed.timescale, NtpTimescale::Ut1);
assert_eq!(parsed.era, NtpEra(0));
Expand Down Expand Up @@ -422,7 +422,7 @@ mod tests {
assert_eq!(parsed.leap, NtpLeapIndicator::NoWarning);
assert!(parsed.mode.is_response());
assert_eq!(parsed.stratum, 4);
assert_eq!(parsed.poll, 5);
assert_eq!(parsed.poll, PollInterval::from_byte(5));
assert_eq!(parsed.precision, 6);
assert_eq!(parsed.timescale, NtpTimescale::Tai);
assert_eq!(parsed.era, NtpEra(7));
Expand Down Expand Up @@ -468,7 +468,7 @@ mod tests {
leap: NtpLeapIndicator::from_bits(i % 4),
mode: NtpMode::from_bits(3 + (i % 2)).unwrap(),
stratum: i.wrapping_add(1),
poll: i.wrapping_add(3) as i8,
poll: PollInterval::from_byte(i.wrapping_add(3)),
precision: i.wrapping_add(4) as i8,
timescale: NtpTimescale::from_bits(i % 4).unwrap(),
era: NtpEra(i.wrapping_add(6)),
Expand Down
17 changes: 17 additions & 0 deletions ntp-proto/src/peer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,23 @@ impl Peer {
self.stratum = message.stratum();
self.reference_id = message.reference_id();

// Handle new requested poll interval
#[cfg(feature = "ntpv5")]
if message.version() == 5 {
let requested_poll = message.poll();

if requested_poll > self.remote_min_poll_interval {
debug!(
?requested_poll,
?self.remote_min_poll_interval,
"Adapting to longer poll interval requested by server"
);
self.remote_min_poll_interval = requested_poll;
}
self.remote_min_poll_interval =
std::cmp::max(self.remote_min_poll_interval, requested_poll);
}

// generate a measurement
let measurement = Measurement::from_packet(
&message,
Expand Down
8 changes: 8 additions & 0 deletions ntp-proto/src/time_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,14 @@ impl PollInterval {
Self(value)
}

pub fn from_byte(value: u8) -> Self {
Self(value as i8)
}

pub fn as_byte(self) -> u8 {
self.0 as u8
}

#[must_use]
pub fn inc(self, limits: PollIntervalLimits) -> Self {
Self(self.0 + 1).min(limits.max)
Expand Down

0 comments on commit 1c2bc15

Please sign in to comment.