DataChannel progress

This commit is contained in:
Théo Monnom
2022-09-19 01:11:18 +02:00
parent dca8cf7796
commit 8380ffadef
21 changed files with 389 additions and 87 deletions
+48
View File
@@ -1,6 +1,8 @@
use cxx::UniquePtr;
use libwebrtc_sys::data_channel as sys_dc;
pub use sys_dc::ffi::Priority;
pub struct DataChannel {
cxx_handle: UniquePtr<sys_dc::ffi::DataChannel>,
}
@@ -10,3 +12,49 @@ impl DataChannel {
Self { cxx_handle }
}
}
#[derive(Debug)]
pub struct DataChannelInit {
#[deprecated]
reliable: bool,
ordered: bool,
max_retransmit_time: Option<i32>,
max_retransmits: Option<i32>,
protocol: String,
negotiated: bool,
id: i32,
priority: Option<Priority>,
}
impl Default for DataChannelInit {
fn default() -> Self {
Self {
reliable: false,
ordered: true,
max_retransmit_time: None,
max_retransmits: None,
protocol: "".to_string(),
negotiated: false,
id: -1,
priority: None,
}
}
}
impl From<DataChannelInit> for sys_dc::ffi::DataChannelInit {
fn from(init: DataChannelInit) -> Self {
Self {
reliable: init.reliable,
ordered: init.ordered,
has_max_retransmit_time: init.max_retransmit_time.is_some(),
max_retransmit_time: init.max_retransmit_time.unwrap_or_default(),
has_max_retransmits: init.max_retransmits.is_some(),
max_retransmits: init.max_retransmits.unwrap_or_default(),
protocol: init.protocol,
negotiated: init.negotiated,
id: init.id,
has_priority: init.priority.is_some(),
priority: init.priority.unwrap_or(Priority::Low),
}
}
}
+13 -1
View File
@@ -2,7 +2,19 @@ use cxx::{SharedPtr, UniquePtr};
use libwebrtc_sys::jsep as sys_jsep;
#[derive(Debug)]
pub struct IceCandidate {}
pub struct IceCandidate {
cxx_handle: UniquePtr<sys_jsep::ffi::IceCandidate>,
}
impl IceCandidate {
pub(crate) fn new(cxx_handle: UniquePtr<sys_jsep::ffi::IceCandidate>) -> Self {
Self { cxx_handle }
}
pub(crate) fn release(self) -> UniquePtr<sys_jsep::ffi::IceCandidate> {
self.cxx_handle
}
}
#[derive(Debug)]
pub struct SessionDescription {
+1
View File
@@ -6,3 +6,4 @@ pub mod peer_connection_factory;
pub mod rtc_error;
pub mod rtp_receiver;
pub mod rtp_transceiver;
pub mod webrtc;
+73 -9
View File
@@ -1,12 +1,15 @@
use cxx::UniquePtr;
use libwebrtc_sys::data_channel as sys_dc;
use libwebrtc_sys::jsep as sys_jsep;
use libwebrtc_sys::peer_connection as sys_pc;
use log::trace;
use std::future::Future;
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use thiserror::Error;
use tokio::sync::{mpsc, oneshot};
use crate::data_channel::DataChannel;
use crate::data_channel::{DataChannel, DataChannelInit};
use crate::jsep::{IceCandidate, SessionDescription};
use crate::media_stream::MediaStream;
use crate::rtc_error::RTCError;
@@ -32,19 +35,19 @@ pub struct PeerConnection {
observer: Box<InternalObserver>,
// Keep alive for C++
native_observer: UniquePtr<sys_pc::ffi::NativePeerConnectionObserver>
native_observer: UniquePtr<sys_pc::ffi::NativePeerConnectionObserver>,
}
impl PeerConnection {
pub(crate) fn new(
cxx_handle: UniquePtr<sys_pc::ffi::PeerConnection>,
observer: Box<InternalObserver>,
native_observer: UniquePtr<sys_pc::ffi::NativePeerConnectionObserver>
native_observer: UniquePtr<sys_pc::ffi::NativePeerConnectionObserver>,
) -> Self {
Self {
cxx_handle,
observer,
native_observer
native_observer,
}
}
@@ -134,6 +137,38 @@ impl PeerConnection {
}
}
pub fn create_data_channel(
&mut self,
label: &str,
init: DataChannelInit,
) -> Result<DataChannel, RTCError> {
let native_init = sys_dc::ffi::create_data_channel_init(init.into());
let res = self
.cxx_handle
.pin_mut()
.create_data_channel(label.to_string(), native_init);
match res {
Ok(cxx_handle) => Ok(DataChannel::new(cxx_handle)),
Err(e) => Err(unsafe { RTCError::from(e.what()) }),
}
}
pub async fn add_ice_candidate(&mut self, candidate: IceCandidate) -> Result<(), SdpError> {
let (tx, mut rx) = mpsc::channel(1);
let observer = sys_pc::AddIceCandidateObserverWrapper::new(Box::new(move |error| {
tx.blocking_send(error).unwrap();
}));
let mut native_observer = sys_pc::ffi::create_native_add_ice_candidate_observer(Box::new(observer));
self.cxx_handle.pin_mut().add_ice_candidate(candidate.release(), native_observer.pin_mut());
match rx.recv().await {
Some(value) => Ok(()),
None => Err(SdpError::RecvError("channel closed".to_string())),
}
}
pub fn close(&mut self) {
self.cxx_handle.pin_mut().close();
}
@@ -467,10 +502,10 @@ impl sys_pc::PeerConnectionObserver for InternalObserver {
}
fn on_ice_candidate(&self, candidate: UniquePtr<libwebrtc_sys::jsep::ffi::IceCandidate>) {
trace!("on_ice_candidate");
trace!("TESTING on_ice_candidate");
let mut handler = self.on_ice_candidate_handler.lock().unwrap();
if let Some(f) = handler.as_mut() {
// TODO(theomonnom)
f(IceCandidate::new(candidate));
}
}
@@ -567,8 +602,11 @@ impl sys_pc::PeerConnectionObserver for InternalObserver {
#[cfg(test)]
mod tests {
use crate::peer_connection_factory::PeerConnectionFactory;
use libwebrtc_sys::peer_connection_factory::ffi::RTCConfiguration;
use crate::data_channel::DataChannelInit;
use crate::jsep::IceCandidate;
use crate::peer_connection_factory::{PeerConnectionFactory, ICEServer, RTCConfiguration};
use tokio::sync::mpsc;
use crate::webrtc::RTCRuntime;
fn init_log() {
let _ = env_logger::builder().is_test(true).try_init();
@@ -578,14 +616,34 @@ mod tests {
async fn create_pc() {
init_log();
let test = RTCRuntime::new();
let factory = PeerConnectionFactory::new();
let config = RTCConfiguration {
ice_servers: vec![],
ice_servers: vec![ICEServer {
urls: vec!["stun:stun1.l.google.com:19302".to_string()],
username: "".into(),
password: "".into(),
}],
};
let mut bob = factory.create_peer_connection(config.clone()).unwrap();
let mut alice = factory.create_peer_connection(config.clone()).unwrap();
let (bob_ice_tx, mut bob_ice_rx) = mpsc::channel::<IceCandidate>(1);
let (alice_ice_tx, mut alice_ice_rx) = mpsc::channel::<IceCandidate>(1);
bob.on_ice_candidate(Box::new(move |candidate| {
bob_ice_tx.blocking_send(candidate).unwrap();
}));
alice.on_ice_candidate(Box::new(move |candidate| {
alice_ice_tx.blocking_send(candidate).unwrap();
}));
bob.create_data_channel("test_dc", DataChannelInit::default())
.unwrap();
let offer = bob.create_offer().await.unwrap();
bob.set_local_description(offer.clone()).await.unwrap();
alice.set_remote_description(offer).await.unwrap();
@@ -593,6 +651,12 @@ mod tests {
alice.set_local_description(answer.clone()).await.unwrap();
bob.set_remote_description(answer).await.unwrap();
let bob_ice = bob_ice_rx.recv().await.unwrap();
let alice_ice = alice_ice_rx.recv().await.unwrap();
bob.add_ice_candidate(alice_ice).await.unwrap();
alice.add_ice_candidate(bob_ice).await.unwrap();
alice.close();
bob.close();
}
@@ -36,9 +36,7 @@ impl PeerConnectionFactory {
match res {
Ok(cxx_handle) => Ok(PeerConnection::new(cxx_handle, observer, native_observer)),
Err(e) => {
Err(RTCError::from(e.what())) // TODO
}
Err(e) => Err(RTCError::from(e.what())),
}
}
}
+14
View File
@@ -0,0 +1,14 @@
use cxx::UniquePtr;
use libwebrtc_sys::webrtc as sys_rtc;
pub struct RTCRuntime {
cxx_handle: UniquePtr<sys_rtc::ffi::RTCRuntime>
}
impl RTCRuntime {
pub fn new() -> Self {
Self {
cxx_handle: sys_rtc::ffi::create_rtc_runtime()
}
}
}