1#![forbid(unsafe_op_in_unsafe_fn)]
9
10mod interface;
11mod raw_socket;
12mod socket;
13
14#[cfg(target_os = "linux")]
15mod hwtimestamp;
16
17use ntp_proto::NtpTimestamp;
18
19pub use interface::InterfaceName;
20use serde::Deserialize;
21pub use socket::UdpSocket;
22
23#[derive(Debug, Clone, Copy, Deserialize)]
28#[serde(rename_all = "kebab-case")]
29pub struct EnableTimestamps {
30 #[serde(default = "bool_true")]
31 pub rx_software: bool,
32 #[serde(default = "bool_true")]
33 pub tx_software: bool,
34 #[serde(default)] pub rx_hardware: bool,
36 #[serde(default)] pub tx_hardware: bool,
38}
39
40impl Default for EnableTimestamps {
41 fn default() -> Self {
42 Self {
43 rx_software: true,
44 tx_software: false,
45 rx_hardware: false,
46 tx_hardware: false,
47 }
48 }
49}
50
51#[derive(Clone, Copy)]
52pub(crate) enum LibcTimestamp {
53 #[cfg_attr(any(target_os = "macos", target_os = "freebsd"), allow(unused))]
54 TimeSpec {
55 seconds: i64,
56 nanos: i64,
57 },
58 TimeVal {
59 seconds: i64,
60 micros: i64,
61 },
62}
63
64impl LibcTimestamp {
65 #[cfg_attr(any(target_os = "macos", target_os = "freebsd"), allow(unused))]
66 fn from_timespec(timespec: libc::timespec) -> Self {
67 Self::TimeSpec {
68 seconds: timespec.tv_sec as _,
69 nanos: timespec.tv_nsec as _,
70 }
71 }
72
73 #[cfg_attr(target_os = "linux", allow(unused))]
74 fn from_timeval(timespec: libc::timeval) -> Self {
75 Self::TimeVal {
76 seconds: timespec.tv_sec as _,
77 micros: timespec.tv_usec as _,
78 }
79 }
80}
81
82impl LibcTimestamp {
83 pub(crate) fn into_ntp_timestamp(self) -> NtpTimestamp {
84 const EPOCH_OFFSET: u32 = (70 * 365 + 17) * 86400;
88
89 match self {
90 LibcTimestamp::TimeSpec { seconds, nanos } => {
91 let seconds = (seconds as u32).wrapping_add(EPOCH_OFFSET);
93
94 let nanos = nanos as u32;
96
97 NtpTimestamp::from_seconds_nanos_since_ntp_era(seconds, nanos)
98 }
99 LibcTimestamp::TimeVal { seconds, micros } => {
100 let seconds = (seconds as u32).wrapping_add(EPOCH_OFFSET);
102 let nanos = micros as u32 * 1000;
103
104 NtpTimestamp::from_seconds_nanos_since_ntp_era(seconds, nanos)
105 }
106 }
107 }
108}
109
110fn bool_true() -> bool {
111 true
112}