use smoltcp::phy::{ChecksumCapabilities, Device, DeviceCapabilities, Medium}; use smoltcp::time::Instant; use smoltcp::wire::{Ipv4Packet, Ipv4Repr}; use std::collections::VecDeque; pub struct VirtualIpDevice { queue: VecDeque>, /// Sends IP packets ip_tx: crossbeam_channel::Sender>, } impl VirtualIpDevice { pub fn new(ip_tx: crossbeam_channel::Sender>) -> Self { Self { queue: VecDeque::new(), ip_tx, } } } impl<'a> Device<'a> for VirtualIpDevice { type RxToken = RxToken; type TxToken = TxToken<'a>; fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { self.queue.pop_front().map(move |buffer| { let rx = RxToken { buffer }; let tx = TxToken { queue: &mut self.queue, tx: Some(self.ip_tx.clone()), }; (rx, tx) }) } fn transmit(&'a mut self) -> Option { Some(TxToken { queue: &mut self.queue, tx: Some(self.ip_tx.clone()), }) } fn capabilities(&self) -> DeviceCapabilities { let mut cap = DeviceCapabilities::default(); cap.medium = Medium::Ip; cap.max_transmission_unit = 65535; cap } } #[doc(hidden)] pub struct RxToken { buffer: Vec, } impl smoltcp::phy::RxToken for RxToken { fn consume(mut self, _timestamp: Instant, f: F) -> smoltcp::Result where F: FnOnce(&mut [u8]) -> smoltcp::Result, { f(&mut self.buffer) } } #[doc(hidden)] pub struct TxToken<'a> { queue: &'a mut VecDeque>, tx: Option>>, } impl<'a> smoltcp::phy::TxToken for TxToken<'a> { fn consume(self, _timestamp: Instant, len: usize, f: F) -> smoltcp::Result where F: FnOnce(&mut [u8]) -> smoltcp::Result, { let mut buffer = Vec::new(); buffer.resize(len, 0); let result = f(&mut buffer); self.tx.map(|tx| tx.send(buffer.clone())); self.queue.push_back(buffer); result } }