Pong over ipv4 response

This commit is contained in:
Andrew Golovashevich 2026-03-09 22:47:28 +03:00
parent 2b376a2239
commit 988f009913
7 changed files with 95 additions and 23 deletions

View File

@ -35,8 +35,8 @@ impl<A: Address> ServersContext<A> for Servers2NetworkCtxTestImpl<A> {
); );
} }
fn report_ping(&mut self, addr: A, id: u64, ping_ms: u64) { fn report_ping(&mut self, addr: A, id: u64, ping_ms: u128) {
println!("{} {ping_ms}", addr.to_string()) println!("{} {ping_ms} ms", addr.to_string())
} }
fn report_error(&mut self, addr: A, id: u64) { fn report_error(&mut self, addr: A, id: u64) {

View File

@ -12,7 +12,7 @@ pub trait NetworkContext {
pub trait ServersContext<A: Address> { pub trait ServersContext<A: Address> {
fn start_measuring(&mut self) -> (u64, impl Iterator<Item = A>); fn start_measuring(&mut self) -> (u64, impl Iterator<Item = A>);
fn report_ping(&mut self, addr: A, id: u64, ping_ms: u64); fn report_ping(&mut self, addr: A, id: u64, ping_ms: u128);
fn report_error(&mut self, addr: A, id: u64); fn report_error(&mut self, addr: A, id: u64);
} }

View File

@ -0,0 +1,39 @@
pub(crate) fn hton16(v: u16, b: &mut [u8]) {
b[0] = (v >> 8) as u8;
b[1] = (v & 0xFF) as u8;
}
pub(crate) fn hton64(v: u64, b: &mut [u8]) {
hton16((v >> 48) as u16, b);
hton16(((v >> 32) & 0xFFFF) as u16, &mut b[2..4]);
hton16(((v >> 16) & 0xFFFF) as u16, &mut b[4..6]);
hton16((v & 0xFFFF) as u16, &mut b[6..8]);
}
pub(crate) fn hton128(v: u128, b: &mut [u8]) {
hton64((v >> 64) as u64, b);
hton64((v & 0xFFFF_FFFF_FFFF_FFFF) as u64, &mut b[8..16]);
}
pub(crate) fn ntoh16(b: &[u8]) -> u16 {
let mut v = 0u16;
v += (b[0] as u16) << 8;
v += b[1] as u16;
return v;
}
pub(crate) fn ntoh64(b: &[u8]) -> u64 {
let mut v = 0u64;
v += (ntoh16(b) as u64) << 48;
v += (ntoh16(&b[2..4]) as u64) << 32;
v += (ntoh16(&b[4..6]) as u64) << 16;
v += ntoh16(&b[6..8]) as u64;
return v;
}
pub(crate) fn ntoh128(b: &[u8]) -> u128 {
let mut v = 0u128;
v += (ntoh64(b) as u128) << 64;
v += ntoh64(&b[8..16]) as u128;
return v;
}

View File

@ -1,23 +1,9 @@
mod checksum; mod checksum;
mod ping; mod ping;
mod pong;
mod conversions;
use checksum::IPv4ChecksumAccumulator; use checksum::IPv4ChecksumAccumulator;
pub use ping::fmt_icmp_echo_req; pub use ping::fmt_icmp_echo_req;
pub use pong::{parse_icmp_echo_res, IcmpPong};
fn hton16(v: u16, b: &mut [u8]) {
b[0] = (v >> 8) as u8;
b[1] = (v & 0xFF) as u8;
}
fn hton64(v: u64, b: &mut [u8]) {
hton16((v >> 48) as u16, b);
hton16(((v >> 32) & 0xFFFF) as u16, &mut b[2..4]);
hton16(((v >> 16) & 0xFFFF) as u16, &mut b[4..6]);
hton16((v & 0xFFFF) as u16, &mut b[6..8]);
}
fn hton128(v: u128, b: &mut [u8]) {
hton64((v >> 64) as u64, b);
hton64((v & 0xFFFF_FFFF_FFFF_FFFF) as u64, &mut b[8..16]);
}

View File

@ -1,5 +1,5 @@
use crate::checksum::IPv4ChecksumAccumulator; use crate::checksum::IPv4ChecksumAccumulator;
use crate::{hton128, hton16, hton64}; use crate::conversions::{hton128, hton16, hton64};
pub fn fmt_icmp_echo_req(buff: &mut [u8], seq_no: u16, req_id: u64, timestamp: u128) -> usize{ pub fn fmt_icmp_echo_req(buff: &mut [u8], seq_no: u16, req_id: u64, timestamp: u128) -> usize{
buff[0] = 8; buff[0] = 8;

24
network/icmp/src/pong.rs Normal file
View File

@ -0,0 +1,24 @@
use crate::checksum::IPv4ChecksumAccumulator;
use crate::conversions::{hton16, hton64, hton128, ntoh16, ntoh64, ntoh128};
pub enum IcmpPong {
WrongChecksum,
Success { req_id: u64, timestamp: u128 },
}
pub fn parse_icmp_echo_res(buff: &[u8]) -> IcmpPong {
let expected_checksum = ntoh16(&buff[2..4]);
let mut checksum = IPv4ChecksumAccumulator::new();
checksum.add_first_byte(buff[0]);
checksum.add_second_byte(buff[1]);
checksum.add_trailing_data(&buff[4..32]);
let actual_checksum = checksum.snapshot();
if actual_checksum != expected_checksum {
return IcmpPong::WrongChecksum;
}
return IcmpPong::Success {
req_id: ntoh64(&buff[8..16]),
timestamp: ntoh128(&buff[16..32]),
};
}

View File

@ -12,10 +12,10 @@ use allocator::Allocator;
use bgtu_networks_2_network_abstract::{Address, ServersContext}; use bgtu_networks_2_network_abstract::{Address, ServersContext};
use std::ptr::NonNull; use std::ptr::NonNull;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use windows::Win32::Networking::WinSock::{WSAEACCES, WSA_ERROR}; use windows::Win32::Networking::WinSock::{AF_INET, AF_INET6, WSAEACCES, WSA_ERROR};
use windows::Win32::System::SystemInformation::GetTickCount; use windows::Win32::System::SystemInformation::GetTickCount;
use windows::Win32::System::Threading::SleepEx; use windows::Win32::System::Threading::SleepEx;
use bgtu_networks_2_network_icmp::fmt_icmp_echo_req; use bgtu_networks_2_network_icmp::{fmt_icmp_echo_req, parse_icmp_echo_res, IcmpPong};
pub unsafe fn run_eventloop<Ctx: ServersContext<WindowsAddressKnown>>(ctx: *mut Ctx) { pub unsafe fn run_eventloop<Ctx: ServersContext<WindowsAddressKnown>>(ctx: *mut Ctx) {
let heap = Allocator::new(); let heap = Allocator::new();
@ -86,6 +86,29 @@ impl<'s, Ctx: ServersContext<WindowsAddressKnown>> RecvCallback<'_, Ctx> {
unsafe { unsafe {
let this = this_ptr.cast::<Self>().as_ref(); let this = this_ptr.cast::<Self>().as_ref();
this.bind_callback(); this.bind_callback();
let buffer_no_ip_header;
match addr.any.native.ss_family {
AF_INET => {
let ipv4_len = ((buffer[0] & 0x0F) as usize) * 4;
buffer_no_ip_header = &buffer[ipv4_len..buffer.len()];
}
AF_INET6 => {
buffer_no_ip_header = &buffer[40..buffer.len()];
// todo extra headers
}
_ => panic!("Unsupported L4 header")
}
match parse_icmp_echo_res(buffer_no_ip_header) {
IcmpPong::WrongChecksum => {
println!("Wrong checksum")
}
IcmpPong::Success { req_id, timestamp } => {
let delta = get_timestamp() - timestamp;
NonNull::new_unchecked(this.ctx).as_mut().report_ping(addr, req_id, delta);
}
}
} }
println!("Received from addr {} data {:02X?}", addr.to_string(), buffer); println!("Received from addr {} data {:02X?}", addr.to_string(), buffer);