Rust CI / cargo fmt (push) Successful in 15s
Rust CI / cargo clippy (push) Failing after 35s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Failing after 32s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Failing after 9s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Failing after 41s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Failing after 7s
Rust CI / cargo doc (push) Successful in 37s
Supply chain / actionlint (push) Successful in 8s
Supply chain / cargo-deny bans licenses sources (push) Failing after 1m47s
Supply chain / cargo-deny advisories (push) Failing after 1m49s
Remove direct `rustix::time::ClockId` imports by centralizing its dependency within the `time` module.
97 lines
3.5 KiB
Rust
97 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::{ClockSample, Monotonic};
|
|
use icmp_socket2::Icmpv4Message;
|
|
use icmp_socket2::Icmpv4Packet;
|
|
use icmp_socket2::packet::WithEchoRequest;
|
|
|
|
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 = ClockSample::<Monotonic>::now();
|
|
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 = ClockSample::<Monotonic>::now();
|
|
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,
|
|
)
|
|
}
|
|
}
|