This directory contains comprehensive summaries of the WebRTC Rust library modules. These summaries provide an overview of the library's architecture, key components, and their interactions.
- STUN - Session Traversal Utilities for NAT for network discovery
- TURN - Traversal Using Relays around NAT for NAT traversal
- RTP - Real-time Transport Protocol for media delivery
- RTCP - RTP Control Protocol for QoS feedback
- SDP - Session Description Protocol for session negotiation
- Signal - Signaling helper functions
- WebRTC ICE - Interactive Connectivity Establishment for NAT traversal
- WebRTC DTLS - Datagram Transport Layer Security for encryption
- WebRTC SRTP - Secure Real-time Transport Protocol for media
- WebRTC SCTP - Stream Control Transmission Protocol for data channels
- WebRTC mDNS - Multicast DNS for ICE candidates
- Interceptor - Media pipeline for processing RTP/RTCP packets
- WebRTC Media - Media sample handling and processing
- WebRTC Data - Data channel implementation
- WebRTC - Main WebRTC module
- WebRTC PeerConnection - Core WebRTC connection management
- Hub - Communication hub for managing multiple peers
- WebRTC Util - Utility functions and helpers
- Examples - Sample applications and usage patterns
The WebRTC Rust library implements the Web Real-Time Communication API following the W3C and IETF standards. It enables browser-compatible peer-to-peer connections for exchanging audio, video, and arbitrary data.
┌─────────────────────────────────────────────────────────────────────────┐
│ Application │
└───────────────────────────────┬─────────────────────────────────────────┘
│
┌───────────────────────────────▼─────────────────────────────────────────┐
│ webrtc::RTCPeerConnection │
└┬────────────────┬─────────────┬───────────────────┬─────────────────────┘
│ │ │ │
┌▼────────────┐ ┌─▼───────────┐┌▼───────────┐ ┌────▼─────────┐
│ webrtc_data │ │ Hub ││ Signal │ │ Interceptor │
│(DataChannel)│ │(Multi-peer) ││(Signaling) │ │(Media Pipeline)
└┬────────────┘ └─────────────┘└────────────┘ └┬────────────┬┘
│ │ │
┌▼────────────┐ ┌──▼─────────┐ │
│ webrtc_sctp │ │webrtc_media│ │
└┬────────────┘ └┬───────────┘ │
│ │ │
┌▼────────────┐ ┌▼───────────┐┌▼─────────┐
│ webrtc_dtls │ │webrtc_rtp ││webrtc_rtcp│
└┬────────────┘ └┬───────────┘└┬─────────┘
│ │ │
│ ┌▼─────────────▼──────────┐
│ │ webrtc_srtp │
│ └┬────────────────────────┘
│ │
┌▼────────────────────────────────────────────▼──────────────────────────┐
│ webrtc_ice │
└┬─────────────────┬───────────────────┬──────────────────┬──────────────┘
│ │ │ │
┌▼────────────┐ ┌─▼──────────┐ ┌─▼───────────┐ ┌──▼───────────┐
│ stun │ │ turn │ │webrtc_mdns │ │ webrtc_util │
└─────────────┘ └────────────┘ └─────────────┘ └──────────────┘
- Signaling: Exchange of session information (using custom implementation or signal module)
- ICE: Establishes connectivity by finding and exchanging network candidates (including mDNS)
- DTLS: Secures the connection using certificate-based authentication
- SCTP/SRTP: Facilitates reliable data channel communication and secure media transport
- Media Pipeline: Processes media through interceptors for functionality like NACK and stats
Each summary page provides:
- Overview of the module's purpose
- Key structs, enums, and traits with their signatures
- Important functions and methods
- Example usage patterns
- Implementation notes
For complete API details, refer to the Rust documentation in the library.
// Create WebRTC API
let api = API::new()?;
// Configure and create peer connection
let config = RTCConfiguration {
ice_servers: vec![
RTCIceServer {
urls: vec!["stun:stun.l.google.com:19302".to_string()],
..Default::default()
},
],
..Default::default()
};
let peer_connection = api.new_peer_connection(config).await?;
// Create data channel
let dc = peer_connection.create_data_channel("channel", None).await?;
// Set up handlers
dc.on_open(Box::new(|| {
println!("Data channel open");
Box::pin(async {})
}));
dc.on_message(Box::new(|msg| {
println!("Message received");
Box::pin(async {})
}));
// Create and set local description
let offer = peer_connection.create_offer(None).await?;
peer_connection.set_local_description(offer.clone()).await?;
// Exchange offer/answer and ICE candidates via signaling
// ...
// When remote description is received
peer_connection.set_remote_description(remote_sdp).await?;
// When remote ICE candidates are received
peer_connection.add_ice_candidate(remote_candidate).await?;
For applications that need custom media processing:
// Create a MediaEngine
let mut m = MediaEngine::default();
m.register_default_codecs()?;
// Create an interceptor registry and add interceptors
let mut registry = Registry::new();
registry.add(Box::new(NoOp::builder()));
registry.add(Box::new(stats::StatsBuilder::default()));
registry.add(Box::new(nack::NackBuilder::default()));
// Create the API with media engine and interceptor registry
let api = APIBuilder::new()
.with_media_engine(m)
.with_interceptor_registry(registry)
.build();
This documentation summary was automatically generated to provide a comprehensive overview of the WebRTC Rust library.
This document provides a comprehensive overview of the examples available in the WebRTC.rs stack. The examples serve as practical demonstrations of various WebRTC functionalities and are organized into categories based on their primary API focus.
WebRTC.rs examples are Rust implementations of the examples originally created for the Pion WebRTC library in Go. These examples provide practical demonstrations of how to use various WebRTC functionalities in Rust applications.
These examples demonstrate audio and video streaming capabilities:
-
Reflect: Demonstrates how to have WebRTC.rs send back to the user exactly what it receives using the same PeerConnection.
-
Play from Disk (VPx): Shows how to send VP8/VP9 video to a browser from a file saved to disk.
-
Play from Disk (H264): Demonstrates sending H264 video to a browser from a file saved to disk.
-
Play from Disk (HEVC): Shows how to stream HEVC/H.265 video from a disk file to a browser.
-
Play from Disk (Renegotiation): Extends the play-from-disk example, demonstrating how to add/remove video tracks from an already negotiated PeerConnection.
-
Insertable Streams: Shows how WebRTC.rs can be used to send E2E encrypted video and decrypt via insertable streams in the browser.
-
Save to Disk (VPx): Demonstrates how to record webcam footage (VP8/VP9 for video, Opus for audio) and save it to disk on the server side.
-
Save to Disk (H264): Shows how to record webcam footage (H264 for video, Opus for audio) and save it to disk on the server side.
-
Broadcast: Demonstrates how to broadcast a video to multiple peers where a broadcaster uploads the video once and the server forwards it to all other peers.
-
RTP Forwarder: Shows how to forward audio/video streams using RTP.
-
RTP to WebRTC: Demonstrates how to take RTP packets sent to a WebRTC.rs process and display them in a browser.
-
Simulcast: Shows how to accept and demux one Track that contains three Simulcast streams, returning the media as three independent Tracks back to the sender.
-
Swap Tracks: Demonstrates how to swap multiple incoming tracks on a single outgoing track.
These examples focus on the data channel capabilities of WebRTC:
-
Data Channels: Demonstrates sending and receiving DataChannel messages from a web browser.
-
Data Channels Create: Similar to the data-channels example, but with the data channel initialized from the server side.
-
Data Channels Close: A variant of data-channels that demonstrates the life cycle of data channels.
-
Data Channels Detach: Shows how to send/receive DataChannel messages using the underlying DataChannel implementation directly, providing a more idiomatic way of interacting with Data Channels.
-
Data Channels Detach Create: Similar to data-channels-detach, but with the data channel initialized in the example.
-
Data Channels Flow Control: Demonstrates how to use flow control in data channels.
-
ORTC: Shows how to use the ORTC API for DataChannel communication.
-
Offer Answer: Demonstrates two WebRTC.rs or Pion instances communicating directly.
-
ICE Restart: Demonstrates WebRTC.rs ICE restart capabilities.
- RC Cycle: A utility example related to reference counting cycles.
Each example is structured as a standalone application and can be run using Cargo:
cargo run --example <example-name>
For instance, to run the data-channels example:
cargo run --example data-channels
Most examples include a web-based client interface, typically served at http://localhost:8080
when the example is running.
The examples rely on several dependencies:
- webrtc: The main WebRTC.rs library
- tokio: For asynchronous programming
- env_logger: For logging
- clap: For command-line argument parsing
- hyper: For HTTP server functionality
- signal: A custom crate for signaling
- Various other utilities for serialization, random number generation, etc.
- These examples are designed for educational purposes and may not represent production-ready code.
- Each example demonstrates specific WebRTC concepts and capabilities.
- The examples serve as a practical complement to the WebRTC.rs API documentation.
The hub
module provides a helper utility for handling one-to-many chat communication in WebRTC applications. It facilitates managing multiple connections and broadcasting messages between them in a centralized manner.
The Hub
struct is the main component of this module. It manages connections and provides methods for registering, unregistering, and broadcasting messages.
pub struct Hub {
conns: Arc<Mutex<HashMap<String, Arc<dyn Conn + Send + Sync>>>>
}
new() -> Self
: Creates a new Hub instance with an empty connections map.async register(&self, conn: Arc<dyn Conn + Send + Sync>)
: Adds a new connection to the Hub. Takes anArc<dyn Conn + Send + Sync>
representing a connection and stores it in the internal map using the remote address as the key. It also starts a read loop for the connection.async chat(&self)
: Starts a stdin read loop to dispatch messages to the hub. This allows sending messages from the console to all connected clients.
async read_loop(conns: Arc<Mutex<HashMap<String, Arc<dyn Conn + Send + Sync>>>>, conn: Arc<dyn Conn + Send + Sync>)
: A background task that continuously reads messages from a connection. When a connection closes, it callsunregister
.async unregister(conns: Arc<Mutex<HashMap<String, Arc<dyn Conn + Send + Sync>>>>, conn: Arc<dyn Conn + Send + Sync>)
: Removes a connection from the Hub and closes it properly.async broadcast(conns: &HashMap<String, Arc<dyn Conn + Send + Sync>>, msg: &str) -> Result<(), Error>
: Sends a message to all connected clients.
The Hub module includes a utilities
submodule that provides helper functions for working with certificates and keys, which are necessary for secure WebRTC communication.
async chat(conn: Arc<dyn Conn + Send + Sync>) -> Result<(), Error>
: Simulates a simple text chat session over a single connection. Takes anArc<dyn Conn + Send + Sync>
and sets up bidirectional communication.load_key_and_certificate(key_path: PathBuf, certificate_path: PathBuf) -> Result<Certificate, Error>
: Reads a certificate and its corresponding private key from files.load_key(path: PathBuf) -> Result<CryptoPrivateKey, Error>
: Loads a cryptographic private key from a PEM file.load_certificate(path: PathBuf) -> Result<Certificate, Error>
: Loads certificate(s) from a PEM file.
The utilities module defines its own error type (Error
enum) for handling various error cases that can occur when working with certificates and keys:
ErrBlockIsNotPrivateKey
ErrUnknownKeyTime
ErrNoPrivateKeyFound
ErrBlockIsNotCertificate
ErrNoCertificateFound
Other(String)
The Hub is designed to be used in a WebRTC server application where multiple clients can connect and communicate. The typical usage pattern is:
- Create a new
Hub
instance. - For each new connection, call
hub.register(conn)
to add it to the Hub. - To enable console input to be broadcast to all clients, call
hub.chat()
.
The Hub automatically handles:
- Tracking all active connections
- Broadcasting messages to all clients
- Cleaning up connections when they are closed
// Create a new hub
let hub = Hub::new();
// When a new connection is established
hub.register(conn).await;
// To start the console chat interface that broadcasts to all clients
hub.chat().await;
- The Hub uses a thread-safe
HashMap
wrapped in anArc<Mutex<...>>
to store connections. - Each connection is identified by its remote address (IP:port).
- The module uses asynchronous Rust with
tokio
for handling concurrent connections. - When a connection is registered, a background task is spawned to continuously read messages from it.
- When a message is received from a connection, it's displayed on the console.
- When a message is typed on the console, it's broadcast to all connected clients.
- Typing "exit" terminates the chat session.
The utilities module provides functions for loading certificates and private keys, which are essential for establishing secure DTLS connections in WebRTC applications. The proper use of these utilities ensures that communication is encrypted.
The Interceptor module provides a flexible and extensible architecture for modifying or monitoring RTP and RTCP packets as they flow through a WebRTC connection. Interceptors can be used to add functionality to PeerConnections by modifying any incoming/outgoing packets or generating new packets as needed.
The Interceptor
trait enables packet processing in the media pipeline. Implementers can:
- Intercept and modify RTP/RTCP packets through binding to streams
- Access stream metadata through the StreamInfo structure
- Manage resource lifecycle with explicit unbind and close operations
- Chain with other interceptors to create processing pipelines
pub trait Interceptor {
// Modifies incoming RTCP packets
fn bind_rtcp_reader<'life0, 'async_trait>(
&'life0 self,
reader: Arc<dyn RTCPReader + Send + Sync>,
) -> Pin<Box<dyn Future<Output = Arc<dyn RTCPReader + Send + Sync>> + Send + 'async_trait>>
where
Self: 'async_trait,
'life0: 'async_trait;
// Modifies outgoing RTCP packets
fn bind_rtcp_writer<'life0, 'async_trait>(
&'life0 self,
writer: Arc<dyn RTCPWriter + Send + Sync>,
) -> Pin<Box<dyn Future<Output = Arc<dyn RTCPWriter + Send + Sync>> + Send + 'async_trait>>
where
Self: 'async_trait,
'life0: 'async_trait;
// Modifies outgoing RTP packets
fn bind_local_stream<'life0, 'life1, 'async_trait>(
&'life0 self,
info: &'life1 StreamInfo,
writer: Arc<dyn RTPWriter + Send + Sync>,
) -> Pin<Box<dyn Future<Output = Arc<dyn RTPWriter + Send + Sync>> + Send + 'async_trait>>
where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
// Cleans up resources for a local stream
fn unbind_local_stream<'life0, 'life1, 'async_trait>(
&'life0 self,
info: &'life1 StreamInfo,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
// Modifies incoming RTP packets
fn bind_remote_stream<'life0, 'life1, 'async_trait>(
&'life0 self,
info: &'life1 StreamInfo,
reader: Arc<dyn RTPReader + Send + Sync>,
) -> Pin<Box<dyn Future<Output = Arc<dyn RTPReader + Send + Sync>> + Send + 'async_trait>>
where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
// Cleans up resources for a remote stream
fn unbind_remote_stream<'life0, 'life1, 'async_trait>(
&'life0 self,
info: &'life1 StreamInfo,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
// Closes the interceptor and cleans up resources
fn close<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where
Self: 'async_trait,
'life0: 'async_trait;
}
The InterceptorBuilder
trait allows for the construction of interceptors:
pub trait InterceptorBuilder {
// Required method
fn build(
&self,
id: &str,
) -> Result<Arc<dyn Interceptor + Send + Sync>, Error>;
}
The Registry
struct acts as a collector for interceptors:
pub struct Registry { /* private fields */ }
Key Methods:
impl Registry {
// Creates a new registry
pub fn new() -> Self { ... }
// Adds a new interceptor builder to the registry
pub fn add(&mut self, builder: Box<dyn InterceptorBuilder + Send + Sync>) { ... }
// Constructs a single interceptor from an InterceptorRegistry
pub fn build(
&self,
id: &str,
) -> Result<Arc<dyn Interceptor + Send + Sync>, Error> { ... }
// Constructs a non-type erased Chain from an Interceptor registry
pub fn build_chain(&self, id: &str) -> Result<Chain, Error> { ... }
}
The Chain
struct is an interceptor that runs all child interceptors in sequence. It allows for composing multiple interceptors together in a pipeline:
pub struct Chain { /* private fields */ }
impl Chain {
// Creates a new Chain with the given interceptors
pub fn new(interceptors: Vec<Arc<dyn Interceptor + Send + Sync>>) -> Self { ... }
// Adds a new interceptor to the chain
pub fn add(&mut self, interceptor: Arc<dyn Interceptor + Send + Sync>) { ... }
}
impl Interceptor for Chain { ... }
A simple pass-through interceptor that doesn't modify any packets:
pub struct NoOp { /* private fields */ }
impl NoOp {
pub fn builder() -> impl InterceptorBuilder + Send + Sync { ... }
}
impl Interceptor for NoOp { ... }
Contains two components:
-
Generator: Detects packet loss and generates NACK messages for retransmission
pub struct Generator { /* private fields */ } pub struct GeneratorBuilder { /* private fields */ } impl Generator { // Creates a new Generator pub fn new(...) -> Self { ... } } impl Interceptor for Generator { ... }
-
Responder: Handles incoming NACK messages by resending lost packets
pub struct Responder { /* private fields */ } pub struct ResponderBuilder { /* private fields */ } impl Responder { // Creates a new Responder pub fn new(...) -> Self { ... } } impl Interceptor for Responder { ... }
Handles RTP and RTCP reporting:
pub struct ReportBuilder { /* private fields */ }
// ReceiverReport: Generates RTCP receiver reports
pub struct ReceiverReport { /* private fields */ }
impl Interceptor for ReceiverReport { ... }
// SenderReport: Generates RTCP sender reports
pub struct SenderReport { /* private fields */ }
impl Interceptor for SenderReport { ... }
The stats interceptor collects RTP and RTCP statistics:
// StatsInterceptor: Tracks metrics like packet counts, bytes, loss, jitter, etc.
pub struct StatsInterceptor { /* private fields */ }
// RTPStats: Holds RTP-specific statistics
pub struct RTPStats {
pub packets: AtomicUsize,
pub header_bytes: AtomicUsize,
pub payload_bytes: AtomicUsize,
pub last_sequence_number: AtomicU16,
pub jitter: AtomicU32,
}
// RTCPStats: Holds RTCP-specific statistics
pub struct RTCPStats {
pub packets: AtomicUsize,
pub bytes: AtomicUsize,
}
impl Interceptor for StatsInterceptor { ... }
Implements the TWCC RTP extension:
-
Sender: Adds TWCC headers to outgoing RTP packets
pub struct Sender { /* private fields */ } pub struct SenderBuilder { /* private fields */ } impl Interceptor for Sender { ... }
-
Receiver: Processes incoming packets with TWCC headers and generates feedback
pub struct Receiver { /* private fields */ } pub struct ReceiverBuilder { /* private fields */ } impl Interceptor for Receiver { ... }
-
Recorder: Records timestamps for TWCC packets
pub struct Recorder { /* private fields */ }
Contains utilities for testing interceptor implementations:
// MockInterceptor: Implements the Interceptor trait for testing
pub struct MockInterceptor { /* private fields */ }
// MockBuilder: Builds mock interceptors
pub struct MockBuilder { /* private fields */ }
// MockStream: Simulates RTP streams for testing
pub struct MockStream { /* private fields */ }
impl Interceptor for MockInterceptor { ... }
Contains information about RTP streams:
pub struct StreamInfo {
pub id: String,
pub attributes: Attributes,
pub ssrc: u32,
pub payload_type: u8,
pub rtp_header_extensions: Vec<RTPHeaderExtension>,
pub mime_type: String,
pub clock_rate: u32,
pub channels: u16,
pub sdp_fmtp_line: String,
pub rtcp_feedback: Vec<RTCPFeedback>,
pub associated_stream: Option<AssociatedStreamInfo>,
}
A generic key/value store used by interceptors to communicate additional metadata:
pub type Attributes = Arc<Mutex<HashMap<String, Arc<dyn Any + Send + Sync>>>>;
-
Creating a single interceptor:
let interceptor = generator_builder.build("nack_generator")?;
-
Composing multiple interceptors:
let registry = Registry::new(); registry.add(Box::new(nack_generator_builder)); registry.add(Box::new(nack_responder_builder)); registry.add(Box::new(stats_builder)); let chain = registry.build_chain("my_interceptors")?;
-
Building a custom interceptor:
struct MyInterceptor { // fields } impl Interceptor for MyInterceptor { // implement methods } struct MyInterceptorBuilder { // fields } impl InterceptorBuilder for MyInterceptorBuilder { fn build(&self, id: &str) -> Result<Arc<dyn Interceptor + Send + Sync>, Error> { // build and return interceptor } }
-
Packet Monitoring: Interceptors can monitor RTP/RTCP packets without modifying them, useful for logging or debugging.
-
Packet Modification: Interceptors can modify packets in transit, such as adding headers or changing payload data.
-
Packet Generation: Interceptors can generate new packets, such as RTCP feedback reports based on observed traffic.
-
Statistics Collection: Interceptors can collect statistics about the media traffic for reporting or analysis.
-
Chain Order: The order of interceptors in a chain matters. For example, statistics collection should typically come after packet modification interceptors.
-
Performance Considerations: Interceptors are in the critical path of media processing, so they should be efficient.
-
Thread Safety: Interceptors must be thread-safe as they may be accessed from multiple threads.
-
Error Handling: Interceptors should handle errors gracefully to avoid disrupting the media flow.
The interceptor architecture provides a powerful mechanism for extending WebRTC functionality. By implementing the Interceptor
trait, developers can create custom packet processing logic that integrates seamlessly with the WebRTC pipeline.
The RTCP (RTP Control Protocol) module implements encoding and decoding of RTCP packets according to RFCs 3550 and 5506. RTCP is a sister protocol of the Real-time Transport Protocol (RTP), providing out-of-band statistics and control information for RTP sessions.
RTCP provides feedback on the quality of service (QoS) in media distribution by periodically sending statistics such as:
- Transmitted octet and packet counts
- Packet loss
- Packet delay variation
- Round-trip delay time
Applications can use this information to control quality of service parameters, adjust flow, or switch codecs.
pub trait Packet: Marshal + Unmarshal + Display + Debug {
fn header(&self) -> Header;
fn destination_ssrc(&self) -> Vec<u32>;
fn raw_size(&self) -> usize;
fn as_any(&self) -> &(dyn Any + Send + Sync);
fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool;
fn cloned(&self) -> Box<dyn Packet + Send + Sync>;
}
The Packet
trait represents an RTCP packet and is implemented by all packet types in the module. It provides essential methods for packet handling and introspection:
header()
: Returns the Header associated with this packetdestination_ssrc()
: Returns an array of SSRC values the packet refers toraw_size()
: Returns the size of the packet in bytesas_any()
: Converts the packet to anAny
type for downcastingequal()
: Compares with another packetcloned()
: Creates a deep copy of the packet
pub fn marshal(packets: &[Box<dyn Packet + Send + Sync>]) -> Result<Bytes, Error>
- Serializes an array of RTCP packets into a single buffer.
pub fn unmarshal<B>(raw_data: &mut B) -> Result<Vec<Box<dyn Packet + Send + Sync>>, Error>
where B: Buf
- Deserializes a buffer containing one or more RTCP packets.
- Handles both compound packets and individual feedback packets.
pub struct Header {
pub version: u8,
pub padding: bool,
pub count: u8,
pub packet_type: PacketType,
pub length: u16,
}
The Header
struct defines the common header for all RTCP packets with fields for:
- RTCP version
- Padding flag
- Count field (varies by packet type)
- Packet type
- Length of the packet
pub struct SenderReport {
pub ssrc: u32,
pub ntp_time: u64,
pub rtp_time: u32,
pub packet_count: u32,
pub octet_count: u32,
pub reports: Vec<ReceptionReport>,
pub profile_extensions: Bytes,
}
Sender Reports provide reception quality feedback and include:
- Sender's SSRC identifier
- NTP timestamp for timing synchronization
- RTP timestamp corresponding to the NTP timestamp
- Sender statistics (packet and octet counts)
- Reception reports for sources this sender has received from
- Optional profile-specific extensions
pub struct ReceiverReport {
pub ssrc: u32,
pub reports: Vec<ReceptionReport>,
pub profile_extensions: Bytes,
}
Receiver Reports contain reception statistics from participants that are not active senders:
- Reporter's SSRC identifier
- List of reception reports
- Optional profile-specific extensions
pub struct ReceptionReport {
pub ssrc: u32,
pub fraction_lost: u8,
pub total_lost: u32,
pub last_sequence_number: u32,
pub jitter: u32,
pub last_sender_report: u32,
pub delay: u32,
}
Reception Reports contain statistics for a specific SSRC source:
- SSRC of the source
- Fraction of packets lost since last report
- Cumulative number of packets lost
- Extended highest sequence number received
- Interarrival jitter
- Last SR (LSR) timestamp
- Delay since last SR (DLSR)
pub struct PictureLossIndication {
pub sender_ssrc: u32,
pub media_ssrc: u32,
}
PLI informs the encoder about the loss of coded video data:
- SSRC of sender
- SSRC of media source affected by the loss
pub struct ReceiverEstimatedMaximumBitrate {
pub sender_ssrc: u32,
pub ssrcs: Vec<u32>,
pub bitrate: u64,
}
REMB provides the sender with the receiver's estimated maximum bitrate:
- SSRC of sender generating the report
- List of SSRCs this feedback applies to
- Maximum bitrate in bits per second
pub struct SourceDescription {
pub chunks: Vec<SourceDescriptionChunk>
}
pub struct SourceDescriptionChunk {
pub source: u32,
pub items: Vec<SourceDescriptionItem>
}
pub struct SourceDescriptionItem {
pub sdes_type: SdesType,
pub text: String
}
SDES packets contain source description items like:
- CNAME (Canonical End-Point Identifier)
- NAME (User name)
- EMAIL (User email)
- PHONE (User phone number)
- And other identification and description fields
pub struct ExtendedReport {
pub sender_ssrc: u32,
pub reports: Vec<Box<dyn Packet + Send + Sync>>,
}
Extended Reports provide additional feedback metrics beyond standard reports:
- Supports various report block types
- Includes VoIP metrics, reception times, statistics summaries
pub struct CompoundPacket {
pub packets: Vec<Box<dyn Packet + Send + Sync>>
}
Compound Packets bundle multiple RTCP packets together:
- Must start with SR or RR packet
- Must include SDES packet with CNAME
- Can contain additional packet types
pub enum Error {
WrongMarshalSize,
InvalidTotalLost,
InvalidHeader,
EmptyCompound,
BadFirstPacket,
MissingCname,
// ... many more error variants
}
The Error
enum provides comprehensive error types for RTCP operations, including:
- Packet validation errors
- Format and padding errors
- Size and structure errors
- Missing required fields
- Invalid values
let pkt = rtcp::unmarshal(&rtcp_data).unwrap();
if let Some(e) = pkt
.as_any()
.downcast_ref::<PictureLossIndication>() {
// Handle PLI packet
}
else if let Some(e) = packet
.as_any()
.downcast_ref::<Goodbye>() {
// Handle Goodbye packet
}
let pkt = PictureLossIndication{
sender_ssrc: sender_ssrc,
media_ssrc: media_ssrc
};
let pli_data = pkt.marshal().unwrap();
// Send pli_data over the network
The module defines various constants for RTCP header fields:
- VERSION_MASK, VERSION_SHIFT for handling version fields
- PADDING_MASK, PADDING_SHIFT for padding fields
- COUNT_MASK, COUNT_SHIFT for count fields
- Format constants (FORMAT_PLI, FORMAT_FIR, etc.) for feedback message types
- HEADER_LENGTH, SSRC_LENGTH for field sizes
- The module follows RFC 3550 (RTP/RTCP) and RFC 5506 (Reduced-Size RTCP)
- Packets are validated during unmarshal operations
- The module supports both compound and reduced-size RTCP packets
- All packet types implement the Packet trait, Marshal, Unmarshal, Display, and Debug traits
- The API uses Rust's type system for type safety and proper error handling
The RTP (Real-time Transport Protocol) module provides a comprehensive implementation of the RTP protocol as defined in RFC 3550. This module enables applications to send and receive real-time data such as audio and video over packet-switched networks.
pub struct Header {
pub version: u8,
pub padding: bool,
pub extension: bool,
pub marker: bool,
pub payload_type: u8,
pub sequence_number: u16,
pub timestamp: u32,
pub ssrc: u32,
pub csrc: Vec<u32>,
pub extension_profile: u16,
pub extensions: Vec<Extension>,
pub extensions_padding: usize,
}
Represents an RTP packet header that contains the metadata required for RTP packet transmission and sequencing.
Key Methods:
get_extension_payload_len(&self) -> usize
: Gets the length of extensions payloadset_extension(&mut self, id: u8, payload: Bytes) -> Result<(), Error>
: Adds or updates an RTP header extensionget_extension_ids(&self) -> Vec<u8>
: Returns all extension IDs present in the headerget_extension(&self, id: u8) -> Option<Bytes>
: Retrieves a specific extension by IDdel_extension(&mut self, id: u8) -> Result<(), Error>
: Removes an extension by ID
pub struct Packet {
pub header: Header,
pub payload: Bytes,
}
Represents a complete RTP packet, containing both the header metadata and payload data.
Key Methods:
marshal_to(&self, buf: &mut [u8]) -> Result<usize, Error>
: Serializes the packet into the provided buffermarshal(&self) -> Result<Bytes, Error>
: Serializes the packet and returns as Bytesmarshal_size(&self) -> usize
: Determines the total size of the marshaled packetunmarshal<B>(raw_packet: &mut B) -> Result<Self, Error>
: Deserializes from raw bytes
pub trait Packetizer: Debug {
fn enable_abs_send_time(&mut self, value: u8);
fn packetize(
&mut self,
payload: &Bytes,
samples: u32
) -> Result<Vec<Packet>, Error>;
fn skip_samples(&mut self, skipped_samples: u32);
fn clone_to(&self) -> Box<dyn Packetizer + Send + Sync>;
}
Packetizes payload data into appropriate RTP packets, handling fragmentation and other codec-specific requirements.
pub trait Payloader: Debug {
fn payload(
&mut self,
mtu: usize,
b: &Bytes
) -> Result<Vec<Bytes>, Error>;
fn clone_to(&self) -> Box<dyn Payloader + Send + Sync>;
}
Handles the codec-specific segmentation of media payloads to fit within MTU size limits.
Implementations include:
Av1Payloader
: For AV1 video codecG7xxPayloader
: For G.711 and G.722 audio codecsH264Payloader
: For H.264 video codecHevcPayloader
: For H.265/HEVC video codecOpusPayloader
: For Opus audio codecVp8Payloader
: For VP8 video codecVp9Payloader
: For VP9 video codec
pub trait Depacketizer {
fn depacketize(&mut self, b: &Bytes) -> Result<Bytes, Error>;
fn is_partition_head(&self, payload: &Bytes) -> bool;
fn is_partition_tail(&self, marker: bool, payload: &Bytes) -> bool;
}
Handles unpacking of RTP payloads, removing RTP-specific framing to extract the original media data.
Implementations include:
H264Packet
: For H.264 video codecH265Packet
: For H.265/HEVC video codecOpusPacket
: For Opus audio codecVp8Packet
: For VP8 video codecVp9Packet
: For VP9 video codec
pub trait Sequencer: Debug {
fn next_sequence_number(&self) -> u16;
fn roll_over_count(&self) -> u64;
fn clone_to(&self) -> Box<dyn Sequencer + Send + Sync>;
}
Generates sequential sequence numbers for RTP packets, handling roll-over conditions when the 16-bit sequence counter wraps.
Factory Functions:
new_random_sequencer() -> Box<dyn Sequencer + Send + Sync>
: Creates a sequencer starting at a random sequence numbernew_fixed_sequencer(s: u16) -> Box<dyn Sequencer + Send + Sync>
: Creates a sequencer starting at a specified sequence number
The RTP module supports various header extensions as defined in RFCs:
pub struct AbsSendTimeExtension;
Implements the Absolute Send Time extension (RFC 5285) that allows for more precise synchronization and timing measurements.
pub struct AudioLevelExtension;
Implements the client-to-mixer audio level extension as specified in RFC 6464.
pub struct TransportCcExtension;
Implements the transport-wide congestion control extension for RTP.
pub struct VideoOrientationExtension;
Implements Coordination of Video Orientation (CVO) as defined in 3GPP TS 26.114.
pub enum Error {
PacketTooShort,
InvalidExtensionLength,
InvalidHeader,
HeaderSizeInsufficient,
TooManyExtensions,
RtpVersionUnsupported,
EmptyPayloadWithMarker,
ReservedException,
ReservededExtensionByte,
InvalidExtensionValues,
PacketizerError,
InvalidNalUnitType,
InvalidPayloadType,
}
Comprehensive error handling for the various failure modes during RTP processing.
// Create a new RTP packet
let mut header = Header::default();
header.payload_type = 96; // Common for H.264
header.sequence_number = 1234;
header.timestamp = 5678;
header.ssrc = 12345678;
let payload = Bytes::from(vec![0, 1, 2, 3, 4]); // Example payload
let packet = Packet {
header,
payload,
};
// Serialize the packet
let serialized = packet.marshal().expect("Failed to marshal packet");
// Deserialize the packet
let mut buf = serialized.clone();
let deserialized = Packet::unmarshal(&mut buf).expect("Failed to unmarshal packet");
// Example of using a packetizer for H.264
let payloader = H264Payloader::default();
let mtu = 1500;
let video_frame = Bytes::from(/* H.264 NAL units */);
let payloads = payloader.payload(mtu, &video_frame).expect("Failed to payload");
// Packetize the payloads into RTP packets
let sequencer = new_random_sequencer();
let packetizer = new_packetizer(
1500, // MTU
96, // Payload type
12345678, // SSRC
payloader,
sequencer,
90000, // Clock rate for H.264
);
let packets = packetizer.packetize(&video_frame, 90000).expect("Failed to packetize");
- RFC 3550: RTP: A Transport Protocol for Real-Time Applications
- RFC 5285: A General Mechanism for RTP Header Extensions
- RFC 6184: RTP Payload Format for H.264 Video
- RFC 6464: A Real-time Transport Protocol (RTP) Header Extension for Client-to-Mixer Audio Level Indication
This RTP module is designed for high-performance real-time media communications, supporting a wide range of codecs and extensions required for modern audio/video applications.
This markdown document provides a comprehensive overview of the Session Description Protocol (SDP) module in the WebRTC Rust implementation. SDP is a format for describing multimedia communication sessions for the purposes of session announcement, session invitation, and parameter negotiation.
pub struct SessionDescription {
pub version: Version,
pub origin: Origin,
pub session_name: SessionName,
pub session_information: Option<Information>,
pub uri: Option<Url>,
pub email_address: Option<EmailAddress>,
pub phone_number: Option<PhoneNumber>,
pub connection_information: Option<ConnectionInformation>,
pub bandwidth: Vec<Bandwidth>,
pub time_descriptions: Vec<TimeDescription>,
pub time_zones: Vec<TimeZone>,
pub encryption_key: Option<EncryptionKey>,
pub attributes: Vec<Attribute>,
pub media_descriptions: Vec<MediaDescription>,
}
The SessionDescription
is the primary structure representing a complete SDP document. It provides a well-defined format for conveying sufficient information to discover and participate in a multimedia session.
new_jsep_session_description(identity: bool) -> Self
: Creates a new SessionDescription with JSEP requirementswith_property_attribute(self, key: String) -> Self
: Adds a property attribute 'a=key'with_value_attribute(self, key: String, value: String) -> Self
: Adds a value attribute 'a=key:value'with_fingerprint(self, algorithm: String, value: String) -> Self
: Adds a fingerprintwith_media(self, md: MediaDescription) -> Self
: Adds a media descriptionget_codec_for_payload_type(&self, payload_type: u8) -> Result<Codec, Error>
: Scans for a codec with the given payload typeget_payload_type_for_codec(&self, wanted: &Codec) -> Result<u8, Error>
: Scans for the payload type of a given codechas_attribute(&self, key: &str) -> bool
: Checks if an attribute existsattribute(&self, key: &str) -> Option<&String>
: Returns the value of an attribute if it existsmarshal(&self) -> String
: Serializes the SDP struct to textunmarshal<R: BufRead + Seek>(reader: &mut R) -> Result<Self, Error>
: Deserializes text into a SessionDescription
pub struct MediaDescription {
pub media_name: MediaName,
pub media_title: Option<Information>,
pub connection_information: Option<ConnectionInformation>,
pub bandwidth: Vec<Bandwidth>,
pub encryption_key: Option<EncryptionKey>,
pub attributes: Vec<Attribute>,
}
MediaDescription
represents a media type within a session (e.g., audio, video, application data).
new_jsep_media_description(codec_type: String, _codec_prefs: Vec<&str>) -> Self
: Creates a new MediaDescription with JSEP settingswith_property_attribute(self, key: String) -> Self
: Adds a property attributewith_value_attribute(self, key: String, value: String) -> Self
: Adds a value attributewith_fingerprint(self, algorithm: String, value: String) -> Self
: Adds a fingerprintwith_ice_credentials(self, username: String, password: String) -> Self
: Adds ICE credentialswith_codec(self, payload_type: u8, name: String, clockrate: u32, channels: u16, fmtp: String) -> Self
: Adds codec informationwith_media_source(self, ssrc: u32, cname: String, stream_label: String, label: String) -> Self
: Adds media source infowith_candidate(self, value: String) -> Self
: Adds an ICE candidate (deprecated)with_extmap(self, e: ExtMap) -> Self
: Adds an extension mapwith_transport_cc_extmap(self) -> Self
: Adds a transport control extension map
pub enum Direction {
Unspecified = 0,
SendRecv = 1, // For bidirectional communication
SendOnly = 2, // For outgoing communication
RecvOnly = 3, // For incoming communication
Inactive = 4, // For no communication
}
The Direction
enum is a marker for the transmission direction of an endpoint.
new(raw: &str) -> Self
: Creates a Direction from a raw string
pub struct ExtMap {
pub value: isize,
pub direction: Direction,
pub uri: Option<Url>,
pub ext_attr: Option<String>,
}
ExtMap
represents the activation of a single RTP header extension.
convert(&self) -> Attribute
: Converts to an Attributeunmarshal<R: BufRead>(reader: &mut R) -> Result<Self, Error>
: Creates an ExtMap from a stringmarshal(&self) -> String
: Creates a string from an ExtMap
pub const TRANSPORT_CC_URI: &str = "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01";
pub const ABS_SEND_TIME_URI: &str = "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
pub const SDES_MID_URI: &str = "urn:ietf:params:rtp-hdrext:sdes:mid";
pub const SDES_RTP_STREAM_ID_URI: &str = "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id";
pub const AUDIO_LEVEL_URI: &str = "urn:ietf:params:rtp-hdrext:ssrc-audio-level";
pub const VIDEO_ORIENTATION_URI: &str = "urn:3gpp:video-orientation";
pub const SDES_REPAIR_RTP_STREAM_ID_URI: &str = "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id";
pub const DEF_EXT_MAP_VALUE_ABS_SEND_TIME: isize = 1;
pub const DEF_EXT_MAP_VALUE_TRANSPORT_CC: isize = 2;
pub const DEF_EXT_MAP_VALUE_SDES_MID: isize = 3;
pub const DEF_EXT_MAP_VALUE_SDES_RTP_STREAM_ID: isize = 4;
pub const ATTR_KEY_END_OF_CANDIDATES: &str = "end-of-candidates";
pub const ATTR_KEY_CANDIDATE: &str = "candidate";
pub const ATTR_KEY_GROUP: &str = "group";
pub const ATTR_KEY_SSRC: &str = "ssrc";
pub const ATTR_KEY_SSRCGROUP: &str = "ssrc-group";
pub const ATTR_KEY_MSID: &str = "msid";
pub const ATTR_KEY_MSID_SEMANTIC: &str = "msid-semantic";
pub const ATTR_KEY_CONNECTION_SETUP: &str = "setup";
pub const ATTR_KEY_MID: &str = "mid";
pub const ATTR_KEY_RTCPMUX: &str = "rtcp-mux";
pub const ATTR_KEY_ICELITE: &str = "ice-lite";
pub const ATTR_KEY_RTCPRSIZE: &str = "rtcp-rsize";
pub const ATTR_KEY_RECV_ONLY: &str = "recvonly";
pub const ATTR_KEY_SEND_ONLY: &str = "sendonly";
pub const ATTR_KEY_INACTIVE: &str = "inactive";
pub const ATTR_KEY_SEND_RECV: &str = "sendrecv";
pub const ATTR_KEY_EXT_MAP: &str = "extmap";
pub const ATTR_KEY_EXTMAP_ALLOW_MIXED: &str = "extmap-allow-mixed";
pub const ATTR_KEY_IDENTITY: &str = "identity";
pub const SEMANTIC_TOKEN_LIP_SYNCHRONIZATION: &str = "LS";
pub const SEMANTIC_TOKEN_FLOW_IDENTIFICATION: &str = "FID";
pub const SEMANTIC_TOKEN_FORWARD_ERROR_CORRECTION: &str = "FEC";
pub const SEMANTIC_TOKEN_WEBRTC_MEDIA_STREAMS: &str = "WMS";
#[non_exhaustive]
pub enum Error {
CodecNotFound,
MissingWhitespace,
MissingColon,
PayloadTypeNotFound,
Io(IoError),
Utf8(FromUtf8Error),
SdpInvalidSyntax(String),
SdpInvalidValue(String),
SdpEmptyTimeDescription,
ParseInt(ParseIntError),
ParseUrl(ParseError),
ParseExtMap(String),
SyntaxError {
s: String,
p: usize,
},
}
The Error
enum defines various error types that can occur when working with SDP data, including parsing errors, invalid syntax, and missing required fields.
pub enum ConnectionRole {
Active,
Passive,
Actpass,
Holdconn,
}
Represents the role of a connection in a session.
pub struct Codec {
pub payload_type: u8,
pub name: String,
pub clock_rate: u32,
pub encoding_parameters: String,
pub fmtp: String,
}
Represents an audio or video codec with its parameters.
// Create a new JSEP Session Description
let mut sd = SessionDescription::new_jsep_session_description(false);
// Add a media description for audio
let audio = MediaDescription::new_jsep_media_description("audio".to_string(), vec![])
.with_codec(111, "opus".to_string(), 48000, 2, "minptime=10;useinbandfec=1".to_string())
.with_ice_credentials("username".to_string(), "password".to_string())
.with_fingerprint("sha-256".to_string(), "fingerprint".to_string());
// Add a media description for video
let video = MediaDescription::new_jsep_media_description("video".to_string(), vec![])
.with_codec(96, "VP8".to_string(), 90000, 0, "".to_string())
.with_ice_credentials("username".to_string(), "password".to_string())
.with_fingerprint("sha-256".to_string(), "fingerprint".to_string());
// Add media descriptions to session
sd = sd.with_media(audio).with_media(video);
// Marshal to SDP string
let sdp_string = sd.marshal();
// Parse SDP from string
let sdp_answer = String::try_from(sdp_string_received_from_peer)?;
// Convert to SessionDescription
let session_desc = SessionDescription::try_from(sdp_answer)?;
// Get payload type for a specific codec
let codec = Codec {
payload_type: 0, // Will be filled by function
name: "opus".to_string(),
clock_rate: 48000,
encoding_parameters: "2".to_string(),
fmtp: "".to_string(),
};
let payload_type = session_desc.get_payload_type_for_codec(&codec)?;
The SDP module implements RFC 4566 (Session Description Protocol) with extensions for WebRTC. It provides:
- Session Description: The top-level structure containing all session information
- Media Descriptions: Descriptions of media streams within a session (audio, video, application)
- Attributes: Key-value pairs providing additional information about the session or media
- Directions: Indicating whether endpoints can send, receive, both, or neither
- Extensions: RTP header extensions for additional functionality
The module supports both serialization (marshal) and deserialization (unmarshal) between Rust structures and the text-based SDP format, allowing for creating, parsing, and manipulating SDP documents for WebRTC applications.
The signal
module in the WebRTC Rust implementation provides essential functionality for WebRTC signaling. Signaling is the process of coordinating communication between peers before establishing a direct WebRTC connection. This module offers utilities for encoding and decoding Session Description Protocol (SDP) messages, reading input data, and setting up a simple HTTP server for receiving SDP information.
The signal module consists of four main functions:
use tokio::sync::mpsc;
pub async fn http_sdp_server(port: u16) -> tokio::sync::mpsc::Receiver<String>
This function starts an HTTP server that consumes Session Description Protocol (SDP) messages. The server listens on the specified port and processes incoming SDP messages received via HTTP POST requests to the /sdp
endpoint.
Parameters:
port
: Au16
value specifying which port the HTTP server should listen on.
Returns:
- A
tokio::sync::mpsc::Receiver<String>
that allows the caller to receive SDP messages when they arrive.
Usage Pattern:
- Call
http_sdp_server
with a port number. - Receive a channel receiver that will provide incoming SDP messages.
- The server runs in the background and forwards any SDP messages received via HTTP POST to the
/sdp
endpoint.
use anyhow::Result;
pub fn must_read_stdin() -> anyhow::Result<String>
This function blocks until input is received from standard input (stdin). It is useful for interactive applications where user input is required.
Returns:
- An
anyhow::Result<String>
containing the input line as a trimmed string or an error.
Usage Pattern:
- Call
must_read_stdin()
when you need to wait for user input. - The function will block until a line is entered in the terminal.
- The input is trimmed and returned as a
String
.
use base64::prelude::BASE64_STANDARD;
use base64::Engine;
pub fn encode(b: &str) -> String
This function encodes input text in base64 format. It is designed to handle SDP messages which may need to be transmitted through text-based protocols or user interfaces.
Parameters:
b
: A string slice containing the text to encode.
Returns:
- A
String
containing the base64-encoded version of the input.
Note:
- The implementation includes commented code for optional compression before encoding, but this is currently disabled.
use anyhow::Result;
use base64::prelude::BASE64_STANDARD;
use base64::Engine;
pub fn decode(s: &str) -> anyhow::Result<String>
This function decodes base64-encoded input back to its original text form. It is the counterpart to the encode
function.
Parameters:
s
: A string slice containing the base64-encoded text to decode.
Returns:
- An
anyhow::Result<String>
containing the decoded text as a string, or an error if decoding fails.
Note:
- Like the
encode
function, there is commented code for optional decompression after decoding.
Internally, the module uses:
- The
hyper
crate for HTTP server functionality - Tokio for asynchronous programming
base64
for encoding and decodinglazy_static
for static variable initialization- Mutex-protected channels for thread-safe communication
The HTTP server implementation includes a handler that processes incoming SDP messages and forwards them through a channel. The server is designed to run indefinitely in a separate task.
The signal module is typically used in WebRTC applications as follows:
-
Setting up signaling:
- Start an HTTP server using
http_sdp_server
to receive SDP offers/answers. - Use the returned channel to process incoming messages.
- Start an HTTP server using
-
Exchanging SDP information:
- Encode local SDP data using
encode
before transmitting it. - Decode received SDP data using
decode
before processing it.
- Encode local SDP data using
-
Interactive applications:
- Use
must_read_stdin
to wait for user input, such as pasting an SDP offer.
- Use
In a typical WebRTC application, this module would be used to:
- Generate a local SDP offer
- Encode it with
encode
- Have the user share the encoded offer with a peer
- Start an HTTP server with
http_sdp_server
to receive the answer - When the peer responds, their encoded answer would be received via HTTP
- The answer would be decoded with
decode
- The decoded answer would be used to establish the WebRTC connection
This signaling process is essential for WebRTC as it handles the initial coordination between peers before direct peer-to-peer communication can be established.
The STUN (Session Traversal Utilities for NAT) module implements the STUN protocol as specified in RFC 5389. STUN is a protocol that serves as a tool for other protocols in dealing with Network Address Translator (NAT) traversal.
pub struct Message {
pub typ: MessageType,
pub length: u32,
pub transaction_id: TransactionId,
pub attributes: Attributes,
pub raw: Vec<u8>,
}
The Message struct is the fundamental unit in STUN communication. It represents a STUN message with the following components:
typ
: The message type (request, response, etc.)length
: The message length in bytestransaction_id
: Unique identifier for the transactionattributes
: Collection of STUN attributes in the messageraw
: Raw binary representation of the message
Key Methods:
new() -> Self
: Creates a new empty messagemarshal_binary() -> Result<Vec<u8>, Error>
: Converts message to binary formatunmarshal_binary(&mut self, data: &[u8]) -> Result<(), Error>
: Parses binary data into messageadd(&mut self, t: AttrType, v: &[u8])
: Adds attribute to messagebuild(&mut self, setters: &[Box<dyn Setter>]) -> Result<(), Error>
: Builds message using settersparse(&self, getters: &mut [G]) -> Result<(), Error>
: Extracts data from message into gettersget(&self, t: AttrType) -> Result<Vec<u8>, Error>
: Gets attribute by typecontains(&self, t: AttrType) -> bool
: Checks if message contains attribute
pub struct Agent { /* private fields */ }
The Agent handles STUN transactions, providing thread-safe concurrency management and timeout handling.
Key Methods:
new(handler: Handler) -> Self
: Creates a new agent with callback handlerstart(&mut self, id: TransactionId, deadline: Instant) -> Result<(), Error>
: Registers a transactionstop(&mut self, id: TransactionId) -> Result<(), Error>
: Stops a transaction with ErrTransactionStoppedprocess(&mut self, message: Message) -> Result<(), Error>
: Processes incoming messagescollect(&mut self, deadline: Instant) -> Result<(), Error>
: Terminates expired transactionsclose(&mut self) -> Result<(), Error>
: Terminates all transactions and closes the agent
pub struct Client { /* private fields */ }
The Client simulates a connection to a STUN server.
Key Methods:
send(&self, m: &Message, handler: Handler) -> Result<(), Error>
: Sends a message asynchronouslyclose(&mut self) -> Result<(), Error>
: Closes the client connection
pub struct XorMappedAddress {
pub ip: IpAddr,
pub port: u16,
}
XorMappedAddress implements the XOR-MAPPED-ADDRESS attribute as defined in RFC 5389 Section 15.2.
Key Methods:
add_to_as(&self, m: &mut Message, t: AttrType) -> Result<(), Error>
: Adds XOR address as specified attributeget_from_as(&mut self, m: &Message, t: AttrType) -> Result<(), Error>
: Extracts XOR address from message
pub enum Error {
ErrAttributeNotFound,
ErrTransactionStopped,
ErrTransactionNotExists,
ErrTransactionExists,
ErrAgentClosed,
ErrTransactionTimeOut,
// ... many other variants
}
The Error enum provides detailed error types for STUN operations, allowing precise error handling and reporting. Common errors include attribute not found, transaction timeout, integrity mismatches, and connection issues.
pub trait Setter {
fn add_to(&self, b: &mut Message) -> Result<(), Error>;
}
The Setter trait defines how objects add attributes to STUN messages.
pub trait Getter {
fn get_from(&mut self, m: &Message) -> Result<(), Error>;
}
The Getter trait defines how objects extract attributes from STUN messages.
pub trait Checker {
fn check(&self, m: &Message) -> Result<(), Error>;
}
The Checker trait validates STUN messages against specific requirements.
The module defines numerous constants for STUN protocol elements:
DEFAULT_PORT
: Default STUN port (3478)DEFAULT_TLS_PORT
: Default STUN-over-TLS port (5349)- Message types:
BINDING_REQUEST
,BINDING_SUCCESS
, etc. - Attribute types:
ATTR_MAPPED_ADDRESS
,ATTR_USERNAME
, etc. - Error codes:
CODE_BAD_REQUEST
,CODE_UNAUTHORIZED
, etc.
Represents a MAPPED-ADDRESS attribute containing an IP address and port.
Implements text-based attributes like Username, Realm, Software, and Nonce.
Implements the FINGERPRINT attribute for integrity checking.
Implements the MESSAGE-INTEGRITY attribute for cryptographic authentication.
// Create a new STUN binding request
let mut msg = Message::new();
msg.set_type(MessageType::BINDING_REQUEST);
msg.new_transaction_id()?;
// Add attributes like USERNAME
let username = Username::new("user".to_string());
username.add_to(&mut msg)?;
// Send message via client
let client = Client::default();
client.send(&msg, my_handler).await?;
This STUN implementation provides a comprehensive API for STUN message handling, attribute management, and client-server communication. It follows RFC 5389 and includes support for message integrity, address handling, and robust error reporting.
The TURN (Traversal Using Relays around NAT) module provides an implementation of the TURN protocol as defined in RFC 5766. It enables clients to request a server to act as a relay for their communications with peers that might be unreachable due to NAT/firewall restrictions.
pub enum Error {
// Over 70 specific error variants for various TURN operations
ErrRelayAddressInvalid,
ErrNoAvailableConns,
// ... more variants
// Error wrapper variants
ParseInt(ParseIntError),
ParseIp(AddrParseError),
Io(IoError),
Util(Error),
Stun(Error),
Other(String),
}
Description: Comprehensive error type used throughout the TURN module to handle various error conditions that may occur during TURN operations.
pub struct Client { /* private fields */ }
Description: A STUN/TURN client that can communicate with a TURN server.
Key Methods:
pub async fn new(config: ClientConfig) -> Result<Self, Error>
: Creates a new TURN client with the specified configuration.pub async fn listen(&self) -> Result<(), Error>
: Starts listening for incoming packets.pub async fn allocate(&self) -> Result<impl Conn, Error>
: Sends an Allocation request to the TURN server.pub async fn close(&self) -> Result<(), Error>
: Closes the client's connection.pub async fn send_binding_request_to(&self, to: &str) -> Result<SocketAddr, Error>
: Sends a STUN binding request to a specific address.pub async fn send_binding_request(&self) -> Result<SocketAddr, Error>
: Sends a STUN binding request to the STUN server.
pub struct Server { /* private fields */ }
Description: An instance of a TURN server that handles client requests and manages allocations.
Key Methods:
pub async fn new(config: ServerConfig) -> Result<Self, Error>
: Creates a new TURN server with the specified configuration.pub async fn delete_allocations_by_username(&self, username: String) -> Result<(), Error>
: Deletes all allocations for a specific username.pub async fn get_allocations_info(&self, five_tuples: Option<Vec<FiveTuple>>) -> Result<HashMap<FiveTuple, AllocationInfo>, Error>
: Retrieves information about active allocations.pub async fn close(&self) -> Result<(), Error>
: Shuts down the TURN server and cleans up resources.
pub struct Allocation { /* private fields */ }
Description: Represents a TURN allocation tied to a five-tuple that relays traffic between clients and peers.
Key Methods:
pub fn new(...) -> Self
: Creates a new allocation.pub async fn has_permission(&self, addr: &SocketAddr) -> bool
: Checks if a peer address has permission to communicate through this allocation.pub async fn add_permission(&self, p: Permission)
: Adds a permission for a peer.pub async fn remove_permission(&self, addr: &SocketAddr) -> bool
: Removes a permission for a peer.pub async fn add_channel_bind(&self, c: ChannelBind, lifetime: Duration) -> Result<(), Error>
: Creates a channel binding for optimized communication.pub async fn remove_channel_bind(&self, number: ChannelNumber) -> bool
: Removes a channel binding.pub async fn close(&self) -> Result<(), Error>
: Closes the allocation and associated resources.pub async fn refresh(&self, lifetime: Duration)
: Updates the allocation's lifetime.
pub trait AuthHandler {
fn auth_handle(
&self,
username: &str,
realm: &str,
src_addr: SocketAddr,
) -> Result<Vec<u8>, Error>;
}
Description: Interface for handling TURN authentication via the STUN long-term credential mechanism.
Implementations:
LongTermAuthHandler
: Implements the AuthHandler trait using the long-term credential mechanism as specified in the TURN RFC.
pub trait RelayAddressGenerator {
fn validate(&self) -> Result<(), Error>;
fn allocate_conn<'life0, 'async_trait>(
&'life0 self,
use_ipv4: bool,
requested_port: u16,
) -> Pin<Box<dyn Future<Output = Result<(Arc<dyn Conn + Send + Sync>, SocketAddr), Error>> + Send + 'async_trait>>
where
Self: 'async_trait,
'life0: 'async_trait;
}
Description: Interface for generating relay addresses and connections for handling TURN allocations.
Implementations:
RelayAddressGeneratorNone
: A no-op implementation that always fails, used for testing.RelayAddressGeneratorStatic
: Uses a fixed IP and allocates ports for relaying.RelayAddressGeneratorRanges
: Dynamically allocates addresses from configured IP ranges.
pub struct FiveTuple {
// Private fields
}
Description: Represents the 5-tuple (client IP, client port, server IP, server port, transport protocol) that uniquely identifies a TURN allocation.
pub struct Permission {
// Private fields
}
Description: Represents a permission for a peer to send data through a TURN allocation.
pub struct ChannelBind {
// Private fields
}
Description: Represents a channel binding that provides an optimized way to communicate through a TURN allocation.
// Protocol ports
pub const DEFAULT_PORT: u16 = 3478;
pub const DEFAULT_TLS_PORT: u16 = 5349;
// Protocol identifiers
pub const PROTO_UDP: u8 = 17;
pub const PROTO_TCP: u8 = 6;
// Channel number constraints
pub const MIN_CHANNEL_NUMBER: u16 = 0x4000;
pub const MAX_CHANNEL_NUMBER: u16 = 0x7FFF;
// Default allocation lifetime
pub const DEFAULT_LIFETIME: Duration = Duration::from_secs(600); // 10 minutes
// Request creation
pub fn allocate_request() -> Result<Message, Error>
pub fn refresh_request(lifetime: Duration) -> Result<Message, Error>
pub fn create_permission_request(xorAddr: &XorPeerAddress) -> Result<Message, Error>
pub fn send_indication(xorAddr: &XorPeerAddress, data: &Data) -> Result<Message, Error>
// Authentication
pub fn generate_auth_key(username: &str, realm: &str, password: &str) -> Vec<u8>
pub fn generate_long_term_credentials() -> (String, String) // (username, password)
Setting up a basic TURN server:
async fn run_turn_server() -> Result<(), Error> {
// Create server config
let server_config = ServerConfig {
realm: "example.org".to_string(),
auth_handler: Arc::new(LongTermAuthHandler::new(
"username".to_string(),
"password".to_string(),
)),
relay_addr_generator: Box::new(RelayAddressGeneratorStatic::new(
"127.0.0.1".parse().unwrap(),
0,
0,
)),
channel_bind_timeout: Duration::from_secs(600),
allocation_lifetime: Duration::from_secs(600),
// more config options...
};
// Create and start server
let server = Server::new(server_config).await?;
// Server runs until explicitly closed
// Shut down server
server.close().await?;
Ok(())
}
Setting up a TURN client:
async fn run_turn_client() -> Result<(), Error> {
// Create client config
let client_config = ClientConfig {
stun_server_addr: "turn-server.example.org:3478".to_string(),
username: "username".to_string(),
password: "password".to_string(),
realm: "example.org".to_string(),
// more config options...
};
// Create client
let client = Client::new(client_config).await?;
// Start listening
client.listen().await?;
// Allocate relay address
let conn = client.allocate().await?;
// Use conn to send/receive data through the TURN server
// Close client
client.close().await?;
Ok(())
}
- The TURN module implements RFC 5766 (TURN) protocol for NAT traversal.
- It supports both IPv4 and IPv6.
- The implementation is async and built with Rust's async/await features.
- It provides comprehensive error handling for all protocol operations.
- The architecture allows for customizable components like authentication and relay address generation.
- Both client and server implementations are provided.
This implementation enables WebRTC applications to traverse NATs and firewalls even when direct peer-to-peer communication is impossible.
The webrtc
module is the main entry point for WebRTC functionality in Rust, providing a complete implementation of the WebRTC API. It enables peer-to-peer communication of audio, video, and arbitrary data by orchestrating ICE, DTLS, SRTP, and SCTP protocols.
The API
struct serves as a factory for WebRTC objects, with configuration for all underlying protocols:
pub struct API { /* private fields */ }
Key Methods:
fn new() -> Result<Self, Error>
: Creates a new API with default settingsfn new_with_engine(media_engine: MediaEngine, registry: Registry) -> Result<Self, Error>
: Creates an API with specific media engine and interceptorsfn new_with_options(options: APIBuilder) -> Result<Self, Error>
: Creates with customized optionsfn new_peer_connection(config: RTCConfiguration) -> Result<Arc<RTCPeerConnection>, Error>
: Creates a new peer connectionfn connection_state(&self) -> RTCPeerConnectionState
: Returns current connection state
The RTCPeerConnection
is the central point for managing WebRTC connections:
pub struct RTCPeerConnection { /* private fields */ }
Key Methods:
Connection Management:
fn create_offer(options: Option<RTCOfferOptions>) -> Result<RTCSessionDescription, Error>
: Creates an SDP offerfn create_answer(options: Option<RTCAnswerOptions>) -> Result<RTCSessionDescription, Error>
: Creates an SDP answerfn set_local_description(desc: RTCSessionDescription) -> Result<(), Error>
: Sets local descriptionfn set_remote_description(desc: RTCSessionDescription) -> Result<(), Error>
: Sets remote descriptionfn add_ice_candidate(candidate: RTCIceCandidateInit) -> Result<(), Error>
: Adds remote ICE candidatefn close() -> Result<(), Error>
: Closes the peer connection
Data Channel:
fn create_data_channel(label: &str, options: Option<RTCDataChannelInit>) -> Result<Arc<RTCDataChannel>, Error>
: Creates data channelfn on_data_channel(f: OnDataChannelHdlrFn) -> ()
: Sets handler for incoming data channels
Media:
fn add_track(track: Arc<dyn TrackLocal + Send + Sync>) -> Result<Arc<RTCRtpSender>, Error>
: Adds media trackfn add_transceiver_from_track(track: Arc<dyn TrackLocal + Send + Sync>, init: Option<RTCRtpTransceiverInit>) -> Result<Arc<RTCRtpTransceiver>, Error>
: Creates transceiver from trackfn add_transceiver_from_kind(kind: RTPCodecType, init: Option<RTCRtpTransceiverInit>) -> Result<Arc<RTCRtpTransceiver>, Error>
: Creates transceiver for media typefn on_track(f: OnTrackHdlrFn) -> ()
: Sets handler for incoming tracks
Events:
fn on_ice_candidate(f: OnICECandidateHdlrFn) -> ()
: Sets ICE candidate handlerfn on_ice_connection_state_change(f: OnICEConnectionStateChangeHdlrFn) -> ()
: Sets ICE state change handlerfn on_peer_connection_state_change(f: OnPeerConnectionStateChangeHdlrFn) -> ()
: Sets connection state handlerfn on_signaling_state_change(f: OnSignalingStateChangeHdlrFn) -> ()
: Sets signaling state handlerfn on_negotiation_needed(f: OnNegotiationNeededHdlrFn) -> ()
: Sets negotiation needed handler
Represents a data channel for sending arbitrary data:
pub struct RTCDataChannel { /* private fields */ }
Key Methods:
fn send_text(text: &str) -> Result<(), Error>
: Sends text datafn send(data: &Bytes) -> Result<(), Error>
: Sends binary datafn close() -> Result<(), Error>
: Closes the data channelfn on_open(f: OnOpenHdlrFn) -> ()
: Sets open event handlerfn on_close(f: OnCloseHdlrFn) -> ()
: Sets close event handlerfn on_message(f: OnMessageHdlrFn) -> ()
: Sets message event handlerfn on_error(f: OnErrorHdlrFn) -> ()
: Sets error event handler
Configuration for creating a peer connection:
pub struct RTCConfiguration {
pub ice_servers: Vec<RTCIceServer>,
pub ice_transport_policy: RTCIceTransportPolicy,
pub bundle_policy: RTCBundlePolicy,
pub rtcp_mux_policy: RTCRtcpMuxPolicy,
pub peer_identity: String,
pub certificates: Vec<Arc<dyn Certificate + Send + Sync>>,
pub icecandidatepoolsize: u8,
// ... other fields
}
Defines STUN/TURN servers for connectivity:
pub struct RTCIceServer {
pub urls: Vec<String>,
pub username: String,
pub credential: String,
pub credential_type: RTCIceCredentialType,
}
Represents an SDP session description:
pub struct RTCSessionDescription {
pub sdp_type: RTCSdpType,
pub sdp: String,
}
Type of SDP in session negotiation:
pub enum RTCSdpType {
Unspecified,
Offer, // Initiating offer
Pranswer, // Provisional answer
Answer, // Final answer
Rollback, // Rollback to previous state
}
Overall connection state:
pub enum RTCPeerConnectionState {
Unspecified,
New,
Connecting,
Connected,
Disconnected,
Failed,
Closed,
}
Signaling process state:
pub enum RTCSignalingState {
Unspecified,
Stable,
HaveLocalOffer,
HaveRemoteOffer,
HaveLocalPranswer,
HaveRemotePranswer,
Closed,
}
ICE connectivity state:
pub enum RTCICEConnectionState {
Unspecified,
New,
Checking,
Connected,
Completed,
Failed,
Disconnected,
Closed,
}
async fn webrtc_example() -> Result<(), Error> {
// Create API
let api = API::new()?;
// Configure and create peer connection
let config = RTCConfiguration {
ice_servers: vec![
RTCIceServer {
urls: vec!["stun:stun.l.google.com:19302".to_string()],
..Default::default()
},
],
..Default::default()
};
let peer_connection = api.new_peer_connection(config).await?;
// Create data channel
let dc = peer_connection.create_data_channel(
"my-data-channel",
Some(RTCDataChannelInit::default())
).await?;
// Set up handlers
dc.on_open(Box::new(|| {
println!("Data channel opened");
Box::pin(async {})
}));
dc.on_message(Box::new(|msg| {
println!("Message received: {:?}", msg);
Box::pin(async {})
}));
// Handle ICE candidates
peer_connection.on_ice_candidate(Box::new(|candidate| {
if let Some(c) = candidate {
println!("New ICE candidate: {}", c.to_json().unwrap());
// Send to remote peer via signaling
}
Box::pin(async {})
}));
// Create offer
let offer = peer_connection.create_offer(None).await?;
peer_connection.set_local_description(offer.clone()).await?;
// Send offer to remote peer via signaling
// ...
// When answer is received from remote
// peer_connection.set_remote_description(answer).await?;
Ok(())
}
- The WebRTC implementation follows the W3C and IETF specifications
- It provides a complete stack from ICE and DTLS to SRTP and SCTP
- The design uses Rust's async/await for efficient I/O operations
- The API is similar to browser WebRTC APIs but adapted to Rust idioms
- The implementation supports both reliable and unreliable data transport
- Media handling includes audio and video with various codecs
- RTP header extensions and RTCP feedback mechanisms are supported
- The peer connection can be used with custom signaling solutions
The webrtc_data
module implements the WebRTC Data Channel functionality, providing APIs for sending and receiving arbitrary data between peers. It operates on top of the SCTP transport protocol, enabling peer-to-peer data exchange with configurable reliability modes.
The DataChannel
struct is the central component, representing a single data channel within an SCTP association:
pub struct DataChannel {
// Private fields
}
Constructor Methods:
// Creates a new data channel
pub fn new(stream: Arc<Stream>, config: Config) -> Self
// Opens a data channel with the specified configuration
pub async fn dial(
association: &Arc<Association>,
identifier: u16,
config: Config,
) -> Result<Self, Error>
// Accepts an incoming data channel
pub async fn accept<T>(
association: &Arc<Association>,
config: Config,
existing_channels: &[T],
) -> Result<Self, Error>
where
T: Borrow<Self>
// Creates a client-side data channel
pub async fn client(stream: Arc<Stream>, config: Config) -> Result<Self, Error>
// Creates a server-side data channel
pub async fn server(stream: Arc<Stream>, config: Config) -> Result<Self, Error>
Send/Receive Methods:
// Reads raw data from the channel
pub async fn read(&self, buf: &mut [u8]) -> Result<usize, Error>
// Reads data with channel metadata
pub async fn read_data_channel(
&self,
buf: &mut [u8],
) -> Result<(usize, bool), Error>
// Writes data to the channel
pub async fn write(&self, data: &Bytes) -> Result<usize, Error>
// Writes data with channel metadata
pub async fn write_data_channel(
&self,
data: &Bytes,
is_string: bool,
) -> Result<usize, Error>
// Sends formatted message (text or binary)
pub async fn send(&self, data: &Bytes) -> Result<(), Error>
Event Handlers:
// Sets the callback for when the channel opens
pub async fn on_open(&self, f: OnOpenHdlrFn) -> Result<(), Error>
// where OnOpenHdlrFn = Box<dyn FnOnce() -> Pin<Box<dyn Future<Output = ()> + Send + 'static>> + Send + Sync>
// Sets the callback for when messages arrive
pub async fn on_message(&self, f: OnMessageHdlrFn) -> Result<(), Error>
// where OnMessageHdlrFn = Box<dyn FnMut(Message) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>> + Send + Sync>
// Sets the callback for when the channel closes
pub async fn on_close(&self, f: OnCloseHdlrFn) -> Result<(), Error>
// where OnCloseHdlrFn = Box<dyn FnOnce() -> Pin<Box<dyn Future<Output = ()> + Send + 'static>> + Send + Sync>
// Sets the callback for errors
pub async fn on_error(&self, f: OnErrorHdlrFn) -> Result<(), Error>
// where OnErrorHdlrFn = Box<dyn FnMut(Error) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>> + Send + Sync>
Buffer Management:
// Returns current size of the outgoing buffer
pub fn buffered_amount(&self) -> usize
// Returns the threshold for the buffered amount low event
pub fn buffered_amount_low_threshold(&self) -> usize
// Sets the threshold for buffer drain notification
pub fn set_buffered_amount_low_threshold(&self, threshold: usize)
// Sets handler for buffer drain events
pub fn on_buffered_amount_low(&self, f: OnBufferedAmountLowFn)
// where OnBufferedAmountLowFn = Box<dyn FnMut() -> Pin<Box<dyn Future<Output = ()> + Send + 'static>> + Send + Sync>
Lifecycle Methods:
// Closes the data channel
pub async fn close(&self) -> Result<(), Error>
Stats and Metrics:
// Returns the number of messages sent
pub fn messages_sent(&self) -> usize
// Returns the number of messages received
pub fn messages_received(&self) -> usize
// Returns the number of bytes sent
pub fn bytes_sent(&self) -> usize
// Returns the number of bytes received
pub fn bytes_received(&self) -> usize
// Returns the stream identifier
pub fn stream_identifier(&self) -> u16
The Config
struct defines the properties and behavior of a data channel:
pub struct Config {
pub label: String,
pub ordered: bool,
pub max_packet_life_time: Option<u16>,
pub max_retransmits: Option<u16>,
pub protocol: String,
pub negotiated: bool,
pub id: Option<u16>,
pub priority: Option<u16>,
}
Key fields:
label
: Identifies the channel for applicationsordered
: If true, messages are delivered in order (reliable)max_packet_life_time
: Maximum time to attempt retransmissionmax_retransmits
: Maximum number of retransmission attemptsnegotiated
: If true, channel ID is negotiated out-of-bandid
: Channel ID when negotiated out-of-band
The Message
enum represents data exchanged over data channels:
// The DataChannelMessage enum (from webrtc crate)
pub enum DataChannelMessage {
Binary(Bytes),
Text(String),
}
// The internal Message enum (from webrtc_data crate)
pub enum Message {
DataChannelAck(DataChannelAck),
DataChannelOpen(DataChannelOpen),
}
The DataChannelMessage
enum represents application data:
Binary
: Raw binary dataText
: UTF-8 text data
The internal Message
enum represents protocol-level messages:
DataChannelAck
: Acknowledgment message for channel establishmentDataChannelOpen
: Channel establishment message
A non-async variant of DataChannel that works with synchronous code:
pub struct PollDataChannel {
// Private fields
}
Key Methods:
// Creates a new polling data channel from an async data channel
pub fn new(data_channel: DataChannel) -> Self
// Detects if messages might be available
pub fn poll_read(&self) -> bool
// Reads a message from the channel (non-blocking)
pub fn read(&self) -> Option<Result<DataChannelMessage, Error>>
// Writes a message to the channel
pub fn write(&self, msg: DataChannelMessage) -> Result<(), Error>
// Gets the label of the data channel
pub fn label(&self) -> String
// Gets the ordered flag of the data channel
pub fn ordered(&self) -> bool
// Gets the max_packet_life_time setting
pub fn max_packet_life_time(&self) -> Option<u16>
// Gets the max_retransmits setting
pub fn max_retransmits(&self) -> Option<u16>
// Gets the protocol of the data channel
pub fn protocol(&self) -> String
// Gets the negotiated flag
pub fn negotiated(&self) -> bool
// Gets the ID of the data channel
pub fn id(&self) -> Option<u16>
// Checks if the channel is ready to use
pub fn ready(&self) -> bool
// Closes the data channel
pub fn close(&self) -> Result<(), Error>
Offers polling-based API for environments where async/await is not available. This is useful for integration with synchronous frameworks or legacy code that can't use Rust's async/await features.
#[non_exhaustive]
pub enum Error {
UnexpectedEndOfBuffer {
expected: usize,
actual: usize,
},
InvalidMessageType(u8),
InvalidChannelType(u8),
InvalidPayloadProtocolIdentifier(u8),
ErrStreamClosed,
Util(webrtc_util::error::Error),
Sctp(Error),
Utf8(FromUtf8Error),
new(String),
}
This enum provides comprehensive error handling for all data channel operations. The #[non_exhaustive]
attribute indicates that additional error variants may be added in future library versions, so code matching on this enum should include a wildcard arm.
// Creating a data channel
let config = Config {
label: "chat".to_string(),
ordered: true,
max_retransmits: Some(3),
..Default::default()
};
let dc = DataChannel::new(config).await?;
// Set handlers
dc.on_open(Box::new(|| {
println!("Data channel open");
Box::pin(async {}) // Return a future that resolves immediately
})).await?;
dc.on_message(Box::new(|msg| {
match msg {
Message::Text(text) => println!("Received text: {}", text),
Message::Binary(data) => println!("Received binary: {} bytes", data.len()),
}
Box::pin(async {}) // Return a future that resolves immediately
})).await?;
// Sending data
dc.send(&Bytes::from("Hello WebRTC!")).await?;
// Close when done
dc.close().await?;
// Accept incoming data channel from an SCTP stream
let dc = DataChannel::accept(sctp_stream).await?;
// Set up handlers and use as above
-
Reliable, Ordered: Default WebRTC behavior (TCP-like)
let config = Config { ordered: true, max_packet_life_time: None, max_retransmits: None, ..Default::default() };
-
Reliable, Unordered: All data arrives but order may change
let config = Config { ordered: false, max_packet_life_time: None, max_retransmits: None, ..Default::default() };
-
Partially Reliable (Timed): May drop packets after time limit
let config = Config { ordered: true, // or false max_packet_life_time: Some(100), // milliseconds max_retransmits: None, ..Default::default() };
-
Partially Reliable (Limited retransmissions): May drop after retries
let config = Config { ordered: true, // or false max_packet_life_time: None, max_retransmits: Some(3), ..Default::default() };
These different modes allow applications to balance reliability against latency based on their specific needs.
The webrtc_dtls
module implements Datagram Transport Layer Security (DTLS) for WebRTC, enabling secure communication over unreliable transports like UDP. It provides encryption, authentication, and integrity for data exchanged in WebRTC connections.
The Config
struct configures DTLS connections with options for security and performance:
pub struct Config {
pub certificates: Vec<Certificate>,
pub cipher_suites: Vec<CipherSuiteId>,
pub signature_schemes: Vec<SignatureScheme>,
pub srtp_protection_profiles: Vec<SrtpProtectionProfile>,
pub client_auth: ClientAuthType,
pub extended_master_secret: ExtendedMasterSecretType,
pub flight_interval: Duration,
pub psk: Option<PskCallback>, // where PskCallback = Arc<dyn (Fn(&[u8]) -> Result<Vec<u8>>) + Send + Sync>
pub psk_identity_hint: Option<Vec<u8>>,
pub insecure_skip_verify: bool,
pub insecure_hashes: bool,
pub insecure_verification: bool,
pub verify_peer_certificate: Option<VerifyPeerCertificateFn>,
pub roots_cas: rustls::RootCertStore,
pub client_cas: rustls::RootCertStore,
pub server_name: String,
pub mtu: usize,
pub replay_protection_window: usize,
}
Key fields:
certificates
: Certificates for authenticationcipher_suites
: Supported encryption algorithmsclient_auth
: Controls client certificate authenticationextended_master_secret
: Enhances security against man-in-the-middle attacksinsecure_skip_verify
: Option to bypass certificate verification (for testing only)
The DTLSConn
struct represents a DTLS connection that wraps an underlying network connection:
pub struct DTLSConn { /* private fields */ }
Key methods:
// Creates a new DTLS connection
pub async fn new(
conn: Arc<dyn Conn + Send + Sync>,
config: Config,
is_client: bool,
initial_state: Option<State>,
) -> Result<Self, Error>
// Reads data from the encrypted connection
pub async fn read(
&self,
p: &mut [u8],
duration: Option<Duration>,
) -> Result<usize, Error>
// Writes data to the encrypted connection
pub async fn write(
&self,
p: &[u8],
duration: Option<Duration>,
) -> Result<usize, Error>
// Gracefully terminates the connection
pub async fn close(&self) -> Result<(), Error>
// Returns state information
pub async fn connection_state(&self) -> State
// Returns the selected SRTP protection profile
pub fn selected_srtpprotection_profile(&self) -> SrtpProtectionProfile
Implements KeyingMaterialExporter
trait:
// Exports cryptographic material for use with other protocols (e.g., SRTP)
pub trait KeyingMaterialExporter {
fn export_keying_material<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
label: &'life1 str,
context: &'life2 [u8],
length: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<u8>, KeyingMaterialExporterError>> + Send + 'async_trait>>
where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
}
The DTLS handshaker manages the DTLS handshake process, negotiating security parameters between peers.
Key functions:
handshake(ctx, cfg, conn, is_client)
: Performs the DTLS handshakegen_self_signed_root_cert(name)
: Generates a self-signed certificate for testing
The State
struct tracks the state of a DTLS connection:
pub struct State {
// Session details
pub local_epoch: u16,
pub remote_epoch: u16,
pub cipher_suite: Option<Box<dyn CipherSuite + Send + Sync>>,
pub is_client: bool,
pub peer_certificates: Vec<Vec<u8>>,
pub identity_hint: Vec<u8>,
// ... other private fields
}
The State
struct implements the KeyingMaterialExporter
trait to export keys for other protocols like SRTP.
The CipherSuite
trait defines encryption algorithms used in DTLS:
pub trait CipherSuite: Debug {
fn id(&self) -> CipherSuiteId;
fn certificate_type(&self) -> ClientCertificateType;
fn hash_func(&self) -> CipherSuiteHash;
fn is_psk(&self) -> bool;
fn is_initialized(&self) -> bool;
// Encryption/decryption methods
fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>, Error>;
fn decrypt(&self, record_layer_header: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>, Error>;
// Key generation methods
fn init(
&mut self,
master_secret: &[u8],
client_random: &[u8],
server_random: &[u8],
is_client: bool,
) -> Result<(), Error>;
}
Supported cipher suites include:
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- TLS_PSK_WITH_AES_128_CCM
- And others
Error type for key material export operations:
#[non_exhaustive]
pub enum KeyingMaterialExporterError {
HandshakeInProgress,
ContextUnsupported,
ReservedExportKeyingMaterial,
CipherSuiteUnset,
Io(IoError),
Hash(String),
}
Controls how the server handles client certificates:
pub enum ClientAuthType {
NoClientCert, // No client certificate is requested
RequestClientCert, // Client certificate is requested but optional
RequireAnyClientCert, // Client must provide a certificate
VerifyClientCertIfGiven, // Verify client certificate if provided
RequireAndVerifyClientCert // Client must provide a valid certificate
}
Controls the "Extended Master Secret" extension (RFC 7627):
pub enum ExtendedMasterSecretType {
Request, // Request but don't require
Require, // Require extension
Disable // Disable extension
}
The DTLSListener
accepts incoming DTLS connections:
pub struct DTLSListener { /* private fields */ }
Key functions:
// Creates a new DTLS listener
pub fn listen(
network: &str,
addr: &str,
config: Config,
) -> Result<Self, Error>
// Accepts incoming DTLS connections
pub async fn accept(&self) -> Result<(DTLSConn, SocketAddr), Error>
// Closes the listener
pub async fn close(&self) -> Result<(), Error>
// Create a configuration
let mut config = Config::default();
// Generate or load certificates
let cert = gen_self_signed_root_cert("example.com")?;
config.certificates = vec![cert];
// Client mode
let conn = UdpSocket::bind("0.0.0.0:0")?;
conn.connect("example.com:443")?;
let dtls_conn = DTLSConn::new(
Arc::new(conn),
config,
true, // is_client
None // initial_state
).await?;
// Use the connection
dtls_conn.write(b"hello", None).await?;
let mut buf = [0u8; 1024];
let n = dtls_conn.read(&mut buf, None).await?;
println!("Read: {}", std::str::from_utf8(&buf[..n])?);
// Export keying material for SRTP
let key_material = dtls_conn.export_keying_material(
"EXTRACTOR-dtls_srtp", // label
&[], // context
key_length // length
)?;
// Close the connection
dtls_conn.close().await?;
- Authentication via certificates or pre-shared keys
- Confidentiality through strong encryption algorithms
- Integrity ensuring data cannot be tampered with
- Forward secrecy with ECDHE key exchange
- Key export for securing other protocols like SRTP
The module provides a complete implementation of DTLS 1.2 suitable for WebRTC applications, with a focus on security and interoperability with other WebRTC implementations.
This document provides a concise technical summary of the webrtc_ice
module, which implements the Interactive Connectivity Establishment (ICE) protocol for WebRTC.
The Agent
struct is central to the ICE implementation, handling candidate gathering, connectivity checks, and connection maintenance.
struct Agent { /* private fields */ }
-
Creation
async fn new(config: AgentConfig) -> Result<Self, Error>
: Creates a new ICE agent with specified configuration
-
Connection Establishment
async fn dial(cancel_rx: Receiver<()>, remote_ufrag: String, remote_pwd: String) -> Result<Arc<impl Conn>, Error>
: Initiates connection as controlling agentasync fn accept(cancel_rx: Receiver<()>, remote_ufrag: String, remote_pwd: String) -> Result<Arc<impl Conn>, Error>
: Accepts connection as controlled agentfn gather_candidates() -> Result<(), Error>
: Initiates the trickle-based gathering process for ICE candidatesfn add_remote_candidate(c: &Arc<dyn Candidate + Send + Sync>) -> Result<(), Error>
: Adds a remote candidate for connection establishment
-
State Management
fn on_connection_state_change(f: OnConnectionStateChangeHdlrFn)
: Sets a handler for connection state changesfn on_candidate(f: OnCandidateHdlrFn)
: Sets a handler for newly gathered candidatesfn on_selected_candidate_pair_change(f: OnSelectedCandidatePairChangeHdlrFn)
: Sets a handler for when the final candidate pair is selectedasync fn restart(ufrag: String, pwd: String) -> Result<(), Error>
: Restarts the ICE agent with new credentials
-
Queries
async fn get_local_candidates() -> Result<Vec<Arc<dyn Candidate + Send + Sync>>, Error>
: Returns local candidatesfn get_selected_candidate_pair() -> Option<Arc<CandidatePair>>
: Returns the selected candidate pair if one existsasync fn get_local_user_credentials() -> (String, String)
: Returns the local ufrag/pwdasync fn get_remote_user_credentials() -> (String, String)
: Returns the remote ufrag/pwdfn get_bytes_sent() -> usize
: Returns bytes sentfn get_bytes_received() -> usize
: Returns bytes received
-
Statistics
async fn get_candidate_pairs_stats() -> Vec<CandidatePairStats>
: Returns stats about candidate pairsasync fn get_local_candidates_stats() -> Vec<CandidateStats>
: Returns stats about local candidatesasync fn get_remote_candidates_stats() -> Vec<CandidateStats>
: Returns stats about remote candidates
-
Cleanup
async fn close() -> Result<(), Error>
: Cleans up and shuts down the agent
The Candidate
trait represents an ICE candidate, providing methods to handle network addresses for connection establishment.
trait Candidate: Display {
fn foundation(&self) -> String;
fn id(&self) -> String;
fn component(&self) -> u16;
fn set_component(&self, c: u16);
fn last_received(&self) -> SystemTime;
fn last_sent(&self) -> SystemTime;
fn network_type(&self) -> NetworkType;
fn address(&self) -> String;
fn port(&self) -> u16;
fn priority(&self) -> u32;
fn related_address(&self) -> Option<CandidateRelatedAddress>;
fn candidate_type(&self) -> CandidateType;
fn tcp_type(&self) -> TcpType;
fn marshal(&self) -> String;
fn addr(&self) -> SocketAddr;
fn close(&self) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + '_>>;
fn seen(&self, outbound: bool);
fn write_to(&self, raw: &[u8], dst: &(dyn Candidate + Send + Sync)) -> Pin<Box<dyn Future<Output = Result<usize, Error>> + Send + '_>>;
fn equal(&self, other: &dyn Candidate) -> bool;
fn set_ip(&self, ip: &IpAddr) -> Result<(), Error>;
fn get_conn(&self) -> Option<&Arc<dyn Conn + Send + Sync>>;
fn get_closed_ch(&self) -> Arc<Mutex<Option<Sender<()>>>>;
}
CandidateType
enumerates possible types of candidates in the ICE protocol.
enum CandidateType {
Host, // Local candidate
ServerReflexive, // Candidate from STUN server
PeerReflexive, // Candidate from remote peer
Relay, // Candidate from TURN server
Unspecified,
}
ConnectionState
represents the current state of an ICE connection.
enum ConnectionState {
Unspecified,
New, // ICE agent is gathering addresses
Checking, // Agent has been given candidates and is attempting to find a match
Connected, // Agent has a pairing but is still checking other pairs
Completed, // Agent has finished
Failed, // Agent never could successfully connect
Disconnected, // Agent connected but has entered a failed state
Closed, // Agent has finished and is no longer handling requests
}
GatheringState
indicates the current state of candidate gathering.
enum GatheringState {
Unspecified,
New, // No gathering activity performed yet
Gathering, // Gathering is in progress
Complete, // Gathering has been completed
}
The UDP multiplexer interfaces for allowing multiple connections via a single UDP socket.
trait UDPMux {
fn close(&self) -> Result<(), Error>;
fn get_conn(&self, params: &UDPMuxConnParams) -> Result<Arc<dyn UDPMuxWriter + Send + Sync>, Error>;
fn remove_conn(&self, conn: &Arc<dyn UDPMuxWriter + Send + Sync>) -> Result<(), Error>;
fn addr(&self) -> SocketAddr;
}
trait UDPMuxWriter {
fn write_to(&self, buf: &[u8], target: &SocketAddr) -> Result<usize, Error>;
fn local_addr(&self) -> Result<SocketAddr, Error>;
fn set_callback(&self, func: Box<dyn FnMut(&[u8], SocketAddr) + Send + Sync>) -> Result<(), Error>;
}
Configuration options for creating an ICE Agent.
struct AgentConfig {
pub urls: Vec<Url>, // STUN/TURN server URLs
pub network_types: Vec<NetworkType>, // Allowed network types
pub udp_network: Arc<dyn UDPNetwork>, // Network implementation
pub disconnected_timeout: Duration, // Time until Disconnected
pub failed_timeout: Duration, // Time until Failed
pub keepalive_interval: Duration, // Interval for keepalive packets
pub check_interval: Duration, // Interval between connectivity checks
pub max_binding_requests: u16, // Max number of binding requests
pub candidate_types: Vec<CandidateType>, // Allowed candidate types
pub role: Role, // Controlling or controlled role
pub trickle: bool, // Enable candidate trickling
pub lite: bool, // Enable ICE-Lite mode
pub udp_mux: Option<Arc<dyn UDPMux + Send + Sync>>, // Custom UDP multiplexer
pub interface_filter: Option<InterfaceFilterFn>, // Filter for network interfaces
pub ip_filter: Option<IpFilterFn>, // Filter for IP addresses
pub nat_1to1_ips: Vec<String>, // 1:1 NAT IP mappings
pub nat_1to1_ip_candidate_type: CandidateType, // Candidate type for NAT 1:1
pub mdns_mode: MulticastDnsMode, // mDNS discovery mode
pub accepting_min_wait: Duration, // Min wait before connecting when accepting
pub accepting_max_wait: Duration, // Max wait before connecting when accepting
}
Different types of networks that ICE can use for connectivity.
enum NetworkType {
Unspecified,
Udp4, // IPv4 UDP
Udp6, // IPv6 UDP
Tcp4, // IPv4 TCP
Tcp6, // IPv6 TCP
Unixgram, // Unix datagram socket
}
Defines the role of the ICE agent in the connection.
enum Role {
Unspecified,
Controlling, // Agent controls negotiation
Controlled, // Agent is controlled in negotiation
}
Options for mDNS candidate discovery.
enum MulticastDnsMode {
Unspecified,
QueryOnly, // Only query mDNS
QueryAndGather, // Query and gather mDNS candidates
Disabled, // Disable mDNS
}
- candidate: Implements various candidate types (host, server reflexive, peer reflexive, relay)
- control: Handles control attributes and role conflict resolution
- external_ip_mapper: Maps internal to external IP addresses
- mdns: Multicast DNS implementation for local candidate discovery
- network_type: Network type handling and filtering
- priority: Candidate priority calculation
- rand: Random generation of ICE attributes and IDs
- state: Connection and gathering state enumerations
- stats: Statistics collection and reporting
- tcp_type: TCP specific candidate types
- udp_mux: UDP multiplexer implementation
- url: STUN/TURN URL handling
- util: ICE utility functions
The module uses a uniform error type webrtc_ice::Error
with variants for different failure scenarios:
enum Error {
// Various error types
ErrUnknownType,
ErrSchemeType,
ErrSTUNQuery,
ErrInvalidICECredentials,
ErrNoMatchingCandidatePair,
ErrClosed,
ErrTimeout,
// ... (other errors)
}
Basic usage pattern:
// Create a configuration
let config = AgentConfig {
urls: vec![Url::parse("stun:stun.l.google.com:19302").unwrap()],
network_types: supported_network_types(),
..Default::default()
};
// Create the agent
let agent = Agent::new(config).await?;
// Set up callbacks
agent.on_candidate(Box::new(|candidate| {
if let Some(c) = candidate {
println!("Gathered candidate: {}", c.marshal());
}
}));
agent.on_connection_state_change(Box::new(|state| {
println!("Connection state changed: {}", state);
}));
// Gather candidates
agent.gather_candidates()?;
// Get local credentials for signaling
let (local_ufrag, local_pwd) = agent.get_local_user_credentials().await;
// Exchange credentials with remote peer via signaling
// ...
// Set remote credentials
agent.set_remote_credentials(remote_ufrag, remote_pwd).await?;
// For controlling side (initiator)
let conn = agent.dial(cancel_rx, remote_ufrag, remote_pwd).await?;
// For controlled side (answerer)
let conn = agent.accept(cancel_rx, remote_ufrag, remote_pwd).await?;
// Use the connection
conn.write(data).await?;
- The ICE agent supports both standard ICE and ICE-Lite modes
- Candidates can be gathered via trickle ICE (incremental) or all at once
- The agent handles NAT traversal using STUN and TURN servers
- IPv4, IPv6, UDP, and TCP transports are supported
- Multiplexing for sharing a single network port is supported
- The agent implements ICE restarts for connection recovery
- Statistics collection provides insights into connection quality
The webrtc_mdns
module provides an implementation of Multicast DNS (mDNS) for WebRTC applications, primarily used for local network service discovery and hostname resolution.
Multicast DNS (mDNS) is a zero-configuration networking protocol that allows devices on a local network to discover and communicate with each other without relying on a centralized DNS server. In WebRTC contexts, mDNS is particularly useful for ICE candidates gathering, where it helps preserve privacy by replacing local IP addresses with randomly generated mDNS hostnames.
The Config
struct provides configuration options for mDNS:
pub struct Config {
pub query_interval: Duration,
pub local_names: Vec<String>,
}
query_interval
: Defines how frequently to repeat querieslocal_names
: List of local mDNS names to respond to
The Config
struct implements Default
for easy initialization.
The DnsConn
struct provides the core functionality for maintaining an mDNS server and performing queries:
pub struct DnsConn { /* private fields */ }
Key methods:
server(addr: SocketAddr, config: Config) -> Result<Self, Error>
: Establishes an mDNS server on the specified socket address with the given configuration.close(&self) -> Result<(), Error>
: Closes the mDNS connection.query(&self, name: &str, close_query_signal: Receiver<()>) -> Result<(ResourceHeader, SocketAddr), Error>
: Performs mDNS queries for a specified name until either receiving a result or a close signal.
The Message
struct represents an mDNS message with fields for various DNS components:
pub struct Message {
pub header: Header,
pub questions: Vec<Question>,
pub answers: Vec<Resource>,
pub authorities: Vec<Resource>,
pub additionals: Vec<Resource>,
}
Methods for encoding and decoding messages:
unpack(&mut self, msg: &[u8]) -> Result<(), Error>
: Parses a raw byte message into the structuredMessage
format.pack(&mut self) -> Result<Vec<u8>, Error>
: Serializes aMessage
into a byte vector.append_pack(&mut self, b: Vec<u8>) -> Result<Vec<u8>, Error>
: Extends an existing packed message.
- Header: Contains metadata about the message (ID, flags, counts)
- Question: Represents a DNS query with name, type, and class
- Resource: Represents DNS resource records like A, AAAA, PTR, etc.
The module supports various DNS resource types:
- A (IPv4 address records)
- AAAA (IPv6 address records)
- CNAME (Canonical name records)
- MX (Mail exchange records)
- NS (Name server records)
- OPT (Option records)
- PTR (Pointer records)
- SOA (Start of authority records)
- SRV (Service records)
- TXT (Text records)
The module uses a unified Error
enum that includes variants for various mDNS-specific issues:
pub enum Error {
ErrJoiningMulticastGroup,
ErrConnectionClosed,
ErrContextElapsed,
// ... and many other variants
}
Error variants cover various failure modes, including:
- Network-related errors (joining multicast groups, connection issues)
- DNS message parsing and formatting errors
- Resource limit exceedances
- Configuration issues
A typical usage pattern involves:
- Creating a configuration with appropriate settings
- Establishing an mDNS server on a UDP socket
- Performing queries as needed
- Closing the connection when done
// Example usage (conceptual)
let config = Config::default();
let conn = DnsConn::server(socket_addr, config)?;
// Create a channel for cancellation
let (tx, rx) = tokio::sync::mpsc::channel(1);
// Query for a hostname
let (resource, addr) = conn.query("example.local", rx).await?;
// Process results...
// Close when done
conn.close().await?;
In WebRTC applications, mDNS is typically used within the ICE (Interactive Connectivity Establishment) framework to:
- Replace local IP addresses with random mDNS hostnames in ICE candidates
- Resolve mDNS hostnames to IP addresses when receiving candidates
- Enhance privacy by preventing exposure of private network information
This functionality is most relevant when gathering and processing ICE candidates during the connection establishment phase of WebRTC peer connections.
The DnsConn
struct implements Send
and Sync
, making it safe to share across threads, while the Message
struct does not implement these traits and should be handled within a single thread.
- The implementation primarily focuses on local network usage
- Some resource types might have limited support
- Error handling is comprehensive but might require application-specific strategies
The webrtc_media
module provides foundational structures and utilities for handling multimedia data in WebRTC applications. It focuses on media sample processing, audio/video format handling, and media I/O operations.
At the heart of this module is the Sample
struct, which contains encoded media and timing information:
pub struct Sample {
pub data: Bytes, // The actual media bitstream data (not packetized format)
pub timestamp: SystemTime, // Wall clock time when the sample was generated
pub duration: Duration, // Duration of the sample
pub packet_timestamp: u32, // RTP packet timestamp for the sample
pub prev_dropped_packets: u16, // Count of packets dropped before building this sample
pub prev_padding_packets: u16, // Count of padding packets detected before building this sample
}
The Sample
struct implements several traits including Clone
, Debug
, and others to facilitate media handling operations.
The webrtc_media
module consists of three main sub-modules:
- audio: Audio-specific functionality
- io: Media I/O operations
- video: Video-specific functionality
The audio module provides structures for handling audio data:
The audio::Sample
struct serves as a specialized sample structure for audio media:
pub struct Sample<Raw> {
// Private fields
}
// Implements conversions between different audio formats
impl From<i16> for Sample<i16> { /* ... */ }
impl From<f32> for Sample<f32> { /* ... */ }
impl From<Sample<i16>> for i16 { /* ... */ }
impl From<Sample<f32>> for f32 { /* ... */ }
impl From<Sample<i16>> for Sample<f32> { /* ... */ }
impl From<Sample<f32>> for Sample<i16> { /* ... */ }
// Standard traits
impl<Raw> Copy for Sample<Raw> where Raw: Copy { /* ... */ }
impl<Raw> Clone for Sample<Raw> where Raw: Clone { /* ... */ }
impl<Raw> Debug for Sample<Raw> where Raw: Debug { /* ... */ }
impl<Raw> Default for Sample<Raw> where Raw: Default { /* ... */ }
impl<Raw> PartialEq for Sample<Raw> where Raw: PartialEq { /* ... */ }
impl<Raw> Eq for Sample<Raw> where Raw: Eq { /* ... */ }
The audio::buffer::Buffer
provides functionality for multi-channel audio handling:
// Generic over both sample type (T) and layout (L)
pub struct Buffer<T, L> {
// Private fields
}
// Two primary layouts
pub struct Interleaved;
pub struct Deinterleaved;
// Layout conversion traits
impl<T: Copy> From<Buffer<T, Interleaved>> for Buffer<T, Deinterleaved> { /* ... */ }
impl<T: Copy> From<Buffer<T, Deinterleaved>> for Buffer<T, Interleaved> { /* ... */ }
// Byte manipulation trait
pub trait FromBytes<T, L, E: ByteOrder> {
fn from_bytes(bytes: &[u8], channels: usize) -> Result<Self, Error> where Self: Sized;
}
Features:
- Buffer format conversions (interleaved ↔ deinterleaved)
- Byte-level manipulation with
FromBytes
trait - Buffer reference handling with
BufferRef
The I/O module provides tools for reading and writing media streams in various formats:
The Writer
trait defines a common interface for media writers:
pub trait Writer {
fn write_rtp(&mut self, pkt: &Packet) -> Result<(), Error>;
fn close(&mut self) -> Result<(), Error>;
}
The trait is implemented by various media format writers, allowing for a unified interface across different container formats.
Multiple format-specific readers and writers:
// Reader for H.264 format
pub struct H264Reader<R: Read> {
// Private fields
}
impl<R: Read> H264Reader<R> {
pub fn new(reader: R, capacity: usize) -> H264Reader<R>;
pub fn next_nal(&mut self) -> Result<NAL, Error>;
}
// Writer for H.264 format
pub struct H264Writer<W: Write + Seek> {
// Private fields
}
impl<W: Write + Seek> Writer for H264Writer<W> {
fn write_rtp(&mut self, pkt: &Packet) -> Result<(), Error>;
fn close(&mut self) -> Result<(), Error>;
}
// Reader for IVF format
pub struct IVFReader<R: Read> {
// Private fields
}
impl<R: Read> IVFReader<R> {
pub fn new(reader: R) -> Result<(IVFReader<R>, IVFFileHeader), Error>;
pub fn reset_reader(&mut self, reset: ResetFn<R>);
pub fn parse_next_frame(&mut self) -> Result<(BytesMut, IVFFrameHeader), Error>;
}
// Writer for IVF format
pub struct IVFWriter<W: Write + Seek> {
// Private fields
}
impl<W: Write + Seek> Writer for IVFWriter<W> {
fn write_rtp(&mut self, pkt: &Packet) -> Result<(), Error>;
fn close(&mut self) -> Result<(), Error>;
}
// Writer for OGG format
pub struct OggWriter<W: Write + Seek> {
// Private fields
}
impl<W: Write + Seek> Writer for OggWriter<W> {
fn write_rtp(&mut self, pkt: &Packet) -> Result<(), Error>;
fn close(&mut self) -> Result<(), Error>;
}
The SampleBuilder
is a crucial component that buffers packets until media frames are complete:
pub struct SampleBuilder<T: Depacketizer> {
// Private fields
}
impl<T: Depacketizer> SampleBuilder<T> {
// Create a new SampleBuilder with specified parameters
pub fn new(max_late: u16, depacketizer: T, sample_rate: u32) -> Self;
// Configure maximum time delay for packet processing
pub fn with_max_time_delay(self, max_late_duration: Duration) -> Self;
// Add an RTP packet to the builder
pub fn push(&mut self, p: Packet);
// Get the next complete sample, if available
pub fn pop(&mut self) -> Option<Sample>;
// Get the next complete sample with its RTP timestamp
pub fn pop_with_timestamp(&mut self) -> Option<(Sample, u32)>;
}
SampleBuilder functionality:
- Maintains a buffer of received RTP packets
- Reconstructs complete media samples from potentially out-of-order packets
- Handles packet loss and timing information
- Configurable through parameters like maximum lateness tolerance
The video module contains specialized structures for video processing, although it appears to be less developed than the audio module at this time.
-
Creating a SampleBuilder:
let sample_builder = SampleBuilder::new( 100, // Maximum packet lateness h264_depacketizer, // Codec-specific depacketizer 90000 // RTP clock rate );
-
Handling incoming RTP packets:
// For each incoming RTP packet sample_builder.push(packet); // Check for completed samples while let Some(sample) = sample_builder.pop() { // Process the complete media sample process_media_sample(sample); }
-
Reading H.264 video:
let mut reader = H264Reader::new(file, 1024); while let Ok(nal) = reader.next_nal() { // Process NAL unit }
-
Writing to container formats:
let writer = IVFWriter::new(file, width, height, 90000); writer.write_rtp(&packet)?; // ... writer.close()?;
-
Working with audio buffers:
// Create a new interleaved audio buffer let buffer = Buffer::<i16, Interleaved>::new(samples, 2); // Stereo // Convert to deinterleaved format let deinterleaved: Buffer<i16, Deinterleaved> = buffer.into(); // Access a sub-range let segment = buffer.sub_range(0..480);
-
Converting between audio formats:
// From byte stream to audio buffer let buffer = Buffer::<i16, Interleaved>::from_bytes::<LittleEndian>(bytes, channels)?;
The webrtc_media
module provides the foundation for handling media in WebRTC applications:
-
Media packet flow:
- RTP packets are received via WebRTC data channels
- The
SampleBuilder
reconstructs complete media samples - Samples are passed to decoders or saved to files
-
Container format support:
- Media can be saved to standard container formats (H.264, IVF, OGG)
- Files can be read from these formats for streaming over WebRTC
The module provides a unified Error
enum for error handling across all operations:
#[non_exhaustive]
pub enum Error {
ErrBufferTooSmall, // Buffer too small to fit data
ErrDataIsEmpty, // Data is empty
ErrInvalidNALUHeader, // Invalid NAL unit header
ErrInvalidNALUHeaderLength, // Invalid NAL unit header length
ErrInvalidSPS, // Invalid sequence parameter set
ErrShortRead, // Incomplete read of expected data
ErrIoError(IoError), // I/O error
ErrUnimplemented, // Feature not implemented
ErrRTPInvalidH264PacketType, // Invalid H.264 packet type
ErrFailedToOpenFile, // Failed to open file
ErrDataOwnership, // Data ownership error
ErrInvalidFileFormat, // Invalid file format
// ... additional error variants
}
The Error
enum ensures consistency in error reporting throughout the media processing pipeline. It is marked as #[non_exhaustive]
to allow for future extensions without breaking compatibility.
The RTCPeerConnection
is the central component of the WebRTC API, providing methods to connect to a remote peer, maintain and monitor the connection, and establish sessions for communication. It orchestrates multiple underlying technologies (ICE, DTLS, SRTP, SCTP) to enable secure, peer-to-peer exchange of audio, video, and data.
pub struct RTCPeerConnection {
// Private fields
}
Peer connections are created through the WebRTC API factory:
let api = API::new()?;
let peer_connection = api.new_peer_connection(config).await?;
The configuration options are provided via the RTCConfiguration
struct:
pub struct RTCConfiguration {
pub ice_servers: Vec<RTCIceServer>,
pub ice_transport_policy: RTCIceTransportPolicy,
pub bundle_policy: RTCBundlePolicy,
pub rtcp_mux_policy: RTCRtcpMuxPolicy,
pub peer_identity: String,
pub certificates: Vec<Arc<dyn Certificate + Send + Sync>>,
pub icecandidatepoolsize: u8,
// Additional fields
}
Common configuration options include:
ice_servers
: STUN/TURN servers for NAT traversalice_transport_policy
: Controls which ICE candidates to usebundle_policy
: Controls media bundling behaviorcertificates
: Custom certificates for DTLS
// Create an offer to initiate connection
fn create_offer(&self, options: Option<RTCOfferOptions>) -> Result<RTCSessionDescription, Error>;
// Create an answer to respond to offer
fn create_answer(&self, options: Option<RTCAnswerOptions>) -> Result<RTCSessionDescription, Error>;
// Set local description (offer or answer)
fn set_local_description(&self, desc: RTCSessionDescription) -> Result<(), Error>;
// Set remote description from peer
fn set_remote_description(&self, desc: RTCSessionDescription) -> Result<(), Error>;
// Add remote ICE candidate
fn add_ice_candidate(&self, candidate: RTCIceCandidateInit) -> Result<(), Error>;
// Gracefully terminate connection
fn close(&self) -> Result<(), Error>;
// Current connection state
fn connection_state(&self) -> RTCPeerConnectionState;
// Current ICE gathering state
fn ice_gathering_state(&self) -> RTCIceGatheringState;
// Current ICE connection state
fn ice_connection_state(&self) -> RTCIceConnectionState;
// Current signaling state
fn signaling_state(&self) -> RTCSignalingState;
// Create data channel
fn create_data_channel(
&self,
label: &str,
options: Option<RTCDataChannelInit>
) -> Result<Arc<RTCDataChannel>, Error>;
// Detect incoming data channels
fn on_data_channel(&self, f: OnDataChannelHdlrFn) -> ();
// Add media track
fn add_track(
&self,
track: Arc<dyn TrackLocal + Send + Sync>
) -> Result<Arc<RTCRtpSender>, Error>;
// Remove media track
fn remove_track(
&self,
sender: Arc<RTCRtpSender>
) -> Result<(), Error>;
// Add transceiver for media
fn add_transceiver_from_track(
&self,
track: Arc<dyn TrackLocal + Send + Sync>,
init: Option<RTCRtpTransceiverInit>
) -> Result<Arc<RTCRtpTransceiver>, Error>;
// Add transceiver by type (audio/video)
fn add_transceiver_from_kind(
&self,
kind: RTPCodecType,
init: Option<RTCRtpTransceiverInit>
) -> Result<Arc<RTCRtpTransceiver>, Error>;
// Get transceivers
fn get_transceivers(&self) -> Vec<Arc<RTCRtpTransceiver>>;
// Handle incoming tracks
fn on_track(&self, f: OnTrackHdlrFn) -> ();
// ICE candidate generation
fn on_ice_candidate(&self, f: OnICECandidateHdlrFn) -> ();
// ICE connection state changes
fn on_ice_connection_state_change(&self, f: OnICEConnectionStateChangeHdlrFn) -> ();
// ICE gathering state changes
fn on_ice_gathering_state_change(&self, f: OnICEGatheringStateChangeHdlrFn) -> ();
// Negotiation needed
fn on_negotiation_needed(&self, f: OnNegotiationNeededHdlrFn) -> ();
// Connection state changes
fn on_peer_connection_state_change(&self, f: OnPeerConnectionStateChangeHdlrFn) -> ();
// Signaling state changes
fn on_signaling_state_change(&self, f: OnSignalingStateChangeHdlrFn) -> ();
pub enum RTCPeerConnectionState {
Unspecified,
New, // Initial state, connection created
Connecting, // ICE agent checking for connectivity
Connected, // ICE agent found viable connection
Disconnected, // ICE connection lost temporarily
Failed, // ICE connection failed permanently
Closed, // Connection closed intentionally
}
pub enum RTCSignalingState {
Unspecified,
Stable, // No SDP exchange in progress
HaveLocalOffer, // Local offer set, remote not yet
HaveRemoteOffer, // Remote offer set, local not yet
HaveLocalPranswer, // Remote offer and local provisional answer
HaveRemotePranswer, // Local offer and remote provisional answer
Closed, // Connection closed
}
pub enum RTCIceGatheringState {
Unspecified,
New, // No gathering performed yet
Gathering, // Currently gathering candidates
Complete, // Gathering finished
}
pub enum RTCIceConnectionState {
Unspecified,
New, // ICE agent created but not gathering
Checking, // ICE agent checking candidates
Connected, // ICE agent found usable connection
Completed, // ICE agent finished checking
Failed, // ICE agent tried all candidates and failed
Disconnected, // ICE connection lost
Closed, // ICE agent shut down
}
// Create peer connection
let peer_connection = api.new_peer_connection(config).await?;
// Set up event handlers
peer_connection.on_ice_candidate(Box::new(|c| {
if let Some(candidate) = c {
// Send candidate to remote peer via signaling
}
Box::pin(async {})
}));
// Add tracks or create data channels if needed
let data_channel = peer_connection.create_data_channel("example", None).await?;
// Create offer
let offer = peer_connection.create_offer(None).await?;
// Set local description
peer_connection.set_local_description(offer.clone()).await?;
// Send offer to remote peer via signaling
// ...
// When ICE candidates are received from remote peer
peer_connection.add_ice_candidate(remote_candidate).await?;
// When answer is received from remote peer
peer_connection.set_remote_description(remote_answer).await?;
// Connection will establish automatically once compatible
// candidates are found and exchanged
// Create peer connection
let peer_connection = api.new_peer_connection(config).await?;
// Set up event handlers
peer_connection.on_ice_candidate(Box::new(|c| {
if let Some(candidate) = c {
// Send candidate to remote peer via signaling
}
Box::pin(async {})
}));
// When offer is received from remote peer
peer_connection.set_remote_description(remote_offer).await?;
// Create answer
let answer = peer_connection.create_answer(None).await?;
// Set local description
peer_connection.set_local_description(answer.clone()).await?;
// Send answer to remote peer via signaling
// ...
// When ICE candidates are received from remote peer
peer_connection.add_ice_candidate(remote_candidate).await?;
// Connection will establish automatically once compatible
// candidates are found and exchanged
-
ICE Candidate Trickling: Send ICE candidates as they're discovered rather than waiting for all
-
BUNDLE and rtcp-mux: Use bundling to reduce the number of transport connections
-
ICE Candidate Filtering: Use ICE transport policy to limit candidates for specific topologies
-
SDP Munging: Avoid manual SDP modification when possible; use the API's abstractions
-
Handling Reconnection: Monitor connection state and implement reconnection logic when needed
-
Media Constraints: Properly configure media constraints based on network conditions
-
Candidate Pair Selection: Understand how candidates are selected and prioritized
The RTCPeerConnection provides a robust, standards-compliant interface for WebRTC communications, abstracting the complex underlying technologies while giving developers control over the connection process.
The webrtc_sctp
module provides Rust implementation of the Stream Control Transmission Protocol (SCTP) for WebRTC. It enables reliable, message-oriented data transport with features like congestion control, message fragmentation, and multiple streams over a single connection.
The Association
represents an SCTP association (connection) between endpoints:
pub struct Association { /* private fields */ }
Two methods for establishing an association:
Association::server(config)
- Accept an SCTP connectionAssociation::client(config)
- Open an SCTP connection
An Association
is configured using the Config
struct:
pub struct Config {
pub net_conn: Arc<dyn Conn + Send + Sync>,
pub max_receive_buffer_size: u32,
pub max_message_size: u32,
pub name: String,
}
open_stream(stream_identifier, default_payload_type)
- Creates a new streamaccept_stream()
- Accepts incoming streamshutdown()
- Initiates graceful shutdownclose()
- Ends association and cleans up resourcesbytes_sent()
/bytes_received()
- Get byte count statistics
The Stream
represents a bi-directional channel for sending/receiving data within an association:
pub struct Stream { /* private fields */ }
read(p)
/read_sctp(p)
- Read data from streamwrite(p)
/write_sctp(p, ppi)
- Write data to streamshutdown(how)
- Shutdown read, write or both halvesstream_identifier()
- Get the stream's identifierset_reliability_params(unordered, rel_type, rel_val)
- Configure reliability
SCTP streams can have different reliability modes:
pub enum ReliabilityType {
Reliable = 0, // Reliable transmission
Rexmit = 1, // Partial reliability by retransmission count
Timed = 2, // Partial reliability by retransmission duration
}
// Create an association
let config = Config {
net_conn: /* a connection implementation */,
max_receive_buffer_size: 65536,
max_message_size: 65536,
name: "example-sctp".to_string(),
};
// Server mode
let association = Association::server(config).await?;
// Client mode
let association = Association::client(config).await?;
// Open a stream
let stream = association.open_stream(
1, // stream ID
PayloadProtocolIdentifier::Binary
).await?;
// Configure reliability
stream.set_reliability_params(
false, // ordered
ReliabilityType::Reliable,
0 // reliability value
);
// Write data
stream.write(&bytes).await?;
// Read data
let bytes_read = stream.read(&mut buffer).await?;
// Shutdown the stream
stream.shutdown(std::net::Shutdown::Both).await?;
// Close the association
association.close().await?;
- Associations: SCTP connections between endpoints
- Streams: Independent bi-directional channels within an association
- Reliability Types: Different reliability guarantees for message delivery
- Payload Protocol Identifiers: Indicate the type of data being transferred
This implementation provides a comprehensive Rust API for SCTP communication in WebRTC applications, supporting both reliable and partially reliable data transmission modes.
The webrtc_srtp
module implements the Secure Real-time Transport Protocol (SRTP), which provides encryption, message authentication, and replay protection for RTP and RTCP packets. It enables secure media transport in WebRTC applications.
Specifies cipher and authentication tag details, similar to TLS cipher suites:
#[repr(u8)]
pub enum ProtectionProfile {
Aes128CmHmacSha1_80 = 1, // AES-CM with 80-bit HMAC-SHA1
Aes128CmHmacSha1_32 = 2, // AES-CM with 32-bit HMAC-SHA1
AeadAes128Gcm = 7, // AEAD AES-128 GCM
AeadAes256Gcm = 8, // AEAD AES-256 GCM
}
impl ProtectionProfile {
pub fn key_len(&self) -> usize
pub fn salt_len(&self) -> usize
pub fn rtp_auth_tag_len(&self) -> usize
pub fn rtcp_auth_tag_len(&self) -> usize
pub fn aead_auth_tag_len(&self) -> usize
pub fn auth_key_len(&self) -> usize
}
Each profile provides methods to determine key length, salt length, and authentication tag lengths for both RTP and RTCP.
Used to configure an SRTP session:
pub struct Config {
pub keys: SessionKeys, // Session keys for encryption/decryption
pub profile: ProtectionProfile, // Selected protection profile
pub local_rtp_options: Option<ContextOption>, // Options for local RTP context
pub remote_rtp_options: Option<ContextOption>, // Options for remote RTP context
pub local_rtcp_options: Option<ContextOption>, // Options for local RTCP context
pub remote_rtcp_options: Option<ContextOption>, // Options for remote RTCP context
}
impl Config {
// Extract session keys from DTLS connection (RFC5764)
pub async fn extract_session_keys_from_dtls(
&mut self,
exporter: impl KeyingMaterialExporter,
is_client: bool,
) -> Result<(), Error>
}
impl Default for Config {}
Provides a bidirectional SRTP session implementing I/O operations:
pub struct Session { /* private fields */ }
impl Session {
// Create a new SRTP session
pub async fn new(
conn: Arc<dyn Conn + Send + Sync>, // Network connection
config: Config, // SRTP configuration
is_rtp: bool, // Whether this is an RTP (true) or RTCP (false) session
) -> Result<Self, Error>
// Open a stream for a specific SSRC
pub async fn open(&self, ssrc: u32) -> Arc<Stream>
// Accept incoming packets and create a stream
pub async fn accept(&self) -> Result<(Arc<Stream>, Option<Header>), Error>
// Close the session and clean up resources
pub async fn close(&self) -> Result<(), Error>
// Write a raw buffer as either RTP or RTCP
pub async fn write(&self, buf: &Bytes, is_rtp: bool) -> Result<usize, Error>
// Encrypt and send an RTP packet
pub async fn write_rtp(&self, pkt: &Packet) -> Result<usize, Error>
// Encrypt and send an RTCP packet
pub async fn write_rtcp(
&self,
pkt: &(dyn Packet + Send + Sync),
) -> Result<usize, Error>
}
Handles encryption/decryption for a single RTP/RTCP stream identified by SSRC:
pub struct Stream { /* private fields */ }
impl Stream {
// Create a new stream with specified SSRC
pub fn new(ssrc: u32, tx: Sender<u32>, is_rtp: bool) -> Self
// Get the SSRC associated with this stream
pub fn get_ssrc(&self) -> u32
// Check if this is an RTP stream (as opposed to RTCP)
pub fn is_rtp_stream(&self) -> bool
// Read and decrypt a raw packet
pub async fn read(&self, buf: &mut [u8]) -> Result<usize, Error>
// Read and decrypt an RTP packet
pub async fn read_rtp(&self, buf: &mut [u8]) -> Result<Packet, Error>
// Read and decrypt RTCP packet(s)
pub async fn read_rtcp(
&self,
buf: &mut [u8],
) -> Result<Vec<Box<dyn Packet + Send + Sync>>, Error>
// Close the stream and clean up resources
pub async fn close(&self) -> Result<(), Error>
}
impl Debug for Stream {}
- Create a
Config
with appropriate protection profile and keys- Either provide keys directly or extract from DTLS with
extract_session_keys_from_dtls
- Either provide keys directly or extract from DTLS with
- Create a
Session
using the config and network connection - Either:
- Call
open
to create a stream for sending/receiving with specific SSRC - Use
accept
to accept incoming packets and create streams dynamically
- Call
- Use the resulting
Stream
objects to read/write encrypted RTP/RTCP data
- Multiple cipher suite options with varying security levels
- Replay protection with configurable window size
- Authentication tag validation
- Secure key derivation from DTLS
The module integrates with WebRTC's transport layers to provide secure media communication with minimal overhead.
The webrtc_util
module provides a collection of utility components and abstractions that support the WebRTC implementation in Rust. This module includes network connection abstractions, buffer handling, marshaling/unmarshaling utilities, replay protection, synchronization primitives, and virtual networking capabilities.
The Buffer struct provides a thread-safe, size-limited buffer for handling binary data in WebRTC applications:
- Manages packet data with configurable limits for both count and size
- Thread-safe for concurrent read/write operations
- Supports asynchronous read and write operations with optional timeouts
- Handles buffer overflow and closure conditions
- Provides methods for monitoring buffer state (count, size, closed status)
Example usage:
// Create a buffer with max 100 packets and 1MB size limit
let buffer = Buffer::new(100, 1024 * 1024);
// Write data to the buffer
buffer.write(&packet_data).await?;
// Read data with a timeout
let mut buf = vec![0; 1500];
let bytes_read = buffer.read(&mut buf, Some(Duration::from_secs(1))).await?;
// Close the buffer
buffer.close().await;
The conn
module provides abstractions for network connections with an async-friendly API:
Conn
trait defines the common interface for network connections- Supports both connected and connection-less UDP operations
- Native implementation for the standard library's
UdpSocket
- Custom implementations like
DisconnectedPacketConn
for specific use cases - Helper functions like
lookup_host
for DNS resolution
Key components:
-
Conn
trait: Defines a common interface for network connections with methods:async connect(&self, addr: SocketAddr) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
async recv(&self, buf: &mut [u8]) -> Pin<Box<dyn Future<Output = Result<usize>> + Send + 'async_trait>>
async recv_from(&self, buf: &mut [u8]) -> Pin<Box<dyn Future<Output = Result<(usize, SocketAddr)>> + Send + 'async_trait>>
async send(&self, buf: &[u8]) -> Pin<Box<dyn Future<Output = Result<usize>> + Send + 'async_trait>>
async send_to(&self, buf: &[u8], target: SocketAddr) -> Pin<Box<dyn Future<Output = Result<usize>> + Send + 'async_trait>>
local_addr(&self) -> Result<SocketAddr>
remote_addr(&self) -> Option<SocketAddr>
async close(&self) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
as_any(&self) -> &(dyn Any + Send + Sync)
-
Listener
trait: Abstracts connection listening and accepting with methods:async accept(&self) -> Pin<Box<dyn Future<Output = Result<(Arc<dyn Conn + Send + Sync>, SocketAddr)>> + Send + 'async_trait>>
addr(&self) -> Result<SocketAddr>
async close(&self) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
The marshal module provides traits for serializing and deserializing data structures:
-
Marshal
: For serializing data structures to binary formatmarshal_to(&self, buf: &mut [u8]) -> Result<usize>
marshal(&self) -> Result<Vec<u8>>
-
Unmarshal
: For deserializing binary data into structured typesunmarshal<T>(data: &[u8]) -> Result<T>
-
MarshalSize
: For determining the binary size of data structuresmarshal_size(&self) -> usize
-
ExactSizeBuf
: Helper trait for exact-size binary buffers
These traits are used throughout the WebRTC stack for encoding and decoding protocol messages.
The replay_detector
module provides mechanisms to detect and prevent replay attacks:
-
ReplayDetector
trait: Common interface for replay protectioncheck(&mut self, seq: u64) -> bool
fail(&mut self, seq: u64)
-
NoOpReplayDetector
: A no-operation implementation for testing -
SlidingWindowDetector
: A sliding window algorithm implementation -
WrappedSlidingWindowDetector
: Handles sequence number wrapping
These components are essential for securing media streams and preventing attackers from replaying previously captured packets.
The sync
module provides thread synchronization primitives that are tailored for WebRTC's needs:
Mutex
: A mutual exclusion primitive for protecting shared dataRwLock
: A reader-writer lock for efficient concurrent access patterns- Associated guard types for RAII-style locking
These primitives provide abstractions over platform-specific synchronization mechanisms.
The vnet
module provides a virtual network implementation for testing WebRTC components without using actual network interfaces:
net
: Virtual network implementationrouter
: Virtual router for packet routinginterface
: Network interface abstractionsnat
: NAT traversal simulationschunk
: Data chunking utilities
This module is particularly useful for testing WebRTC applications in controlled environments and simulating various network conditions.
The KeyingMaterialExporter
trait provides functionality for extracting keying material from cryptographic contexts:
async export_keying_material<'life0, 'life1, 'life2, 'async_trait>(&'life0 self, label: &'life1 str, context: &'life2 [u8], length: usize) -> Pin<Box<dyn Future<Output = Result<Vec<u8>, KeyingMaterialExporterError>> + Send + 'async_trait>>
This trait is used for:
- Generating symmetric keys for SRTP and other secure protocols
- Decoupling DTLS and SRTP components to avoid direct dependencies
The module uses a comprehensive error type (Error
) that covers various failure scenarios:
- Network-related errors (connection, addressing)
- Buffer-related errors (full, closed, too short)
- Parsing errors (IP addresses, integers)
- Virtual network errors
- I/O errors
The webrtc_util
module serves as foundation for other WebRTC components:
- Provides network abstractions used by ICE, DTLS, and other transport protocols
- Offers buffering mechanisms used in media transport
- Implements serialization/deserialization for protocol messages
- Enables secure key derivation for encrypted communications
- Facilitates testing through virtual network components
The utilities in this module are typically used in these scenarios:
- Network communication in WebRTC stacks
- Protocol message serialization and deserialization
- Media packet buffering and flow control
- Security key derivation and management
- Thread-safe state management
- Testing and simulation
Most of the APIs in this module are designed with asynchronous programming in mind:
- Async/await support for network operations
- Future-based APIs that integrate with async runtimes like Tokio
- Thread-safe primitives for concurrent access
Components in this module are generally designed to be thread-safe:
Buffer
uses internal synchronization for thread-safe operationsMutex
andRwLock
provide explicit synchronization primitives- Connection implementations are typically shareable across threads
- Thread-safe error handling
The webrtc_util
module provides essential utilities that form the foundation of the WebRTC implementation in Rust. By abstracting common operations like network communication, serialization, buffering, and synchronization, it enables other WebRTC components to focus on their specific protocol implementations rather than reinventing these fundamental building blocks.