1818
1919#include < functional>
2020
21- #include " data_track.pb.h"
2221#include " ffi.pb.h"
2322#include " ffi_client.h"
2423#include " livekit/audio_stream.h"
2524#include " livekit/e2ee.h"
26- #include " livekit/local_data_track.h"
2725#include " livekit/local_participant.h"
28- #include " livekit/local_track_publication.h"
2926#include " livekit/remote_audio_track.h"
3027#include " livekit/remote_data_track.h"
3128#include " livekit/remote_participant.h"
@@ -65,6 +62,16 @@ std::shared_ptr<livekit::RemoteParticipant> createRemoteParticipant(const proto:
6562 pinfo.metadata (), std::move (attrs), kind, reason);
6663}
6764
65+ void readyForRoomEvent (std::uint64_t room_handle) {
66+ FfiRequest req;
67+ req.mutable_ready_for_room_event ()->set_room_handle (room_handle);
68+
69+ const auto resp = FfiClient::instance ().sendRequest (req);
70+ if (!resp.has_ready_for_room_event ()) {
71+ throw std::runtime_error (" FfiResponse missing ready_for_room_event" );
72+ }
73+ }
74+
6875} // namespace
6976Room::Room () : subscription_thread_dispatcher_(std::make_unique<SubscriptionThreadDispatcher>()) {}
7077
@@ -104,20 +111,28 @@ void Room::setDelegate(RoomDelegate* delegate) {
104111
105112bool Room::Connect (const std::string& url, const std::string& token, const RoomOptions& options) {
106113 TRACE_EVENT0 (" livekit" , " Room::Connect" );
107-
108114 {
109115 const std::scoped_lock<std::mutex> g (lock_);
110116 if (connection_state_ != ConnectionState::Disconnected) {
111117 throw std::runtime_error (" already connected" );
112118 }
113119 connection_state_ = ConnectionState::Reconnecting;
114120 }
115- auto fut = FfiClient::instance ().connectAsync (url, token, options);
121+
122+ FfiClient::ListenerId listenerId = 0 ;
116123 try {
124+ listenerId = FfiClient::instance ().AddListener ([this ](const proto::FfiEvent& e) { OnEvent (e); });
125+ {
126+ const std::scoped_lock<std::mutex> g (lock_);
127+ listener_id_ = listenerId;
128+ }
129+
130+ auto fut = FfiClient::instance ().connectAsync (url, token, options);
117131 auto connectCb = fut.get (); // fut will throw if it fails to connect to the room
118132
119133 const auto & owned_room = connectCb.result ().room ();
120134 auto new_room_handle = std::make_shared<FfiHandle>(owned_room.handle ().id ());
135+ const auto room_handle_id = static_cast <std::uint64_t >(new_room_handle->get ());
121136 auto new_room_info = fromProto (owned_room.info ());
122137
123138 // Setup local particpant
@@ -141,6 +156,7 @@ bool Room::Connect(const std::string& url, const std::string& token, const RoomO
141156 std::make_unique<LocalParticipant>(std::move (participant_handle), pinfo.sid (), pinfo.name (), pinfo.identity (),
142157 pinfo.metadata (), std::move (attrs), kind, reason);
143158 }
159+
144160 // Setup remote participants
145161 std::unordered_map<std::string, std::shared_ptr<RemoteParticipant>> new_remote_participants;
146162 {
@@ -178,17 +194,31 @@ bool Room::Connect(const std::string& url, const std::string& token, const RoomO
178194 connection_state_ = ConnectionState::Connected;
179195 }
180196
181- // Install listener (Room is fully initialized)
182- auto listenerId = FfiClient::instance ().AddListener ([this ](const proto::FfiEvent& e) { OnEvent (e); });
197+ readyForRoomEvent (room_handle_id);
198+ return true ;
199+ } catch (const std::exception& e) {
200+ int listener_to_remove = 0 ;
201+ std::unique_ptr<LocalParticipant> local_participant_to_cleanup;
183202 {
184203 const std::scoped_lock<std::mutex> g (lock_);
185- listener_id_ = listenerId;
204+ connection_state_ = ConnectionState::Disconnected;
205+ if (listener_id_ == listenerId) {
206+ listener_to_remove = listener_id_;
207+ listener_id_ = 0 ;
208+ }
209+ local_participant_to_cleanup = std::move (local_participant_);
210+ remote_participants_.clear ();
211+ room_handle_.reset ();
212+ e2ee_manager_.reset ();
213+ text_stream_readers_.clear ();
214+ byte_stream_readers_.clear ();
215+ }
216+ if (local_participant_to_cleanup) {
217+ local_participant_to_cleanup->shutdown ();
218+ }
219+ if (listener_to_remove != 0 ) {
220+ FfiClient::instance ().RemoveListener (listener_to_remove);
186221 }
187-
188- return true ;
189- } catch (const std::exception& e) {
190- // On error, set the connection_state_ to Disconnected
191- connection_state_ = ConnectionState::Disconnected;
192222 LK_LOG_ERROR (" Room::Connect failed: {}" , e.what ());
193223 return false ;
194224 }
0 commit comments