1#[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
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::websocket::WebSocketTransport;
16use super::{
17 ConnectionState, DiscoveredPeer, Transport, TransportAddr, TransportCongestion, TransportError,
18 TransportId, TransportState, TransportType,
19};
20
21pub enum TransportHandle {
26 Udp(UdpTransport),
28 #[cfg(feature = "sim-transport")]
30 Sim(SimTransport),
31 #[cfg(any(target_os = "linux", target_os = "macos"))]
33 Ethernet(EthernetTransport),
34 Tcp(TcpTransport),
36 WebSocket(Box<WebSocketTransport>),
38 Tor(TorTransport),
40 #[cfg(feature = "webrtc-transport")]
42 WebRtc(Box<WebRtcTransport>),
43 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
45 Ble(DefaultBleTransport),
46}
47
48impl TransportHandle {
49 pub(crate) fn is_operator_routing_adjacency(
50 &self,
51 addr: &TransportAddr,
52 handshake_is_initiator: bool,
53 ) -> bool {
54 match self {
55 TransportHandle::WebSocket(transport) => {
56 transport.is_configured_adjacency(addr, handshake_is_initiator)
57 }
58 TransportHandle::Udp(transport) => {
59 transport.is_operator_routing_adjacency(handshake_is_initiator)
60 }
61 _ => false,
62 }
63 }
64
65 pub(crate) fn canonical_addr(
69 &self,
70 addr: &TransportAddr,
71 ) -> Result<TransportAddr, TransportError> {
72 match self {
73 #[cfg(feature = "webrtc-transport")]
74 TransportHandle::WebRtc(_) => super::webrtc::canonical_webrtc_addr(addr),
75 _ => Ok(addr.clone()),
76 }
77 }
78
79 #[cfg(feature = "webrtc-transport")]
82 pub(crate) fn drain_link_negotiations(
83 &mut self,
84 limit: usize,
85 ) -> Vec<super::link_negotiation::OutboundLinkNegotiation> {
86 match self {
87 TransportHandle::WebRtc(transport) => transport.drain_link_negotiations(limit),
88 _ => Vec::new(),
89 }
90 }
91
92 #[cfg(feature = "webrtc-transport")]
94 pub(crate) fn ingest_link_negotiation(
95 &self,
96 source: secp256k1::PublicKey,
97 message: super::link_negotiation::LinkNegotiationMessage,
98 ) -> Result<(), TransportError> {
99 match self {
100 TransportHandle::WebRtc(transport) if message.link_type == "webrtc" => {
101 transport.ingest_link_negotiation(source, message)
102 }
103 _ => Err(TransportError::NotSupported(
104 "no enabled adapter accepts this link negotiation".into(),
105 )),
106 }
107 }
108
109 pub async fn start(&mut self) -> Result<(), TransportError> {
111 match self {
112 TransportHandle::Udp(t) => t.start_async().await,
113 #[cfg(feature = "sim-transport")]
114 TransportHandle::Sim(t) => t.start_async().await,
115 #[cfg(any(target_os = "linux", target_os = "macos"))]
116 TransportHandle::Ethernet(t) => t.start_async().await,
117 TransportHandle::Tcp(t) => t.start_async().await,
118 TransportHandle::WebSocket(t) => t.start_async().await,
119 TransportHandle::Tor(t) => t.start_async().await,
120 #[cfg(feature = "webrtc-transport")]
121 TransportHandle::WebRtc(t) => t.start_async().await,
122 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
123 TransportHandle::Ble(t) => t.start_async().await,
124 }
125 }
126
127 pub async fn stop(&mut self) -> Result<(), TransportError> {
129 match self {
130 TransportHandle::Udp(t) => t.stop_async().await,
131 #[cfg(feature = "sim-transport")]
132 TransportHandle::Sim(t) => t.stop_async().await,
133 #[cfg(any(target_os = "linux", target_os = "macos"))]
134 TransportHandle::Ethernet(t) => t.stop_async().await,
135 TransportHandle::Tcp(t) => t.stop_async().await,
136 TransportHandle::WebSocket(t) => t.stop_async().await,
137 TransportHandle::Tor(t) => t.stop_async().await,
138 #[cfg(feature = "webrtc-transport")]
139 TransportHandle::WebRtc(t) => t.stop_async().await,
140 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
141 TransportHandle::Ble(t) => t.stop_async().await,
142 }
143 }
144
145 pub async fn send(&self, addr: &TransportAddr, data: &[u8]) -> Result<usize, TransportError> {
147 match self {
148 TransportHandle::Udp(t) => t.send_async(addr, data).await,
149 #[cfg(feature = "sim-transport")]
150 TransportHandle::Sim(t) => t.send_async(addr, data).await,
151 #[cfg(any(target_os = "linux", target_os = "macos"))]
152 TransportHandle::Ethernet(t) => t.send_async(addr, data).await,
153 TransportHandle::Tcp(t) => t.send_async(addr, data).await,
154 TransportHandle::WebSocket(t) => t.send_async(addr, data).await,
155 TransportHandle::Tor(t) => t.send_async(addr, data).await,
156 #[cfg(feature = "webrtc-transport")]
157 TransportHandle::WebRtc(t) => Box::pin(t.send_async(addr, data)).await,
159 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
160 TransportHandle::Ble(t) => t.send_async(addr, data).await,
161 }
162 }
163
164 pub(crate) async fn send_with_timeout(
165 &self,
166 addr: &TransportAddr,
167 data: &[u8],
168 timeout: std::time::Duration,
169 ) -> Result<usize, TransportError> {
170 match self {
171 TransportHandle::Tcp(transport) => {
172 transport.send_async_with_timeout(addr, data, timeout).await
173 }
174 _ => self.send(addr, data).await,
175 }
176 }
177
178 pub fn transport_id(&self) -> TransportId {
180 match self {
181 TransportHandle::Udp(t) => t.transport_id(),
182 #[cfg(feature = "sim-transport")]
183 TransportHandle::Sim(t) => t.transport_id(),
184 #[cfg(any(target_os = "linux", target_os = "macos"))]
185 TransportHandle::Ethernet(t) => t.transport_id(),
186 TransportHandle::Tcp(t) => t.transport_id(),
187 TransportHandle::WebSocket(t) => t.transport_id(),
188 TransportHandle::Tor(t) => t.transport_id(),
189 #[cfg(feature = "webrtc-transport")]
190 TransportHandle::WebRtc(t) => t.transport_id(),
191 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
192 TransportHandle::Ble(t) => t.transport_id(),
193 }
194 }
195
196 pub(crate) fn uses_fips_byte_stream_framing(&self) -> bool {
198 matches!(self, TransportHandle::Tcp(_) | TransportHandle::Tor(_))
199 }
200
201 pub fn name(&self) -> Option<&str> {
203 match self {
204 TransportHandle::Udp(t) => t.name(),
205 #[cfg(feature = "sim-transport")]
206 TransportHandle::Sim(t) => t.name(),
207 #[cfg(any(target_os = "linux", target_os = "macos"))]
208 TransportHandle::Ethernet(t) => t.name(),
209 TransportHandle::Tcp(t) => t.name(),
210 TransportHandle::WebSocket(t) => t.name(),
211 TransportHandle::Tor(t) => t.name(),
212 #[cfg(feature = "webrtc-transport")]
213 TransportHandle::WebRtc(t) => t.name(),
214 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
215 TransportHandle::Ble(t) => t.name(),
216 }
217 }
218
219 pub fn transport_type(&self) -> &TransportType {
221 match self {
222 TransportHandle::Udp(t) => t.transport_type(),
223 #[cfg(feature = "sim-transport")]
224 TransportHandle::Sim(t) => t.transport_type(),
225 #[cfg(any(target_os = "linux", target_os = "macos"))]
226 TransportHandle::Ethernet(t) => t.transport_type(),
227 TransportHandle::Tcp(t) => t.transport_type(),
228 TransportHandle::WebSocket(t) => t.transport_type(),
229 TransportHandle::Tor(t) => t.transport_type(),
230 #[cfg(feature = "webrtc-transport")]
231 TransportHandle::WebRtc(t) => t.transport_type(),
232 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
233 TransportHandle::Ble(t) => t.transport_type(),
234 }
235 }
236
237 pub fn state(&self) -> TransportState {
239 match self {
240 TransportHandle::Udp(t) => t.state(),
241 #[cfg(feature = "sim-transport")]
242 TransportHandle::Sim(t) => t.state(),
243 #[cfg(any(target_os = "linux", target_os = "macos"))]
244 TransportHandle::Ethernet(t) => t.state(),
245 TransportHandle::Tcp(t) => t.state(),
246 TransportHandle::WebSocket(t) => t.state(),
247 TransportHandle::Tor(t) => t.state(),
248 #[cfg(feature = "webrtc-transport")]
249 TransportHandle::WebRtc(t) => t.state(),
250 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
251 TransportHandle::Ble(t) => t.state(),
252 }
253 }
254
255 pub fn mtu(&self) -> u16 {
257 match self {
258 TransportHandle::Udp(t) => t.mtu(),
259 #[cfg(feature = "sim-transport")]
260 TransportHandle::Sim(t) => t.mtu(),
261 #[cfg(any(target_os = "linux", target_os = "macos"))]
262 TransportHandle::Ethernet(t) => t.mtu(),
263 TransportHandle::Tcp(t) => t.mtu(),
264 TransportHandle::WebSocket(t) => t.mtu(),
265 TransportHandle::Tor(t) => t.mtu(),
266 #[cfg(feature = "webrtc-transport")]
267 TransportHandle::WebRtc(t) => t.mtu(),
268 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
269 TransportHandle::Ble(t) => t.mtu(),
270 }
271 }
272
273 pub fn link_mtu(&self, addr: &TransportAddr) -> u16 {
278 match self {
279 TransportHandle::Udp(t) => t.link_mtu(addr),
280 #[cfg(feature = "sim-transport")]
281 TransportHandle::Sim(t) => t.link_mtu(addr),
282 #[cfg(any(target_os = "linux", target_os = "macos"))]
283 TransportHandle::Ethernet(t) => t.link_mtu(addr),
284 TransportHandle::Tcp(t) => t.link_mtu(addr),
285 TransportHandle::WebSocket(t) => t.link_mtu(addr),
286 TransportHandle::Tor(t) => t.link_mtu(addr),
287 #[cfg(feature = "webrtc-transport")]
288 TransportHandle::WebRtc(t) => t.link_mtu(addr),
289 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
290 TransportHandle::Ble(t) => t.link_mtu(addr),
291 }
292 }
293
294 pub fn local_addr(&self) -> Option<std::net::SocketAddr> {
296 match self {
297 TransportHandle::Udp(t) => t.local_addr(),
298 #[cfg(feature = "sim-transport")]
299 TransportHandle::Sim(_) => None,
300 #[cfg(any(target_os = "linux", target_os = "macos"))]
301 TransportHandle::Ethernet(_) => None,
302 TransportHandle::Tcp(t) => t.local_addr(),
303 TransportHandle::WebSocket(t) => t.local_addr(),
304 TransportHandle::Tor(_) => None,
305 #[cfg(feature = "webrtc-transport")]
306 TransportHandle::WebRtc(_) => None,
307 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
308 TransportHandle::Ble(_) => None,
309 }
310 }
311
312 pub(crate) fn resolved_udp_socket_addr_if_cached(
317 &self,
318 addr: &TransportAddr,
319 ) -> Option<std::net::SocketAddr> {
320 match self {
321 TransportHandle::Udp(t) => t.resolved_socket_addr_if_cached(addr),
322 _ => None,
323 }
324 }
325
326 pub fn interface_name(&self) -> Option<&str> {
328 match self {
329 TransportHandle::Udp(_) => None,
330 #[cfg(feature = "sim-transport")]
331 TransportHandle::Sim(_) => None,
332 #[cfg(any(target_os = "linux", target_os = "macos"))]
333 TransportHandle::Ethernet(t) => Some(t.interface_name()),
334 TransportHandle::Tcp(_) => None,
335 TransportHandle::WebSocket(_) => None,
336 TransportHandle::Tor(_) => None,
337 #[cfg(feature = "webrtc-transport")]
338 TransportHandle::WebRtc(_) => None,
339 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
340 TransportHandle::Ble(_) => None,
341 }
342 }
343
344 pub fn onion_address(&self) -> Option<&str> {
346 match self {
347 TransportHandle::Tor(t) => t.onion_address(),
348 _ => None,
349 }
350 }
351
352 pub fn tor_monitoring(&self) -> Option<TorMonitoringInfo> {
354 match self {
355 TransportHandle::Tor(t) => t.cached_monitoring(),
356 _ => None,
357 }
358 }
359
360 pub fn tor_mode(&self) -> Option<&str> {
362 match self {
363 TransportHandle::Tor(t) => Some(t.mode()),
364 _ => None,
365 }
366 }
367
368 pub fn discover(&self) -> Result<Vec<DiscoveredPeer>, TransportError> {
370 match self {
371 TransportHandle::Udp(t) => t.discover(),
372 #[cfg(feature = "sim-transport")]
373 TransportHandle::Sim(t) => t.discover(),
374 #[cfg(any(target_os = "linux", target_os = "macos"))]
375 TransportHandle::Ethernet(t) => t.discover(),
376 TransportHandle::Tcp(t) => t.discover(),
377 TransportHandle::WebSocket(t) => t.discover(),
378 TransportHandle::Tor(t) => t.discover(),
379 #[cfg(feature = "webrtc-transport")]
380 TransportHandle::WebRtc(t) => t.discover(),
381 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
382 TransportHandle::Ble(t) => t.discover(),
383 }
384 }
385
386 pub fn auto_connect(&self) -> bool {
388 match self {
389 TransportHandle::Udp(t) => t.auto_connect(),
390 #[cfg(feature = "sim-transport")]
391 TransportHandle::Sim(t) => t.auto_connect(),
392 #[cfg(any(target_os = "linux", target_os = "macos"))]
393 TransportHandle::Ethernet(t) => t.auto_connect(),
394 TransportHandle::Tcp(t) => t.auto_connect(),
395 TransportHandle::WebSocket(t) => t.auto_connect(),
396 TransportHandle::Tor(t) => t.auto_connect(),
397 #[cfg(feature = "webrtc-transport")]
398 TransportHandle::WebRtc(t) => t.auto_connect(),
399 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
400 TransportHandle::Ble(t) => t.auto_connect(),
401 }
402 }
403
404 pub fn accept_connections(&self) -> bool {
406 match self {
407 TransportHandle::Udp(t) => t.accept_connections(),
408 #[cfg(feature = "sim-transport")]
409 TransportHandle::Sim(t) => t.accept_connections(),
410 #[cfg(any(target_os = "linux", target_os = "macos"))]
411 TransportHandle::Ethernet(t) => t.accept_connections(),
412 TransportHandle::Tcp(t) => t.accept_connections(),
413 TransportHandle::WebSocket(t) => t.accept_connections(),
414 TransportHandle::Tor(t) => t.accept_connections(),
415 #[cfg(feature = "webrtc-transport")]
416 TransportHandle::WebRtc(t) => t.accept_connections(),
417 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
418 TransportHandle::Ble(t) => t.accept_connections(),
419 }
420 }
421
422 pub async fn connect(&self, addr: &TransportAddr) -> Result<(), TransportError> {
430 match self {
431 TransportHandle::Udp(_) => Ok(()), #[cfg(feature = "sim-transport")]
433 TransportHandle::Sim(_) => Ok(()), #[cfg(any(target_os = "linux", target_os = "macos"))]
435 TransportHandle::Ethernet(_) => Ok(()), TransportHandle::Tcp(t) => t.connect_async(addr).await,
437 TransportHandle::WebSocket(t) => t.connect_async(addr).await,
438 TransportHandle::Tor(t) => t.connect_async(addr).await,
439 #[cfg(feature = "webrtc-transport")]
440 TransportHandle::WebRtc(t) => t.connect_async(addr).await,
441 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
442 TransportHandle::Ble(t) => t.connect_async(addr).await,
443 }
444 }
445
446 pub fn connection_state(&self, addr: &TransportAddr) -> ConnectionState {
452 match self {
453 TransportHandle::Udp(_) => ConnectionState::Connected,
454 #[cfg(feature = "sim-transport")]
455 TransportHandle::Sim(_) => ConnectionState::Connected,
456 #[cfg(any(target_os = "linux", target_os = "macos"))]
457 TransportHandle::Ethernet(_) => ConnectionState::Connected,
458 TransportHandle::Tcp(t) => t.connection_state_sync(addr),
459 TransportHandle::WebSocket(t) => t.connection_state_sync(addr),
460 TransportHandle::Tor(t) => t.connection_state_sync(addr),
461 #[cfg(feature = "webrtc-transport")]
462 TransportHandle::WebRtc(t) => t.connection_state_sync(addr),
463 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
464 TransportHandle::Ble(t) => t.connection_state_sync(addr),
465 }
466 }
467
468 pub async fn close_connection(&self, addr: &TransportAddr) {
473 match self {
474 TransportHandle::Udp(t) => t.close_connection(addr),
475 #[cfg(feature = "sim-transport")]
476 TransportHandle::Sim(t) => t.close_connection(addr),
477 #[cfg(any(target_os = "linux", target_os = "macos"))]
478 TransportHandle::Ethernet(t) => t.close_connection(addr),
479 TransportHandle::Tcp(t) => t.close_connection_async(addr).await,
480 TransportHandle::WebSocket(t) => t.close_connection_async(addr).await,
481 TransportHandle::Tor(t) => t.close_connection_async(addr).await,
482 #[cfg(feature = "webrtc-transport")]
483 TransportHandle::WebRtc(t) => t.close_connection_async(addr).await,
484 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
485 TransportHandle::Ble(t) => t.close_connection_async(addr).await,
486 }
487 }
488
489 pub fn close_connection_detached(&self, _addr: &TransportAddr) {
491 #[cfg(feature = "webrtc-transport")]
492 if let TransportHandle::WebRtc(transport) = self {
493 transport.close_connection_detached(_addr);
494 }
495 }
496
497 pub fn is_operational(&self) -> bool {
499 self.state().is_operational()
500 }
501
502 pub fn congestion(&self) -> TransportCongestion {
508 match self {
509 TransportHandle::Udp(t) => t.congestion(),
510 #[cfg(feature = "sim-transport")]
511 TransportHandle::Sim(_) => TransportCongestion::default(),
512 #[cfg(any(target_os = "linux", target_os = "macos"))]
513 TransportHandle::Ethernet(_) => TransportCongestion::default(),
514 TransportHandle::Tcp(_) => TransportCongestion::default(),
515 TransportHandle::WebSocket(_) => TransportCongestion::default(),
516 TransportHandle::Tor(_) => TransportCongestion::default(),
517 #[cfg(feature = "webrtc-transport")]
518 TransportHandle::WebRtc(_) => TransportCongestion::default(),
519 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
520 TransportHandle::Ble(_) => TransportCongestion::default(),
521 }
522 }
523
524 pub fn transport_stats(&self) -> serde_json::Value {
528 match self {
529 TransportHandle::Udp(t) => {
530 serde_json::to_value(t.stats().snapshot()).unwrap_or_default()
531 }
532 #[cfg(feature = "sim-transport")]
533 TransportHandle::Sim(t) => serde_json::to_value(t.stats()).unwrap_or_default(),
534 #[cfg(any(target_os = "linux", target_os = "macos"))]
535 TransportHandle::Ethernet(t) => {
536 let snap = t.stats().snapshot();
537 serde_json::json!({
538 "frames_sent": snap.frames_sent,
539 "frames_recv": snap.frames_recv,
540 "bytes_sent": snap.bytes_sent,
541 "bytes_recv": snap.bytes_recv,
542 "send_errors": snap.send_errors,
543 "recv_errors": snap.recv_errors,
544 "beacons_sent": snap.beacons_sent,
545 "beacons_recv": snap.beacons_recv,
546 "frames_too_short": snap.frames_too_short,
547 "frames_too_long": snap.frames_too_long,
548 })
549 }
550 TransportHandle::Tcp(t) => {
551 serde_json::to_value(t.stats().snapshot()).unwrap_or_default()
552 }
553 TransportHandle::WebSocket(t) => serde_json::to_value(t.stats()).unwrap_or_default(),
554 TransportHandle::Tor(t) => {
555 serde_json::to_value(t.stats().snapshot()).unwrap_or_default()
556 }
557 #[cfg(feature = "webrtc-transport")]
558 TransportHandle::WebRtc(t) => serde_json::json!({
559 "mtu": t.mtu(),
560 "state": t.state().to_string(),
561 }),
562 #[cfg(any(target_os = "linux", feature = "host-ble-transport", test))]
563 TransportHandle::Ble(t) => {
564 serde_json::to_value(t.stats().snapshot()).unwrap_or_default()
565 }
566 }
567 }
568}