From 2c503997204043fcd24d70854799509c0675d76d Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Tue, 30 Apr 2024 11:45:21 -0700 Subject: Remove voice participants for a connection when shutting it down. When teleporting or moving around, connections to regions are shut down. We need to track which participants are associated with the given connections and remove those participants when the connection is shut down. --- indra/newview/llvoicewebrtc.cpp | 68 +++++++++++++++++++++++++---------------- indra/newview/llvoicewebrtc.h | 11 ++++--- 2 files changed, 47 insertions(+), 32 deletions(-) diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 87106ba6d5..2bd6eee84d 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -810,9 +810,12 @@ void LLWebRTCVoiceClient::OnConnectionEstablished(const std::string &channelID, } mSession = mNextSession; mNextSession.reset(); + } + if (mSession) + { // Add ourselves as a participant. - mSession->addParticipant(gAgentID); + mSession->addParticipant(gAgentID, gAgent.getRegion()->getRegionID()); } // The current session was established. @@ -833,14 +836,19 @@ void LLWebRTCVoiceClient::OnConnectionEstablished(const std::string &channelID, void LLWebRTCVoiceClient::OnConnectionShutDown(const std::string &channelID, const LLUUID ®ionID) { - if (gAgent.getRegion()->getRegionID() == regionID) + if (mSession && (mSession->mChannelID == channelID)) { - if (mSession && mSession->mChannelID == channelID) + if (gAgent.getRegion()->getRegionID() == regionID) { - LL_DEBUGS("Voice") << "Main WebRTC Connection Shut Down." << LL_ENDL; + if (mSession && mSession->mChannelID == channelID) + { + LL_DEBUGS("Voice") << "Main WebRTC Connection Shut Down." << LL_ENDL; + } } + mSession->removeAllParticipants(regionID); } } + void LLWebRTCVoiceClient::OnConnectionFailure(const std::string &channelID, const LLUUID ®ionID, LLVoiceClientStatusObserver::EStatusType status_type) @@ -1092,13 +1100,13 @@ LLWebRTCVoiceClient::participantStatePtr_t LLWebRTCVoiceClient::findParticipantB return result; } -LLWebRTCVoiceClient::participantStatePtr_t LLWebRTCVoiceClient::addParticipantByID(const std::string &channelID, const LLUUID &id) +LLWebRTCVoiceClient::participantStatePtr_t LLWebRTCVoiceClient::addParticipantByID(const std::string &channelID, const LLUUID &id, const LLUUID& region) { participantStatePtr_t result; LLWebRTCVoiceClient::sessionState::ptr_t session = sessionState::matchSessionByChannelID(channelID); if (session) { - result = session->addParticipant(id); + result = session->addParticipant(id, region); if (session->mNotifyOnFirstJoin && (id != gAgentID)) { notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINED); @@ -1107,7 +1115,7 @@ LLWebRTCVoiceClient::participantStatePtr_t LLWebRTCVoiceClient::addParticipantBy return result; } -void LLWebRTCVoiceClient::removeParticipantByID(const std::string &channelID, const LLUUID &id) +void LLWebRTCVoiceClient::removeParticipantByID(const std::string &channelID, const LLUUID &id, const LLUUID& region) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE @@ -1116,7 +1124,7 @@ void LLWebRTCVoiceClient::removeParticipantByID(const std::string &channelID, co if (session) { participantStatePtr_t participant = session->findParticipantByID(id); - if (participant) + if (participant && (participant->mRegion == region)) { session->removeParticipant(participant); } @@ -1125,17 +1133,18 @@ void LLWebRTCVoiceClient::removeParticipantByID(const std::string &channelID, co // participantState level participant management -LLWebRTCVoiceClient::participantState::participantState(const LLUUID& agent_id) : +LLWebRTCVoiceClient::participantState::participantState(const LLUUID& agent_id, const LLUUID& region) : mURI(agent_id.asString()), mAvatarID(agent_id), mIsSpeaking(false), mIsModeratorMuted(false), mLevel(0.f), - mVolume(LLVoiceClient::VOLUME_DEFAULT) + mVolume(LLVoiceClient::VOLUME_DEFAULT), + mRegion(region) { } -LLWebRTCVoiceClient::participantStatePtr_t LLWebRTCVoiceClient::sessionState::addParticipant(const LLUUID& agent_id) +LLWebRTCVoiceClient::participantStatePtr_t LLWebRTCVoiceClient::sessionState::addParticipant(const LLUUID& agent_id, const LLUUID& region) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE @@ -1147,26 +1156,27 @@ LLWebRTCVoiceClient::participantStatePtr_t LLWebRTCVoiceClient::sessionState::ad if (iter != mParticipantsByUUID.end()) { result = iter->second; + result->mRegion = region; } - if(!result) + if (!result) { // participant isn't already in one list or the other. - result.reset(new participantState(agent_id)); + result.reset(new participantState(agent_id, region)); mParticipantsByUUID.insert(participantUUIDMap::value_type(agent_id, result)); - result->mAvatarID = agent_id; - - LLWebRTCVoiceClient::getInstance()->lookupName(agent_id); + result->mAvatarID = agent_id; + } - LLSpeakerVolumeStorage::getInstance()->getSpeakerVolume(result->mAvatarID, result->mVolume); - if (!LLWebRTCVoiceClient::sShuttingDown) - { - LLWebRTCVoiceClient::getInstance()->notifyParticipantObservers(); - } + LLWebRTCVoiceClient::getInstance()->lookupName(agent_id); - LL_DEBUGS("Voice") << "Participant \"" << result->mURI << "\" added." << LL_ENDL; + LLSpeakerVolumeStorage::getInstance()->getSpeakerVolume(result->mAvatarID, result->mVolume); + if (!LLWebRTCVoiceClient::sShuttingDown) + { + LLWebRTCVoiceClient::getInstance()->notifyParticipantObservers(); } + LL_DEBUGS("Voice") << "Participant \"" << result->mURI << "\" added." << LL_ENDL; + return result; } @@ -1218,13 +1228,17 @@ void LLWebRTCVoiceClient::sessionState::removeParticipant(const LLWebRTCVoiceCli } } -void LLWebRTCVoiceClient::sessionState::removeAllParticipants() +void LLWebRTCVoiceClient::sessionState::removeAllParticipants(const LLUUID ®ion) { LL_DEBUGS("Voice") << "called" << LL_ENDL; - while (!mParticipantsByUUID.empty()) + + for (auto &&participant : mParticipantsByUUID) { - removeParticipant(mParticipantsByUUID.begin()->second); + if (region.isNull() || (participant.second->mRegion == region)) + { + removeParticipant(participant.second); + } } } @@ -2836,7 +2850,7 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b new_participant |= joined; if (!participant && joined && (primary || !isSpatial())) { - participant = LLWebRTCVoiceClient::getInstance()->addParticipantByID(mChannelID, agent_id); + participant = LLWebRTCVoiceClient::getInstance()->addParticipantByID(mChannelID, agent_id, mRegionID); } if (participant) @@ -2846,7 +2860,7 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b // an existing participant is leaving. if (agent_id != gAgentID) { - LLWebRTCVoiceClient::getInstance()->removeParticipantByID(mChannelID, agent_id); + LLWebRTCVoiceClient::getInstance()->removeParticipantByID(mChannelID, agent_id, mRegionID); } } else diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h index 67e4a4ea6f..af1efa5fe5 100644 --- a/indra/newview/llvoicewebrtc.h +++ b/indra/newview/llvoicewebrtc.h @@ -228,7 +228,7 @@ public: struct participantState { public: - participantState(const LLUUID& agent_id); + participantState(const LLUUID& agent_id, const LLUUID& region); bool isAvatar(); @@ -240,12 +240,13 @@ public: F32 mVolume; // the gain applied to the participant bool mIsSpeaking; bool mIsModeratorMuted; + LLUUID mRegion; }; typedef boost::shared_ptr participantStatePtr_t; participantStatePtr_t findParticipantByID(const std::string &channelID, const LLUUID &id); - participantStatePtr_t addParticipantByID(const std::string& channelID, const LLUUID &id); - void removeParticipantByID(const std::string& channelID, const LLUUID &id); + participantStatePtr_t addParticipantByID(const std::string& channelID, const LLUUID &id, const LLUUID& region); + void removeParticipantByID(const std::string& channelID, const LLUUID &id, const LLUUID& region); protected: @@ -262,9 +263,9 @@ public: static void addSession(const std::string &channelID, ptr_t& session); virtual ~sessionState(); - participantStatePtr_t addParticipant(const LLUUID& agent_id); + participantStatePtr_t addParticipant(const LLUUID& agent_id, const LLUUID& region); void removeParticipant(const participantStatePtr_t &participant); - void removeAllParticipants(); + void removeAllParticipants(const LLUUID& region = LLUUID()); participantStatePtr_t findParticipantByID(const LLUUID& id); -- cgit v1.3 From f9cb9a2b057b2ebc2e1f5cbf479e56595c0fdfb8 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Tue, 30 Apr 2024 12:58:07 -0700 Subject: Can't delete from a map while iterating over it. --- indra/newview/llvoicewebrtc.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 2bd6eee84d..0823358e03 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -1230,16 +1230,19 @@ void LLWebRTCVoiceClient::sessionState::removeParticipant(const LLWebRTCVoiceCli void LLWebRTCVoiceClient::sessionState::removeAllParticipants(const LLUUID ®ion) { - LL_DEBUGS("Voice") << "called" << LL_ENDL; - + std::vector participantsToRemove; - for (auto &&participant : mParticipantsByUUID) + for (auto& participantEntry : mParticipantsByUUID) { - if (region.isNull() || (participant.second->mRegion == region)) + if (region.isNull() || (participantEntry.second->mRegion == region)) { - removeParticipant(participant.second); + participantsToRemove.push_back(participantEntry.second); } } + for (auto& participant : participantsToRemove) + { + removeParticipant(participant); + } } // Initiated the various types of sessions. -- cgit v1.3 From 1bca2b20361c9723d4d8bb6d03684ed2dc729703 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Tue, 30 Apr 2024 15:35:48 -0700 Subject: don't register callbacks from the data channel twice. --- indra/llwebrtc/llwebrtc.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index d07e6deea4..97c04ae446 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -957,6 +957,10 @@ void LLWebRTCPeerConnectionImpl::OnRemoveTrack(rtc::scoped_refptr channel) { + if (mDataChannel) + { + mDataChannel->UnregisterObserver(); + } mDataChannel = channel; channel->RegisterObserver(this); } -- cgit v1.3 From 07c3095a785864b39b03d979d43b7d0d7a932a81 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Thu, 2 May 2024 11:07:36 -0700 Subject: Unregister requested data channel when using the negotiated one. When creating a new connection, the viewer builds a data channel interface. It then gets a new one, which is a proxy. The viewer uses the new one, and therefore must unregister the callbacks from the old one. Also, update the position data before sending it after the join is sent. --- indra/llwebrtc/llwebrtc.cpp | 4 ++++ indra/newview/llvoicewebrtc.cpp | 6 +++++- indra/newview/llvoicewebrtc.h | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index d07e6deea4..97c04ae446 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -957,6 +957,10 @@ void LLWebRTCPeerConnectionImpl::OnRemoveTrack(rtc::scoped_refptr channel) { + if (mDataChannel) + { + mDataChannel->UnregisterObserver(); + } mDataChannel = channel; channel->RegisterObserver(this); } diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 0823358e03..7c438dfa9a 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -2688,7 +2688,11 @@ bool LLVoiceWebRTCConnection::connectionStateMachine() { sendJoin(); // tell the Secondlife WebRTC server that we're here via the data channel. setVoiceConnectionState(VOICE_STATE_SESSION_UP); - LLWebRTCVoiceClient::getInstance()->sendPositionUpdate(true); + if (isSpatial()) + { + LLWebRTCVoiceClient::getInstance()->updatePosition(); + LLWebRTCVoiceClient::getInstance()->sendPositionUpdate(true); + } } break; } diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h index af1efa5fe5..c417dfe329 100644 --- a/indra/newview/llvoicewebrtc.h +++ b/indra/newview/llvoicewebrtc.h @@ -201,7 +201,8 @@ public: void OnConnectionFailure(const std::string &channelID, const LLUUID ®ionID, LLVoiceClientStatusObserver::EStatusType status_type = LLVoiceClientStatusObserver::ERROR_UNKNOWN); - void sendPositionUpdate(bool force); + void updatePosition(void); // update the internal position state + void sendPositionUpdate(bool force); // send the position to the voice server. void updateOwnVolume(); ////////////////////////////// @@ -398,7 +399,6 @@ public: ///////////////////////////// // Sending updates of current state - void updatePosition(void); void setListenerPosition(const LLVector3d &position, const LLVector3 &velocity, const LLQuaternion &rot); void setAvatarPosition(const LLVector3d &position, const LLVector3 &velocity, const LLQuaternion &rot); -- cgit v1.3 From 05b2dd913fcb1c5485ce19885e4e60f26752e6b0 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Thu, 2 May 2024 13:15:44 -0700 Subject: Update the participant's region when crossing region boundaries. --- indra/newview/llvoicewebrtc.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 7c438dfa9a..ddbe2eb552 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -553,6 +553,7 @@ void LLWebRTCVoiceClient::updateNeighboringRegions() // Estate voice requires connection to neighboring regions. mNeighboringRegions.clear(); + // add current region. mNeighboringRegions.insert(gAgent.getRegion()->getRegionID()); // base off of speaker position as it'll move more slowly than camera position. @@ -924,6 +925,13 @@ void LLWebRTCVoiceClient::updatePosition(void) enforceTether(); updateNeighboringRegions(); + + // update own region id to be the region id avatar is currently in. + LLWebRTCVoiceClient::participantStatePtr_t participant = findParticipantByID("Estate", gAgentID); + if(participant) + { + participant->mRegion = gAgent.getRegion()->getRegionID(); + } } } -- cgit v1.3