Skip to content

Commit

Permalink
try so_timestamp on macos
Browse files Browse the repository at this point in the history
  • Loading branch information
folkertdev authored and davidv1992 committed Jan 19, 2024
1 parent b784982 commit 00df4a0
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/raw_socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use crate::{
mod freebsd;
#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "macos")]
mod macos;

// A struct providing safe wrappers around various socket api calls
#[derive(Debug, Hash)]
Expand Down
35 changes: 35 additions & 0 deletions src/raw_socket/macos.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::cerr;

use super::RawSocket;

impl RawSocket {
pub(crate) fn so_timestamp(&self, options: u32) -> std::io::Result<()> {
// Documentation on the timestamping calls:
//
// - linux: https://www.kernel.org/doc/Documentation/networking/timestamping.txt
// - freebsd: https://man.freebsd.org/cgi/man.cgi?setsockopt
//
// SAFETY:
//
// - the socket is provided by (safe) rust, and will outlive the call
// - method is guaranteed to be a valid "name" argument
// - the options pointer outlives the call
// - the `option_len` corresponds with the options pointer
//
// Only some bits are valid to set in `options`, but setting invalid bits is
// perfectly safe
//
// > Setting other bit returns EINVAL and does not change the current state.
unsafe {
cerr(libc::setsockopt(
self.fd,
libc::SOL_SOCKET,
libc::SO_TIMESTAMP,
&options as *const _ as *const libc::c_void,
std::mem::size_of_val(&options) as libc::socklen_t,
))
}?;

Ok(())
}
}
10 changes: 7 additions & 3 deletions src/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,23 @@ use crate::{
raw_socket::RawSocket,
};

#[cfg(not(any(target_os = "linux", target_os = "freebsd")))]
#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "macos")))]
mod fallback;
#[cfg(target_os = "freebsd")]
mod freebsd;
#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "macos")]
mod macos;

#[cfg(not(any(target_os = "linux", target_os = "freebsd")))]
#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "macos")))]
use self::fallback::*;
#[cfg(target_os = "freebsd")]
use self::freebsd::*;
#[cfg(target_os = "linux")]
pub use self::linux::*;
#[cfg(target_os = "macos")]
use self::macos::*;

#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Default)]
pub struct Timestamp {
Expand All @@ -30,7 +34,7 @@ pub struct Timestamp {
}

impl Timestamp {
#[cfg_attr(target_os = "macos", unused)] // macos does not do nanoseconds
#[cfg_attr(target_os = "macos", allow(unused))] // macos does not do nanoseconds
pub(crate) fn from_timespec(timespec: libc::timespec) -> Self {
Self {
seconds: timespec.tv_sec as _,
Expand Down
14 changes: 14 additions & 0 deletions src/socket/macos.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::raw_socket::RawSocket;

use super::InterfaceTimestampMode;

pub(super) fn configure_timestamping(
socket: &RawSocket,
mode: InterfaceTimestampMode,
) -> std::io::Result<()> {
match mode {
InterfaceTimestampMode::None => Ok(()),
InterfaceTimestampMode::SoftwareRecv => socket.so_timestamp(1),
_ => Err(std::io::ErrorKind::Unsupported.into()),
}
}

0 comments on commit 00df4a0

Please sign in to comment.