diff options
-rw-r--r-- | indra/llwebrtc/llwebrtc.cpp | 203 | ||||
-rw-r--r-- | indra/newview/llvoicewebrtc.cpp | 437 | ||||
-rw-r--r-- | indra/newview/llvoicewebrtc.h | 43 |
3 files changed, 261 insertions, 422 deletions
diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index e55d94d128..9b3ec2889b 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -86,7 +86,9 @@ void LLWebRTCImpl::init() mPlayoutDevice = 0; mRecordingDevice = 0; rtc::InitializeSSL(); - rtc::LogMessage::LogToDebug(rtc::LS_WARNING); + rtc::LogMessage::LogToDebug(rtc::LS_NONE); + rtc::LogMessage::SetLogToStderr(true); + mTaskQueueFactory = webrtc::CreateDefaultTaskQueueFactory(); mNetworkThread = rtc::Thread::CreateWithSocketServer(); @@ -98,7 +100,7 @@ void LLWebRTCImpl::init() mSignalingThread = rtc::Thread::Create(); mSignalingThread->SetName("WebRTCSignalingThread", nullptr); mSignalingThread->Start(); - + mWorkerThread->PostTask( [this]() { @@ -466,93 +468,98 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection() RTC_DCHECK(!mPeerConnection); mAnswerReceived = false; - webrtc::PeerConnectionInterface::RTCConfiguration config; - config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan; - webrtc::PeerConnectionInterface::IceServer server; - server.uri = "stun:roxie-turn.staging.secondlife.io:3478"; - config.servers.push_back(server); - server.uri = "stun:stun.l.google.com:19302"; - config.servers.push_back(server); - server.uri = "stun:stun1.l.google.com:19302"; - config.servers.push_back(server); - server.uri = "stun:stun2.l.google.com:19302"; - config.servers.push_back(server); - server.uri = "stun:stun3.l.google.com:19302"; - config.servers.push_back(server); - server.uri = "stun:stun4.l.google.com:19302"; - config.servers.push_back(server); - - webrtc::PeerConnectionDependencies pc_dependencies(this); - auto error_or_peer_connection = mPeerConnectionFactory->CreatePeerConnectionOrError(config, std::move(pc_dependencies)); - if (error_or_peer_connection.ok()) - { - mPeerConnection = std::move(error_or_peer_connection.value()); - } - else - { - RTC_LOG(LS_ERROR) << __FUNCTION__ << "Error creating peer connection: " << error_or_peer_connection.error().message(); - return false; - } - - webrtc::DataChannelInit init; - init.ordered = true; - - auto data_channel_or_error = mPeerConnection->CreateDataChannelOrError("SLData", &init); - if (data_channel_or_error.ok()) - { - mDataChannel = std::move(data_channel_or_error.value()); - - mDataChannel->RegisterObserver(this); - } - - RTC_LOG(LS_INFO) << __FUNCTION__ << " " << mPeerConnection->signaling_state(); - - cricket::AudioOptions audioOptions; - audioOptions.auto_gain_control = true; - audioOptions.echo_cancellation = false; // incompatible with opus stereo - audioOptions.noise_suppression = true; - - mLocalStream = mPeerConnectionFactory->CreateLocalMediaStream("SLStream"); - rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track( - mPeerConnectionFactory->CreateAudioTrack("SLAudio", mPeerConnectionFactory->CreateAudioSource(audioOptions).get())); - audio_track->set_enabled(true); - mLocalStream->AddTrack(audio_track); - - mPeerConnection->AddTrack(audio_track, {"SLStream"}); - - auto senders = mPeerConnection->GetSenders(); - - for (auto &sender : senders) - { - webrtc::RtpParameters params; - webrtc::RtpCodecParameters codecparam; - codecparam.name = "opus"; - codecparam.kind = cricket::MEDIA_TYPE_AUDIO; - codecparam.clock_rate = 48000; - codecparam.num_channels = 2; - codecparam.parameters["stereo"] = "1"; - codecparam.parameters["sprop-stereo"] = "1"; - params.codecs.push_back(codecparam); - sender->SetParameters(params); - } - - auto receivers = mPeerConnection->GetReceivers(); - for (auto &receiver : receivers) - { - webrtc::RtpParameters params; - webrtc::RtpCodecParameters codecparam; - codecparam.name = "opus"; - codecparam.kind = cricket::MEDIA_TYPE_AUDIO; - codecparam.clock_rate = 48000; - codecparam.num_channels = 2; - codecparam.parameters["stereo"] = "1"; - codecparam.parameters["sprop-stereo"] = "1"; - params.codecs.push_back(codecparam); - receiver->SetParameters(params); - } - - webrtc::PeerConnectionInterface::RTCOfferAnswerOptions offerOptions; - mPeerConnection->CreateOffer(this, offerOptions); + mWebRTCImpl->PostSignalingTask( + [this]() + { + webrtc::PeerConnectionInterface::RTCConfiguration config; + config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan; + webrtc::PeerConnectionInterface::IceServer server; + server.uri = "stun:roxie-turn.staging.secondlife.io:3478"; + config.servers.push_back(server); + server.uri = "stun:stun.l.google.com:19302"; + config.servers.push_back(server); + server.uri = "stun:stun1.l.google.com:19302"; + config.servers.push_back(server); + server.uri = "stun:stun2.l.google.com:19302"; + config.servers.push_back(server); + server.uri = "stun:stun3.l.google.com:19302"; + config.servers.push_back(server); + server.uri = "stun:stun4.l.google.com:19302"; + config.servers.push_back(server); + + config.set_min_port(60000); + config.set_max_port(60100); + + webrtc::PeerConnectionDependencies pc_dependencies(this); + auto error_or_peer_connection = mPeerConnectionFactory->CreatePeerConnectionOrError(config, std::move(pc_dependencies)); + if (error_or_peer_connection.ok()) + { + mPeerConnection = std::move(error_or_peer_connection.value()); + } + else + { + RTC_LOG(LS_ERROR) << __FUNCTION__ << "Error creating peer connection: " << error_or_peer_connection.error().message(); + return; + } + + webrtc::DataChannelInit init; + init.ordered = true; + + auto data_channel_or_error = mPeerConnection->CreateDataChannelOrError("SLData", &init); + if (data_channel_or_error.ok()) + { + mDataChannel = std::move(data_channel_or_error.value()); + + mDataChannel->RegisterObserver(this); + } + + cricket::AudioOptions audioOptions; + audioOptions.auto_gain_control = true; + audioOptions.echo_cancellation = false; // incompatible with opus stereo + audioOptions.noise_suppression = true; + + mLocalStream = mPeerConnectionFactory->CreateLocalMediaStream("SLStream"); + rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track( + mPeerConnectionFactory->CreateAudioTrack("SLAudio", mPeerConnectionFactory->CreateAudioSource(audioOptions).get())); + audio_track->set_enabled(true); + mLocalStream->AddTrack(audio_track); + + mPeerConnection->AddTrack(audio_track, {"SLStream"}); + + auto senders = mPeerConnection->GetSenders(); + + for (auto &sender : senders) + { + webrtc::RtpParameters params; + webrtc::RtpCodecParameters codecparam; + codecparam.name = "opus"; + codecparam.kind = cricket::MEDIA_TYPE_AUDIO; + codecparam.clock_rate = 48000; + codecparam.num_channels = 2; + codecparam.parameters["stereo"] = "1"; + codecparam.parameters["sprop-stereo"] = "1"; + params.codecs.push_back(codecparam); + sender->SetParameters(params); + } + + auto receivers = mPeerConnection->GetReceivers(); + for (auto &receiver : receivers) + { + webrtc::RtpParameters params; + webrtc::RtpCodecParameters codecparam; + codecparam.name = "opus"; + codecparam.kind = cricket::MEDIA_TYPE_AUDIO; + codecparam.clock_rate = 48000; + codecparam.num_channels = 2; + codecparam.parameters["stereo"] = "1"; + codecparam.parameters["sprop-stereo"] = "1"; + params.codecs.push_back(codecparam); + receiver->SetParameters(params); + } + + webrtc::PeerConnectionInterface::RTCOfferAnswerOptions offerOptions; + mPeerConnection->CreateOffer(this, offerOptions); + }); return true; } @@ -839,7 +846,7 @@ void LLWebRTCPeerConnectionImpl::OnIceCandidate(const webrtc::IceCandidateInterf else { mCachedIceCandidates.push_back( - webrtc::CreateIceCandidate(candidate->sdp_mid(), candidate->sdp_mline_index(), candidate->candidate())); + webrtc::CreateIceCandidate(candidate->sdp_mid(), candidate->sdp_mline_index(), candidate->candidate())); } } @@ -878,21 +885,16 @@ void LLWebRTCPeerConnectionImpl::OnSuccess(webrtc::SessionDescriptionInterface * sdp_mangled_stream << sdp_line << "\n"; } } - - webrtc::CreateSessionDescription(webrtc::SdpType::kOffer, sdp_mangled_stream.str()); - - - - mPeerConnection->SetLocalDescription(std::unique_ptr<webrtc::SessionDescriptionInterface>( - webrtc::CreateSessionDescription(webrtc::SdpType::kOffer, sdp_mangled_stream.str())), - rtc::scoped_refptr<webrtc::SetLocalDescriptionObserverInterface>(this)); + RTC_LOG(LS_INFO) << __FUNCTION__ << " Local SDP: " << sdp_mangled_stream.str(); - - + for (auto &observer : mSignalingObserverList) { observer->OnOfferAvailable(sdp_mangled_stream.str()); } + + mPeerConnection->SetLocalDescription(std::unique_ptr<webrtc::SessionDescriptionInterface>(webrtc::CreateSessionDescription(webrtc::SdpType::kOffer, sdp_mangled_stream.str())), + rtc::scoped_refptr<webrtc::SetLocalDescriptionObserverInterface>(this)); } void LLWebRTCPeerConnectionImpl::OnFailure(webrtc::RTCError error) { RTC_LOG(LS_ERROR) << ToString(error.type()) << ": " << error.message(); } @@ -930,7 +932,6 @@ void LLWebRTCPeerConnectionImpl::OnSetRemoteDescriptionComplete(webrtc::RTCError // void LLWebRTCPeerConnectionImpl::OnSetLocalDescriptionComplete(webrtc::RTCError error) { - } // diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index ec1e6a353d..9a1b3525d7 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -455,17 +455,29 @@ void LLWebRTCVoiceClient::idle(void* user_data) // // -void LLWebRTCVoiceClient::predProcessSessionStates(const LLWebRTCVoiceClient::sessionStatePtr_t& session) +void LLWebRTCVoiceClient::sessionState::processSessionStates() { - session->processSessionStates(); + auto iter = mSessions.begin(); + while (iter != mSessions.end()) + { + if (!iter->second->processConnectionStates()) + { + iter = mSessions.erase(iter); + } + else + { + iter++; + } + } } -void LLWebRTCVoiceClient::sessionState::processSessionStates() +bool LLWebRTCVoiceClient::sessionState::processConnectionStates() { - std::map<std::string, connectionPtr_t>::iterator iter; - for (iter = mWebRTCConnections.begin(); iter != mWebRTCConnections.end();) + std::list<connectionPtr_t>::iterator iter = mWebRTCConnections.begin(); + + while (iter != mWebRTCConnections.end()) { - if (!iter->second->connectionStateMachine()) + if (!iter->get()->connectionStateMachine()) { iter = mWebRTCConnections.erase(iter); } @@ -474,6 +486,7 @@ void LLWebRTCVoiceClient::sessionState::processSessionStates() ++iter; } } + return !mWebRTCConnections.empty(); } void LLWebRTCVoiceClient::voiceConnectionCoro() @@ -488,33 +501,39 @@ void LLWebRTCVoiceClient::voiceConnectionCoro() llcoro::suspendUntilTimeout(UPDATE_THROTTLE_SECONDS); // add session for region or parcel voice. LLViewerRegion *regionp = gAgent.getRegion(); - if (!regionp) + if (!regionp || regionp->getRegionID().isNull()) { continue; } - if (regionp->getRegionID().isNull()) - { - continue; - } - if (mVoiceEnabled && (!mAudioSession || mAudioSession->mIsSpatial)) + + if (mVoiceEnabled && (!mAudioSession || mAudioSession->isSpatial()) && !mNextAudioSession) { // check to see if parcel changed. std::string channelID = regionp->getRegionID().asString(); LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); S32 parcel_local_id = INVALID_PARCEL_ID; - if (parcel && parcel->getLocalID() != INVALID_PARCEL_ID && !parcel->getParcelFlagUseEstateVoiceChannel()) + if (parcel && parcel->getLocalID() != INVALID_PARCEL_ID) { - parcel_local_id = parcel->getLocalID(); - channelID += "-" + std::to_string(parcel->getLocalID()); + if (!parcel->getParcelFlagAllowVoice()) + { + channelID.clear(); + } + else if (!parcel->getParcelFlagUseEstateVoiceChannel()) + { + parcel_local_id = parcel->getLocalID(); + channelID += "-" + std::to_string(parcel->getLocalID()); + } } - if (!mAudioSession || channelID != mAudioSession->mChannelID) + + if ((mNextAudioSession && channelID != mNextAudioSession->mChannelID) || + (!mAudioSession && !channelID.empty()) || + (mAudioSession && channelID != mAudioSession->mChannelID)) { setSpatialChannel(channelID, "", parcel_local_id); } } - sessionState::for_each(boost::bind(predProcessSessionStates, _1)); - reapEmptySessions(); + sessionState::processSessionStates(); if (mVoiceEnabled) { updatePosition(); @@ -829,7 +848,7 @@ void LLWebRTCVoiceClient::predUpdateOwnVolume(const LLWebRTCVoiceClient::session void LLWebRTCVoiceClient::predSendData(const LLWebRTCVoiceClient::sessionStatePtr_t& session, const std::string& spatial_data, const std::string& volume_data) { - if (session->mIsSpatial && !spatial_data.empty()) + if (session->isSpatial() && !spatial_data.empty()) { session->sendData(spatial_data); } @@ -843,7 +862,7 @@ void LLWebRTCVoiceClient::sessionState::sendData(const std::string &data) { for (auto& connection : mWebRTCConnections) { - connection.second->sendData(data); + connection->sendData(data); } } @@ -852,7 +871,7 @@ void LLWebRTCVoiceClient::sessionState::setMuteMic(bool muted) mMuted = muted; for (auto& connection : mWebRTCConnections) { - connection.second->setMuteMic(muted); + connection->setMuteMic(muted); } } @@ -861,7 +880,7 @@ void LLWebRTCVoiceClient::sessionState::setMicGain(F32 gain) mMicGain = gain; for (auto& connection : mWebRTCConnections) { - connection.second->setMicGain(gain); + connection->setMicGain(gain); } } @@ -870,7 +889,7 @@ void LLWebRTCVoiceClient::sessionState::setSpeakerVolume(F32 volume) mSpeakerVolume = volume; for (auto& connection : mWebRTCConnections) { - connection.second->setSpeakerVolume(volume); + connection->setSpeakerVolume(volume); } } @@ -878,52 +897,6 @@ void LLWebRTCVoiceClient::sendLocalAudioUpdates() { } - -void LLWebRTCVoiceClient::joinedAudioSession(const sessionStatePtr_t &session) -{ - LL_DEBUGS("Voice") << "Joined Audio Session" << LL_ENDL; - if(mAudioSession != session) - { - sessionStatePtr_t oldSession = mAudioSession; - - mAudioSession = session; - mAudioSessionChanged = true; - - // The old session may now need to be deleted. - reapSession(oldSession); - } - - // This is the session we're joining. - if(mIsJoiningSession) - { - LLSD WebRTCevent(LLSDMap("channel", session->mChannelID) - ("session", "joined")); - - mWebRTCPump.post(WebRTCevent); - - if(!session->mIsChannel) - { - // this is a p2p session. Make sure the other end is added as a participant. - participantStatePtr_t participant(session->addParticipant(LLUUID(session->mChannelID))); - if(participant) - { - if(participant->mAvatarIDValid) - { - lookupName(participant->mAvatarID); - } - else if(!session->mName.empty()) - { - participant->mDisplayName = session->mName; - avatarNameResolved(participant->mAvatarID, session->mName); - } - - // TODO: Question: Do we need to set up mAvatarID/mAvatarIDValid here? - LL_INFOS("Voice") << "added caller as participant (" << participant->mAvatarID << ")"<< LL_ENDL; - } - } - } -} - void LLWebRTCVoiceClient::reapSession(const sessionStatePtr_t &session) { if(session) @@ -950,19 +923,6 @@ void LLWebRTCVoiceClient::reapSession(const sessionStatePtr_t &session) } -void LLWebRTCVoiceClient::leftAudioSession(const sessionStatePtr_t &session) -{ - if (mAudioSession == session) - { - LLSD WebRTCevent(LLSDMap("channel", session->mChannelID) - ("session", "removed")); - - mWebRTCPump.post(WebRTCevent); - } -} - - - void LLWebRTCVoiceClient::muteListChanged() { // The user's mute list has been updated. Go through the current participant list and sync it with the mute list. @@ -1215,149 +1175,47 @@ void LLWebRTCVoiceClient::removeParticipantByID(const std::string &channelID, co } } - -// Check for parcel boundary crossing -bool LLWebRTCVoiceClient::checkParcelChanged(bool update) -{ - LLViewerRegion *region = gAgent.getRegion(); - LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - - if(region && parcel) - { - S32 parcelLocalID = parcel->getLocalID(); - std::string regionName = region->getName(); - - // LL_DEBUGS("Voice") << "Region name = \"" << regionName << "\", parcel local ID = " << parcelLocalID << ", cap URI = \"" << capURI << "\"" << LL_ENDL; - - // The region name starts out empty and gets filled in later. - // Also, the cap gets filled in a short time after the region cross, but a little too late for our purposes. - // If either is empty, wait for the next time around. - if(!regionName.empty()) - { - if((parcelLocalID != mCurrentParcelLocalID) || (regionName != mCurrentRegionName)) - { - // We have changed parcels. Initiate a parcel channel lookup. - if (update) - { - mCurrentParcelLocalID = parcelLocalID; - mCurrentRegionName = regionName; - } - return true; - } - } - } - return false; -} - -bool LLWebRTCVoiceClient::switchChannel( - const std::string channelID, - bool spatial, - bool no_reconnect, - bool is_p2p, - std::string hash, - S32 parcel_local_id) +bool LLWebRTCVoiceClient::switchChannel(const std::string channelID, + sessionState::ESessionType session_type, + S32 parcel_local_id) { - bool needsSwitch = false; - if (mAudioSession) { - if (mSessionTerminateRequested) + // If we're already in a channel, or if we're joining one, terminate + // so we can rejoin with the new session data. + sessionTerminate(); + notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL); + deleteSession(mAudioSession); + } + + if (channelID.empty()) + { + // Leave any channel we may be in + LL_DEBUGS("Voice") << "leaving channel" << LL_ENDL; + + if (mNextAudioSession) { - // If a terminate has been requested, we need to compare against where the URI we're already headed to. - if(mNextAudioSession) - { - if (mNextAudioSession->mChannelID != channelID) - needsSwitch = true; - } - else - { - // mNextAudioSession is null -- this probably means we're on our way back to spatial. - if (!channelID.empty()) - { - // We do want to process a switch in this case. - needsSwitch = true; - } - } + deleteSession(mNextAudioSession); } - else + // If voice was on, turn it off + if (LLVoiceClient::getInstance()->getUserPTTState()) { - // Otherwise, compare against the URI we're in now. - if(mAudioSession) - { - if (mAudioSession->mChannelID != channelID) - { - needsSwitch = true; - } - } - else - { - if (!channelID.empty()) - { - // mAudioSession is null -- it's not clear what case would cause this. - // For now, log it as a warning and see if it ever crops up. - LL_WARNS("Voice") << "No current audio session... Forcing switch" << LL_ENDL; - needsSwitch = true; - } - } + LLVoiceClient::getInstance()->setUserPTTState(false); } + + notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED); } else { - if (!mNextAudioSession || mNextAudioSession->mChannelID != channelID) + if (mNextAudioSession) { - needsSwitch = true; + deleteSession(mNextAudioSession); } + LL_DEBUGS("Voice") << "switching to channel " << channelID << LL_ENDL; + mNextAudioSession = addSession(channelID, parcel_local_id); + mNextAudioSession->mSessionType = session_type; } - - if(needsSwitch) - { - if (mAudioSession) - { - // If we're already in a channel, or if we're joining one, terminate - // so we can rejoin with the new session data. - sessionTerminate(); - notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL); - deleteSession(mAudioSession); - } - - if (channelID.empty()) - { - // Leave any channel we may be in - LL_DEBUGS("Voice") << "leaving channel" << LL_ENDL; - - if (mNextAudioSession) - { - mAudioSession->shutdownAllConnections(); - } - sessionStatePtr_t oldSession = mNextAudioSession; - mNextAudioSession.reset(); - - // The old session may now need to be deleted. - reapSession(oldSession); - - // If voice was on, turn it off - if (LLVoiceClient::getInstance()->getUserPTTState()) - { - LLVoiceClient::getInstance()->setUserPTTState(false); - } - - notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED); - } - else - { - if (mNextAudioSession) - { - deleteSession(mNextAudioSession); - } - LL_DEBUGS("Voice") << "switching to channel " << channelID << LL_ENDL; - mNextAudioSession = addSession(channelID, parcel_local_id); - mNextAudioSession->mIsSpatial = spatial; - mNextAudioSession->mReconnect = !no_reconnect; - mNextAudioSession->mIsP2P = is_p2p; - } - } - - return needsSwitch; + return true; } void LLWebRTCVoiceClient::joinSession(const sessionStatePtr_t &session) @@ -1376,7 +1234,7 @@ void LLWebRTCVoiceClient::setNonSpatialChannel( const std::string &uri, const std::string &credentials) { - switchChannel(uri, false, false, false, credentials); + switchChannel(uri, sessionState::SESSION_TYPE_P2P); } bool LLWebRTCVoiceClient::setSpatialChannel( @@ -1386,7 +1244,7 @@ bool LLWebRTCVoiceClient::setSpatialChannel( LL_DEBUGS("Voice") << "got spatial channel uri: \"" << uri << "\"" << LL_ENDL; - if((mAudioSession && !(mAudioSession->mIsSpatial)) || (mNextAudioSession && !(mNextAudioSession->mIsSpatial))) + if((mAudioSession && !mAudioSession->isSpatial()) || (mNextAudioSession && !mNextAudioSession->isSpatial())) { // User is in a non-spatial chat or joining a non-spatial chat. Don't switch channels. LL_INFOS("Voice") << "in non-spatial chat, not switching channels" << LL_ENDL; @@ -1394,13 +1252,13 @@ bool LLWebRTCVoiceClient::setSpatialChannel( } else { - return switchChannel(uri, true, false, false, "", parcel_local_id); + return switchChannel(uri, parcel_local_id == INVALID_PARCEL_ID ? sessionState::SESSION_TYPE_ESTATE : sessionState::SESSION_TYPE_PARCEL, parcel_local_id); } } void LLWebRTCVoiceClient::callUser(const LLUUID &uuid) { - switchChannel(uuid.asString(), false, true, true); + switchChannel(uuid.asString(), sessionState::SESSION_TYPE_P2P); } void LLWebRTCVoiceClient::endUserIMSession(const LLUUID &uuid) @@ -1419,9 +1277,7 @@ bool LLWebRTCVoiceClient::answerInvite(std::string &channelID) sessionStatePtr_t session(findP2PSession(LLUUID(channelID))); if(session) { - session->mIsSpatial = false; - session->mReconnect = false; - session->mIsP2P = true; + session->mSessionType = sessionState::ESessionType::SESSION_TYPE_P2P; joinSession(session); return true; @@ -1604,7 +1460,7 @@ bool LLWebRTCVoiceClient::inSpatialChannel(void) if(mAudioSession) { - result = mAudioSession->mIsSpatial; + result = mAudioSession->isSpatial(); } return result; @@ -2061,34 +1917,12 @@ BOOL LLWebRTCVoiceClient::getAreaVoiceDisabled() return mAreaVoiceDisabled; } -void LLWebRTCVoiceClient::reapEmptySessions() -{ - sessionState::reapEmptySessions(); - - // mAudioSession or mNextAudioSession was reaped, - // so reset them. - if (mAudioSession && !sessionState::hasSession(mAudioSession->mChannelID)) - { - mAudioSession.reset(); - } - if (mNextAudioSession && !sessionState::hasSession(mNextAudioSession->mChannelID)) - { - mNextAudioSession.reset(); - } -} - //------------------------------------------------------------------------ std::map<std::string, LLWebRTCVoiceClient::sessionState::ptr_t> LLWebRTCVoiceClient::sessionState::mSessions; LLWebRTCVoiceClient::sessionState::sessionState() : mErrorStatusCode(0), - mIsChannel(false), - mIsSpatial(false), - mIsP2P(false), - mIncoming(false), - mVoiceActive(false), - mReconnect(false), mVolumeDirty(false), mMuteDirty(false), mParticipantsChanged(false) @@ -2102,8 +1936,7 @@ LLWebRTCVoiceClient::sessionState::ptr_t LLWebRTCVoiceClient::sessionState::crea sessionState::ptr_t session(new sessionState()); session->mChannelID = channelID; - connectionPtr_t connection = connectionPtr_t(new LLVoiceWebRTCConnection(region_id, parcelLocalID, channelID)); - session->mWebRTCConnections[channelID] = connection; + session->mWebRTCConnections.emplace_back(new LLVoiceWebRTCConnection(region_id, parcelLocalID, channelID)); session->mPrimaryConnectionID = channelID; @@ -2202,7 +2035,7 @@ void LLWebRTCVoiceClient::sessionState::for_eachPredicate(const std::pair<std::s LLWebRTCVoiceClient::sessionStatePtr_t LLWebRTCVoiceClient::findP2PSession(const LLUUID &agent_id) { sessionStatePtr_t result = sessionState::matchSessionByChannelID(agent_id.asString()); - if (result && result->mIsP2P) + if (result && result->mSessionType == sessionState::SESSION_TYPE_P2P) { return result; } @@ -2217,7 +2050,7 @@ void LLWebRTCVoiceClient::sessionState::shutdownAllConnections() { for (auto &&connection : mWebRTCConnections) { - connection.second->shutDown(); + connection->shutDown(); } } @@ -2277,14 +2110,16 @@ void LLWebRTCVoiceClient::deleteSession(const sessionStatePtr_t &session) verifySessionState(); session->shutdownAllConnections(); // If this is the current audio session, clean up the pointer which will soon be dangling. - if(mAudioSession == session) + bool deleteAudioSession = mAudioSession == session; + bool deleteNextAudioSession = mNextAudioSession == session; + if (deleteAudioSession) { mAudioSession.reset(); mAudioSessionChanged = true; } // ditto for the next audio session - if(mNextAudioSession == session) + if (deleteNextAudioSession) { mNextAudioSession.reset(); } @@ -2696,73 +2531,68 @@ void LLVoiceWebRTCConnection::OnPeerShutDown() void LLVoiceWebRTCConnection::processIceUpdates() { - if (LLWebRTCVoiceClient::isShuttingDown()) - { - return; - } - if (mShutDown) - { - return; - } - LLViewerRegion *regionp = LLWorld::instance().getRegionFromID(mRegionID); - if (!regionp || !regionp->capabilitiesReceived()) + if (mShutDown || LLWebRTCVoiceClient::isShuttingDown()) { - LL_DEBUGS("Voice") << "no capabilities for ice gathering; waiting " << LL_ENDL; return; } - std::string url = regionp->getCapability("VoiceSignalingRequest"); - if (url.empty()) - { - return; - } - - LL_DEBUGS("Voice") << "region ready to complete voice signaling; url=" << url << LL_ENDL; - - LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("voiceAccountProvision", httpPolicy)); - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions); - bool iceCompleted = false; LLSD body; { if (!mTrickling) { - if (mIceCandidates.size()) + if (!mIceCandidates.empty() || mIceCompleted) { - LLSD candidates = LLSD::emptyArray(); - for (auto &ice_candidate : mIceCandidates) + LLViewerRegion *regionp = LLWorld::instance().getRegionFromID(mRegionID); + if (!regionp || !regionp->capabilitiesReceived()) { - LLSD body_candidate; - body_candidate["sdpMid"] = ice_candidate.sdp_mid; - body_candidate["sdpMLineIndex"] = ice_candidate.mline_index; - body_candidate["candidate"] = ice_candidate.candidate; - candidates.append(body_candidate); + LL_DEBUGS("Voice") << "no capabilities for ice gathering; waiting " << LL_ENDL; + return; } - body["candidates"] = candidates; - mIceCandidates.clear(); - } - else if (mIceCompleted) - { - LLSD body_candidate; - body_candidate["completed"] = true; - body["candidate"] = body_candidate; - iceCompleted = mIceCompleted; - mIceCompleted = false; - } - else - { - return; + + std::string url = regionp->getCapability("VoiceSignalingRequest"); + if (url.empty()) + { + return; + } + + LL_DEBUGS("Voice") << "region ready to complete voice signaling; url=" << url << LL_ENDL; + if (!mIceCandidates.empty()) { + LLSD candidates = LLSD::emptyArray(); + for (auto &ice_candidate : mIceCandidates) + { + LLSD body_candidate; + body_candidate["sdpMid"] = ice_candidate.sdp_mid; + body_candidate["sdpMLineIndex"] = ice_candidate.mline_index; + body_candidate["candidate"] = ice_candidate.candidate; + candidates.append(body_candidate); + } + body["candidates"] = candidates; + mIceCandidates.clear(); + } + else if (mIceCompleted) + { + LLSD body_candidate; + body_candidate["completed"] = true; + body["candidate"] = body_candidate; + iceCompleted = mIceCompleted; + mIceCompleted = false; + } + + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter( + new LLCoreHttpUtil::HttpCoroutineAdapter("voiceAccountProvision", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions); + LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost( + url, + LLCore::HttpRequest::DEFAULT_POLICY_ID, + body, + boost::bind(&LLVoiceWebRTCConnection::onIceUpdateComplete, this, iceCompleted, _1), + boost::bind(&LLVoiceWebRTCConnection::onIceUpdateError, this, 3, url, body, iceCompleted, _1)); + mOutstandingRequests++; + mTrickling = true; } - LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost( - url, - LLCore::HttpRequest::DEFAULT_POLICY_ID, - body, - boost::bind(&LLVoiceWebRTCConnection::onIceUpdateComplete, this, iceCompleted, _1), - boost::bind(&LLVoiceWebRTCConnection::onIceUpdateError, this, 3, url, body, iceCompleted, _1)); - mOutstandingRequests++; - mTrickling = true; } } } @@ -2862,7 +2692,7 @@ void LLVoiceWebRTCConnection::OnVoiceConnectionRequestFailure(std::string url, i } bool LLVoiceWebRTCConnection::connectionStateMachine() -{ +{ processIceUpdates(); switch (getVoiceConnectionState()) @@ -2872,6 +2702,7 @@ bool LLVoiceWebRTCConnection::connectionStateMachine() if (mShutDown) { setVoiceConnectionState(VOICE_STATE_DISCONNECT); + break; } mTrickling = false; mIceCompleted = false; diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h index f311f241dc..1e8ecdf5c2 100644 --- a/indra/newview/llvoicewebrtc.h +++ b/indra/newview/llvoicewebrtc.h @@ -330,7 +330,9 @@ public: bool isCallBackPossible(); bool isTextIMPossible(); - void processSessionStates(); + static void processSessionStates(); + + bool processConnectionStates(); void OnConnectionEstablished(const std::string &channelID); void OnConnectionFailure(const std::string &channelID); @@ -347,6 +349,15 @@ public: bool isEmpty() { return mWebRTCConnections.empty(); } + bool isSpatial() { return mSessionType == SESSION_TYPE_ESTATE || mSessionType == SESSION_TYPE_PARCEL; } + + typedef enum e_session_type + { + SESSION_TYPE_ESTATE = 1, + SESSION_TYPE_PARCEL, + SESSION_TYPE_P2P + } ESessionType; + std::string mHandle; std::string mGroupHandle; std::string mChannelID; @@ -362,9 +373,8 @@ public: LLUUID mIMSessionID; LLUUID mCallerID; int mErrorStatusCode; - bool mIsChannel; // True for both group and spatial channels (false for p2p, PSTN) - bool mIsSpatial; // True for spatial channels - bool mIsP2P; + ESessionType mSessionType; + bool mIncoming; bool mVoiceActive; bool mReconnect; // Whether we should try to reconnect to this session if it's dropped @@ -381,16 +391,17 @@ public: LLUUID mVoiceFontID; static void VerifySessions(); - static bool hasSession(const std::string &sessionID) { return mSessions.find(sessionID) != mSessions.end(); } + static bool hasSession(const std::string &sessionID) + { return mSessions.find(sessionID) != mSessions.end(); } private: - std::map<std::string, connectionPtr_t> mWebRTCConnections; - std::string mPrimaryConnectionID; + std::list<connectionPtr_t> mWebRTCConnections; + std::string mPrimaryConnectionID; + static std::map<std::string, ptr_t> mSessions; // canonical list of outstanding sessions. sessionState(); - static std::map<std::string, ptr_t> mSessions; // canonical list of outstanding sessions. static void for_eachPredicate(const std::pair<std::string, LLWebRTCVoiceClient::sessionState::wptr_t> &a, sessionFunc_t func); @@ -406,7 +417,6 @@ public: // Private Member Functions ////////////////////////////////////////////////////// - static void predProcessSessionStates(const LLWebRTCVoiceClient::sessionStatePtr_t &session); static void predOnConnectionEstablished(const LLWebRTCVoiceClient::sessionStatePtr_t &session, std::string channelID); static void predOnConnectionFailure(const LLWebRTCVoiceClient::sessionStatePtr_t &session, std::string channelID); static void predSendData(const LLWebRTCVoiceClient::sessionStatePtr_t &session, const std::string& spatial_data, const std::string& volume_data); @@ -415,7 +425,6 @@ public: static void predSetMicGain(const LLWebRTCVoiceClient::sessionStatePtr_t &session, F32 volume); static void predSetSpeakerVolume(const LLWebRTCVoiceClient::sessionStatePtr_t &session, F32 volume); static void predShutdownSession(const LLWebRTCVoiceClient::sessionStatePtr_t &session); - void reapEmptySessions(); ////////////////////////////// /// @name TVC/Server management and communication @@ -476,9 +485,6 @@ public: void verifySessionState(void); - void joinedAudioSession(const sessionStatePtr_t &session); - void leftAudioSession(const sessionStatePtr_t &session); - // This is called in several places where the session _may_ need to be deleted. // It contains logic for whether to delete the session or keep it around. void reapSession(const sessionStatePtr_t &session); @@ -596,12 +602,8 @@ private: bool mIsInitialized; bool mShutdownComplete; - bool checkParcelChanged(bool update = false); bool switchChannel(const std::string channelID, - bool spatial = true, - bool no_reconnect = false, - bool is_p2p = false, - std::string hash = "", + sessionState::ESessionType sessionType, S32 parcel_local_id = INVALID_PARCEL_ID); void joinSession(const sessionStatePtr_t &session); @@ -808,6 +810,10 @@ protected: } EVoiceConnectionState getVoiceConnectionState() { + if (mVoiceStateMutex.isLocked()) + { + LL_WARNS("Voice") << "LOCKED." << LL_ENDL; + } LLMutexLock lock(&mVoiceStateMutex); return mVoiceConnectionState; } @@ -839,6 +845,7 @@ protected: llwebrtc::LLWebRTCDataInterface *mWebRTCDataInterface; }; +#define VOICE_ELAPSED LLVoiceTimer(__FUNCTION__); #endif //LL_WebRTC_VOICE_CLIENT_H |