1use bytes::BytesMut;
3use log::{debug, warn};
4use smoltcp::phy::{Checksum, Device, Medium};
5use tokio::sync::mpsc::Sender;
6
7const TEAR_OFF_BUFFER_SIZE: usize = 65536;
8
9pub struct ChannelDevice {
10 pub mtu: usize,
11 pub medium: Medium,
12 pub tx: Sender<BytesMut>,
13 pub rx: Option<BytesMut>,
14 tear_off_buffer: BytesMut,
15}
16
17impl ChannelDevice {
18 pub fn new(mtu: usize, medium: Medium, tx: Sender<BytesMut>) -> Self {
19 Self {
20 mtu,
21 medium,
22 tx,
23 rx: None,
24 tear_off_buffer: BytesMut::with_capacity(TEAR_OFF_BUFFER_SIZE),
25 }
26 }
27}
28
29pub struct RxToken(pub BytesMut);
30
31impl Device for ChannelDevice {
32 type RxToken<'a> = RxToken where Self: 'a;
33 type TxToken<'a> = &'a mut ChannelDevice where Self: 'a;
34
35 fn receive(
36 &mut self,
37 _timestamp: smoltcp::time::Instant,
38 ) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
39 self.rx.take().map(|x| (RxToken(x), self))
40 }
41
42 fn transmit(&mut self, _timestamp: smoltcp::time::Instant) -> Option<Self::TxToken<'_>> {
43 if self.tx.capacity() == 0 {
44 debug!("ran out of transmission capacity");
45 return None;
46 }
47 Some(self)
48 }
49
50 fn capabilities(&self) -> smoltcp::phy::DeviceCapabilities {
51 let mut capabilities = smoltcp::phy::DeviceCapabilities::default();
52 capabilities.medium = self.medium;
53 capabilities.max_transmission_unit = self.mtu;
54 capabilities.checksum = smoltcp::phy::ChecksumCapabilities::ignored();
55 capabilities.checksum.tcp = Checksum::Tx;
56 capabilities.checksum.ipv4 = Checksum::Tx;
57 capabilities.checksum.icmpv4 = Checksum::Tx;
58 capabilities.checksum.icmpv6 = Checksum::Tx;
59 capabilities
60 }
61}
62
63impl smoltcp::phy::RxToken for RxToken {
64 fn consume<R, F>(mut self, f: F) -> R
65 where
66 F: FnOnce(&mut [u8]) -> R,
67 {
68 f(&mut self.0[..])
69 }
70}
71
72impl<'a> smoltcp::phy::TxToken for &'a mut ChannelDevice {
73 fn consume<R, F>(self, len: usize, f: F) -> R
74 where
75 F: FnOnce(&mut [u8]) -> R,
76 {
77 self.tear_off_buffer.resize(len, 0);
78 let result = f(&mut self.tear_off_buffer[..]);
79 let chunk = self.tear_off_buffer.split();
80 if let Err(error) = self.tx.try_send(chunk) {
81 warn!("failed to transmit packet: {}", error);
82 }
83
84 if self.tear_off_buffer.capacity() < self.mtu {
85 self.tear_off_buffer = BytesMut::with_capacity(TEAR_OFF_BUFFER_SIZE);
86 }
87 result
88 }
89}