1#[cfg(target_os = "linux")]
4use super::ble::DefaultBleTransport;
5#[cfg(any(target_os = "linux", target_os = "macos"))]
6use super::ethernet::EthernetTransport;
7#[cfg(feature = "sim-transport")]
8use super::sim::SimTransport;
9use super::tcp::TcpTransport;
10use super::tor::TorTransport;
11use super::tor::control::TorMonitoringInfo;
12use super::udp::UdpTransport;
13#[cfg(feature = "webrtc-transport")]
14use super::webrtc::WebRtcTransport;
15use super::{
16 ConnectionState, DiscoveredPeer, Transport, TransportAddr, TransportCongestion, TransportError,
17 TransportId, TransportState, TransportType,
18};
19
20pub enum TransportHandle {
25 Udp(UdpTransport),
27 #[cfg(feature = "sim-transport")]
29 Sim(SimTransport),
30 #[cfg(any(target_os = "linux", target_os = "macos"))]
32 Ethernet(EthernetTransport),
33 Tcp(TcpTransport),
35 Tor(TorTransport),
37 #[cfg(feature = "webrtc-transport")]
39 WebRtc(Box<WebRtcTransport>),
40 #[cfg(target_os = "linux")]
42 Ble(DefaultBleTransport),
43}
44
45impl TransportHandle {
46 pub async fn start(&mut self) -> Result<(), TransportError> {
48 match self {
49 TransportHandle::Udp(t) => t.start_async().await,
50 #[cfg(feature = "sim-transport")]
51 TransportHandle::Sim(t) => t.start_async().await,
52 #[cfg(any(target_os = "linux", target_os = "macos"))]
53 TransportHandle::Ethernet(t) => t.start_async().await,
54 TransportHandle::Tcp(t) => t.start_async().await,
55 TransportHandle::Tor(t) => t.start_async().await,
56 #[cfg(feature = "webrtc-transport")]
57 TransportHandle::WebRtc(t) => t.start_async().await,
58 #[cfg(target_os = "linux")]
59 TransportHandle::Ble(t) => t.start_async().await,
60 }
61 }
62
63 pub async fn stop(&mut self) -> Result<(), TransportError> {
65 match self {
66 TransportHandle::Udp(t) => t.stop_async().await,
67 #[cfg(feature = "sim-transport")]
68 TransportHandle::Sim(t) => t.stop_async().await,
69 #[cfg(any(target_os = "linux", target_os = "macos"))]
70 TransportHandle::Ethernet(t) => t.stop_async().await,
71 TransportHandle::Tcp(t) => t.stop_async().await,
72 TransportHandle::Tor(t) => t.stop_async().await,
73 #[cfg(feature = "webrtc-transport")]
74 TransportHandle::WebRtc(t) => t.stop_async().await,
75 #[cfg(target_os = "linux")]
76 TransportHandle::Ble(t) => t.stop_async().await,
77 }
78 }
79
80 pub async fn send(&self, addr: &TransportAddr, data: &[u8]) -> Result<usize, TransportError> {
82 match self {
83 TransportHandle::Udp(t) => t.send_async(addr, data).await,
84 #[cfg(feature = "sim-transport")]
85 TransportHandle::Sim(t) => t.send_async(addr, data).await,
86 #[cfg(any(target_os = "linux", target_os = "macos"))]
87 TransportHandle::Ethernet(t) => t.send_async(addr, data).await,
88 TransportHandle::Tcp(t) => t.send_async(addr, data).await,
89 TransportHandle::Tor(t) => t.send_async(addr, data).await,
90 #[cfg(feature = "webrtc-transport")]
91 TransportHandle::WebRtc(t) => t.send_async(addr, data).await,
92 #[cfg(target_os = "linux")]
93 TransportHandle::Ble(t) => t.send_async(addr, data).await,
94 }
95 }
96
97 pub fn transport_id(&self) -> TransportId {
99 match self {
100 TransportHandle::Udp(t) => t.transport_id(),
101 #[cfg(feature = "sim-transport")]
102 TransportHandle::Sim(t) => t.transport_id(),
103 #[cfg(any(target_os = "linux", target_os = "macos"))]
104 TransportHandle::Ethernet(t) => t.transport_id(),
105 TransportHandle::Tcp(t) => t.transport_id(),
106 TransportHandle::Tor(t) => t.transport_id(),
107 #[cfg(feature = "webrtc-transport")]
108 TransportHandle::WebRtc(t) => t.transport_id(),
109 #[cfg(target_os = "linux")]
110 TransportHandle::Ble(t) => t.transport_id(),
111 }
112 }
113
114 pub fn name(&self) -> Option<&str> {
116 match self {
117 TransportHandle::Udp(t) => t.name(),
118 #[cfg(feature = "sim-transport")]
119 TransportHandle::Sim(t) => t.name(),
120 #[cfg(any(target_os = "linux", target_os = "macos"))]
121 TransportHandle::Ethernet(t) => t.name(),
122 TransportHandle::Tcp(t) => t.name(),
123 TransportHandle::Tor(t) => t.name(),
124 #[cfg(feature = "webrtc-transport")]
125 TransportHandle::WebRtc(t) => t.name(),
126 #[cfg(target_os = "linux")]
127 TransportHandle::Ble(t) => t.name(),
128 }
129 }
130
131 pub fn transport_type(&self) -> &TransportType {
133 match self {
134 TransportHandle::Udp(t) => t.transport_type(),
135 #[cfg(feature = "sim-transport")]
136 TransportHandle::Sim(t) => t.transport_type(),
137 #[cfg(any(target_os = "linux", target_os = "macos"))]
138 TransportHandle::Ethernet(t) => t.transport_type(),
139 TransportHandle::Tcp(t) => t.transport_type(),
140 TransportHandle::Tor(t) => t.transport_type(),
141 #[cfg(feature = "webrtc-transport")]
142 TransportHandle::WebRtc(t) => t.transport_type(),
143 #[cfg(target_os = "linux")]
144 TransportHandle::Ble(t) => t.transport_type(),
145 }
146 }
147
148 pub fn state(&self) -> TransportState {
150 match self {
151 TransportHandle::Udp(t) => t.state(),
152 #[cfg(feature = "sim-transport")]
153 TransportHandle::Sim(t) => t.state(),
154 #[cfg(any(target_os = "linux", target_os = "macos"))]
155 TransportHandle::Ethernet(t) => t.state(),
156 TransportHandle::Tcp(t) => t.state(),
157 TransportHandle::Tor(t) => t.state(),
158 #[cfg(feature = "webrtc-transport")]
159 TransportHandle::WebRtc(t) => t.state(),
160 #[cfg(target_os = "linux")]
161 TransportHandle::Ble(t) => t.state(),
162 }
163 }
164
165 pub fn mtu(&self) -> u16 {
167 match self {
168 TransportHandle::Udp(t) => t.mtu(),
169 #[cfg(feature = "sim-transport")]
170 TransportHandle::Sim(t) => t.mtu(),
171 #[cfg(any(target_os = "linux", target_os = "macos"))]
172 TransportHandle::Ethernet(t) => t.mtu(),
173 TransportHandle::Tcp(t) => t.mtu(),
174 TransportHandle::Tor(t) => t.mtu(),
175 #[cfg(feature = "webrtc-transport")]
176 TransportHandle::WebRtc(t) => t.mtu(),
177 #[cfg(target_os = "linux")]
178 TransportHandle::Ble(t) => t.mtu(),
179 }
180 }
181
182 pub fn link_mtu(&self, addr: &TransportAddr) -> u16 {
187 match self {
188 TransportHandle::Udp(t) => t.link_mtu(addr),
189 #[cfg(feature = "sim-transport")]
190 TransportHandle::Sim(t) => t.link_mtu(addr),
191 #[cfg(any(target_os = "linux", target_os = "macos"))]
192 TransportHandle::Ethernet(t) => t.link_mtu(addr),
193 TransportHandle::Tcp(t) => t.link_mtu(addr),
194 TransportHandle::Tor(t) => t.link_mtu(addr),
195 #[cfg(feature = "webrtc-transport")]
196 TransportHandle::WebRtc(t) => t.link_mtu(addr),
197 #[cfg(target_os = "linux")]
198 TransportHandle::Ble(t) => t.link_mtu(addr),
199 }
200 }
201
202 pub fn local_addr(&self) -> Option<std::net::SocketAddr> {
204 match self {
205 TransportHandle::Udp(t) => t.local_addr(),
206 #[cfg(feature = "sim-transport")]
207 TransportHandle::Sim(_) => None,
208 #[cfg(any(target_os = "linux", target_os = "macos"))]
209 TransportHandle::Ethernet(_) => None,
210 TransportHandle::Tcp(t) => t.local_addr(),
211 TransportHandle::Tor(_) => None,
212 #[cfg(feature = "webrtc-transport")]
213 TransportHandle::WebRtc(_) => None,
214 #[cfg(target_os = "linux")]
215 TransportHandle::Ble(_) => None,
216 }
217 }
218
219 pub(crate) fn resolved_udp_socket_addr_if_cached(
224 &self,
225 addr: &TransportAddr,
226 ) -> Option<std::net::SocketAddr> {
227 match self {
228 TransportHandle::Udp(t) => t.resolved_socket_addr_if_cached(addr),
229 _ => None,
230 }
231 }
232
233 pub fn interface_name(&self) -> Option<&str> {
235 match self {
236 TransportHandle::Udp(_) => None,
237 #[cfg(feature = "sim-transport")]
238 TransportHandle::Sim(_) => None,
239 #[cfg(any(target_os = "linux", target_os = "macos"))]
240 TransportHandle::Ethernet(t) => Some(t.interface_name()),
241 TransportHandle::Tcp(_) => None,
242 TransportHandle::Tor(_) => None,
243 #[cfg(feature = "webrtc-transport")]
244 TransportHandle::WebRtc(_) => None,
245 #[cfg(target_os = "linux")]
246 TransportHandle::Ble(_) => None,
247 }
248 }
249
250 pub fn onion_address(&self) -> Option<&str> {
252 match self {
253 TransportHandle::Tor(t) => t.onion_address(),
254 _ => None,
255 }
256 }
257
258 pub fn tor_monitoring(&self) -> Option<TorMonitoringInfo> {
260 match self {
261 TransportHandle::Tor(t) => t.cached_monitoring(),
262 _ => None,
263 }
264 }
265
266 pub fn tor_mode(&self) -> Option<&str> {
268 match self {
269 TransportHandle::Tor(t) => Some(t.mode()),
270 _ => None,
271 }
272 }
273
274 pub fn discover(&self) -> Result<Vec<DiscoveredPeer>, TransportError> {
276 match self {
277 TransportHandle::Udp(t) => t.discover(),
278 #[cfg(feature = "sim-transport")]
279 TransportHandle::Sim(t) => t.discover(),
280 #[cfg(any(target_os = "linux", target_os = "macos"))]
281 TransportHandle::Ethernet(t) => t.discover(),
282 TransportHandle::Tcp(t) => t.discover(),
283 TransportHandle::Tor(t) => t.discover(),
284 #[cfg(feature = "webrtc-transport")]
285 TransportHandle::WebRtc(t) => t.discover(),
286 #[cfg(target_os = "linux")]
287 TransportHandle::Ble(t) => t.discover(),
288 }
289 }
290
291 pub fn auto_connect(&self) -> bool {
293 match self {
294 TransportHandle::Udp(t) => t.auto_connect(),
295 #[cfg(feature = "sim-transport")]
296 TransportHandle::Sim(t) => t.auto_connect(),
297 #[cfg(any(target_os = "linux", target_os = "macos"))]
298 TransportHandle::Ethernet(t) => t.auto_connect(),
299 TransportHandle::Tcp(t) => t.auto_connect(),
300 TransportHandle::Tor(t) => t.auto_connect(),
301 #[cfg(feature = "webrtc-transport")]
302 TransportHandle::WebRtc(t) => t.auto_connect(),
303 #[cfg(target_os = "linux")]
304 TransportHandle::Ble(t) => t.auto_connect(),
305 }
306 }
307
308 pub fn accept_connections(&self) -> bool {
310 match self {
311 TransportHandle::Udp(t) => t.accept_connections(),
312 #[cfg(feature = "sim-transport")]
313 TransportHandle::Sim(t) => t.accept_connections(),
314 #[cfg(any(target_os = "linux", target_os = "macos"))]
315 TransportHandle::Ethernet(t) => t.accept_connections(),
316 TransportHandle::Tcp(t) => t.accept_connections(),
317 TransportHandle::Tor(t) => t.accept_connections(),
318 #[cfg(feature = "webrtc-transport")]
319 TransportHandle::WebRtc(t) => t.accept_connections(),
320 #[cfg(target_os = "linux")]
321 TransportHandle::Ble(t) => t.accept_connections(),
322 }
323 }
324
325 pub async fn connect(&self, addr: &TransportAddr) -> Result<(), TransportError> {
333 match self {
334 TransportHandle::Udp(_) => Ok(()), #[cfg(feature = "sim-transport")]
336 TransportHandle::Sim(_) => Ok(()), #[cfg(any(target_os = "linux", target_os = "macos"))]
338 TransportHandle::Ethernet(_) => Ok(()), TransportHandle::Tcp(t) => t.connect_async(addr).await,
340 TransportHandle::Tor(t) => t.connect_async(addr).await,
341 #[cfg(feature = "webrtc-transport")]
342 TransportHandle::WebRtc(t) => t.connect_async(addr).await,
343 #[cfg(target_os = "linux")]
344 TransportHandle::Ble(t) => t.connect_async(addr).await,
345 }
346 }
347
348 pub fn connection_state(&self, addr: &TransportAddr) -> ConnectionState {
354 match self {
355 TransportHandle::Udp(_) => ConnectionState::Connected,
356 #[cfg(feature = "sim-transport")]
357 TransportHandle::Sim(_) => ConnectionState::Connected,
358 #[cfg(any(target_os = "linux", target_os = "macos"))]
359 TransportHandle::Ethernet(_) => ConnectionState::Connected,
360 TransportHandle::Tcp(t) => t.connection_state_sync(addr),
361 TransportHandle::Tor(t) => t.connection_state_sync(addr),
362 #[cfg(feature = "webrtc-transport")]
363 TransportHandle::WebRtc(t) => t.connection_state_sync(addr),
364 #[cfg(target_os = "linux")]
365 TransportHandle::Ble(t) => t.connection_state_sync(addr),
366 }
367 }
368
369 pub async fn close_connection(&self, addr: &TransportAddr) {
374 match self {
375 TransportHandle::Udp(t) => t.close_connection(addr),
376 #[cfg(feature = "sim-transport")]
377 TransportHandle::Sim(t) => t.close_connection(addr),
378 #[cfg(any(target_os = "linux", target_os = "macos"))]
379 TransportHandle::Ethernet(t) => t.close_connection(addr),
380 TransportHandle::Tcp(t) => t.close_connection_async(addr).await,
381 TransportHandle::Tor(t) => t.close_connection_async(addr).await,
382 #[cfg(feature = "webrtc-transport")]
383 TransportHandle::WebRtc(t) => t.close_connection_async(addr).await,
384 #[cfg(target_os = "linux")]
385 TransportHandle::Ble(t) => t.close_connection_async(addr).await,
386 }
387 }
388
389 pub fn is_operational(&self) -> bool {
391 self.state().is_operational()
392 }
393
394 pub fn congestion(&self) -> TransportCongestion {
400 match self {
401 TransportHandle::Udp(t) => t.congestion(),
402 #[cfg(feature = "sim-transport")]
403 TransportHandle::Sim(_) => TransportCongestion::default(),
404 #[cfg(any(target_os = "linux", target_os = "macos"))]
405 TransportHandle::Ethernet(_) => TransportCongestion::default(),
406 TransportHandle::Tcp(_) => TransportCongestion::default(),
407 TransportHandle::Tor(_) => TransportCongestion::default(),
408 #[cfg(feature = "webrtc-transport")]
409 TransportHandle::WebRtc(_) => TransportCongestion::default(),
410 #[cfg(target_os = "linux")]
411 TransportHandle::Ble(_) => TransportCongestion::default(),
412 }
413 }
414
415 pub fn transport_stats(&self) -> serde_json::Value {
419 match self {
420 TransportHandle::Udp(t) => {
421 serde_json::to_value(t.stats().snapshot()).unwrap_or_default()
422 }
423 #[cfg(feature = "sim-transport")]
424 TransportHandle::Sim(t) => serde_json::to_value(t.stats()).unwrap_or_default(),
425 #[cfg(any(target_os = "linux", target_os = "macos"))]
426 TransportHandle::Ethernet(t) => {
427 let snap = t.stats().snapshot();
428 serde_json::json!({
429 "frames_sent": snap.frames_sent,
430 "frames_recv": snap.frames_recv,
431 "bytes_sent": snap.bytes_sent,
432 "bytes_recv": snap.bytes_recv,
433 "send_errors": snap.send_errors,
434 "recv_errors": snap.recv_errors,
435 "beacons_sent": snap.beacons_sent,
436 "beacons_recv": snap.beacons_recv,
437 "frames_too_short": snap.frames_too_short,
438 "frames_too_long": snap.frames_too_long,
439 })
440 }
441 TransportHandle::Tcp(t) => {
442 serde_json::to_value(t.stats().snapshot()).unwrap_or_default()
443 }
444 TransportHandle::Tor(t) => {
445 serde_json::to_value(t.stats().snapshot()).unwrap_or_default()
446 }
447 #[cfg(feature = "webrtc-transport")]
448 TransportHandle::WebRtc(t) => serde_json::json!({
449 "mtu": t.mtu(),
450 "state": t.state().to_string(),
451 }),
452 #[cfg(target_os = "linux")]
453 TransportHandle::Ble(t) => {
454 serde_json::to_value(t.stats().snapshot()).unwrap_or_default()
455 }
456 }
457 }
458}