Remove legacy src/config.rs and migrate all application consumers to the nested Settings model. Baseliner, metrics, pingers, ratecontroller, reflector selector, and main now use Settings. Derived min rates become methods on NetworkSettings rather than stored legacy fields. MeasurementType and ObservabilityProtocol move into the settings module.
98 lines
3.5 KiB
Rust
98 lines
3.5 KiB
Rust
// SPDX-FileCopyrightText: 2022-Present Charles Corrigan mailto:chas-iot@runegate.org (github @chas-iot)
|
|
// SPDX-FileCopyrightText: 2022-Present Daniel Lakeland mailto:dlakelan@street-artists.org (github @dlakelan)
|
|
// SPDX-FileCopyrightText: 2022-Present Mark Baker mailto:mark@vpost.net (github @Fail-Safe)
|
|
// SPDX-FileCopyrightText: 2022-Present Nils Andreas Svee mailto:contact@lochnair.net (github @Lochnair)
|
|
//
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
use std::net::IpAddr;
|
|
use std::time::Instant;
|
|
|
|
use crate::pinger::{PingError, PingListener, PingReply, PingSender};
|
|
use crate::settings::MeasurementType;
|
|
use crate::time::Time;
|
|
use icmp_socket2::Icmpv4Message;
|
|
use icmp_socket2::Icmpv4Packet;
|
|
use icmp_socket2::packet::WithEchoRequest;
|
|
use rustix::time::ClockId;
|
|
|
|
pub struct PingerICMPEchoListener {}
|
|
|
|
pub struct PingerICMPEchoSender {}
|
|
|
|
impl PingListener for PingerICMPEchoListener {
|
|
// Result: RTT, down time, up time
|
|
fn parse_packet(
|
|
&self,
|
|
id: u16,
|
|
reflector: IpAddr,
|
|
measurement_type: MeasurementType,
|
|
pkt: Icmpv4Packet,
|
|
) -> Result<PingReply, PingError> {
|
|
match pkt.typ {
|
|
0 => {
|
|
if let Icmpv4Message::EchoReply {
|
|
identifier,
|
|
sequence,
|
|
payload,
|
|
} = pkt.message
|
|
{
|
|
if identifier != id {
|
|
return Err(PingError::WrongID {
|
|
expected: id,
|
|
found: identifier,
|
|
});
|
|
}
|
|
|
|
let time_sent = match payload.as_slice().try_into() {
|
|
Ok(bytes) => u64::from_be_bytes(bytes) as i64,
|
|
Err(_) => {
|
|
return Err(PingError::InvalidPacket(format!(
|
|
"Expected 8 bytes payload, but found {}",
|
|
payload.len()
|
|
)));
|
|
}
|
|
};
|
|
|
|
let clock = Time::new(ClockId::Monotonic);
|
|
let time_ms = clock.to_milliseconds() as i64;
|
|
|
|
let rtt = (time_ms - time_sent) as f64;
|
|
Ok(PingReply {
|
|
reflector,
|
|
measurement_type,
|
|
seq: sequence,
|
|
rtt,
|
|
current_time: time_ms,
|
|
down_time: (rtt / 2.0) as f64,
|
|
up_time: (rtt / 2.0) as f64,
|
|
originate_timestamp: time_sent,
|
|
receive_timestamp: 0,
|
|
transmit_timestamp: 0,
|
|
last_receive_time_s: Instant::now(),
|
|
})
|
|
} else {
|
|
Err(PingError::InvalidPacket(format!(
|
|
"Packet had type {:?}, but did not match the structure",
|
|
pkt.typ
|
|
)))
|
|
}
|
|
}
|
|
type_ => Err(PingError::InvalidType(format!("{:?}", type_))),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PingSender for PingerICMPEchoSender {
|
|
fn craft_packet(&self, id: u16, seq: u16) -> (Icmpv4Packet, i64) {
|
|
let clock = Time::new(ClockId::Monotonic);
|
|
let time_ms = clock.to_milliseconds();
|
|
let payload = time_ms.to_be_bytes().to_vec();
|
|
|
|
(
|
|
Icmpv4Packet::with_echo_request(id, seq, payload).unwrap(),
|
|
time_ms as i64,
|
|
)
|
|
}
|
|
}
|