Rust wrappers for libdatachannel, a WebRTC Data Channels standalone implementation in C++.
This crate provides two traits that end user must implement, DataChannelHandler
and
PeerConnectionHandler
, which defined all callbacks for RtcPeerConnection
and
RtcDataChannel
structs respectively.
Aforementioned traits are defined as follows:
```rust pub trait DataChannelHandler { fn onopen(&mut self) {} fn onclosed(&mut self) {} fn onerror(&mut self, err: &str) {} fn onmessage(&mut self, msg: &[u8]) {} fn onbufferedamountlow(&mut self) {} fn onavailable(&mut self) {} }
pub trait PeerConnectionHandler { type DCH;
fn data_channel_handler(&mut self) -> Self::DCH;
fn on_description(&mut self, sess_desc: SessionDescription) {}
fn on_candidate(&mut self, cand: IceCandidate) {}
fn on_connection_state_change(&mut self, state: ConnectionState) {}
fn on_gathering_state_change(&mut self, state: GatheringState) {}
fn on_data_channel(&mut self, data_channel: Box<RtcDataChannel<Self::DCH>>) {}
} ```
Note that all on_*
methods have a default no-operation implementation.
The main struct, RtcPeerconnection
, takes a RtcConfig
(which defines ICE servers)
and a instance of PeerConnectionHandler
.
Here is the basic workflow:
```rust use datachannel::{DataChannelHandler, PeerConnectionHandler, RtcConfig, RtcPeerConnection};
struct MyChannel;
impl DataChannelHandler for MyChannel { fn on_open(&mut self) { // TODO: notify that the data channel is ready (optional) }
fn on_message(&mut self, msg: &[u8]) {
// TODO: process the received message
}
}
struct MyConnection;
impl PeerConnectionHandler for MyConnection { type DCH = MyChannel;
/// Used to create the `RtcDataChannel` received through `on_data_channel`.
fn data_channel_handler(&mut self) -> Self::DCH {
MyChannel
}
fn on_data_channel(&mut self, mut dc: Box<RtcDataChannel<Self::DCH>>) {
// TODO: store `dc` to keep receiving its messages (otherwise it will be dropped)
}
}
let iceservers = vec!["stun:stun.l.google.com:19302"]; let conf = RtcConfig::new(&iceservers);
let mut pc = RtcPeerConnection::new(&conf, MyConnection)?;
let mut dc = pc.createdatachannel("test-dc", MyChannel)?;
// TODO: exchange SessionDescription
and IceCandidate
with remote peer
// TODO: wait for dc
to be opened (should be signaled through on_open
)
// ...
// Then send a message
dc.send("Hello Peer!".as_bytes())?;
```
Complete implementation example can be found in the tests.
See also async-datachannel for an async-based implementation.
log
Default Enables logging provided by the log
crate.tracing
Enables logging provided by the tracing
crate.static
Build and link statically (with all dependencies, including OpenSSL
).Note that CMake
is required to compile libdatachannel through
datachannel-sys.
Clone the repo recursively:
sh
git clone --recursive https://github.com/lerouxrgd/datachannel-rs.git
By default libdatachannel will be built and linked dynamically. However there is a
static
Cargo feature that will build and link it statically (with all its
dependencies, including OpenSSL
).
You probably need to set the following environment variables if your build fails with an
OpenSSL
related error.
sh
export OPENSSL_ROOT_DIR=/usr/local/Cellar/openssl@1.1/1.1.1i/
export OPENSSL_LIBRARIES=/usr/local/Cellar/openssl@1.1/1.1.1i/lib
With the paths of your local OpenSSL
installation.
Required dependencies:
```sh
sudo apt install build-essential cmake pkg-config libssl-dev clang ```