A pure Rust implementation of WebRTC API

Overview

WebRTC.rs

License: MIT Discord Twitter

A pure Rust implementation of WebRTC stack. Rewrite Pion WebRTC stack (http://Pion.ly) in Rust

Sponsored with 💖 by

Stream Chat embark

Roadmap

WebRTC.rs

Work in Progress Towards 1.0

Contributors or pull requests are welcome!

Comments
  • Add method to delete `allocation` by `username`

    Add method to delete `allocation` by `username`

    Synopsis

    We are currently trying to replace Coturn with this implementation. But currently it does not have alternatives to specific Coturn's functionality e.g. providing metrics, TCP fallback, external management capabilities. So we want to elaborate on that starting with exposing some management interfaces.

    Here is the Coturn's telnet protocol for reference:

    TURN Server
    Coturn-4.5.2 'dan Eider'
    
      ?, h, help - print this text
    
      quit, q, exit, bye - end CLI session
    
      stop, shutdown, halt - shutdown TURN Server
    
      pc - print configuration
    
      sr <realm> - set CLI session realm
    
      ur - unset CLI session realm
    
      so <origin> - set CLI session origin
    
      uo - unset CLI session origin
    
      tc <param-name> - toggle a configuration parameter
         (see pc command output for togglable param names)
    
      cc <param-name> <param-value> - change a configuration parameter
         (see pc command output for changeable param names)
    
      ps [username] - print sessions, with optional exact user match
    
      psp <usernamestr> - print sessions, with partial user string match
    
      psd <file-name> - dump ps command output into file on the TURN server system
    
      pu [udp|tcp|dtls|tls]- print current users
    
      lr - log reset
    
      aas ip[:port} - add an alternate server reference
      das ip[:port] - delete an alternate server reference
      atas ip[:port] - add a TLS alternate server reference
      dtas ip[:port] - delete a TLS alternate server reference
    
      cs <session-id> - cancel session, forcefully
    
    

    The particular function that we need is being able to forcefully close specific allocations.

    Solution

    Add the ability to communicate with the applications main loop, running in the Server::read_loop() method.

    Add Server.delete_allocations_by_username(&self, username: String) function.

    Also, there are some low-hanging fruits in terms of optimizations, so this pull request includes minor refactoring aimed at improving overall performance.

    opened by logist322 17
  • Project roadmap

    Project roadmap

    Hi, first of all, I am a Pion lover. It's great to see movement in the Rust world. Since this project is very recent, how serious is this project? I am planning long-term for some of our software components. Rust might be valuable for us but we need WebRTC support. So don't get my question offensive in any way. Just curious if this is something I could base our stack on in the future.

    Cheers Chris

    opened by chrisprobst 17
  • Fix datachannel id setting for 0.5.0 release

    Fix datachannel id setting for 0.5.0 release

    Per comments here, this prevents a RTCDataChannel id from updating on open unless a) the value was not negotiated, and b) the value is equal to zero (i.e., the null value by existing crate convention). This fixes most of the existing error cases and does not introduce new ones. It does, however, miss one specific case (where a user creates a non-negotiated data channel with id = 0). Fixing that case would be a sizeable refactor. There is a TODO comment for addressing it.

    opened by stuqdog 16
  • sctp: allow partial reads

    sctp: allow partial reads

    This PR modifies read behaviour to permit partial reads and no longer return ErrShortBuffer if the buffer is too small to fit a whole message. The buffer will be filled up to its size and the rest of the msg will be returned upon the next call to read.

    Closes #273

    opened by melekes 15
  • File descriptor (socket) leak

    File descriptor (socket) leak

    Sockets opened in ICEGatherer seem to be leaked. They will never be closed even when the PeerConnections are closed. Finally, my server becomes unavailable with too many open files error.

    I've investigated into webrtc's source code, and found that CandidateBase.close() is an no-op. Of course, it is because tokio's UdpSocket does not provide close(). Despite all, the sockets should be closed when it is dropped. Therefore, I guess that the socket is not dropped.

    RTCPeerConnection holds Arc<PeerConnectionInternal> and there are other holders too. In v0.2.1, the peerconnection has no problem, dropped well. However, other holders seems not to drop it. I have no idea where the others are, but internal_rtcp_writer (peer_connection.rs, line 170) or pci (peer_connection.rs, line 1163, 1345, 1393) may have created reference cycle.

    If possible, those references should be replaced by std::sync::Weak to break the cycle. Pion or other webrtc libraries written in garbage-collected languages may not suffer from this issue because the GC can detect and free those circular references well. Because Rust does not have one, we should use weak references to avoid this problem. It will also fix other memory leaks too.

    opened by qbx2 14
  • Udp connection not close (reopen #174)

    Udp connection not close (reopen #174)

    hi

    This is an issue reopen from 174, as state before the code below will leave some socket unreleased in the task/thread/process

    let pc = peer_connection.clone();
    peer_connection
            .on_peer_connection_state_change(Box::new(move |s: RTCPeerConnectionState| {
                info!("Peer Connection State has changed: {}", s);
                let is_failed = s == RTCPeerConnectionState::Failed;
                let pc1 = pc.clone();
                Box::pin(async move {
                    if is_failed {
                        pc1.close().await.ok();
                    }
                })
            }))
            .await;
    

    So I try to make it async way, as it did get fixed, for some time

        let (box_sdr, mut box_rcvr) = tokio::sync::mpsc::channel::<VCError>(1);
        peer_connection
            .on_peer_connection_state_change(Box::new(move |s: RTCPeerConnectionState| {
                info!("Peer Connection State has changed: {}", s);
                let is_failed = s == RTCPeerConnectionState::Failed;
                if is_failed {
                    info!("Peer Connection has gone to failed");
                }
                let box_sdr = box_sdr.clone();
                Box::pin(async move {
                    if is_failed {
                        box_sdr.send(VCError::biz("Connection failed", 10)).await;
                    }
                })
            }))
            .await;
    
        let peer_connection = peer_connection.clone();
        rt::spawn(async move {
            loop {
                let box_result = box_rcvr.try_recv();
                if box_result.is_ok() {
                    tokio::time::sleep(Duration::from_secs(8)).await;
                    peer_connection.close().await;
                    break;
                } 
                tokio::time::sleep(Duration::from_secs(4)).await;
            }
        });
    

    But when the task went heavy and cpu get big burden, say, 50 rtc jobs delivering large bitrate stream, I found the issue reappear from time to time. Leaving udp sockets unreleased.

    I have one audio tranceiver channel, one video tranceiver channel and a data channel initialized from client side, the task get notified(started) after data channel is established. Every event handler of the peer_connection are independent, which means they are not chained. After some log working, I am pretty sure all the data I created are dropped. So once more I need some help here, just like the error before, maybe there's some cons I need to watch out?

    Maybe there's other part I neglected? Hope you could help.

    bug 
    opened by shiqifeng2000 12
  • How to create an RTCSessionDescription structure?

    How to create an RTCSessionDescription structure?

    Hi there,

    I'm trying to get webrtc-rs to interact with the browser-webrtc available in web_sys.RtcPeerConnection. I started with the example here:

    https://github.com/webrtc-rs/examples/blob/5a0e2861c66a45fca93aadf9e70a5b045b26dc9e/examples/data-channels/data-channels.rs

    So I'm creating an APIBuilder::new()[...].new_peer_connection(config) that should create an offer, which will be sent to the web_sys.RtcPeerConnection implementation.

    The web_sys then sends back an answer that I would like to feed to the peer_connection, and here is my problem: web_sys only gives me a String, not an RTCSessionDescription as needed by the peer_connection. And the RTCSessionDescription has a private field, so I cannot do:

    peer_connection.set_local_description(RTCSessionDescription{
      sdp_type: RTCSdpType::Answer,
      sdp: answer_string,
      parsed: None
    }
    

    I looked around at the methods of peer_connection but couldn't find an easy way to feed the answer-string to it.

    opened by ineiti 12
  • [WebRTC] double check simulcast example and play-from-disk-renegotiation example

    [WebRTC] double check simulcast example and play-from-disk-renegotiation example

    Pion's simulcast example can receives two streams with rid = "f" and "h" ~~and play-from-disk-renegotiation example has video grid when click add video multiple times.~~

    opened by rainliu 11
  • Remove unnecessary async in public API

    Remove unnecessary async in public API

    mind if i create a PR that makes all callback setters (e.g. RTCPeerConnection::on_ice_candidate()) non async? Currently callbacks are stored behind tokio::Mutex'es, i believe that ArcSwap can be used here, so we can use atomic load/store. It wont affect performance in any way, just some quality of life improvements.

    All good with me. I'd like to get rid of tokio::Mutex, replacing it with sync variants, where that's possible

    So i've refactored all public callback setters here.

    Regarding removing tokio::Mutexes that you've mentioned, well, i've replaced some of those, but i don't want this PR to become even bigger, and it would be nice if you provide some feedback first. I've used both ArcSwap and std::Mutex, i guess its ok to use blocking mutex in simple cases, when you don't need to hold it, e.g. copy, store, swap, take one-liners. I will prepare follow-up PRs on this issue if this PR looks good to you.

    And one more thing regarding the callbacks, maybe it makes sense to make them just dumb Box<dyn Fn(_)>? So Box<dyn (FnMut(ConnectionState) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>>) + Send + Sync> => Box<dyn (Fn(ConnectionState)) + Send + Sync>. Yeah, that might hurt users in some rare cases, but it would make everything simpler.

    ack @k0nserv

    opened by alexlapa 10
  • Firefox SDP parsing fails due to missing C line on media level

    Firefox SDP parsing fails due to missing C line on media level

    Hey,

    I noticed that, at least in my modified reflect example, Firefox throws a DOM exception when applying the answer SDP.

    Example SDP
    v=0
    o=- 4985367504486208344 356629000 IN IP4 0.0.0.0
    s=-
    t=0 0
    a=fingerprint:sha-256 D5:67:46:98:F8:D8:05:4B:D5:42:4E:FD:04:C7:03:93:B9:90:C8:AD:A2:82:3E:AE:24:E3:4A:B8:54:2D:76:31
    a=group:BUNDLE 1 2
    m=audio 0 UDP/TLS/RTP/SAVPF 0
    a=candidate:167090039 1 udp 2130706431 :: 50760 typ host
    a=candidate:167090039 2 udp 2130706431 :: 50760 typ host
    a=candidate:3498147984 1 udp 2130706431 192.168.1.76 59816 typ host
    a=candidate:3498147984 2 udp 2130706431 192.168.1.76 59816 typ host
    a=candidate:3122685691 1 udp 2130706431 192.168.1.33 57564 typ host
    a=candidate:3122685691 2 udp 2130706431 192.168.1.33 57564 typ host
    a=end-of-candidates
    m=video 9 UDP/TLS/RTP/SAVPF 120
    c=IN IP4 0.0.0.0
    a=setup:active
    a=mid:1
    a=ice-ufrag:nzCUobTruNCKeWEl
    a=ice-pwd:pSowjNuaNylpeKBFgTsFUNwQRdrzDQxe
    a=rtcp-mux
    a=rtcp-rsize
    a=rtpmap:120 VP8/90000
    a=fmtp:120 max-fs=12288;max-fr=60
    a=rtcp-fb:120 nack
    a=rtcp-fb:120 nack pli
    a=rtcp-fb:120 ccm fir
    a=rtcp-fb:120 goog-remb
    a=rtcp-fb:120 transport-cc
    a=extmap:7 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
    a=recvonly
    m=application 9 UDP/DTLS/SCTP webrtc-datachannel
    c=IN IP4 0.0.0.0
    a=setup:active
    a=mid:2
    a=sendrecv
    a=sctp-port:5000
    a=ice-ufrag:nzCUobTruNCKeWEl
    a=ice-pwd:pSowjNuaNylpeKBFgTsFUNwQRdrzDQxe
    

    This causes the following exception to be thrown in Firefox:

    Uncaught (in promise) DOMException: SIPCC Failed to parse SDP: SDP Parse Error on line 39:  c= connection line not specified for every media level, validation failed.
    

    This makes sense, the c line is missing for the audio track.

    This is the relevant part of the Firefox source code: https://searchfox.org/mozilla-central/source/third_party/sipcc/sdp_main.c#955

    opened by k0nserv 9
  • datachannel intermittently closes with an error

    datachannel intermittently closes with an error

    First, I want to say thank you for building nice project! I have an issue that datachannel intermittently closes with an error.

    Webrtc: 0.1.1 Rust: 1.55 stable

    Case 1. [2021-10-05T17:11:04Z WARN webrtc_sctp::association] [] failed to read packets on net_conn: Alert is Fatal or Close Notify

    Case 2. [2021-10-05T17:16:18Z WARN webrtc_sctp::association] [] failed to handle_inbound: chunk too short

    In my case, I used datachannel with max_retransmits = 0, ordered = false. These errors occurred even without heavy load. When I use other webrtc libraries (pion, aiortc, werift), I don't have the issue that datachannel closes

    bug 
    opened by qbx2 9
  • Make `RTCPeerConnection::on_track` spec-compliant

    Make `RTCPeerConnection::on_track` spec-compliant

    Currently RTCPeerConnection::on_track accepts OnTrackHdlrFn which is:

    pub type OnTrackHdlrFn = Box<
        dyn (FnMut(
                Option<Arc<TrackRemote>>,
                Option<Arc<RTCRtpReceiver>>,
            ) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>>)
            + Send
            + Sync,
    >;
    

    When according to the WebRTc spec RTCTrackEvent is supposed to be:

    interface RTCTrackEvent : Event {
      readonly attribute RTCRtpReceiver receiver;
      readonly attribute MediaStreamTrack track;
      [SameObject] readonly attribute FrozenArray<MediaStream> streams;
      readonly attribute RTCRtpTransceiver transceiver;
    };
    

    So, excluding MediaStreams, since i don't see it being used anywhere, this callback is supposed to look like this:

    pub type OnTrackHdlrFn = Box<
        dyn (FnMut(
                Arc<TrackRemote>,
                Arc<RTCRtpReceiver>,
                Arc<RTCRtpTransceiver>,
            ) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>>)
            + Send
            + Sync,
    >;
    
    opened by alexlapa 2
  • Force high bitrate for incoming video

    Force high bitrate for incoming video

    Hi, I'm using a modified version of the broadcast example to achieve just that in an production environment, is there a way to force a high bitrate for incoming video ?

    opened by Wicpar 2
  • Limited Web (Wasm through js_sys) layer for code reuse ?

    Limited Web (Wasm through js_sys) layer for code reuse ?

    Hi,

    I was wondering if there was a way to reuse code written with this lib in a frontend wasm project, obviously not all features, but maybe a subset.

    enhancement help wanted 
    opened by Wicpar 4
  • [sctp] `max-message-size` SDP attribute is ignored

    [sctp] `max-message-size` SDP attribute is ignored

    Refs https://github.com/pion/webrtc/issues/1396

    Right now maximum message size is fixed to 65kB. We should respect max-message-size attribute from the remote's SDP.

    enhancement subcrate:data 
    opened by melekes 0
  • Fix outbound RTCP intercept

    Fix outbound RTCP intercept

    Currently intercepting outbound RTCP to read sent packets via RTCPWriter doesn't work because these outbound writers aren't configured to take part in the interceptor chain. There are issues with the underlying writer not being Send that prevent approaching this in the same way as RTCPReader

    bug subcrate:interceptor 
    opened by k0nserv 0
Releases(v0.6.0)
  • v0.6.0(Nov 15, 2022)

    This release contains various improvements and bug fixes.

    The full changelog is available here.

    Notably, big chunks of the API level interfaces have changed from async to sync which should be an ergonomic improvement for everyone, thanks to @alexlapa for their work on this.

    MSRV

    With this version we've adopted a MSRV(minimum supported rust version) policy. Namely, we support versions of the Rust compiler released in the last six months. This is a minimum and we don't aim to drop support aggressively, but if you are running an older version there is always a risk that we'll drop support for it. Changes to the minimum Rust version will not be breaking from a semver perspective.

    Contributors

    • @algesten
    • @alexlapa
    • @ericfont
    • @karaziox
    • @KokaKiwi
    • @k0nserv
    • @melekes
    • @KillingSpark
    • @llacqie
    • @logist322

    Thanks to all contributors who helped make this release happen 🎉

    Source code(tar.gz)
    Source code(zip)
  • v0.5.1(Sep 19, 2022)

  • v0.5.0(Sep 7, 2022)

  • v0.4.0(Jan 17, 2022)

    • Breaking change: remove unnecessary async call for registering interceptors (by @jelmansouri)
    • Fix Interceptor's wrong rtcp-reader flow when have more than a stream https://github.com/webrtc-rs/interceptor/issues/2 (by @robashton)
    • Fix ReadRTCP issue https://github.com/webrtc-rs/webrtc/issues/151 (by @robashton)
    • RTP crate internal refactoring (by @zotho)
    Source code(tar.gz)
    Source code(zip)
  • v0.3.4(Dec 16, 2021)

  • v0.3.3(Dec 11, 2021)

    • [ICE] Fix closing connection for UDP mux (by @k0nserv)
    • [RTCP] Fix TWCC unmarshal bug for empty feedbacks
    • [RTCP] Fix unmarshal handling for the case of padding bit not corrected set by Firefox
    Source code(tar.gz)
    Source code(zip)
  • v0.3.2(Dec 6, 2021)

  • v0.3.1(Nov 15, 2021)

  • v0.3.0(Nov 8, 2021)

    • [x] fix reference cycle caused memory leak
    • [x] [RTCP] add eXtended Report (XR) support #116
    • [x] [Interceptor] add TWCC support #117
    • [x] [RTP] add H.265 codec support #114
    • [x] [ICE] add UDPMux feature #102 (by @k0nserv)
    Source code(tar.gz)
    Source code(zip)
  • v0.2.1(Oct 20, 2021)

    • [x] fix Datachannel leak #120
    • add sctp_transport's accept_data_channels loop cancellation handling
    • add data_channel's read_loop cancellation handling
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Oct 9, 2021)

  • v0.1.3(Oct 7, 2021)

  • v0.1.2(Oct 6, 2021)

  • v0.1.1(Oct 1, 2021)

  • v0.1.0(Sep 26, 2021)

    This release contains implementation of major WebRTC stack protocols:

    • [x] SDP
    • [x] mDNS
    • [x] STUN
    • [x] TURN
    • [x] ICE
    • [x] DTLS
    • [x] RTP
    • [x] RTCP
    • [x] SRTP
    • [x] SCTP
    • [x] DataChannel API
    • [x] Media API
    • [x] PeerConnection API

    Examples provide code samples to show how to use webrtc-rs to build media and data channel applications.

    Source code(tar.gz)
    Source code(zip)
  • v0.1.0-beta.0.0.15(Sep 25, 2021)

  • v0.1.0-beta.0.0.14(Sep 24, 2021)

Owner
WebRTC.rs
WebRTC in Rust
WebRTC.rs
A library for easily creating WebRTC data channel connections in Rust

Cyberdeck A library for easily creating WebRTC data channel connections in Rust.

RICHΛRD ΛNΛYΛ 34 Nov 10, 2022
A multiplayer web based roguelike built on Rust and WebRTC

Gorgon A multiplayer web-based roguelike build on Rust and WebRTC. License This project is licensed under either of Apache License, Version 2.0, (LICE

RICHΛRD ΛNΛYΛ 2 Sep 19, 2022
Easy-to-use wrapper for WebRTC DataChannels peer-to-peer connections written in Rust and compiling to WASM.

Easy-to-use wrapper for WebRTC DataChannels peer-to-peer connections written in Rust and compiling to WASM.

null 56 Nov 24, 2022
All-batteries included GStreamer WebRTC producer

webrtcsink All-batteries included GStreamer WebRTC producer, that tries its best to do The Right Thing™. Use case The webrtcbin element in GStreamer i

Centricular 75 Nov 21, 2022
Backroll is a pure Rust implementation of GGPO rollback networking library.

backroll-rs Backroll is a pure Rust implementation of GGPO rollback networking library. Development Status This is still in an untested alpha stage. A

Hourai Teahouse 268 Nov 19, 2022
Modrinth API is a simple library for using Modrinth's API in Rust projects

Ferinth is a simple library for using the Modrinth API in Rust projects. It uses reqwest as its HTTP(S) client and deserialises responses to typed structs using serde.

null 17 Nov 17, 2022
The Safe Network Core. API message definitions, routing and nodes, client core api.

safe_network The Safe Network Core. API message definitions, routing and nodes, client core api. License This Safe Network repository is licensed unde

MaidSafe 95 Nov 19, 2022
An implementation of the ZITADEL gRPC API in Rust.

An implementation of the ZITADEL gRPC API in Rust. Complemented with other useful elements such as ServiceAccount auth.

Christoph Bühler 10 Nov 11, 2022
rseip (eip-rs) - EtherNet/IP in pure Rust

rseip rseip (eip-rs) - EtherNet/IP in pure Rust Features Pure Rust Library Asynchronous Extensible Explicit Messaging (Connected / Unconnected) Open S

joylei 15 Nov 4, 2022
Pure rust mqtt cilent

NOTE: Archived. No further development under this repo. Follow progress of a different implementation here Pure rust MQTT client which strives to be s

Ather Energy Pvt Ltd 200 Oct 14, 2022
Docker daemon API in Rust

Bollard: an asynchronous rust client library for the docker API Bollard leverages the latest Hyper and Tokio improvements for an asynchronous API cont

Niel Drummond 421 Dec 1, 2022
A rust client and structures to interact with the Clever-Cloud API.

Clever-Cloud Software Development Kit - Rust edition This crate provides structures and client to interact with the Clever-Cloud API. Status This crat

Clever Cloud 6 Jun 3, 2022
Revolt backend API server, built with Rust.

Delta Description Delta is a blazing fast API server built with Rust for Revolt. Features: Robust and efficient API routes for running a chat platform

Revolt 724 Nov 19, 2022
Podman-api-rs - Rust interface to Podman (libpod).

podman-api Rust interface to Podman Usage Add the following to your Cargo.toml file [dependencies] podman-api = "0.1" SSL Connection To enable HTTPS c

Wojciech Kępka 41 Nov 19, 2022
ZeroNS: a name service centered around the ZeroTier Central API

ZeroNS: a name service centered around the ZeroTier Central API ZeroNS provides names that are a part of ZeroTier Central's configured networks; once

ZeroTier, Inc. 318 Nov 23, 2022
A wrapper for the Google Cloud DNS API

cloud-dns is a crate providing a client to interact with Google Cloud DNS v1

Embark 5 May 24, 2022
Obtain (wildcard) certificates from let's encrypt using dns-01 without the need for API access to your DNS provider.

Agnos Presentation Agnos is a single-binary program allowing you to easily obtain certificates (including wildcards) from Let's Encrypt using DNS-01 c

Arthur Carcano 240 Nov 18, 2022
Hammerspoon plugin and API to interact with Yabai socket directly

Yabai.spoon NOTE: no longer using it or intending to maintain it see #2. Yabai.spoon is lua 5.4 library to interact with yabai socket directly within

null 2 May 17, 2022
🔌 A curseforge proxy server, keeping your API key safe and sound.

?? CFPROXY - The curseforge proxy server Curseforge has locked down their API and now restricts access without authentification. This spells trouble f

null 6 Nov 7, 2022