chimemon/src/chrony_refclock.rs
2025-05-03 23:12:15 -07:00

71 lines
2.2 KiB
Rust

use async_trait::async_trait;
use chimemon::{ChimemonMessage, ChimemonTarget, ChimemonTargetChannel, ChronySockConfig};
use libc::{c_double, c_int, timeval};
use log::debug;
use std::mem;
use std::os::unix::net::UnixDatagram;
use std::path::PathBuf;
const CHRONY_MAGIC: c_int = 0x534f434b;
pub struct ChronySockServer {
sock_path: PathBuf,
}
#[repr(C)]
#[derive(Debug)]
pub struct ChronyTimeReport {
tv: timeval,
offset: c_double,
pulse: c_int,
leap: c_int,
_pad: c_int,
magic: c_int,
}
impl ChronySockServer {
pub fn new(config: ChronySockConfig) -> Self {
ChronySockServer {
sock_path: config.sock.into(),
}
}
}
#[async_trait]
impl ChimemonTarget for ChronySockServer {
async fn run(mut self, mut chan: ChimemonTargetChannel) {
loop {
let msg = chan.recv().await.unwrap();
match msg {
ChimemonMessage::TimeReport(tr) => {
if tr.valid {
{
let frame = ChronyTimeReport {
tv: timeval {
tv_sec: tr.system_time.timestamp(),
tv_usec: tr.system_time.timestamp(),
},
offset: tr.offset.num_nanoseconds().unwrap() as f64 / 1e9,
leap: if tr.leap_flag { 1 } else { 0 },
pulse: 0,
_pad: 0,
magic: CHRONY_MAGIC,
};
let bs = unsafe {
std::slice::from_raw_parts(
(&frame as *const ChronyTimeReport) as *const u8,
mem::size_of::<ChronyTimeReport>(),
)
};
debug!("Sending to chrony sock {:#?}", frame);
let sock = UnixDatagram::unbound().unwrap();
sock.send_to(bs, &self.sock_path).unwrap();
}
}
}
_ => continue,
}
}
}
}