use std::net::IpAddr;
use etherparse::{NetSlice, SlicedPacket, TransportSlice};
#[derive(Clone, Debug)]
pub struct Frame {
pub timestamp_secs: u64,
pub timestamp_usecs: u32,
pub bytes: Vec<u8>,
}
#[derive(Clone, Debug)]
pub struct TcpSegment<'a> {
pub src_ip: IpAddr,
pub dst_ip: IpAddr,
pub src_port: u16,
pub dst_port: u16,
pub payload: &'a [u8],
}
#[must_use]
pub fn extract_tcp(frame_bytes: &[u8]) -> Option<TcpSegment<'_>> {
let sliced = SlicedPacket::from_ethernet(frame_bytes).ok()?;
let (src_ip, dst_ip) = match sliced.net.as_ref()? {
NetSlice::Ipv4(ipv4) => {
let hdr = ipv4.header();
(
IpAddr::V4(hdr.source_addr()),
IpAddr::V4(hdr.destination_addr()),
)
}
NetSlice::Ipv6(ipv6) => {
let hdr = ipv6.header();
(
IpAddr::V6(hdr.source_addr()),
IpAddr::V6(hdr.destination_addr()),
)
}
NetSlice::Arp(_) => return None,
};
let TransportSlice::Tcp(tcp) = sliced.transport? else {
return None;
};
let payload = tcp.payload();
Some(TcpSegment {
src_ip,
dst_ip,
src_port: tcp.source_port(),
dst_port: tcp.destination_port(),
payload,
})
}