1use smoltcp::phy;
2use smoltcp::time::Instant;
3use std::cell::RefCell;
4use std::collections::VecDeque;
5use std::rc::Rc;
6
7use crate::metrics::ChannelMetrics;
8
9use ya_relay_util::Payload;
10
11type Pcap = RefCell<Box<dyn phy::PcapSink>>;
12
13pub struct CaptureDevice {
15 tx_queue: VecDeque<Vec<u8>>,
16 rx_queue: VecDeque<Payload>,
17 medium: phy::Medium,
18 max_transmission_unit: usize,
19 pcap: Option<Pcap>,
20 metrics: Rc<RefCell<ChannelMetrics>>,
21}
22
23impl Default for CaptureDevice {
24 fn default() -> Self {
25 Self {
26 tx_queue: Default::default(),
27 rx_queue: Default::default(),
28 medium: Default::default(),
29 max_transmission_unit: 1280,
30 pcap: Default::default(),
31 metrics: Default::default(),
32 }
33 }
34}
35
36impl CaptureDevice {
37 pub fn tap(mtu: usize) -> Self {
38 Self {
39 max_transmission_unit: mtu,
40 ..Default::default()
41 }
42 }
43
44 pub fn tun(mtu: usize) -> Self {
45 Self {
46 medium: phy::Medium::Ip,
47 max_transmission_unit: mtu,
48 ..Default::default()
49 }
50 }
51
52 pub fn pcap_tap<S>(mtu: usize, mut pcap: S) -> Self
53 where
54 S: phy::PcapSink + 'static,
55 {
56 pcap.global_header(phy::PcapLinkType::Ethernet);
57 let pcap = RefCell::new(Box::new(pcap));
58
59 Self {
60 max_transmission_unit: mtu,
61 pcap: Some(pcap),
62 ..Default::default()
63 }
64 }
65
66 pub fn pcap_tun<S>(mtu: usize, mut pcap: S) -> Self
67 where
68 S: phy::PcapSink + 'static,
69 {
70 pcap.global_header(phy::PcapLinkType::Ip);
71 let pcap = RefCell::new(Box::new(pcap));
72
73 Self {
74 medium: phy::Medium::Ip,
75 max_transmission_unit: mtu,
76 pcap: Some(pcap),
77 ..Default::default()
78 }
79 }
80
81 #[inline]
82 pub fn is_tun(&self) -> bool {
83 self.medium == phy::Medium::Ip
84 }
85
86 #[inline]
87 pub fn metrics(&self) -> ChannelMetrics {
88 self.metrics.borrow().clone()
89 }
90
91 #[inline]
92 pub fn phy_rx(&mut self, data: impl Into<Payload>) {
93 self.rx_queue.push_back(data.into());
94 }
95
96 #[inline]
97 pub fn next_phy_tx(&mut self) -> Option<Vec<u8>> {
98 self.tx_queue.pop_front()
99 }
100}
101
102impl phy::Device for CaptureDevice {
103 type RxToken<'a> = RxToken<'a>
104 where
105 Self: 'a;
106 type TxToken<'a> = TxToken<'a>
107 where
108 Self: 'a;
109
110 fn receive(&mut self, timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
111 let item = self.rx_queue.pop_front();
112 item.map(move |buffer| {
113 let rx = RxToken {
114 buffer,
115 pcap: &self.pcap,
116 metrics: self.metrics.clone(),
117 timestamp,
118 };
119 let tx = TxToken {
120 queue: &mut self.tx_queue,
121 pcap: &self.pcap,
122 metrics: self.metrics.clone(),
123 timestamp,
124 };
125 (rx, tx)
126 })
127 }
128
129 fn transmit(&mut self, timestamp: Instant) -> Option<Self::TxToken<'_>> {
130 Some(TxToken {
131 queue: &mut self.tx_queue,
132 pcap: &self.pcap,
133 metrics: self.metrics.clone(),
134 timestamp,
135 })
136 }
137
138 fn capabilities(&self) -> phy::DeviceCapabilities {
139 let mut caps = phy::DeviceCapabilities::default();
140 caps.max_transmission_unit = self.max_transmission_unit;
141 caps.medium = self.medium;
142 caps
143 }
144}
145
146pub struct RxToken<'a> {
148 buffer: Payload,
149 pcap: &'a Option<Pcap>,
150 metrics: Rc<RefCell<ChannelMetrics>>,
151 timestamp: Instant,
152}
153
154impl<'a> phy::RxToken for RxToken<'a> {
155 fn consume<R, F>(mut self, f: F) -> R
156 where
157 F: FnOnce(&mut [u8]) -> R,
158 {
159 let result = f(self.buffer.as_mut());
160
161 {
162 let mut metrics = self.metrics.borrow_mut();
163 metrics.rx.push(self.buffer.len() as f32);
164 }
165
166 if let Some(pcap) = self.pcap {
167 pcap.borrow_mut()
168 .packet(self.timestamp, self.buffer.as_ref());
169 }
170
171 result
172 }
173}
174
175pub struct TxToken<'a> {
177 queue: &'a mut VecDeque<Vec<u8>>,
178 pcap: &'a Option<Pcap>,
179 metrics: Rc<RefCell<ChannelMetrics>>,
180 timestamp: Instant,
181}
182
183impl<'a> phy::TxToken for TxToken<'a> {
184 fn consume<R, F>(self, len: usize, f: F) -> R
185 where
186 F: FnOnce(&mut [u8]) -> R,
187 {
188 let mut buffer = vec![0; len];
189 buffer.resize(len, 0);
190 let result = f(&mut buffer);
191
192 {
193 let mut metrics = self.metrics.borrow_mut();
194 metrics.tx.push(buffer.len() as f32);
195 }
196
197 if let Some(pcap) = self.pcap {
198 pcap.borrow_mut().packet(self.timestamp, buffer.as_ref());
199 }
200
201 self.queue.push_back(buffer);
202 result
203 }
204}