use sntpc::{Error, NtpContext, NtpTimestampGenerator, NtpUdpSocket, sntp_process_response, sntp_send_request};
use std::net::SocketAddr;
#[derive(Default, Copy, Clone)]
pub struct MockTimestampGen;
impl NtpTimestampGenerator for MockTimestampGen {
fn init(&mut self) {}
fn timestamp_sec(&self) -> u64 {
0u64
}
fn timestamp_subsec_micros(&self) -> u32 {
0u32
}
}
pub struct MockUdpSocket {
write_result: sntpc::Result<usize>,
read: [u8; 48],
read_result: sntpc::Result<(usize, SocketAddr)>,
}
impl MockUdpSocket {
#[must_use]
pub fn new(dest_addr: SocketAddr, data: [u8; 48]) -> Self {
Self {
write_result: Ok(48),
read: data,
read_result: Ok((data.len(), dest_addr)),
}
}
pub fn update_write_result(&mut self, value: sntpc::Result<usize>) {
self.write_result = value;
}
pub fn update_read_result(&mut self, value: sntpc::Result<(usize, SocketAddr)>) {
self.read_result = value;
}
}
impl NtpUdpSocket for MockUdpSocket {
async fn send_to(&self, _buf: &[u8], _addr: SocketAddr) -> sntpc::Result<usize> {
self.write_result
}
async fn recv_from(&self, buf: &mut [u8]) -> sntpc::Result<(usize, SocketAddr)> {
buf.copy_from_slice(&self.read);
self.read_result
}
}
#[test]
fn test_kiss_of_death() {
let defined_codes = [
"ACST", "AUTH", "AUTO", "BCST", "CRYP", "DENY", "DROP", "RSTR", "INIT", "MCST", "NKEY", "RATE", "RMOT", "STEP",
];
for code in defined_codes {
let dest: SocketAddr = "127.0.0.1:123".parse().unwrap();
let data = {
const TIMESTAMP: u64 = 9_487_534_653_230_284_800u64;
let mut data = [0u8; 48];
data[0] = 0xE4;
data[12..16].copy_from_slice(code.as_bytes());
data[24..32].copy_from_slice(TIMESTAMP.to_be_bytes().as_ref());
data
};
let mut socket = MockUdpSocket::new(dest, data);
socket.update_read_result(Ok((data.len(), dest)));
let context = NtpContext::new(MockTimestampGen);
let mut executor: miniloop::executor::Executor<1> = miniloop::executor::Executor::new();
let mut handler: miniloop::task::Handle<()> = miniloop::task::Handle::default();
let mut task = miniloop::task::Task::new("test", async {
let result = sntp_send_request(dest, &socket, context).await;
assert!(result.is_ok());
let result = sntp_process_response(dest, &socket, context, result.unwrap()).await;
match result.unwrap_err() {
Error::KissOfDeath(kod_code) => assert_eq!(kod_code.as_str(), code),
_ => unreachable!("Unexpected error code"),
}
});
let _ = executor.spawn(&mut task, &mut handler);
executor.run();
}
}