wip x2
This commit is contained in:
@@ -1,28 +1,23 @@
|
|||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use std::error;
|
|
||||||
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use tokio::time::sleep;
|
||||||
use tokio::sync::{mpsc, Mutex as AsyncMutex};
|
use tokio::sync::{mpsc, Mutex as AsyncMutex};
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use prost::Message;
|
use prost::Message;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
|
||||||
use tokio::time::sleep;
|
|
||||||
use tracing::{debug, error, info, trace, warn};
|
use tracing::{debug, error, info, trace, warn};
|
||||||
|
|
||||||
use crate::{proto, signal_client};
|
use crate::{proto, signal_client};
|
||||||
use livekit_webrtc::data_channel::{DataChannel, DataChannelInit, DataSendError, DataState};
|
use livekit_webrtc::data_channel::{DataChannel, DataChannelInit, DataSendError, DataState};
|
||||||
use livekit_webrtc::jsep::{IceCandidate, SdpParseError, SessionDescription};
|
use livekit_webrtc::jsep::{IceCandidate, SdpParseError, SessionDescription};
|
||||||
use livekit_webrtc::media_stream::MediaStream;
|
|
||||||
use livekit_webrtc::peer_connection::{
|
use livekit_webrtc::peer_connection::{
|
||||||
IceConnectionState, PeerConnectionState, RTCOfferAnswerOptions,
|
IceConnectionState, PeerConnectionState, RTCOfferAnswerOptions,
|
||||||
};
|
};
|
||||||
use livekit_webrtc::peer_connection_factory::RTCConfiguration;
|
use livekit_webrtc::peer_connection_factory::RTCConfiguration;
|
||||||
use livekit_webrtc::rtc_error::RTCError;
|
|
||||||
use livekit_webrtc::rtp_receiver::RtpReceiver;
|
|
||||||
|
|
||||||
use crate::proto::data_packet::Value;
|
use crate::proto::data_packet::Value;
|
||||||
use crate::proto::{
|
use crate::proto::{
|
||||||
@@ -33,10 +28,8 @@ use crate::rtc_engine::lk_runtime::LKRuntime;
|
|||||||
use crate::rtc_engine::pc_transport::PCTransport;
|
use crate::rtc_engine::pc_transport::PCTransport;
|
||||||
use crate::rtc_engine::rtc_events::{RTCEmitter, RTCEvent, RTCEvents};
|
use crate::rtc_engine::rtc_events::{RTCEmitter, RTCEvent, RTCEvents};
|
||||||
use crate::signal_client::{SignalClient, SignalError, SignalEvent, SignalEvents, SignalOptions};
|
use crate::signal_client::{SignalClient, SignalError, SignalEvent, SignalEvents, SignalOptions};
|
||||||
use std::cell::RefCell;
|
|
||||||
|
|
||||||
use super::{rtc_events, EngineEvents};
|
use super::{rtc_events, EngineEmitter, EngineError, EngineEvent, EngineEvents, EngineResult};
|
||||||
use super::{EngineEmitter, EngineError, EngineEvent, EngineEvents, EngineResult};
|
|
||||||
//
|
//
|
||||||
// TODO(theomonnom): Smarter retry intervals
|
// TODO(theomonnom): Smarter retry intervals
|
||||||
pub(crate) const RECONNECT_ATTEMPTS: u32 = 10;
|
pub(crate) const RECONNECT_ATTEMPTS: u32 = 10;
|
||||||
@@ -60,7 +53,7 @@ pub enum PCState {
|
|||||||
Closed,
|
Closed,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
pub struct SessionInfo {
|
pub struct SessionInfo {
|
||||||
url: String,
|
url: String,
|
||||||
token: String,
|
token: String,
|
||||||
@@ -70,6 +63,7 @@ pub struct SessionInfo {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EngineInternal {
|
pub struct EngineInternal {
|
||||||
lk_runtime: Arc<LKRuntime>,
|
lk_runtime: Arc<LKRuntime>,
|
||||||
|
info: Mutex<SessionInfo>,
|
||||||
signal_client: Arc<SignalClient>,
|
signal_client: Arc<SignalClient>,
|
||||||
session: Arc<RwLock<Option<RTCSession>>>,
|
session: Arc<RwLock<Option<RTCSession>>>,
|
||||||
reconnecting: AtomicBool,
|
reconnecting: AtomicBool,
|
||||||
@@ -283,7 +277,12 @@ impl EngineInternal {
|
|||||||
tokio::spawn(self.clone().engine_task(rtc_events));
|
tokio::spawn(self.clone().engine_task(rtc_events));
|
||||||
|
|
||||||
if !join_response.subscriber_primary {
|
if !join_response.subscriber_primary {
|
||||||
session.read().unwrap().negotiate_publisher().await?;
|
session
|
||||||
|
.read()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.negotiate_publisher()
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(engine_events)
|
Ok(engine_events)
|
||||||
@@ -327,19 +326,24 @@ impl EngineInternal {
|
|||||||
|
|
||||||
trace!("sending ice_candidate ({:?}) - {:?}", target, ice_candidate);
|
trace!("sending ice_candidate ({:?}) - {:?}", target, ice_candidate);
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn({
|
||||||
signal_client
|
let signal_client = self.signal_client.clone();
|
||||||
.send(signal_request::Message::Trickle(TrickleRequest {
|
async move {
|
||||||
candidate_init: json,
|
signal_client
|
||||||
target: target as i32,
|
.send(signal_request::Message::Trickle(TrickleRequest {
|
||||||
}))
|
candidate_init: json,
|
||||||
.await;
|
target: target as i32,
|
||||||
|
}))
|
||||||
|
.await;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
RTCEvent::ConnectionChange { state, target } => {
|
RTCEvent::ConnectionChange { state, target } => {
|
||||||
trace!("connection change, {:?} {:?}", state, target);
|
trace!("connection change, {:?} {:?}", state, target);
|
||||||
let subscriber_primary = session
|
let subscriber_primary = self
|
||||||
|
.session
|
||||||
.read()
|
.read()
|
||||||
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.join_response
|
.join_response
|
||||||
.lock()
|
.lock()
|
||||||
@@ -348,22 +352,26 @@ impl EngineInternal {
|
|||||||
let is_primary = subscriber_primary && target == SignalTarget::Subscriber;
|
let is_primary = subscriber_primary && target == SignalTarget::Subscriber;
|
||||||
|
|
||||||
if is_primary && state == PeerConnectionState::Connected {
|
if is_primary && state == PeerConnectionState::Connected {
|
||||||
let old_state = session
|
let old_state = self
|
||||||
|
.session
|
||||||
.read()
|
.read()
|
||||||
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.pc_state
|
.pc_state
|
||||||
.swap(PCState::Connected as u8, Ordering::SeqCst);
|
.swap(PCState::Connected as u8, Ordering::SeqCst);
|
||||||
if old_state == PCState::New as u8 {
|
if old_state == PCState::New as u8 {
|
||||||
let _ = emitter.send(EngineEvent::Connected).await; // First time connected
|
let _ = self.engine_emitter.send(EngineEvent::Connected).await;
|
||||||
|
// First time connected
|
||||||
}
|
}
|
||||||
} else if state == PeerConnectionState::Failed {
|
} else if state == PeerConnectionState::Failed {
|
||||||
session
|
self.session
|
||||||
.read()
|
.read()
|
||||||
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.pc_state
|
.pc_state
|
||||||
.store(PCState::Disconnected as u8, Ordering::SeqCst);
|
.store(PCState::Disconnected as u8, Ordering::SeqCst);
|
||||||
|
|
||||||
Self::handle_disconnected(signal_client, engine_inner, emitter);
|
self.handle_disconnected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RTCEvent::DataChannel {
|
RTCEvent::DataChannel {
|
||||||
@@ -372,22 +380,27 @@ impl EngineInternal {
|
|||||||
} => {
|
} => {
|
||||||
if target == SignalTarget::Subscriber {
|
if target == SignalTarget::Subscriber {
|
||||||
if data_channel.label() == RELIABLE_DC_LABEL {
|
if data_channel.label() == RELIABLE_DC_LABEL {
|
||||||
*session.read().unwrap().sub_reliable_dc.lock() = Some(data_channel);
|
*self.session.read().as_ref().unwrap().sub_reliable_dc.lock() =
|
||||||
|
Some(data_channel);
|
||||||
} else {
|
} else {
|
||||||
*session.read().unwrap().sub_lossy_dc.lock() = Some(data_channel);
|
*self.session.read().as_ref().unwrap().sub_lossy_dc.lock() =
|
||||||
|
Some(data_channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RTCEvent::Offer { offer, target } => {
|
RTCEvent::Offer { offer, target } => {
|
||||||
if target == SignalTarget::Publisher {
|
if target == SignalTarget::Publisher {
|
||||||
// Send the publisher offer to the server
|
// Send the publisher offer to the server
|
||||||
tokio::spawn(async move {
|
tokio::spawn({
|
||||||
signal_client
|
let signal_client = self.signal_client.clone();
|
||||||
.send(signal_request::Message::Offer(proto::SessionDescription {
|
async move {
|
||||||
r#type: "offer".to_string(),
|
signal_client
|
||||||
sdp: offer.to_string(),
|
.send(signal_request::Message::Offer(proto::SessionDescription {
|
||||||
}))
|
r#type: "offer".to_string(),
|
||||||
.await;
|
sdp: offer.to_string(),
|
||||||
|
}))
|
||||||
|
.await;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -397,7 +410,8 @@ impl EngineInternal {
|
|||||||
target,
|
target,
|
||||||
} => {
|
} => {
|
||||||
if target == SignalTarget::Subscriber {
|
if target == SignalTarget::Subscriber {
|
||||||
let _ = emitter
|
let _ = self
|
||||||
|
.engine_emitter
|
||||||
.send(EngineEvent::AddTrack {
|
.send(EngineEvent::AddTrack {
|
||||||
rtp_receiver,
|
rtp_receiver,
|
||||||
streams,
|
streams,
|
||||||
@@ -435,6 +449,7 @@ impl EngineInternal {
|
|||||||
let sdp = SessionDescription::from(answer.r#type.parse().unwrap(), &answer.sdp)?;
|
let sdp = SessionDescription::from(answer.r#type.parse().unwrap(), &answer.sdp)?;
|
||||||
self.session
|
self.session
|
||||||
.read()
|
.read()
|
||||||
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.publisher_pc
|
.publisher_pc
|
||||||
.lock()
|
.lock()
|
||||||
@@ -448,14 +463,8 @@ impl EngineInternal {
|
|||||||
trace!("received offer for the subscriber: {:?}", offer);
|
trace!("received offer for the subscriber: {:?}", offer);
|
||||||
let sdp = SessionDescription::from(offer.r#type.parse().unwrap(), &offer.sdp)?;
|
let sdp = SessionDescription::from(offer.r#type.parse().unwrap(), &offer.sdp)?;
|
||||||
|
|
||||||
let subscriber_pc = self
|
let session = self.session.read();
|
||||||
.session
|
let mut subscriber_pc = session.as_ref().unwrap().subscriber_pc.lock().await;
|
||||||
.read()
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.subscriber_pc
|
|
||||||
.lock()
|
|
||||||
.await;
|
|
||||||
|
|
||||||
subscriber_pc.set_remote_description(sdp).await?;
|
subscriber_pc.set_remote_description(sdp).await?;
|
||||||
let answer = subscriber_pc
|
let answer = subscriber_pc
|
||||||
@@ -467,13 +476,16 @@ impl EngineInternal {
|
|||||||
.set_local_description(answer.clone())
|
.set_local_description(answer.clone())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn({
|
||||||
self.signal_client
|
let signal_client = self.signal_client.clone();
|
||||||
.send(signal_request::Message::Answer(proto::SessionDescription {
|
async move {
|
||||||
r#type: "answer".to_string(),
|
signal_client
|
||||||
sdp: answer.to_string(),
|
.send(signal_request::Message::Answer(proto::SessionDescription {
|
||||||
}))
|
r#type: "answer".to_string(),
|
||||||
.await;
|
sdp: answer.to_string(),
|
||||||
|
}))
|
||||||
|
.await;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
signal_response::Message::Trickle(trickle) => {
|
signal_response::Message::Trickle(trickle) => {
|
||||||
@@ -490,6 +502,7 @@ impl EngineInternal {
|
|||||||
if trickle.target == SignalTarget::Publisher as i32 {
|
if trickle.target == SignalTarget::Publisher as i32 {
|
||||||
self.session
|
self.session
|
||||||
.read()
|
.read()
|
||||||
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.publisher_pc
|
.publisher_pc
|
||||||
.lock()
|
.lock()
|
||||||
@@ -499,6 +512,7 @@ impl EngineInternal {
|
|||||||
} else {
|
} else {
|
||||||
self.session
|
self.session
|
||||||
.read()
|
.read()
|
||||||
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.subscriber_pc
|
.subscriber_pc
|
||||||
.lock()
|
.lock()
|
||||||
@@ -508,7 +522,10 @@ impl EngineInternal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
signal_response::Message::Update(update) => {
|
signal_response::Message::Update(update) => {
|
||||||
let _ = emitter.send(EngineEvent::ParticipantUpdate(update)).await;
|
let _ = self
|
||||||
|
.engine_emitter
|
||||||
|
.send(EngineEvent::ParticipantUpdate(update))
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -531,34 +548,22 @@ impl EngineInternal {
|
|||||||
for i in 0..RECONNECT_ATTEMPTS {
|
for i in 0..RECONNECT_ATTEMPTS {
|
||||||
if full_reconnect {
|
if full_reconnect {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
let _ = emitter.send(EngineEvent::Restarting).await;
|
let _ = self.engine_emitter.send(EngineEvent::Restarting).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("restarting connection... attempt: {}", i);
|
info!("restarting connection... attempt: {}", i);
|
||||||
if let Err(err) = Self::try_restart_connection(
|
if let Err(err) = self.try_restart_connection().await {
|
||||||
signal_client.clone(),
|
|
||||||
engine_inner.clone(),
|
|
||||||
emitter.clone(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
error!("restarting connection failed: {}", err);
|
error!("restarting connection failed: {}", err);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
let _ = emitter.send(EngineEvent::Resuming).await;
|
let _ = self.engine_emitter.send(EngineEvent::Resuming).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("resuming connection... attempt: {}", i);
|
info!("resuming connection... attempt: {}", i);
|
||||||
if let Err(err) = Self::try_resume_connection(
|
if let Err(err) = self.try_resume_connection().await {
|
||||||
signal_client.clone(),
|
|
||||||
engine_inner.clone(),
|
|
||||||
emitter.clone(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
error!("resuming connection failed: {}", err);
|
error!("resuming connection failed: {}", err);
|
||||||
if let EngineError::Signal(_) = err {
|
if let EngineError::Signal(_) = err {
|
||||||
full_reconnect = true;
|
full_reconnect = true;
|
||||||
@@ -576,21 +581,17 @@ impl EngineInternal {
|
|||||||
// TODO DISCONNECT
|
// TODO DISCONNECT
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn try_restart_connection(
|
async fn try_restart_connection(self: &Arc<Self>) -> EngineResult<()> {
|
||||||
self: Arc<Self>,
|
|
||||||
signal_client: Arc<SignalClient>,
|
|
||||||
emitter: EngineEmitter,
|
|
||||||
) -> EngineResult<()> {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn try_resume_connection(
|
async fn try_resume_connection(self: &Arc<Self>) -> EngineResult<()> {
|
||||||
self: Arc<Self>,
|
let mut info = self.info.lock();
|
||||||
signal_client: Arc<SignalClient>,
|
info.options.sid = self
|
||||||
emitter: EngineEmitter,
|
.session
|
||||||
) -> EngineResult<()> {
|
.read()
|
||||||
let mut options = engine_inner.options.lock().clone();
|
.as_ref()
|
||||||
options.sid = engine_inner
|
.unwrap()
|
||||||
.join_response
|
.join_response
|
||||||
.lock()
|
.lock()
|
||||||
.participant
|
.participant
|
||||||
@@ -599,24 +600,34 @@ impl EngineInternal {
|
|||||||
.sid
|
.sid
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
signal_client
|
self.signal_client.close().await;
|
||||||
.reconnect(
|
self.signal_client
|
||||||
&engine_inner.url,
|
.connect(&info.url, &info.token.clone(), info.options.clone())
|
||||||
&engine_inner.token.lock().clone(),
|
|
||||||
options,
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let _ = emitter.send(EngineEvent::SignalResumed).await;
|
self.engine_emitter.send(EngineEvent::SignalResumed).await;
|
||||||
|
|
||||||
engine_inner
|
self.session
|
||||||
|
.read()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
.subscriber_pc
|
.subscriber_pc
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
.prepare_ice_restart();
|
.prepare_ice_restart();
|
||||||
|
|
||||||
if engine_inner.has_published.load(Ordering::SeqCst) {
|
if self
|
||||||
engine_inner
|
.session
|
||||||
|
.read()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.has_published
|
||||||
|
.load(Ordering::SeqCst)
|
||||||
|
{
|
||||||
|
self.session
|
||||||
|
.read()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
.publisher_pc
|
.publisher_pc
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
@@ -626,12 +637,15 @@ impl EngineInternal {
|
|||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
self.session
|
||||||
|
.read()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.wait_pc_connection()
|
||||||
|
.await?;
|
||||||
|
|
||||||
Self::wait_pc_connection(engine_inner).await?;
|
self.signal_client.flush_queue().await;
|
||||||
signal_client.flush_queue().await;
|
self.engine_emitter.send(EngineEvent::Resumed);
|
||||||
|
|
||||||
let _ = emitter.send(EngineEvent::Resumed);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user