mod addr;
mod capabilities;
mod provider;
mod udp;
#[cfg(feature = "ble")]
mod ble;
pub use crate::connection::{
Connection as QuicConnection, ConnectionError, ConnectionStats, Event as ConnectionEvent,
FinishError, PathStats, ReadError, RecvStream, SendStream, ShouldTransmit, StreamEvent,
Streams, WriteError,
};
pub use crate::endpoint::{
AcceptError, ConnectError, ConnectionHandle, Endpoint as QuicEndpoint, Incoming,
};
pub use crate::shared::{ConnectionId, EcnCodepoint};
pub use crate::transport_error::{Code as TransportErrorCode, Error as TransportError};
pub use crate::transport_parameters;
pub use addr::{LoRaParams, TransportAddr, TransportType};
pub use capabilities::{BandwidthClass, TransportCapabilities, TransportCapabilitiesBuilder};
pub use provider::{
InboundDatagram, LinkQuality, ProtocolEngine, TransportDiagnostics,
TransportError as ProviderError, TransportProvider, TransportRegistry, TransportStats,
};
pub use udp::UdpTransport;
#[cfg(feature = "ble")]
pub use ble::{
ANT_QUIC_SERVICE_UUID, BleConfig, BleConnection, BleConnectionState, BleTransport,
CCCD_DISABLE, CCCD_ENABLE_INDICATION, CCCD_ENABLE_NOTIFICATION, CCCD_UUID,
CharacteristicHandle, ConnectionPoolStats, DiscoveredDevice, RX_CHARACTERISTIC_UUID,
ResumeToken, ScanEvent, ScanState, TX_CHARACTERISTIC_UUID,
};
pub async fn default_registry(bind_addr: &str) -> Result<TransportRegistry, std::io::Error> {
use std::sync::Arc;
let mut registry = TransportRegistry::new();
let udp = UdpTransport::bind(bind_addr.parse().map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("invalid address: {e}"),
)
})?)
.await?;
registry.register(Arc::new(udp));
Ok(registry)
}
#[cfg(test)]
mod tests {
use super::*;
use std::net::SocketAddr;
#[test]
fn test_transport_addr_creation() {
let udp_addr: SocketAddr = "192.168.1.1:9000".parse().unwrap();
let addr = TransportAddr::Udp(udp_addr);
assert_eq!(addr.transport_type(), TransportType::Udp);
let ble_addr = TransportAddr::ble([0x00, 0x11, 0x22, 0x33, 0x44, 0x55], None);
assert_eq!(ble_addr.transport_type(), TransportType::Ble);
let lora_addr = TransportAddr::lora([0xDE, 0xAD, 0xBE, 0xEF]);
assert_eq!(lora_addr.transport_type(), TransportType::LoRa);
}
#[test]
fn test_protocol_engine_selection() {
let broadband = TransportCapabilities::broadband();
assert_eq!(
ProtocolEngine::for_transport(&broadband),
ProtocolEngine::Quic
);
let ble = TransportCapabilities::ble();
assert_eq!(
ProtocolEngine::for_transport(&ble),
ProtocolEngine::Constrained
);
let lora = TransportCapabilities::lora_long_range();
assert_eq!(
ProtocolEngine::for_transport(&lora),
ProtocolEngine::Constrained
);
}
#[test]
fn test_capability_profiles() {
let broadband = TransportCapabilities::broadband();
assert!(broadband.supports_full_quic());
assert_eq!(broadband.bandwidth_class(), BandwidthClass::High);
let ble = TransportCapabilities::ble();
assert!(!ble.supports_full_quic());
assert!(ble.link_layer_acks);
assert!(ble.power_constrained);
let lora = TransportCapabilities::lora_long_range();
assert!(!lora.supports_full_quic());
assert!(lora.half_duplex);
assert!(lora.broadcast);
let i2p = TransportCapabilities::i2p();
assert!(!i2p.supports_full_quic());
let yggdrasil = TransportCapabilities::yggdrasil();
assert!(yggdrasil.supports_full_quic());
}
#[test]
fn test_transport_registry_empty() {
let registry = TransportRegistry::new();
assert!(registry.is_empty());
assert_eq!(registry.len(), 0);
assert!(!registry.has_quic_capable_transport());
}
#[test]
fn test_bandwidth_estimation() {
let lora = TransportCapabilities::lora_long_range();
let time = lora.estimate_transmission_time(222);
assert!(time.as_secs() >= 5);
assert!(time.as_secs() <= 7);
}
}