Touch up parcel voice enable/disable.

master
Roxie Linden 2023-12-18 11:45:15 -08:00
parent a60593164e
commit a7509747b2
3 changed files with 263 additions and 424 deletions

View File

@ -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)
{
}
//

View File

@ -455,17 +455,29 @@ void LLWebRTCVoiceClient::idle(void* user_data)
//
//
void LLWebRTCVoiceClient::predProcessSessionStates(const LLWebRTCVoiceClient::sessionStatePtr_t& session)
{
session->processSessionStates();
}
void LLWebRTCVoiceClient::sessionState::processSessionStates()
{
std::map<std::string, connectionPtr_t>::iterator iter;
for (iter = mWebRTCConnections.begin(); iter != mWebRTCConnections.end();)
auto iter = mSessions.begin();
while (iter != mSessions.end())
{
if (!iter->second->connectionStateMachine())
if (!iter->second->processConnectionStates())
{
iter = mSessions.erase(iter);
}
else
{
iter++;
}
}
}
bool LLWebRTCVoiceClient::sessionState::processConnectionStates()
{
std::list<connectionPtr_t>::iterator iter = mWebRTCConnections.begin();
while (iter != mWebRTCConnections.end())
{
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)
bool LLWebRTCVoiceClient::switchChannel(const std::string channelID,
sessionState::ESessionType session_type,
S32 parcel_local_id)
{
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 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())
if (mShutDown || LLWebRTCVoiceClient::isShuttingDown())
{
return;
}
if (mShutDown)
{
return;
}
LLViewerRegion *regionp = LLWorld::instance().getRegionFromID(mRegionID);
if (!regionp || !regionp->capabilitiesReceived())
{
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();
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;
}
else if (mIceCompleted)
{
LLSD body_candidate;
body_candidate["completed"] = true;
body["candidate"] = body_candidate;
iceCompleted = mIceCompleted;
mIceCompleted = false;
}
else
{
return;
}
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;

View File

@ -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