Crate wrtc

source ·
Expand description

wrtc is a crate which wraps a webrtc library into simpler, more friendly API:

  • It offers semi-automatic connection negotiation via signal exchange.
  • It’s build around async Rust.
  • Its primitives implement Stream trait, making them composable and reducing the amount of closures and capturing that webrtc crate requires.

Its design is partially inspired by NodeJS SimplePeer library and it offers the same message negotiation format: therefore it can be used to communicate with WebRTC peers written in that library as well.

Atm. this library is focused on Data Channels - other WebRTC primitives may be implemented in the future.

Examples

use wrtc::{Options, Error, PeerConnection};
use std::sync::Arc;
use bytes::Bytes;
use futures_util::{SinkExt, StreamExt};
use tokio::task::JoinHandle;

fn exchange(from: Arc<PeerConnection>, to: Arc<PeerConnection>) -> JoinHandle<Result<(), Error>> {
    // Create a task that will exchange signals between two peers
    // necessary to negotiate and establish connection. This part
    // is not covered by WebRTC and may require setting up a 3rd
    // party connection ie. via WebSockets.
    tokio::spawn(async move {
        while let Some(signal) = from.signal().await {
            to.apply_signal(signal).await?;
        }
        Ok(())
    })
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    let options = Options::with_data_channels(&["test-dc"]);
    let initiator = Arc::new(PeerConnection::start(true, options.clone()).await?);
    let acceptor = Arc::new(PeerConnection::start(false, options).await?);

    // setup tasks to negotiate connection between two peers
    let _ = exchange(initiator.clone(), acceptor.clone());
    let _ = exchange(acceptor.clone(), initiator.clone());

    // wait for connection become established
    initiator.connected().await?;
    acceptor.connected().await?;

    {
        // both connections have defined only one data channel ("test-dc")
        // so we know that the next incoming data channels belong to the same pair
        let mut dc1 = initiator.data_channels().next().await.unwrap();
        let mut dc2 = acceptor.data_channels().next().await.unwrap();

        // wait for the data channels to be ready
        dc1.ready().await?;
        dc2.ready().await?;

        assert_eq!(dc1.label(), "test-dc");
        assert_eq!(dc2.label(), "test-dc");

        // send message from dc1 and receive it at dc2
        let data: Bytes = "hello".into();
        dc1.send(data.clone()).await?;
        let msg = dc2.next().await.unwrap()?;
        assert_eq!(msg.data, data);
    }

    // gracefully close both peers
    initiator.close().await?;
    acceptor.close().await?;
    Ok(())
}

Re-exports

Modules