| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Sans-I/O WebRTC implementation in Rust
Sponsored with 💖 by
Silver Sponsors:
Bronze Sponsors:
AdrianEddy
RTC is a pure Rust implementation of WebRTC using a sans-I/O architecture. Unlike traditional WebRTC libraries, RTC separates protocol logic from I/O operations, giving you complete control over networking, threading, and async runtime integration.
Sans-I/O (without I/O) is a design pattern where the library handles protocol logic but you control all I/O operations. Instead of the library performing network reads and writes directly, you feed it network data and it tells you what to send.
Benefits:
The sans-I/O architecture uses a simple event loop with six core methods:
Additional methods for external control:
use rtc::peer_connection::RTCPeerConnection;
use rtc::peer_connection::configuration::RTCConfigurationBuilder;
use rtc::peer_connection::event::{RTCPeerConnectionEvent, RTCTrackEvent};
use rtc::peer_connection::state::RTCPeerConnectionState;
use rtc::peer_connection::message::RTCMessage;
use rtc::peer_connection::sdp::RTCSessionDescription;
use rtc::shared::{TaggedBytesMut, TransportContext, TransportProtocol};
use rtc::sansio::Protocol;
use std::time::{Duration, Instant};
use tokio::net::UdpSocket;
use bytes::BytesMut;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Setup peer connection
let config = RTCConfigurationBuilder::new().build();
let mut pc = RTCPeerConnection::new(config)?;
// Signaling: Create offer and set local description
let offer = pc.create_offer(None)?;
pc.set_local_description(offer.clone())?;
// TODO: Send offer.sdp to remote peer via your signaling channel
// signaling_channel.send_offer(&offer.sdp).await?;
// TODO: Receive answer from remote peer via your signaling channel
// let answer_sdp = signaling_channel.receive_answer().await?;
// let answer = RTCSessionDescription::answer(answer_sdp)?;
// pc.set_remote_description(answer)?;
// Bind UDP socket
let socket = UdpSocket::bind("0.0.0.0:0").await?;
let local_addr = socket.local_addr()?;
let mut buf = vec![0u8; 2000];
'EventLoop: loop {
// 1. Send outgoing packets
while let Some(msg) = pc.poll_write() {
socket.send_to(&msg.message, msg.transport.peer_addr).await?;
}
// 2. Handle events
while let Some(event) = pc.poll_event() {
match event {
RTCPeerConnectionEvent::OnConnectionStateChangeEvent(state) => {
println!("Connection state: {state}");
if state == RTCPeerConnectionState::Failed {
return Ok(());
}
}
RTCPeerConnectionEvent::OnTrack(RTCTrackEvent::OnOpen(init)) => {
println!("New track: {}", init.track_id);
}
_ => {}
}
}
// 3. Handle incoming messages
while let Some(message) = pc.poll_read() {
match message {
RTCMessage::RtpPacket(track_id, packet) => {
println!("RTP packet on track {track_id}");
}
RTCMessage::DataChannelMessage(channel_id, msg) => {
println!("Data channel message");
}
_ => {}
}
}
// 4. Handle timeouts
let timeout = pc.poll_timeout()
.unwrap_or(Instant::now() + Duration::from_secs(86400));
let delay = timeout.saturating_duration_since(Instant::now());
if delay.is_zero() {
pc.handle_timeout(Instant::now())?;
continue;
}
// 5. Multiplex I/O
tokio::select! {
_ = stop_rx.recv() => {
break 'EventLoop,
}
_ = tokio::time::sleep(delay) => {
pc.handle_timeout(Instant::now())?;
}
Ok(message) = message_rx.recv() => {
pc.handle_write(message)?;
}
Ok(event) = event_rx.recv() => {
pc.handle_event(event)?;
}
Ok((n, peer_addr)) = socket.recv_from(&mut buf) => {
pc.handle_read(TaggedBytesMut {
now: Instant::now(),
transport: TransportContext {
local_addr,
peer_addr,
ecn: None,
transport_protocol: TransportProtocol::UDP,
},
message: BytesMut::from(&buf[..n]),
})?;
}
}
}
pc.close()?;
Ok(())
}The repository includes comprehensive examples demonstrating various use cases:
Run an example:
cargo run --example data-channels-answerRTC is built from composable crates, each implementing a specific protocol:
RTC
Media
Interceptor
DataChannel
RTP
RTCP
SRTP
SCTP
DTLS
mDNS
STUN
TURN
ICE
SDP
Shared
use rtc::data_channel::RTCDataChannelInit;
fn example(mut pc: RTCPeerConnection) -> Result<(), Box<dyn std::error::Error>> {
// Create a data channel
let init = RTCDataChannelInit {
ordered: true,
max_retransmits: None,
..Default::default()
};
let mut dc = pc.create_data_channel("my-channel", Some(init))?;
// Send data
dc.send_text("Hello, WebRTC!")?;
Ok(())
}use rtc::media_stream::MediaStreamTrack;
use rtc::rtp_transceiver::rtp_sender::{RTCRtpCodec, RtpCodecKind};
fn example(mut pc: RTCPeerConnection) -> Result<(), Box<dyn std::error::Error>> {
// Create a video track
let track = MediaStreamTrack::new(
"stream-id".to_string(),
"track-id".to_string(),
"Camera".to_string(),
RtpCodecKind::Video,
vec![RTCRtpEncodingParameters {
rtp_coding_parameters: RTCRtpCodingParameters {
ssrc: Some(ssrc),
..Default::default()
},
codec: RTCRtpCodec::default(),
..Default::default()
}],
);
// Add to peer connection
let sender_id = pc.add_track(track)?;
Ok(())
}WebRTC requires an external signaling channel (e.g., WebSocket, HTTP) to exchange offers and answers:
fn example(mut pc: RTCPeerConnection) -> Result<(), Box<dyn std::error::Error>> {
// Create and send offer
let offer = pc.create_offer(None)?;
pc.set_local_description(offer.clone())?;
// Send offer.sdp via your signaling channel
// Receive and apply answer
// let answer = receive_answer_from_signaling()?;
// pc.set_remote_description(answer)?;
Ok(())
}This implementation follows these specifications:
# Build the library
cargo build
# Run tests
cargo test
# Build documentation
cargo doc --open
# Run examples
cargo run --example data-channels-answerThis project follows Semantic Versioning:
While the version is 0.x, the minor version acts as the major — i.e., a minor bump may include breaking changes. Once 1.0.0 is released, full semver stability guarantees apply.
Pre-release versions are published with the following suffixes, in order of increasing stability:
For example: 1.0.0-alpha.1 → 1.0.0-beta.1 → 1.0.0-rc.1 → 1.0.0.
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under either of:
at your option.
Special thanks to all contributors and the WebRTC-rs community for making this project possible.
| Back | FazBrowse Home | New Git URL |