Internal SessionEvents to avoid confusion with the RoomEvents

This commit is contained in:
Théo Monnom
2022-12-27 20:57:35 +01:00
parent 5f290de593
commit 9d05259c5a
4 changed files with 118 additions and 75 deletions
@@ -2,7 +2,8 @@ use crate::proto::{data_packet, DataPacket, UserPacket};
use crate::room::participant::{ use crate::room::participant::{
impl_participant_trait, ParticipantInternalTrait, ParticipantShared, ParticipantTrait, impl_participant_trait, ParticipantInternalTrait, ParticipantShared, ParticipantTrait,
}; };
use crate::room::{RoomError, RoomEmitter}; use crate::room::room_session::SessionEmitter;
use crate::room::RoomError;
use crate::rtc_engine::RTCEngine; use crate::rtc_engine::RTCEngine;
#[derive(Debug)] #[derive(Debug)]
@@ -18,10 +19,10 @@ impl LocalParticipant {
identity: ParticipantIdentity, identity: ParticipantIdentity,
name: String, name: String,
metadata: String, metadata: String,
room_emitter: RoomEmitter, internal_tx: SessionEmitter,
) -> Self { ) -> Self {
Self { Self {
shared: ParticipantShared::new(sid, identity, name, metadata, room_emitter), shared: ParticipantShared::new(sid, identity, name, metadata, internal_tx),
rtc_engine, rtc_engine,
} }
} }
@@ -3,6 +3,7 @@ use crate::room::id::{ParticipantIdentity, ParticipantSid, TrackSid};
use crate::room::participant::local_participant::LocalParticipant; use crate::room::participant::local_participant::LocalParticipant;
use crate::room::participant::remote_participant::RemoteParticipant; use crate::room::participant::remote_participant::RemoteParticipant;
use crate::room::publication::{TrackPublication, TrackPublicationTrait}; use crate::room::publication::{TrackPublication, TrackPublicationTrait};
use crate::room::room_session::SessionEmitter;
use livekit_utils::enum_dispatch; use livekit_utils::enum_dispatch;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use std::collections::HashMap; use std::collections::HashMap;
@@ -18,7 +19,7 @@ pub(super) struct ParticipantShared {
pub(super) name: Mutex<String>, pub(super) name: Mutex<String>,
pub(super) metadata: Mutex<String>, pub(super) metadata: Mutex<String>,
pub(super) tracks: RwLock<HashMap<TrackSid, TrackPublication>>, pub(super) tracks: RwLock<HashMap<TrackSid, TrackPublication>>,
pub(super) room_emitter: RoomEmitter, pub(super) internal_tx: SessionEmitter,
} }
impl ParticipantShared { impl ParticipantShared {
@@ -27,7 +28,7 @@ impl ParticipantShared {
identity: ParticipantIdentity, identity: ParticipantIdentity,
name: String, name: String,
metadata: String, metadata: String,
room_emitter: RoomEmitter, internal_tx: SessionEmitter,
) -> Self { ) -> Self {
Self { Self {
sid: Mutex::new(sid), sid: Mutex::new(sid),
@@ -35,7 +36,7 @@ impl ParticipantShared {
name: Mutex::new(name), name: Mutex::new(name),
metadata: Mutex::new(metadata), metadata: Mutex::new(metadata),
tracks: Default::default(), tracks: Default::default(),
room_emitter internal_tx,
} }
} }
@@ -7,16 +7,18 @@ use crate::room::publication::{
RemoteTrackPublication, TrackPublication, TrackPublicationInternalTrait, TrackPublicationTrait, RemoteTrackPublication, TrackPublication, TrackPublicationInternalTrait, TrackPublicationTrait,
}; };
use crate::room::room_session::RoomSession; use crate::room::room_session::RoomSession;
use crate::room::room_session::SessionEmitter;
use crate::room::room_session::SessionEvent;
use crate::room::track::remote_audio_track::RemoteAudioTrack; use crate::room::track::remote_audio_track::RemoteAudioTrack;
use crate::room::track::remote_track::RemoteTrackHandle; use crate::room::track::remote_track::RemoteTrackHandle;
use crate::room::track::remote_video_track::RemoteVideoTrack; use crate::room::track::remote_video_track::RemoteVideoTrack;
use crate::room::track::{TrackKind, TrackTrait}; use crate::room::track::{TrackKind, TrackTrait};
use crate::room::{RoomEmitter, RoomEvent, TrackError}; use crate::room::{RoomEvent, TrackError};
use livekit_webrtc::media_stream::MediaStreamTrackHandle; use livekit_webrtc::media_stream::MediaStreamTrackHandle;
use std::collections::HashSet; use std::collections::HashSet;
use std::time::Duration; use std::time::Duration;
use tokio::time::{sleep, timeout}; use tokio::time::timeout;
use tracing::{debug, debug_span, error, instrument, Instrument, Level}; use tracing::{debug, error, instrument, Level};
use super::ParticipantTrait; use super::ParticipantTrait;
@@ -33,10 +35,10 @@ impl RemoteParticipant {
identity: ParticipantIdentity, identity: ParticipantIdentity,
name: String, name: String,
metadata: String, metadata: String,
room_emitter: RoomEmitter, internal_tx: SessionEmitter,
) -> Self { ) -> Self {
Self { Self {
shared: ParticipantShared::new(sid, identity, name, metadata, room_emitter), shared: ParticipantShared::new(sid, identity, name, metadata, internal_tx),
} }
} }
@@ -50,10 +52,9 @@ impl RemoteParticipant {
}) })
} }
#[instrument(level = Level::DEBUG, skip(room_session))] #[instrument(level = Level::DEBUG)]
pub(crate) async fn add_subscribed_media_track( pub(crate) async fn add_subscribed_media_track(
self: Arc<Self>, self: Arc<Self>,
room_session: RoomSession,
sid: TrackSid, sid: TrackSid,
media_track: MediaStreamTrackHandle, media_track: MediaStreamTrackHandle,
) { ) {
@@ -67,7 +68,7 @@ impl RemoteParticipant {
return publication; return publication;
} }
tokio::task::yield_now(); tokio::task::yield_now().await;
} }
} }
}; };
@@ -108,30 +109,28 @@ impl RemoteParticipant {
.add_track_publication(TrackPublication::Remote(remote_publication.clone())); .add_track_publication(TrackPublication::Remote(remote_publication.clone()));
track.start(); track.start();
self.shared.room_emitter.send(RoomEvent::TrackSubscribed { self.shared
track: track, .internal_tx
publication: remote_publication, .send(SessionEvent::Room(RoomEvent::TrackSubscribed {
participant: self.clone(), track: track,
}); publication: remote_publication,
participant: self.clone(),
}));
} else { } else {
error!("could not find published track with sid: {:?}", sid); error!("could not find published track with sid: {:?}", sid);
self.shared self.shared
.room_emitter .internal_tx
.send(RoomEvent::TrackSubscriptionFailed { .send(SessionEvent::Room(RoomEvent::TrackSubscriptionFailed {
sid: sid.clone(), sid: sid.clone(),
error: TrackError::TrackNotFound(sid.clone().to_string()), error: TrackError::TrackNotFound(sid.clone().to_string()),
participant: self.clone(), participant: self.clone(),
}); }));
} }
} }
#[instrument(level = Level::DEBUG, skip(room_session))] #[instrument(level = Level::DEBUG)]
pub(crate) async fn update_tracks( pub(crate) async fn update_tracks(self: Arc<Self>, tracks: Vec<TrackInfo>) {
self: Arc<Self>,
room_session: RoomSession,
tracks: Vec<TrackInfo>,
) {
let mut valid_tracks = HashSet::<TrackSid>::new(); let mut valid_tracks = HashSet::<TrackSid>::new();
for track in tracks { for track in tracks {
@@ -143,10 +142,12 @@ impl RemoteParticipant {
.add_track_publication(TrackPublication::Remote(publication.clone())); .add_track_publication(TrackPublication::Remote(publication.clone()));
// This is a new track, fire publish events // This is a new track, fire publish events
self.shared.room_emitter.send(RoomEvent::TrackPublished { self.shared
publication: publication.clone(), .internal_tx
participant: self.clone(), .send(SessionEvent::Room(RoomEvent::TrackPublished {
}); publication: publication.clone(),
participant: self.clone(),
}));
} }
valid_tracks.insert(track.sid.into()); valid_tracks.insert(track.sid.into());
+83 -43
View File
@@ -10,10 +10,19 @@ use parking_lot::{Mutex, RwLock};
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::atomic::{AtomicU8, Ordering}; use std::sync::atomic::{AtomicU8, Ordering};
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::mpsc;
use tokio::sync::oneshot; use tokio::sync::oneshot;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
use tracing::{error, instrument, Level}; use tracing::{error, instrument, Level};
pub(crate) type SessionEmitter = mpsc::UnboundedSender<SessionEvent>;
pub(crate) type SessionEvents = mpsc::UnboundedReceiver<SessionEvent>;
/// Used internally for participants and tracks
pub(crate) enum SessionEvent {
Room(RoomEvent), // Send a public event
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)] #[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum ConnectionState { pub enum ConnectionState {
Disconnected, Disconnected,
@@ -43,7 +52,7 @@ struct SessionInner {
participants: RwLock<HashMap<ParticipantSid, Arc<RemoteParticipant>>>, participants: RwLock<HashMap<ParticipantSid, Arc<RemoteParticipant>>>,
rtc_engine: Arc<RTCEngine>, rtc_engine: Arc<RTCEngine>,
local_participant: Arc<LocalParticipant>, local_participant: Arc<LocalParticipant>,
room_emitter: RoomEmitter, internal_tx: SessionEmitter,
} }
#[derive(Debug)] #[derive(Debug)]
@@ -68,6 +77,7 @@ impl SessionHandle {
.connect(url, token, SignalOptions::default()) .connect(url, token, SignalOptions::default())
.await?; .await?;
let (internal_tx, internal_rx) = mpsc::unbounded_channel();
let join_response = rtc_engine.join_response().unwrap(); let join_response = rtc_engine.join_response().unwrap();
let pi = join_response.participant.unwrap().clone(); let pi = join_response.participant.unwrap().clone();
let local_participant = Arc::new(LocalParticipant::new( let local_participant = Arc::new(LocalParticipant::new(
@@ -76,8 +86,9 @@ impl SessionHandle {
pi.identity.into(), pi.identity.into(),
pi.name, pi.name,
pi.metadata, pi.metadata,
room_emitter.clone(), internal_tx.clone(),
)); ));
let room_info = join_response.room.unwrap(); let room_info = join_response.room.unwrap();
let inner = Arc::new(SessionInner { let inner = Arc::new(SessionInner {
state: AtomicU8::new(ConnectionState::Disconnected as u8), state: AtomicU8::new(ConnectionState::Disconnected as u8),
@@ -86,7 +97,7 @@ impl SessionHandle {
participants: Default::default(), participants: Default::default(),
rtc_engine, rtc_engine,
local_participant, local_participant,
room_emitter, internal_tx,
}); });
for pi in join_response.other_participants { for pi in join_response.other_participants {
@@ -95,13 +106,16 @@ impl SessionHandle {
inner.create_participant(pi.sid.into(), pi.identity.into(), pi.name, pi.metadata) inner.create_participant(pi.sid.into(), pi.identity.into(), pi.name, pi.metadata)
}; };
participant.update_info(pi.clone()); participant.update_info(pi.clone());
participant participant.update_tracks(pi.tracks).await;
.update_tracks(RoomSession::from(inner.clone()), pi.tracks)
.await;
} }
let (close_emitter, close_receiver) = oneshot::channel(); let (close_emitter, close_receiver) = oneshot::channel();
let session_task = tokio::spawn(inner.clone().room_task(engine_events, close_receiver)); let session_task = tokio::spawn(inner.clone().room_task(
engine_events,
internal_rx,
close_receiver,
room_emitter,
));
inner inner
.update_connection_state(ConnectionState::Connected) .update_connection_state(ConnectionState::Connected)
@@ -161,18 +175,32 @@ impl SessionInner {
async fn room_task( async fn room_task(
self: Arc<Self>, self: Arc<Self>,
mut engine_events: EngineEvents, mut engine_events: EngineEvents,
mut internal_rx: SessionEvents,
mut close_receiver: oneshot::Receiver<()>, mut close_receiver: oneshot::Receiver<()>,
room_emitter: RoomEmitter,
) { ) {
loop { loop {
tokio::select! { tokio::select! {
biased;
res = internal_rx.recv() => {
match res {
Some(event) => {
if let Err(err) = self.on_internal_event(event, &room_emitter).await {
error!("failed to handle internal event: {:?}", err);
}
},
_ => panic!("internal_rx has been closed unexpectedly")
};
}
res = engine_events.recv() => { res = engine_events.recv() => {
if let Some(event) = res { match res {
if let Err(err) = self.on_engine_event(event).await { Some(event) => {
error!("failed to handle engine event: {:?}", err); if let Err(err) = self.on_engine_event(event).await {
} error!("failed to handle engine event: {:?}", err);
} else { }
panic!("engine_events has been closed unexpectedly"); },
} _ => panic!("engine_events has been closed unexpectedly")
};
}, },
_ = &mut close_receiver => { _ = &mut close_receiver => {
break; break;
@@ -181,6 +209,27 @@ impl SessionInner {
} }
} }
async fn on_internal_event(
&self,
event: SessionEvent,
room_emitter: &RoomEmitter,
) -> EngineResult<()> {
match event {
SessionEvent::Room(event) => {
if self.state.load(Ordering::Acquire) != ConnectionState::Connected as u8
&& matches!(event, RoomEvent::TrackPublished { .. })
{
return Ok(()); // Ignore the event
}
// Forward the event to the public channel
let _ = room_emitter.send(event);
}
}
Ok(())
}
#[instrument(level = Level::DEBUG)] #[instrument(level = Level::DEBUG)]
async fn on_engine_event(self: &Arc<Self>, event: EngineEvent) -> RoomResult<()> { async fn on_engine_event(self: &Arc<Self>, event: EngineEvent) -> RoomResult<()> {
match event { match event {
@@ -188,7 +237,7 @@ impl SessionInner {
EngineEvent::MediaTrack { EngineEvent::MediaTrack {
track, track,
stream, stream,
receiver, receiver: _,
} => { } => {
let stream_id = stream.id(); let stream_id = stream.id();
let lk_stream_id = unpack_stream_id(&stream_id); let lk_stream_id = unpack_stream_id(&stream_id);
@@ -200,23 +249,14 @@ impl SessionInner {
} }
let (participant_sid, track_sid) = lk_stream_id.unwrap(); let (participant_sid, track_sid) = lk_stream_id.unwrap();
let track_sid = track_sid.to_owned().into();
let remote_participant = self.get_participant(&participant_sid.to_string().into()); let remote_participant = self.get_participant(&participant_sid.to_string().into());
if let Some(remote_participant) = remote_participant { if let Some(remote_participant) = remote_participant {
tokio::spawn({ tokio::spawn(async move {
let session_inner = self.clone(); remote_participant
{ .add_subscribed_media_track(track_sid, track)
let track_sid = track_sid.to_owned().into(); .await;
async move {
remote_participant
.add_subscribed_media_track(
RoomSession::from(session_inner),
track_sid,
track,
)
.await;
}
}
}); });
} else { } else {
// The server should send participant updates before sending a new offer // The server should send participant updates before sending a new offer
@@ -257,8 +297,8 @@ impl SessionInner {
self.state.store(state as u8, Ordering::Release); self.state.store(state as u8, Ordering::Release);
let _ = self let _ = self
.room_emitter .internal_tx
.send(RoomEvent::ConnectionStateChanged(state)); .send(SessionEvent::Room(RoomEvent::ConnectionStateChanged(state)));
} }
/// Update the participants inside a Room. /// Update the participants inside a Room.
@@ -283,9 +323,7 @@ impl SessionInner {
} else { } else {
// Participant is already connected, update the it // Participant is already connected, update the it
remote_participant.update_info(pi.clone()); remote_participant.update_info(pi.clone());
remote_participant remote_participant.update_tracks(pi.tracks).await;
.update_tracks(RoomSession::from(self.clone()), pi.tracks)
.await;
} }
} else { } else {
// Create a new participant // Create a new participant
@@ -295,13 +333,13 @@ impl SessionInner {
}; };
let _ = self let _ = self
.room_emitter .internal_tx
.send(RoomEvent::ParticipantConnected(remote_participant.clone())); .send(SessionEvent::Room(RoomEvent::ParticipantConnected(
remote_participant.clone(),
)));
remote_participant.update_info(pi.clone()); remote_participant.update_info(pi.clone());
remote_participant remote_participant.update_tracks(pi.tracks).await;
.update_tracks(RoomSession::from(self.clone()), pi.tracks)
.await;
} }
} }
} }
@@ -313,9 +351,11 @@ impl SessionInner {
self.participants.write().remove(&remote_participant.sid()); self.participants.write().remove(&remote_participant.sid());
// TODO(theomonnom): Unpublish all tracks // TODO(theomonnom): Unpublish all tracks
let _ = self.room_emitter.send(RoomEvent::ParticipantDisconnected( let _ = self
remote_participant.clone(), .internal_tx
)); .send(SessionEvent::Room(RoomEvent::ParticipantDisconnected(
remote_participant.clone(),
)));
} }
/// Create a new participant /// Create a new participant
@@ -332,7 +372,7 @@ impl SessionInner {
identity, identity,
name, name,
metadata, metadata,
self.room_emitter.clone(), self.internal_tx.clone(),
)); ));
self.participants.write().insert(sid, p.clone()); self.participants.write().insert(sid, p.clone());