#web-rtc #peer #remote-peer #networking #p2p #wasm

just-webrtc

Just simple, fast and easy WebRTC peers for both native and wasm

3 unstable releases

0.2.0 Sep 30, 2024
0.1.1 Mar 30, 2024
0.1.0 Mar 29, 2024

#1897 in Network programming

MIT/Apache

65KB
1K SLoC

Just WebRTC

crates.io documentation license build status

Just simple, fast and easy WebRTC peers in Rust.

Supports WebRTC on both native and wasm32 targets, with an identical API for both.

just-webrtc is modular, only including WebRTC types and implementations. No signalling here!

Roll your own signalling setup, or use the ready-made standard signalling client/server at just-webrtc-signalling

... Maybe WebRTC can be easy?

[dependencies]
just-webrtc = "0.2"

Documentation

See docs.rs for the complete API reference.

Examples

This basic example creates a 'local' and a 'remote' peer with a single data channel.

See the data_channels test for a compiling version of this example.

For complete examples, including signalling, see the Examples in the repository.

Peer A - Local peer (creates the local peer from configuration):

Note: "local peer" is WebRTC-speak for the initial peer that creates the offer. Internally this peer is also referred to as the "offerer"

use anyhow::Result;
use just_webrtc::{
    DataChannelExt,
    PeerConnectionExt,
    SimpleLocalPeerConnection,
    types::{SessionDescription, ICECandidate, PeerConnectionState}
};

async fn run_local_peer() -> Result<()> {
    // create simple local peer connection with unordered data channel
    let local_peer_connection = SimpleLocalPeerConnection::build(false).await?;

    // output offer and candidates for remote peer
    let offer = local_peer_connection.get_local_description().await.unwrap();
    let candidates = local_peer_connection.collect_ice_candidates().await?;

    // ... send the offer and the candidates to Peer B via external signalling implementation ...
    let signalling = (offer, candidates);

    // ... receive the answer and candidates from Peer B via external signalling implementation ...
    let (answer, candidates) = signalling;

    // update local peer from received answer and candidates
    local_peer_connection.set_remote_description(answer).await?;
    local_peer_connection.add_ice_candidates(candidates).await?;

    // local signalling is complete! we can now wait for a complete connection
    while local_peer_connection.state_change().await != PeerConnectionState::Connected {}

    // receive data channel from local peer
    let local_channel = local_peer_connection.receive_channel().await.unwrap();
    // wait for data channels to be ready
    local_channel.wait_ready().await;

    // send data to remote (answerer)
    local_channel.send(&bytes::Bytes::from("hello remote!")).await?;
    // recv data from remote (answerer)
    let recv = local_channel.receive().await.unwrap();
    assert_eq!(&recv, "hello local!");

    Ok(())
}

Peer B - Remote peer (creates the remote peer from a received offer):

Note: "remote peer" is WebRTC-speak for the peer that receives an offer from the "local peer". Internally this peer is also referred to as the "answerer"

use anyhow::Result;
use just_webrtc::{
    DataChannelExt,
    PeerConnectionExt,
    SimpleRemotePeerConnection,
    types::{SessionDescription, ICECandidate, PeerConnectionState}
};

async fn run_remote_peer(offer: SessionDescription, candidates: Vec<ICECandidate>) -> Result<()> {
    // ... receive the offer and the candidates from Peer A via external signalling implementation ...

    // create simple remote peer connection from received offer and candidates
    let remote_peer_connection = SimpleRemotePeerConnection::build(offer).await?;
    remote_peer_connection.add_ice_candidates(candidates).await?;
    // output answer and candidates for local peer
    let answer = remote_peer_connection.get_local_description().await.unwrap();
    let candidates = remote_peer_connection.collect_ice_candidates().await?;

    // ... send the answer and the candidates back to Peer A via external signalling implementation ...
    let _signalling = (answer, candidates);

    // remote signalling is complete! we can now wait for a complete connection
    while remote_peer_connection.state_change().await != PeerConnectionState::Connected {}

    // receive data channel from local and remote peers
    let remote_channel = remote_peer_connection.receive_channel().await.unwrap();
    // wait for data channels to be ready
    remote_channel.wait_ready().await;

    // send/recv data from local (offerer) to remote (answerer)
    let recv = remote_channel.receive().await.unwrap();
    assert_eq!(&recv, "hello remote!");
    // send/recv data from remote (answerer) to local (offerer)
    remote_channel.send(&bytes::Bytes::from("hello local!")).await?;

    Ok(())
}

License

This project is licensed under either of

at your option.

Dependencies

~0.8–18MB
~251K SLoC