Skip to main content

Crate librice

Crate librice 

Source
Expand description

§librice

An async implementation based on rice-proto using the rice-c bindings.

§Relevant standards

  • RFC5245: Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols
  • RFC5389: Session Traversal Utilities for NAT (STUN)
  • RFC5766: Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN)
  • RFC5769: Test Vectors for Session Traversal Utilities for NAT (STUN)
  • RFC6062: Traversal Using Relays around NAT (TURN) Extensions for TCP Allocations
  • RFC6156: Traversal Using Relays around NAT (TURN) Extension for IPv6
  • RFC6544: TCP Candidates with Interactive Connectivity Establishment (ICE)
  • RFC7675: Session Traversal Utilities for NAT (STUN) Usage for Consent Freshness
  • RFC8445: Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal
  • RFC8489: Session Traversal Utilities for NAT (STUN)
  • RFC8656: Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN)
  • RFC8838: Trickle ICE: Incremental Provisioning of Candidates for the Interactive Connectivity Establishment (ICE) Protocol

§Building

librice has the same build requirements as rice-c and the crate level documentation for rice-c provides guidelines on how to build rice-c and projects that depend on rice-c.

§Example

use core::net::SocketAddr;
use futures::stream::StreamExt;
use librice::agent::{Agent, AgentMessage};
use librice::stream::Credentials;
use librice::candidate::{Candidate, CandidateType, TransportType};

let agent = Agent::default();
// Configure the agent as you wish.
// e.g. add a stun server.
// agent.add_stun_server(TransportType::Udp, SocketAddr::new([192, 168, 0, 1], 3478));

// Add a stream and component within that stream for data flow.
let stream = agent.add_stream();
let local_credentials = Credentials::new("luser", "lpass");
stream.set_local_credentials(&local_credentials);
let component = stream.add_component().unwrap();

// At some point you will also need the remote credentials to be able to successfully connect
// with the peer. If trickle-ice, then this can occur during candidate gathering, otherwise,
// should occur before the remote candidates are added to the agent.
let remote_credentials = Credentials::new("ruser", "rpass");
stream.set_local_credentials(&remote_credentials);

// Retrieve the receive end of a message queue that indicates gathering state, component state,
// and other such messages.
let mut messages = agent.messages();

// start gathering candidates.
stream.gather_candidates().await.unwrap();

while let Some(msg) = messages.next().await {
   match msg {
       AgentMessage::GatheredCandidate(stream, gathered) => {
            // based on local policy, you can choose to never add the locally gathered
            // candidate to the stream to avoid using a candidate for connectivity checks later.
            stream.add_local_gathered_candidate(gathered);
            // For trickle-ice handling, you would send the gathered candidate to the peer.
        }
        AgentMessage::GatheringComplete(component) => {
            // For non trickle-ice handling, if all relevant components in a stream have
            // completed gathering, you would retrieve the list of local candidates
            // and send that to the peer along with any other setup information required.
            println!("component {} has completed gathering", component.id());
            let stream = component.stream();
            for cand in stream.local_candidates() {
                println!(
                    "stream {} has gathered local candidate {}",
                    stream.id(),
                    cand.to_sdp_string()
                );
            }
            break;
        }
        AgentMessage::ComponentStateChange(component, new_state) => {
            println!("component {} has changed state to {new_state:?}", component.id());
        },
   }
}

// On receiving remote candidates from the peer you would add them to the agent in order to
// start connectivity checks.
stream.add_remote_candidate(&remote_candidate);

// Once the complete set of remote candidates have been received, then notify the agent of
// this.
stream.end_of_remote_candidates();

// connectivity checks will progress and either a successful pair (the selected pair) will be
// found, or failure will be signaled for the component's connection state.
// while let Some(msg) = messages.next().await {
//     match msg {
//         ...
//     }
// }

// once a selected pair is chosen, data can be received.
let recv = component.recv();
// and sent
component.send([1, 2, 3, 4].as_slice()).await;

Modules§

agent
ICE Agent implementation as specified in RFC 8445
candidate
ICE Candidates
component
A Component in an ICE Stream
runtime
Async runtime abstraction
socket
Socket helpers for handling UDP and TCP transports
stream
An ICE Stream

Structs§

Address
A network address.

Enums§

AddressFamily
The family of an address.
Feature
A feature.
IntegrityAlgorithm
The supported authentication mechanisms.

Functions§

random_string
Generate a random sequence of characters suitable for username fragments and passwords.