1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
//! Transport abstraction for multi-transport support
//!
//! This module provides a common interface for different transport protocols:
//! - QUIC (primary, high-performance)
//! - TCP (fallback, universal compatibility)
//! - WebSocket (gateway compatibility)
//! - WebTransport (future browser support)
use anyhow::Result;
use async_trait::async_trait;
use bytes::Bytes;
use std::fmt;
use std::net::SocketAddr;
use std::time::Duration;
use thiserror::Error;
/// Transport error types
#[derive(Error, Debug)]
pub enum TransportError {
#[error("Connection failed: {0}")]
ConnectionFailed(String),
#[error("Connection closed: {0}")]
ConnectionClosed(String),
#[error("Send failed: {0}")]
SendFailed(String),
#[error("Receive failed: {0}")]
ReceiveFailed(String),
#[error("Timeout after {0:?}")]
Timeout(Duration),
#[error("Transport not available: {0}")]
NotAvailable(String),
#[error("Protocol error: {0}")]
ProtocolError(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
}
/// Transport type identifier
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TransportType {
/// QUIC transport (primary)
Quic,
/// TCP transport (fallback)
Tcp,
/// WebSocket transport
WebSocket,
/// WebTransport (HTTP/3 based)
WebTransport,
}
impl fmt::Display for TransportType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TransportType::Quic => write!(f, "QUIC"),
TransportType::Tcp => write!(f, "TCP"),
TransportType::WebSocket => write!(f, "WebSocket"),
TransportType::WebTransport => write!(f, "WebTransport"),
}
}
}
/// Transport capabilities for feature detection
#[derive(Debug, Clone, Copy)]
pub struct TransportCapabilities {
/// Supports multiplexed streams
pub multiplexing: bool,
/// Supports 0-RTT connection establishment
pub zero_rtt: bool,
/// Supports connection migration
pub migration: bool,
/// Native encryption support
pub encryption: bool,
/// Supports unreliable datagrams
pub datagrams: bool,
/// Maximum message size (None = unlimited)
pub max_message_size: Option<usize>,
}
impl TransportCapabilities {
/// QUIC capabilities
pub fn quic() -> Self {
Self {
multiplexing: true,
zero_rtt: true,
migration: true,
encryption: true,
datagrams: true,
max_message_size: None,
}
}
/// TCP capabilities
pub fn tcp() -> Self {
Self {
multiplexing: false,
zero_rtt: false,
migration: false,
encryption: false,
datagrams: false,
max_message_size: None,
}
}
/// WebSocket capabilities
pub fn websocket() -> Self {
Self {
multiplexing: false,
zero_rtt: false,
migration: false,
encryption: true,
datagrams: false,
max_message_size: Some(16 * 1024 * 1024), // 16MB typical limit
}
}
/// WebTransport capabilities
pub fn webtransport() -> Self {
Self {
multiplexing: true,
zero_rtt: false,
migration: false,
encryption: true,
datagrams: true,
max_message_size: None,
}
}
}
/// Connection metrics for monitoring
#[derive(Debug, Clone, Default)]
pub struct ConnectionMetrics {
/// Bytes sent
pub bytes_sent: u64,
/// Bytes received
pub bytes_received: u64,
/// Round-trip time estimate
pub rtt: Option<Duration>,
/// Number of active streams
pub active_streams: usize,
/// Connection uptime
pub uptime: Duration,
}
/// A transport connection handle
#[async_trait]
pub trait Connection: Send + Sync {
/// Send data over the connection
async fn send(&mut self, data: Bytes) -> Result<(), TransportError>;
/// Receive data from the connection
async fn receive(&mut self) -> Result<Bytes, TransportError>;
/// Close the connection gracefully
async fn close(&mut self) -> Result<(), TransportError>;
/// Check if the connection is still alive
fn is_alive(&self) -> bool;
/// Get connection metrics
fn metrics(&self) -> ConnectionMetrics;
/// Get the remote address
fn remote_addr(&self) -> SocketAddr;
/// Get the transport type
fn transport_type(&self) -> TransportType;
}
/// Transport trait for different protocols
#[async_trait]
pub trait Transport: Send + Sync {
/// Get the transport type
fn transport_type(&self) -> TransportType;
/// Get transport capabilities
fn capabilities(&self) -> TransportCapabilities;
/// Check if this transport is available in the current environment
fn is_available(&self) -> bool;
/// Connect to a remote peer
async fn connect(&self, addr: SocketAddr) -> Result<Box<dyn Connection>, TransportError>;
/// Start listening for incoming connections
async fn listen(&self, addr: SocketAddr) -> Result<(), TransportError>;
/// Accept an incoming connection
async fn accept(&self) -> Result<Box<dyn Connection>, TransportError>;
/// Get transport-specific statistics
fn stats(&self) -> TransportStats;
}
/// Statistics for a transport
#[derive(Debug, Clone, Default)]
pub struct TransportStats {
/// Total connections established
pub connections_established: u64,
/// Total connections failed
pub connections_failed: u64,
/// Currently active connections
pub active_connections: usize,
/// Total bytes sent
pub bytes_sent: u64,
/// Total bytes received
pub bytes_received: u64,
/// Average RTT
pub avg_rtt: Option<Duration>,
}
/// Transport selection strategy
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TransportSelectionStrategy {
/// Prefer lowest latency
LowestLatency,
/// Prefer highest bandwidth
HighestBandwidth,
/// Prefer most features
MostCapable,
/// Use first available
FirstAvailable,
/// Prefer specific transport type
PreferType(TransportType),
}
/// Transport selector for automatic transport selection
pub struct TransportSelector {
transports: Vec<Box<dyn Transport>>,
strategy: TransportSelectionStrategy,
}
impl TransportSelector {
/// Create a new transport selector
pub fn new(strategy: TransportSelectionStrategy) -> Self {
Self {
transports: Vec::new(),
strategy,
}
}
/// Register a transport
pub fn register(&mut self, transport: Box<dyn Transport>) {
self.transports.push(transport);
}
/// Select the best transport based on strategy
pub fn select(&self) -> Option<&dyn Transport> {
match self.strategy {
TransportSelectionStrategy::FirstAvailable => self
.transports
.iter()
.find(|t| t.is_available())
.map(|b| b.as_ref()),
TransportSelectionStrategy::PreferType(transport_type) => {
// Try preferred type first
self.transports
.iter()
.find(|t| t.transport_type() == transport_type && t.is_available())
.map(|b| b.as_ref())
.or_else(|| {
// Fallback to any available
self.transports
.iter()
.find(|t| t.is_available())
.map(|b| b.as_ref())
})
}
TransportSelectionStrategy::MostCapable => {
// Score transports by capability count
self.transports
.iter()
.filter(|t| t.is_available())
.max_by_key(|t| {
let cap = t.capabilities();
let mut score = 0;
if cap.multiplexing {
score += 10;
}
if cap.zero_rtt {
score += 5;
}
if cap.migration {
score += 3;
}
if cap.encryption {
score += 8;
}
if cap.datagrams {
score += 2;
}
score
})
.map(|b| b.as_ref())
}
TransportSelectionStrategy::LowestLatency => {
// Use transport with lowest average RTT
self.transports
.iter()
.filter(|t| t.is_available())
.min_by_key(|t| t.stats().avg_rtt.unwrap_or(Duration::MAX))
.map(|b| b.as_ref())
}
TransportSelectionStrategy::HighestBandwidth => {
// Use transport type ranking (QUIC > TCP > WebSocket)
let preference = [
TransportType::Quic,
TransportType::WebTransport,
TransportType::Tcp,
TransportType::WebSocket,
];
preference.iter().find_map(|&preferred| {
self.transports
.iter()
.find(|t| t.transport_type() == preferred && t.is_available())
.map(|b| b.as_ref())
})
}
}
}
/// Get all available transports
pub fn available_transports(&self) -> Vec<TransportType> {
self.transports
.iter()
.filter(|t| t.is_available())
.map(|t| t.transport_type())
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_transport_type_display() {
assert_eq!(TransportType::Quic.to_string(), "QUIC");
assert_eq!(TransportType::Tcp.to_string(), "TCP");
assert_eq!(TransportType::WebSocket.to_string(), "WebSocket");
assert_eq!(TransportType::WebTransport.to_string(), "WebTransport");
}
#[test]
fn test_capabilities() {
let quic_cap = TransportCapabilities::quic();
assert!(quic_cap.multiplexing);
assert!(quic_cap.zero_rtt);
assert!(quic_cap.encryption);
let tcp_cap = TransportCapabilities::tcp();
assert!(!tcp_cap.multiplexing);
assert!(!tcp_cap.zero_rtt);
assert!(!tcp_cap.encryption);
let ws_cap = TransportCapabilities::websocket();
assert!(!ws_cap.multiplexing);
assert!(ws_cap.encryption);
assert!(ws_cap.max_message_size.is_some());
}
#[test]
fn test_transport_selector_empty() {
let selector = TransportSelector::new(TransportSelectionStrategy::FirstAvailable);
assert!(selector.available_transports().is_empty());
}
}