NTP packet analysis, authenticated UDP, clock filters and source consensus
///|
test "empty measurement selection" {
assert_true(@ntp.lowest_delay([]) is None)
}
///|
test "eight-stage clock filter example" {
let filter = @ntp.ClockFilter::new()
for i = 1; i <= 8; i = i + 1 {
let now = i.to_double()
filter.begin_poll(now)
ignore(
filter.observe({
offset_seconds: 0.01,
delay_seconds: 0.02,
dispersion_seconds: 0.000001,
received_at: now,
}),
)
}
let result = filter.estimate(8.0).unwrap()
assert_eq(result.valid_samples, 8)
assert_eq(result.reach, 255)
assert_eq(result.offset_seconds, 0.01)
assert_true(!result.fresh)
}pub struct ClockFilter {
entries : Array[FilterSample]
precision : Double
tolerance : Double
last_time : Double?
accepted : FilterEstimate?
reach : Int
} derive(Debug)fn ClockFilter::new(precision_seconds? : Double, frequency_tolerance? : Double) -> ClockFilter raise NtpErrorfn ClockFilter::observe(self : ClockFilter, sample : FilterSample) -> FilterEstimate? raise NtpErrorpub(all) struct Datagram {
header : Packet
extensions : Array[ExtensionField]
mac : Bytes
} derive(Eq, Debug)pub(all) struct FilterEstimate {
offset_seconds : Double
delay_seconds : Double
dispersion_seconds : Double
jitter_seconds : Double
selected_at : Double
evaluated_at : Double
valid_samples : Int
reach : Int
fresh : Bool
} derive(Debug)fn FilterEstimate::root_distance(self : FilterEstimate, root_delay_seconds : Double, root_dispersion_seconds : Double) -> Double raise NtpErrorfn analyze(sent : Timestamp, reply : Packet, arrived : Timestamp, pivot_unix : Double) -> ResponseInfo raise NtpErrorfn combine_peers(peers : Array[PeerEstimate], minimum? : Int, cluster_minimum? : Int, maximum_distance? : Double) -> Consensus? raise NtpErrorInstall
Download zipNTP packet analysis, authenticated UDP, clock filters and source consensus