rustfmt & signal_client improvememts
- handle ping message - recv now only returns on SignalResponse
This commit is contained in:
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
/target
|
target
|
||||||
/.idea
|
/.idea
|
||||||
/libwebrtc
|
/libwebrtc
|
||||||
Generated
+3
-1
@@ -495,6 +495,9 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "livekit"
|
name = "livekit"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"livekit-core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "livekit-core"
|
name = "livekit-core"
|
||||||
@@ -1063,7 +1066,6 @@ dependencies = [
|
|||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"tracing",
|
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -11,3 +11,6 @@ members = [
|
|||||||
"crates/livekit-webrtc",
|
"crates/livekit-webrtc",
|
||||||
"crates/livekit-webrtc/libwebrtc-sys"
|
"crates/livekit-webrtc/libwebrtc-sys"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
livekit-core = { path = "crates/livekit-core" }
|
||||||
@@ -7,7 +7,7 @@ edition = "2021"
|
|||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
tokio-tungstenite = { version = "0.17.2", features = ["native-tls"] }
|
tokio-tungstenite = { version = "0.17.2", features = ["native-tls"] }
|
||||||
tokio = { version = "1", features = ["full", "tracing"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
url = "2.2.2"
|
url = "2.2.2"
|
||||||
futures-util = "0.3.23"
|
futures-util = "0.3.23"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
use tracing::{event, Level};
|
use tracing::{event, Level};
|
||||||
|
|
||||||
use livekit_webrtc::peer_connection_factory::PeerConnectionFactory;
|
use livekit_webrtc::peer_connection_factory::PeerConnectionFactory;
|
||||||
|
|||||||
@@ -43,5 +43,3 @@ impl LocalParticipant {
|
|||||||
self.engine.lock().await.publish_data(&data, kind).await.map_err(Into::into)
|
self.engine.lock().await.publish_data(&data, kind).await.map_err(Into::into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tracing::{Level, event};
|
|
||||||
|
use tracing::{event, Level};
|
||||||
|
|
||||||
use livekit_webrtc::jsep::{IceCandidate, SessionDescription};
|
use livekit_webrtc::jsep::{IceCandidate, SessionDescription};
|
||||||
use livekit_webrtc::peer_connection::{
|
use livekit_webrtc::peer_connection::{
|
||||||
IceConnectionState, PeerConnection, RTCOfferAnswerOptions, SignalingState,
|
IceConnectionState, PeerConnection, RTCOfferAnswerOptions, SignalingState,
|
||||||
};
|
};
|
||||||
use livekit_webrtc::rtc_error::RTCError;
|
use livekit_webrtc::rtc_error::RTCError;
|
||||||
|
|
||||||
const NEGOTIATION_FREQUENCY: Duration = Duration::from_millis(150); // TODO(theomonnom)
|
const NEGOTIATION_FREQUENCY: Duration = Duration::from_millis(150);
|
||||||
|
|
||||||
pub type OnOfferHandler = Box<dyn (FnMut(SessionDescription) -> Pin<Box<dyn Future<Output=()> + Send + 'static>>) + Send + Sync>;
|
pub type OnOfferHandler = Box<dyn (FnMut(SessionDescription) -> Pin<Box<dyn Future<Output=()> + Send + 'static>>) + Send + Sync>;
|
||||||
|
|
||||||
@@ -20,6 +23,12 @@ pub struct PCTransport {
|
|||||||
renegotiate: bool,
|
renegotiate: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Debug for PCTransport {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||||
|
f.write_str("PCTransport")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PCTransport {
|
impl PCTransport {
|
||||||
pub fn new(peer_connection: PeerConnection) -> Self {
|
pub fn new(peer_connection: PeerConnection) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -45,6 +54,7 @@ impl PCTransport {
|
|||||||
self.on_offer_handler = Some(handler);
|
self.on_offer_handler = Some(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
pub async fn add_ice_candidate(&mut self, ice_candidate: IceCandidate) -> Result<(), RTCError> {
|
pub async fn add_ice_candidate(&mut self, ice_candidate: IceCandidate) -> Result<(), RTCError> {
|
||||||
if self.peer_connection.remote_description().is_none() {
|
if self.peer_connection.remote_description().is_none() {
|
||||||
self.pending_candidates.push(ice_candidate);
|
self.pending_candidates.push(ice_candidate);
|
||||||
@@ -57,6 +67,7 @@ impl PCTransport {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
pub async fn set_remote_description(
|
pub async fn set_remote_description(
|
||||||
&mut self,
|
&mut self,
|
||||||
remote_description: SessionDescription,
|
remote_description: SessionDescription,
|
||||||
@@ -79,12 +90,14 @@ impl PCTransport {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
pub async fn negotiate(&mut self) -> Result<(), RTCError> {
|
pub async fn negotiate(&mut self) -> Result<(), RTCError> {
|
||||||
// TODO(theomonnom) Debounce here with NEGOTIATION_FREQUENCY
|
// TODO(theomonnom) Debounce here with NEGOTIATION_FREQUENCY
|
||||||
self.create_and_send_offer(RTCOfferAnswerOptions::default())
|
self.create_and_send_offer(RTCOfferAnswerOptions::default())
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
async fn create_and_send_offer(
|
async fn create_and_send_offer(
|
||||||
&mut self,
|
&mut self,
|
||||||
options: RTCOfferAnswerOptions,
|
options: RTCOfferAnswerOptions,
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use tokio::time::sleep;
|
|
||||||
|
|
||||||
use crate::local_participant::LocalParticipant;
|
use crate::local_participant::LocalParticipant;
|
||||||
use crate::proto::data_packet;
|
|
||||||
use crate::rtc_engine;
|
use crate::rtc_engine;
|
||||||
use crate::rtc_engine::{EngineError, RTCEngine};
|
use crate::rtc_engine::{EngineError, RTCEngine};
|
||||||
|
|
||||||
@@ -23,12 +20,11 @@ pub struct Room {
|
|||||||
engine: Arc<Mutex<RTCEngine>>,
|
engine: Arc<Mutex<RTCEngine>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument(skip(url, token))]
|
||||||
pub async fn connect(url: &str, token: &str) -> Result<Room, RoomError> {
|
pub async fn connect(url: &str, token: &str) -> Result<Room, RoomError> {
|
||||||
let engine = rtc_engine::connect(url, token).await?;
|
let engine = rtc_engine::connect(url, token).await?;
|
||||||
|
|
||||||
engine.on_data(Box::new(|packet| {
|
engine.on_data(Box::new(|packet| {
|
||||||
|
|
||||||
Box::pin(async move {})
|
Box::pin(async move {})
|
||||||
})).await;
|
})).await;
|
||||||
|
|
||||||
@@ -58,15 +54,3 @@ impl Room {
|
|||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjgxMzc0NDgsImlzcyI6IkFQSXpLYkFTaUNWYWtnSiIsIm5hbWUiOiJ3ZWIiLCJuYmYiOjE2NjQ1Mzc0NDgsInN1YiI6IndlYiIsInZpZGVvIjp7InJvb21DcmVhdGUiOnRydWUsInJvb21Kb2luIjp0cnVlfX0.6VMDdXJYrW3KWrEzxx4hzbmMQnjQIRILQ48Qrbx5j44
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_test() {
|
|
||||||
// console_subscriber::init();
|
|
||||||
|
|
||||||
let mut room = connect("ws://localhost:7880", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NzEyMzk4NjAsImlzcyI6IkFQSXpLYkFTaUNWYWtnSiIsIm5hbWUiOiJ0ZXN0IiwibmJmIjoxNjY0MDM5ODYwLCJzdWIiOiJ0ZXN0IiwidmlkZW8iOnsicm9vbUFkbWluIjp0cnVlLCJyb29tQ3JlYXRlIjp0cnVlLCJyb29tSm9pbiI6dHJ1ZX19.0Bee2jI2cSZveAbZ8MLc-ADoMYQ4l8IRxcAxpXAS6a8").await.unwrap();
|
|
||||||
room.local_participant().publish_data(b"This is a test", data_packet::Kind::Reliable).await.unwrap();
|
|
||||||
|
|
||||||
sleep(Duration::from_secs(60)).await;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
@@ -23,15 +23,15 @@ use livekit_webrtc::peer_connection_factory::{
|
|||||||
};
|
};
|
||||||
use livekit_webrtc::rtc_error::RTCError;
|
use livekit_webrtc::rtc_error::RTCError;
|
||||||
|
|
||||||
|
use crate::{proto, signal_client};
|
||||||
use crate::lk_runtime::LKRuntime;
|
use crate::lk_runtime::LKRuntime;
|
||||||
use crate::pc_transport::PCTransport;
|
use crate::pc_transport::PCTransport;
|
||||||
use crate::proto::data_packet::Value;
|
|
||||||
use crate::proto::{
|
use crate::proto::{
|
||||||
data_packet, signal_request, signal_response, DataPacket, JoinResponse, SignalTarget,
|
data_packet, DataPacket, JoinResponse, signal_request, signal_response, SignalTarget,
|
||||||
TrickleRequest, UserPacket,
|
TrickleRequest, UserPacket,
|
||||||
};
|
};
|
||||||
|
use crate::proto::data_packet::Value;
|
||||||
use crate::signal_client::{SignalClient, SignalError};
|
use crate::signal_client::{SignalClient, SignalError};
|
||||||
use crate::{proto, signal_client};
|
|
||||||
|
|
||||||
const LOSSY_DC_LABEL: &str = "_lossy";
|
const LOSSY_DC_LABEL: &str = "_lossy";
|
||||||
const RELIABLE_DC_LABEL: &str = "_reliable";
|
const RELIABLE_DC_LABEL: &str = "_reliable";
|
||||||
@@ -142,7 +142,7 @@ pub struct RTCEngine {
|
|||||||
lk_runtime: Arc<LKRuntime>, // Keep a reference while we're using the RTCEngine
|
lk_runtime: Arc<LKRuntime>, // Keep a reference while we're using the RTCEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument(skip(url, token))]
|
||||||
pub async fn connect(url: &str, token: &str) -> Result<RTCEngine, EngineError> {
|
pub async fn connect(url: &str, token: &str) -> Result<RTCEngine, EngineError> {
|
||||||
// Acquire an existing/a new LKRuntime
|
// Acquire an existing/a new LKRuntime
|
||||||
let mut lk_runtime_ref = LK_RUNTIME.lock().await;
|
let mut lk_runtime_ref = LK_RUNTIME.lock().await;
|
||||||
@@ -214,11 +214,11 @@ impl RTCEngine {
|
|||||||
*self.internal.on_data_handler.lock().await = Some(f);
|
*self.internal.on_data_handler.lock().await = Some(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn data_channel(&self, kind: data_packet::Kind) -> &Arc<Mutex<DataChannel>> {
|
fn data_channel(&self, kind: data_packet::Kind) -> Arc<Mutex<DataChannel>> {
|
||||||
if kind == data_packet::Kind::Reliable {
|
if kind == data_packet::Kind::Reliable {
|
||||||
&self.internal.reliable_dc
|
self.internal.reliable_dc.clone()
|
||||||
} else {
|
} else {
|
||||||
&self.internal.lossy_dc
|
self.internal.lossy_dc.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,7 +394,7 @@ impl RTCEngine {
|
|||||||
let _ = signal_client.send(signal_request::Message::Trickle(
|
let _ = signal_client.send(signal_request::Message::Trickle(
|
||||||
TrickleRequest {
|
TrickleRequest {
|
||||||
candidate_init: json,
|
candidate_init: json,
|
||||||
target: target as i32
|
target: target as i32,
|
||||||
},
|
},
|
||||||
)).await;
|
)).await;
|
||||||
});
|
});
|
||||||
@@ -502,7 +502,7 @@ impl RTCEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// TODO{theomonnom) Trigger reconnect
|
// TODO(theomonnom) Trigger reconnect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
use futures::future::poll_fn;
|
|
||||||
use futures_util::stream::{SplitSink, SplitStream};
|
|
||||||
use futures_util::{SinkExt, StreamExt};
|
|
||||||
use prost::Message as ProstMessage;
|
|
||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
|
use futures::future::poll_fn;
|
||||||
|
use futures_util::{SinkExt, StreamExt};
|
||||||
|
use futures_util::stream::{SplitSink, SplitStream};
|
||||||
|
use prost::Message as ProstMessage;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
use tokio_tungstenite::tungstenite::{
|
|
||||||
protocol::frame::{coding::CloseCode, CloseFrame},
|
|
||||||
Error as WsError, Message,
|
|
||||||
};
|
|
||||||
use tokio_tungstenite::{connect_async, MaybeTlsStream, WebSocketStream};
|
use tokio_tungstenite::{connect_async, MaybeTlsStream, WebSocketStream};
|
||||||
use tracing::{event, span, Level};
|
use tokio_tungstenite::tungstenite::{Error as WsError, Message};
|
||||||
|
use tokio_tungstenite::tungstenite::protocol::CloseFrame;
|
||||||
|
use tokio_tungstenite::tungstenite::protocol::frame::coding::CloseCode;
|
||||||
|
use tracing::{event, Level};
|
||||||
|
|
||||||
use crate::proto::{signal_request, signal_response, SignalRequest, SignalResponse};
|
use crate::proto::{signal_request, signal_response, SignalRequest, SignalResponse};
|
||||||
|
use crate::signal_client::SendMessage::Pong;
|
||||||
|
|
||||||
pub const PROTOCOL_VERSION: u32 = 8;
|
pub const PROTOCOL_VERSION: u32 = 8;
|
||||||
|
|
||||||
@@ -32,21 +33,26 @@ type SignalResult<T> = Result<T, SignalError>;
|
|||||||
type WebSocket = WebSocketStream<MaybeTlsStream<TcpStream>>;
|
type WebSocket = WebSocketStream<MaybeTlsStream<TcpStream>>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct RecvMessage {
|
enum RecvMessage {
|
||||||
|
Signal {
|
||||||
response_chn: oneshot::Sender<Option<signal_response::Message>>,
|
response_chn: oneshot::Sender<Option<signal_response::Message>>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SendMessage {
|
enum SendMessage {
|
||||||
|
Signal {
|
||||||
signal: signal_request::Message,
|
signal: signal_request::Message,
|
||||||
response_chn: oneshot::Sender<SignalResult<()>>,
|
response_chn: oneshot::Sender<SignalResult<()>>,
|
||||||
|
},
|
||||||
|
Pong {
|
||||||
|
ping_data: Vec<u8>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SignalClient {
|
pub struct SignalClient {
|
||||||
read_sender: mpsc::Sender<RecvMessage>,
|
read_tx: mpsc::Sender<RecvMessage>,
|
||||||
write_sender: mpsc::Sender<SendMessage>,
|
write_tx: mpsc::Sender<SendMessage>,
|
||||||
write_shutdown_sender: oneshot::Sender<()>,
|
|
||||||
read_shutdown_sender: oneshot::Sender<()>,
|
|
||||||
read_handle: JoinHandle<()>,
|
read_handle: JoinHandle<()>,
|
||||||
write_handle: JoinHandle<()>,
|
write_handle: JoinHandle<()>,
|
||||||
}
|
}
|
||||||
@@ -57,7 +63,7 @@ impl Debug for SignalClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument(skip(url, token))]
|
||||||
pub async fn connect(url: &str, token: &str) -> SignalResult<SignalClient> {
|
pub async fn connect(url: &str, token: &str) -> SignalResult<SignalClient> {
|
||||||
let mut lk_url = url::Url::parse(url)?;
|
let mut lk_url = url::Url::parse(url)?;
|
||||||
lk_url.set_path("/rtc");
|
lk_url.set_path("/rtc");
|
||||||
@@ -74,21 +80,13 @@ pub async fn connect(url: &str, token: &str) -> SignalResult<SignalClient> {
|
|||||||
|
|
||||||
let (read_tx, read_rx) = mpsc::channel::<RecvMessage>(8);
|
let (read_tx, read_rx) = mpsc::channel::<RecvMessage>(8);
|
||||||
let (write_tx, write_rx) = mpsc::channel::<SendMessage>(8);
|
let (write_tx, write_rx) = mpsc::channel::<SendMessage>(8);
|
||||||
let (read_shutdown_tx, read_shutdown_rx) = oneshot::channel();
|
|
||||||
let (write_shutdown_tx, write_shutdown_rx) = oneshot::channel();
|
|
||||||
|
|
||||||
let read_handle = tokio::spawn(SignalClient::ws_read(read_rx, ws_reader, read_shutdown_rx));
|
let read_handle = tokio::spawn(SignalClient::ws_read(read_rx, ws_reader, write_tx.clone()));
|
||||||
let write_handle = tokio::spawn(SignalClient::ws_write(
|
let write_handle = tokio::spawn(SignalClient::ws_write(write_rx, ws_writer));
|
||||||
write_rx,
|
|
||||||
ws_writer,
|
|
||||||
write_shutdown_rx,
|
|
||||||
));
|
|
||||||
|
|
||||||
Ok(SignalClient {
|
Ok(SignalClient {
|
||||||
read_sender: read_tx,
|
read_tx,
|
||||||
write_sender: write_tx,
|
write_tx,
|
||||||
write_shutdown_sender: write_shutdown_tx,
|
|
||||||
read_shutdown_sender: read_shutdown_tx,
|
|
||||||
read_handle,
|
read_handle,
|
||||||
write_handle,
|
write_handle,
|
||||||
})
|
})
|
||||||
@@ -96,98 +94,114 @@ pub async fn connect(url: &str, token: &str) -> SignalResult<SignalClient> {
|
|||||||
|
|
||||||
impl SignalClient {
|
impl SignalClient {
|
||||||
pub async fn close(self) {
|
pub async fn close(self) {
|
||||||
let _ = self.write_shutdown_sender.send(());
|
drop(self.read_tx);
|
||||||
let _ = self.write_handle.await;
|
drop(self.write_tx);
|
||||||
let _ = self.read_shutdown_sender.send(());
|
|
||||||
let _ = self.read_handle.await;
|
let _ = self.read_handle.await;
|
||||||
|
let _ = self.write_handle.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn recv(&self) -> Option<signal_response::Message> {
|
pub async fn recv(&self) -> Option<signal_response::Message> {
|
||||||
let (send, recv) = oneshot::channel();
|
let (send, recv) = oneshot::channel();
|
||||||
let msg = RecvMessage { response_chn: send };
|
let msg = RecvMessage::Signal { response_chn: send };
|
||||||
let _ = self.read_sender.send(msg).await;
|
let _ = self.read_tx.send(msg).await;
|
||||||
recv.await.expect("channel closed")
|
recv.await.expect("channel closed")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&self, signal: signal_request::Message) -> SignalResult<()> {
|
pub async fn send(&self, signal: signal_request::Message) -> SignalResult<()> {
|
||||||
let (send, recv) = oneshot::channel();
|
let (send, recv) = oneshot::channel();
|
||||||
let msg = SendMessage {
|
let msg = SendMessage::Signal {
|
||||||
signal,
|
signal,
|
||||||
response_chn: send,
|
response_chn: send,
|
||||||
};
|
};
|
||||||
let _ = self.write_sender.send(msg).await;
|
let _ = self.write_tx.send(msg).await;
|
||||||
recv.await.expect("channel closed")
|
recv.await.expect("channel closed")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
|
||||||
async fn ws_write(
|
async fn ws_write(
|
||||||
mut write_receiver: mpsc::Receiver<SendMessage>,
|
mut write_receiver: mpsc::Receiver<SendMessage>,
|
||||||
mut ws_writer: SplitSink<WebSocket, Message>,
|
mut ws_writer: SplitSink<WebSocket, Message>,
|
||||||
mut shutdown_receiver: oneshot::Receiver<()>,
|
|
||||||
) {
|
) {
|
||||||
loop {
|
while let Some(msg) = write_receiver.recv().await {
|
||||||
tokio::select! {
|
match msg {
|
||||||
Some(msg) = write_receiver.recv() => {
|
SendMessage::Signal {
|
||||||
event!(Level::TRACE, "sending: {:?}", msg.signal);
|
signal,
|
||||||
|
response_chn,
|
||||||
|
} => {
|
||||||
|
event!(Level::TRACE, "sending: {:?}", signal);
|
||||||
|
|
||||||
let req = SignalRequest {
|
let req = SignalRequest {
|
||||||
message: Some(msg.signal),
|
message: Some(signal),
|
||||||
};
|
};
|
||||||
|
|
||||||
let write_res = ws_writer.send(Message::Binary(req.encode_to_vec())).await;
|
let write_res = ws_writer.send(Message::Binary(req.encode_to_vec())).await;
|
||||||
if let Err(err) = write_res {
|
if let Err(err) = write_res {
|
||||||
event!(Level::ERROR, "failed to send message to ws: {:?}", err);
|
event!(Level::ERROR, "failed to send signal: {:?}", err);
|
||||||
let _ = msg.response_chn.send(Err(err.into()));
|
let _ = response_chn.send(Err(err.into()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = msg.response_chn.send(Ok(()));
|
let _ = response_chn.send(Ok(()));
|
||||||
},
|
}
|
||||||
_ = (&mut shutdown_receiver) => {
|
Pong { ping_data } => {
|
||||||
let _ = ws_writer.send(Message::Close(Some(CloseFrame {
|
if let Err(err) = ws_writer.send(Message::Pong(ping_data)).await {
|
||||||
|
event!(Level::ERROR, "failed to send pong message: {:?}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = ws_writer
|
||||||
|
.send(Message::Close(Some(CloseFrame {
|
||||||
code: CloseCode::Normal,
|
code: CloseCode::Normal,
|
||||||
reason: "disconnected by client".into()
|
reason: "disconnected by client".into(),
|
||||||
}))).await;
|
})))
|
||||||
|
.await;
|
||||||
let _ = ws_writer.flush().await;
|
let _ = ws_writer.flush().await;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
|
||||||
async fn ws_read(
|
async fn ws_read(
|
||||||
mut read_receiver: mpsc::Receiver<RecvMessage>,
|
mut read_receiver: mpsc::Receiver<RecvMessage>,
|
||||||
mut ws_reader: SplitStream<WebSocket>,
|
mut ws_reader: SplitStream<WebSocket>,
|
||||||
mut shutdown_receiver: oneshot::Receiver<()>,
|
write_tx: mpsc::Sender<SendMessage>,
|
||||||
) {
|
) {
|
||||||
|
while let Some(RecvMessage::Signal { mut response_chn }) = read_receiver.recv().await {
|
||||||
|
tokio::select! {
|
||||||
|
read = Self::handle_msg(&mut ws_reader, &write_tx) => {
|
||||||
|
let _ = response_chn.send(read);
|
||||||
|
}
|
||||||
|
_ = poll_fn(|cx| response_chn.poll_closed(cx)) => {
|
||||||
|
continue; // Cancelled
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_msg(
|
||||||
|
ws_reader: &mut SplitStream<WebSocket>,
|
||||||
|
write_tx: &mpsc::Sender<SendMessage>,
|
||||||
|
) -> Option<signal_response::Message> {
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
let read = ws_reader.next().await?;
|
||||||
Some(mut msg) = read_receiver.recv() => {
|
|
||||||
tokio::select! {
|
|
||||||
Some(read) = ws_reader.next() => {
|
|
||||||
match read {
|
match read {
|
||||||
Ok(Message::Binary(data)) => {
|
Ok(Message::Binary(data)) => {
|
||||||
let res = SignalResponse::decode(data.as_slice()).expect("failed to decode SignalResponse");
|
let res = SignalResponse::decode(data.as_slice())
|
||||||
let signal = res.message.unwrap();
|
.expect("failed to decode SignalResponse");
|
||||||
event!(Level::TRACE, "received: {:?}", signal);
|
event!(Level::TRACE, "received: {:?}", res);
|
||||||
let _ = msg.response_chn.send(Some(signal));
|
return Some(res.message.unwrap());
|
||||||
|
}
|
||||||
|
Ok(Message::Ping(data)) => {
|
||||||
|
let _ = write_tx.send(Pong { ping_data: data });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Ok(Message::Close(close)) => {
|
||||||
|
event!(Level::DEBUG, "server closed the connection: {:?}", close);
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
event!(Level::ERROR, "unhandled websocket message {:?}", read);
|
event!(Level::ERROR, "unhandled websocket message {:?}", read);
|
||||||
let _ = msg.response_chn.send(None);
|
return None;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
_ = poll_fn(|cx| msg.response_chn.poll_closed(cx)) => {
|
|
||||||
continue; // Cancelled
|
|
||||||
},
|
|
||||||
else => {
|
|
||||||
break; // Connection closed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ = (&mut shutdown_receiver) => break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ class IceCandidate {
|
|||||||
|
|
||||||
rust::String sdp_mid() const;
|
rust::String sdp_mid() const;
|
||||||
int sdp_mline_index() const;
|
int sdp_mline_index() const;
|
||||||
rust::String candidate() const; // TODO(theomonnom) Return livekit::Candidate instead of rust::String
|
rust::String candidate() const; // TODO(theomonnom) Return livekit::Candidate
|
||||||
|
// instead of rust::String
|
||||||
|
|
||||||
rust::String stringify() const;
|
rust::String stringify() const;
|
||||||
std::unique_ptr<webrtc::IceCandidateInterface> release();
|
std::unique_ptr<webrtc::IceCandidateInterface> release();
|
||||||
@@ -30,7 +31,9 @@ class IceCandidate {
|
|||||||
std::unique_ptr<webrtc::IceCandidateInterface> ice_candidate_;
|
std::unique_ptr<webrtc::IceCandidateInterface> ice_candidate_;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<IceCandidate> create_ice_candidate(rust::String sdp_mid, int sdp_mline_index, rust::String sdp);
|
std::unique_ptr<IceCandidate> create_ice_candidate(rust::String sdp_mid,
|
||||||
|
int sdp_mline_index,
|
||||||
|
rust::String sdp);
|
||||||
|
|
||||||
static std::unique_ptr<IceCandidate> _unique_ice_candidate() {
|
static std::unique_ptr<IceCandidate> _unique_ice_candidate() {
|
||||||
return nullptr; // Ignore
|
return nullptr; // Ignore
|
||||||
@@ -49,7 +52,9 @@ class SessionDescription {
|
|||||||
std::unique_ptr<webrtc::SessionDescriptionInterface> session_description_;
|
std::unique_ptr<webrtc::SessionDescriptionInterface> session_description_;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<SessionDescription> create_session_description(SdpType type, rust::String sdp);
|
std::unique_ptr<SessionDescription> create_session_description(
|
||||||
|
SdpType type,
|
||||||
|
rust::String sdp);
|
||||||
|
|
||||||
static std::unique_ptr<SessionDescription> _unique_session_description() {
|
static std::unique_ptr<SessionDescription> _unique_session_description() {
|
||||||
return nullptr; // Ignore
|
return nullptr; // Ignore
|
||||||
|
|||||||
@@ -69,7 +69,8 @@ create_native_add_ice_candidate_observer(
|
|||||||
|
|
||||||
class NativePeerConnectionObserver : public webrtc::PeerConnectionObserver {
|
class NativePeerConnectionObserver : public webrtc::PeerConnectionObserver {
|
||||||
public:
|
public:
|
||||||
explicit NativePeerConnectionObserver(std::shared_ptr<RTCRuntime> rtc_runtime,
|
explicit NativePeerConnectionObserver(
|
||||||
|
std::shared_ptr<RTCRuntime> rtc_runtime,
|
||||||
rust::Box<PeerConnectionObserverWrapper> observer);
|
rust::Box<PeerConnectionObserverWrapper> observer);
|
||||||
|
|
||||||
void OnSignalingChange(
|
void OnSignalingChange(
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ class PeerConnectionFactory {
|
|||||||
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_factory_;
|
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_factory_;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<PeerConnectionFactory> create_peer_connection_factory(std::shared_ptr<RTCRuntime> rtc_runtime);
|
std::unique_ptr<PeerConnectionFactory> create_peer_connection_factory(
|
||||||
|
std::shared_ptr<RTCRuntime> rtc_runtime);
|
||||||
std::unique_ptr<NativeRTCConfiguration> create_rtc_configuration(
|
std::unique_ptr<NativeRTCConfiguration> create_rtc_configuration(
|
||||||
RTCConfiguration conf);
|
RTCConfiguration conf);
|
||||||
} // namespace livekit
|
} // namespace livekit
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ namespace livekit {
|
|||||||
DataChannel::DataChannel(
|
DataChannel::DataChannel(
|
||||||
std::shared_ptr<RTCRuntime> rtc_runtime,
|
std::shared_ptr<RTCRuntime> rtc_runtime,
|
||||||
rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel)
|
rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel)
|
||||||
: rtc_runtime_(std::move(rtc_runtime)), data_channel_(std::move(data_channel)) {}
|
: rtc_runtime_(std::move(rtc_runtime)),
|
||||||
|
data_channel_(std::move(data_channel)) {}
|
||||||
|
|
||||||
void DataChannel::register_observer(NativeDataChannelObserver& observer) {
|
void DataChannel::register_observer(NativeDataChannelObserver& observer) {
|
||||||
data_channel_->RegisterObserver(&observer);
|
data_channel_->RegisterObserver(&observer);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::Debug;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
#[cxx::bridge(namespace = "livekit")]
|
#[cxx::bridge(namespace = "livekit")]
|
||||||
|
|||||||
@@ -84,9 +84,11 @@ impl Display for ffi::SdpParseError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for ffi::SessionDescription {}
|
unsafe impl Send for ffi::SessionDescription {}
|
||||||
|
|
||||||
unsafe impl Sync for ffi::SessionDescription {}
|
unsafe impl Sync for ffi::SessionDescription {}
|
||||||
|
|
||||||
unsafe impl Send for ffi::IceCandidate {}
|
unsafe impl Send for ffi::IceCandidate {}
|
||||||
|
|
||||||
unsafe impl Sync for ffi::IceCandidate {}
|
unsafe impl Sync for ffi::IceCandidate {}
|
||||||
|
|
||||||
impl ffi::SdpParseError {
|
impl ffi::SdpParseError {
|
||||||
|
|||||||
@@ -152,7 +152,8 @@ void NativePeerConnectionObserver::OnRemoveStream(
|
|||||||
|
|
||||||
void NativePeerConnectionObserver::OnDataChannel(
|
void NativePeerConnectionObserver::OnDataChannel(
|
||||||
rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) {
|
rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) {
|
||||||
observer_->on_data_channel(std::make_unique<DataChannel>(rtc_runtime_, data_channel));
|
observer_->on_data_channel(
|
||||||
|
std::make_unique<DataChannel>(rtc_runtime_, data_channel));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativePeerConnectionObserver::OnRenegotiationNeeded() {
|
void NativePeerConnectionObserver::OnRenegotiationNeeded() {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use cxx::UniquePtr;
|
use cxx::UniquePtr;
|
||||||
|
|
||||||
use crate::candidate::ffi::Candidate;
|
use crate::candidate::ffi::Candidate;
|
||||||
@@ -259,21 +260,27 @@ pub mod ffi {
|
|||||||
|
|
||||||
// https://webrtc.github.io/webrtc-org/native-code/native-apis/
|
// https://webrtc.github.io/webrtc-org/native-code/native-apis/
|
||||||
unsafe impl Send for ffi::PeerConnection {}
|
unsafe impl Send for ffi::PeerConnection {}
|
||||||
|
|
||||||
unsafe impl Sync for ffi::PeerConnection {}
|
unsafe impl Sync for ffi::PeerConnection {}
|
||||||
|
|
||||||
unsafe impl Send for ffi::NativePeerConnectionObserver {}
|
unsafe impl Send for ffi::NativePeerConnectionObserver {}
|
||||||
|
|
||||||
unsafe impl Sync for ffi::NativePeerConnectionObserver {}
|
unsafe impl Sync for ffi::NativePeerConnectionObserver {}
|
||||||
|
|
||||||
unsafe impl Sync for ffi::NativeAddIceCandidateObserver {}
|
unsafe impl Sync for ffi::NativeAddIceCandidateObserver {}
|
||||||
|
|
||||||
unsafe impl Send for ffi::NativeAddIceCandidateObserver {}
|
unsafe impl Send for ffi::NativeAddIceCandidateObserver {}
|
||||||
|
|
||||||
unsafe impl Sync for ffi::NativeSetRemoteSdpObserverHandle {}
|
unsafe impl Sync for ffi::NativeSetRemoteSdpObserverHandle {}
|
||||||
|
|
||||||
unsafe impl Send for ffi::NativeSetRemoteSdpObserverHandle {}
|
unsafe impl Send for ffi::NativeSetRemoteSdpObserverHandle {}
|
||||||
|
|
||||||
unsafe impl Sync for ffi::NativeSetLocalSdpObserverHandle {}
|
unsafe impl Sync for ffi::NativeSetLocalSdpObserverHandle {}
|
||||||
|
|
||||||
unsafe impl Send for ffi::NativeSetLocalSdpObserverHandle {}
|
unsafe impl Send for ffi::NativeSetLocalSdpObserverHandle {}
|
||||||
|
|
||||||
unsafe impl Sync for ffi::NativeCreateSdpObserverHandle {}
|
unsafe impl Sync for ffi::NativeCreateSdpObserverHandle {}
|
||||||
|
|
||||||
unsafe impl Send for ffi::NativeCreateSdpObserverHandle {}
|
unsafe impl Send for ffi::NativeCreateSdpObserverHandle {}
|
||||||
|
|
||||||
impl Default for ffi::RTCOfferAnswerOptions {
|
impl Default for ffi::RTCOfferAnswerOptions {
|
||||||
|
|||||||
@@ -67,7 +67,8 @@ std::unique_ptr<PeerConnection> PeerConnectionFactory::create_peer_connection(
|
|||||||
return std::make_unique<PeerConnection>(rtc_runtime_, result.value());
|
return std::make_unique<PeerConnection>(rtc_runtime_, result.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PeerConnectionFactory> create_peer_connection_factory(std::shared_ptr<RTCRuntime> rtc_runtime) {
|
std::unique_ptr<PeerConnectionFactory> create_peer_connection_factory(
|
||||||
|
std::shared_ptr<RTCRuntime> rtc_runtime) {
|
||||||
return std::make_unique<PeerConnectionFactory>(std::move(rtc_runtime));
|
return std::make_unique<PeerConnectionFactory>(std::move(rtc_runtime));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
use std::any::Any;
|
|
||||||
|
|
||||||
use crate::jsep::CreateSdpObserver;
|
|
||||||
use crate::peer_connection::PeerConnectionObserver;
|
|
||||||
|
|
||||||
#[cxx::bridge(namespace = "livekit")]
|
#[cxx::bridge(namespace = "livekit")]
|
||||||
pub mod ffi {
|
pub mod ffi {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -59,4 +54,5 @@ pub mod ffi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for ffi::PeerConnectionFactory {}
|
unsafe impl Send for ffi::PeerConnectionFactory {}
|
||||||
|
|
||||||
unsafe impl Sync for ffi::PeerConnectionFactory {}
|
unsafe impl Sync for ffi::PeerConnectionFactory {}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
use crate::rtc_error::ffi::RTCErrorType;
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
|
use crate::rtc_error::ffi::RTCErrorType;
|
||||||
|
|
||||||
// cxx doesn't support custom Exception type, so we serialize RTCError inside the cxx::Exception "what" string
|
// cxx doesn't support custom Exception type, so we serialize RTCError inside the cxx::Exception "what" string
|
||||||
|
|
||||||
#[cxx::bridge(namespace = "livekit")]
|
#[cxx::bridge(namespace = "livekit")]
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use cxx::UniquePtr;
|
|
||||||
|
|
||||||
#[cxx::bridge(namespace = "livekit")]
|
#[cxx::bridge(namespace = "livekit")]
|
||||||
pub mod ffi {
|
pub mod ffi {
|
||||||
unsafe extern "C++" {
|
unsafe extern "C++" {
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use cxx::UniquePtr;
|
|
||||||
|
|
||||||
#[cxx::bridge(namespace = "livekit")]
|
#[cxx::bridge(namespace = "livekit")]
|
||||||
pub mod ffi {
|
pub mod ffi {
|
||||||
unsafe extern "C++" {
|
unsafe extern "C++" {
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use cxx::UniquePtr;
|
|
||||||
|
|
||||||
#[cxx::bridge(namespace = "livekit")]
|
#[cxx::bridge(namespace = "livekit")]
|
||||||
pub mod ffi {
|
pub mod ffi {
|
||||||
unsafe extern "C++" {
|
unsafe extern "C++" {
|
||||||
@@ -12,4 +10,5 @@ pub mod ffi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for ffi::RTCRuntime {}
|
unsafe impl Send for ffi::RTCRuntime {}
|
||||||
|
|
||||||
unsafe impl Sync for ffi::RTCRuntime {}
|
unsafe impl Sync for ffi::RTCRuntime {}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use cxx::UniquePtr;
|
use cxx::UniquePtr;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
use libwebrtc_sys::data_channel as sys_dc;
|
use libwebrtc_sys::data_channel as sys_dc;
|
||||||
|
pub use sys_dc::ffi::{DataState, Priority};
|
||||||
pub use sys_dc::ffi::{Priority, DataState};
|
|
||||||
|
|
||||||
pub struct DataChannel {
|
pub struct DataChannel {
|
||||||
cxx_handle: UniquePtr<sys_dc::ffi::DataChannel>,
|
cxx_handle: UniquePtr<sys_dc::ffi::DataChannel>,
|
||||||
@@ -100,7 +100,8 @@ impl DataChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub type OnStateChangeHandler = Box<dyn FnMut() + Send + Sync>;
|
pub type OnStateChangeHandler = Box<dyn FnMut() + Send + Sync>;
|
||||||
pub type OnMessageHandler = Box<dyn FnMut(&[u8], bool) + Send + Sync>; // data, is_binary
|
pub type OnMessageHandler = Box<dyn FnMut(&[u8], bool) + Send + Sync>;
|
||||||
|
// data, is_binary
|
||||||
pub type OnBufferedAmountChangeHandler = Box<dyn FnMut(u64) + Send + Sync>;
|
pub type OnBufferedAmountChangeHandler = Box<dyn FnMut(u64) + Send + Sync>;
|
||||||
|
|
||||||
struct InternalDataChannelObserver {
|
struct InternalDataChannelObserver {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use std::fmt::{Debug, Display, Formatter, write};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
use cxx::UniquePtr;
|
|
||||||
use libwebrtc_sys::jsep as sys_jsep;
|
|
||||||
|
|
||||||
pub use sys_jsep::ffi::{SdpType, SdpParseError};
|
use cxx::UniquePtr;
|
||||||
|
|
||||||
|
use libwebrtc_sys::jsep as sys_jsep;
|
||||||
|
pub use sys_jsep::ffi::{SdpParseError, SdpType};
|
||||||
|
|
||||||
// TODO Maybe we can replace that by a serialized IceCandidateInit
|
// TODO Maybe we can replace that by a serialized IceCandidateInit
|
||||||
pub struct IceCandidate {
|
pub struct IceCandidate {
|
||||||
|
|||||||
@@ -626,6 +626,7 @@ impl sys_pc::PeerConnectionObserver for InternalObserver {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
use libwebrtc_sys::peer_connection::ffi::RTCOfferAnswerOptions;
|
use libwebrtc_sys::peer_connection::ffi::RTCOfferAnswerOptions;
|
||||||
use libwebrtc_sys::peer_connection_factory::ffi::{ContinualGatheringPolicy, IceTransportsType};
|
use libwebrtc_sys::peer_connection_factory::ffi::{ContinualGatheringPolicy, IceTransportsType};
|
||||||
|
|
||||||
@@ -652,7 +653,7 @@ mod tests {
|
|||||||
password: "".into(),
|
password: "".into(),
|
||||||
}],
|
}],
|
||||||
continual_gathering_policy: ContinualGatheringPolicy::GatherOnce,
|
continual_gathering_policy: ContinualGatheringPolicy::GatherOnce,
|
||||||
ice_transport_type: IceTransportsType::All
|
ice_transport_type: IceTransportsType::All,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut bob = factory.create_peer_connection(config.clone()).unwrap();
|
let mut bob = factory.create_peer_connection(config.clone()).unwrap();
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
// TODO(theomonnom) Wrap the RTCError ffi so we can use Option(u16)
|
// TODO(theomonnom) Wrap the RTCError ffi so we can use Option(u16)
|
||||||
pub use libwebrtc_sys::rtc_error::ffi::RTCError;
|
pub use libwebrtc_sys::rtc_error::ffi::RTCError;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use cxx::{SharedPtr};
|
use cxx::SharedPtr;
|
||||||
|
|
||||||
use libwebrtc_sys::webrtc as sys_rtc;
|
use libwebrtc_sys::webrtc as sys_rtc;
|
||||||
|
|
||||||
|
|||||||
Generated
+1347
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
|||||||
|
[workspace]
|
||||||
|
members = ["*"]
|
||||||
|
exclude = ["target"]
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "simple_room"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
tracing = "0.1"
|
||||||
|
tracing-subscriber = "0.3"
|
||||||
|
livekit = { path = "../.." }
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
use livekit::proto::data_packet;
|
||||||
|
use livekit::room;
|
||||||
|
|
||||||
|
const URL: &str = "ws://localhost:7880";
|
||||||
|
const TOKEN : &str = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjgxMzc0NDgsImlzcyI6IkFQSXpLYkFTaUNWYWtnSiIsIm5hbWUiOiJ3ZWIiLCJuYmYiOjE2NjQ1Mzc0NDgsInN1YiI6IndlYiIsInZpZGVvIjp7InJvb21DcmVhdGUiOnRydWUsInJvb21Kb2luIjp0cnVlfX0.6VMDdXJYrW3KWrEzxx4hzbmMQnjQIRILQ48Qrbx5j44";
|
||||||
|
|
||||||
|
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjgxMzc0NDgsImlzcyI6IkFQSXpLYkFTaUNWYWtnSiIsIm5hbWUiOiJ3ZWIiLCJuYmYiOjE2NjQ1Mzc0NDgsInN1YiI6IndlYiIsInZpZGVvIjp7InJvb21DcmVhdGUiOnRydWUsInJvb21Kb2luIjp0cnVlfX0.6VMDdXJYrW3KWrEzxx4hzbmMQnjQIRILQ48Qrbx5j44
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<(), room::RoomError> {
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
|
let mut room = room::connect(URL, TOKEN).await?;
|
||||||
|
room.local_participant()
|
||||||
|
.publish_data(b"this is a test", data_packet::Kind::Reliable)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
+2
-1
@@ -1 +1,2 @@
|
|||||||
|
// export everything inside livekit-core
|
||||||
|
pub use livekit_core::*;
|
||||||
Reference in New Issue
Block a user