summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autobuild.xml24
-rw-r--r--indra/llwebrtc/llwebrtc.cpp56
-rw-r--r--indra/llwebrtc/llwebrtc.h3
-rw-r--r--indra/llwebrtc/llwebrtc_impl.h16
-rw-r--r--indra/newview/llvoicewebrtc.cpp411
-rw-r--r--indra/newview/llvoicewebrtc.h31
6 files changed, 295 insertions, 246 deletions
diff --git a/autobuild.xml b/autobuild.xml
index 3a3e2e5f14..f9c99514a1 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -2901,15 +2901,29 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>creds</key>
<string>github</string>
<key>hash</key>
- <string>8b0191fae0860782a3e79b886364129c433cfd6b</string>
+ <string>a49fb3bb8aaf8325e7c6c4b6036db3da16afa2c9</string>
<key>hash_algorithm</key>
<string>sha1</string>
<key>url</key>
- <string>https://api.github.com/repos/secondlife/3p-webrtc-build/releases/assets/157215889</string>
+ <string>https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.53/webrtc-m114.5735.08.53.8337236647-darwin64-8337236647.tar.zst</string>
</map>
<key>name</key>
<string>darwin64</string>
</map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>598baa054f63624a8e16883541c1f3dc7aa15a8a</string>
+ <key>hash_algorithm</key>
+ <string>sha1</string>
+ <key>url</key>
+ <string>https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.53/webrtc-m114.5735.08.53.8337236647-linux64-8337236647.tar.zst</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
<key>windows64</key>
<map>
<key>archive</key>
@@ -2917,11 +2931,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>creds</key>
<string>github</string>
<key>hash</key>
- <string>64eccac933cee532dc065d9f9729a21d8347aae4</string>
+ <string>59d5f2e40612ab7b0b1a5da8ba288f48d5979216</string>
<key>hash_algorithm</key>
<string>sha1</string>
<key>url</key>
- <string>https://api.github.com/repos/secondlife/3p-webrtc-build/releases/assets/157215892</string>
+ <string>https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.53/webrtc-m114.5735.08.53.8337236647-windows64-8337236647.tar.zst</string>
</map>
<key>name</key>
<string>windows64</string>
@@ -2934,7 +2948,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>vcs_url</key>
<string>https://github.com/secondlife/3p-webrtc-build</string>
<key>version</key>
- <string>m114.5735.08.52.8319849783</string>
+ <string>m114.5735.08.53.8337236647</string>
</map>
<key>xmlrpc-epi</key>
<map>
diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp
index b7501bd0e0..34d950b804 100644
--- a/indra/llwebrtc/llwebrtc.cpp
+++ b/indra/llwebrtc/llwebrtc.cpp
@@ -562,8 +562,10 @@ void LLWebRTCImpl::freePeerConnection(LLWebRTCPeerConnectionInterface* peer_conn
// Most peer connection (signaling) happens on
// the signaling thread.
-LLWebRTCPeerConnectionImpl::LLWebRTCPeerConnectionImpl() :
+LLWebRTCPeerConnectionImpl::LLWebRTCPeerConnectionImpl() :
mWebRTCImpl(nullptr),
+ mClosing(false),
+ mPeerConnection(nullptr),
mMute(false),
mAnswerReceived(false)
{
@@ -580,13 +582,24 @@ void LLWebRTCPeerConnectionImpl::init(LLWebRTCImpl * webrtc_impl)
}
void LLWebRTCPeerConnectionImpl::terminate()
{
- mWebRTCImpl->SignalingBlockingCall(
- [this]()
+ rtc::scoped_refptr<webrtc::PeerConnectionInterface> connection;
+ mPeerConnection.swap(connection);
+ rtc::scoped_refptr<webrtc::DataChannelInterface> dataChannel;
+ mDataChannel.swap(dataChannel);
+ rtc::scoped_refptr<webrtc::MediaStreamInterface> localStream;
+ mLocalStream.swap(localStream);
+
+ mWebRTCImpl->PostSignalingTask(
+ [=]()
{
- if (mPeerConnection)
+ if (connection)
{
- mPeerConnection->Close();
- mPeerConnection = nullptr;
+ connection->Close();
+ }
+ if (dataChannel)
+ {
+ dataChannel->UnregisterObserver();
+ dataChannel->Close();
}
});
}
@@ -710,24 +723,9 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection()
bool LLWebRTCPeerConnectionImpl::shutdownConnection()
{
- if (mPeerConnection)
- {
- mWebRTCImpl->PostSignalingTask(
- [this]()
- {
- if (mPeerConnection)
- {
- mPeerConnection->Close();
- mPeerConnection = nullptr;
- }
- for (auto &observer : mSignalingObserverList)
- {
- observer->OnPeerConnectionShutdown();
- }
- });
- return true;
- }
- return false;
+ mClosing = true;
+ terminate();
+ return true;
}
void LLWebRTCPeerConnectionImpl::enableSenderTracks(bool enable)
@@ -1057,14 +1055,16 @@ void LLWebRTCPeerConnectionImpl::OnSuccess(webrtc::SessionDescriptionInterface *
}
RTC_LOG(LS_INFO) << __FUNCTION__ << " Local SDP: " << sdp_mangled_stream.str();
-
+ std::string mangled_sdp = sdp_mangled_stream.str();
for (auto &observer : mSignalingObserverList)
{
- observer->OnOfferAvailable(sdp_mangled_stream.str());
+ observer->OnOfferAvailable(mangled_sdp);
}
+
+ mPeerConnection->SetLocalDescription(std::unique_ptr<webrtc::SessionDescriptionInterface>(
+ webrtc::CreateSessionDescription(webrtc::SdpType::kOffer, mangled_sdp)),
+ rtc::scoped_refptr<webrtc::SetLocalDescriptionObserverInterface>(this));
- 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)
diff --git a/indra/llwebrtc/llwebrtc.h b/indra/llwebrtc/llwebrtc.h
index dab7774499..be2e5cdf68 100644
--- a/indra/llwebrtc/llwebrtc.h
+++ b/indra/llwebrtc/llwebrtc.h
@@ -192,9 +192,6 @@ class LLWebRTCSignalingObserver
// Called when the data channel has been established and data
// transfer can begin.
virtual void OnDataChannelReady(LLWebRTCDataInterface *data_interface) = 0;
-
- // Called when a peer connection has finished shutting down.
- virtual void OnPeerConnectionShutdown() = 0;
};
diff --git a/indra/llwebrtc/llwebrtc_impl.h b/indra/llwebrtc/llwebrtc_impl.h
index 1f696e8c66..38810a29b5 100644
--- a/indra/llwebrtc/llwebrtc_impl.h
+++ b/indra/llwebrtc/llwebrtc_impl.h
@@ -346,21 +346,23 @@ class LLWebRTCPeerConnectionImpl : public LLWebRTCPeerConnectionInterface,
LLWebRTCImpl * mWebRTCImpl;
+ bool mClosing;
+
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> mPeerConnectionFactory;
- bool mMute;
+ bool mMute;
// signaling
- std::vector<LLWebRTCSignalingObserver *> mSignalingObserverList;
+ std::vector<LLWebRTCSignalingObserver *> mSignalingObserverList;
std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> mCachedIceCandidates;
- bool mAnswerReceived;
+ bool mAnswerReceived;
- rtc::scoped_refptr<webrtc::PeerConnectionInterface> mPeerConnection;
- rtc::scoped_refptr<webrtc::MediaStreamInterface> mLocalStream;
+ rtc::scoped_refptr<webrtc::PeerConnectionInterface> mPeerConnection;
+ rtc::scoped_refptr<webrtc::MediaStreamInterface> mLocalStream;
// data
- std::vector<LLWebRTCDataObserver *> mDataObserverList;
- rtc::scoped_refptr<webrtc::DataChannelInterface> mDataChannel;
+ std::vector<LLWebRTCDataObserver *> mDataObserverList;
+ rtc::scoped_refptr<webrtc::DataChannelInterface> mDataChannel;
};
}
diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp
index cae7154bc2..6aab67ca63 100644
--- a/indra/newview/llvoicewebrtc.cpp
+++ b/indra/newview/llvoicewebrtc.cpp
@@ -1,5 +1,5 @@
/**
- * @file LLWebRTCVoiceClient.cpp
+ * @file llvoicewebrtc.cpp
* @brief Implementation of LLWebRTCVoiceClient class which is the interface to the voice client process.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
@@ -585,8 +585,19 @@ void LLWebRTCVoiceClient::setDevicesListUpdated(bool state)
mDevicesListUpdated = state;
}
-void LLWebRTCVoiceClient::OnDevicesChanged(const llwebrtc::LLWebRTCVoiceDeviceList &render_devices,
- const llwebrtc::LLWebRTCVoiceDeviceList &capture_devices)
+// the singleton 'this' pointer will outlive the work queue.
+void LLWebRTCVoiceClient::OnDevicesChanged(const llwebrtc::LLWebRTCVoiceDeviceList& render_devices,
+ const llwebrtc::LLWebRTCVoiceDeviceList& capture_devices)
+{
+ LL::WorkQueue::postMaybe(mMainQueue,
+ [=]
+ {
+ OnDevicesChangedImpl(render_devices, capture_devices);
+ });
+}
+
+void LLWebRTCVoiceClient::OnDevicesChangedImpl(const llwebrtc::LLWebRTCVoiceDeviceList &render_devices,
+ const llwebrtc::LLWebRTCVoiceDeviceList &capture_devices)
{
std::string inputDevice = gSavedSettings.getString("VoiceInputAudioDevice");
std::string outputDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
@@ -1412,6 +1423,7 @@ void LLWebRTCVoiceClient::setVoiceEnabled(bool enabled)
updatePosition();
if (!mIsCoroutineActive)
{
+ mMainQueue = LL::WorkQueue::getInstance("mainloop");
LLCoros::instance().launch("LLWebRTCVoiceClient::voiceConnectionCoro",
boost::bind(&LLWebRTCVoiceClient::voiceConnectionCoro, LLWebRTCVoiceClient::getInstance()));
}
@@ -2000,6 +2012,7 @@ LLVoiceWebRTCConnection::LLVoiceWebRTCConnection(const LLUUID &regionID, const s
mWebRTCPeerConnectionInterface = llwebrtc::newPeerConnection();
mWebRTCPeerConnectionInterface->setSignalingObserver(this);
+ mMainQueue = LL::WorkQueue::getInstance("mainloop");
}
LLVoiceWebRTCConnection::~LLVoiceWebRTCConnection()
@@ -2026,32 +2039,35 @@ LLVoiceWebRTCConnection::~LLVoiceWebRTCConnection()
// negotiated, updates about the best connectivity paths may trickle in. These need to be
// sent to the Secondlife WebRTC server via the simulator so that both sides have a clear
// view of the network environment.
+
+// callback from llwebrtc
void LLVoiceWebRTCConnection::OnIceGatheringState(llwebrtc::LLWebRTCSignalingObserver::EIceGatheringState state)
{
- LL_DEBUGS("Voice") << "Ice Gathering voice account. " << state << LL_ENDL;
+ LL::WorkQueue::postMaybe(mMainQueue,
+ [=] {
+ LL_DEBUGS("Voice") << "Ice Gathering voice account. " << state << LL_ENDL;
- switch (state)
- {
- case llwebrtc::LLWebRTCSignalingObserver::EIceGatheringState::ICE_GATHERING_COMPLETE:
- {
- LLMutexLock lock(&mVoiceStateMutex);
- mIceCompleted = true;
- break;
- }
- case llwebrtc::LLWebRTCSignalingObserver::EIceGatheringState::ICE_GATHERING_NEW:
- {
- LLMutexLock lock(&mVoiceStateMutex);
- mIceCompleted = false;
- }
- default:
- break;
- }
+ switch (state)
+ {
+ case llwebrtc::LLWebRTCSignalingObserver::EIceGatheringState::ICE_GATHERING_COMPLETE:
+ {
+ mIceCompleted = true;
+ break;
+ }
+ case llwebrtc::LLWebRTCSignalingObserver::EIceGatheringState::ICE_GATHERING_NEW:
+ {
+ mIceCompleted = false;
+ }
+ default:
+ break;
+ }
+ });
}
-void LLVoiceWebRTCConnection::OnIceCandidate(const llwebrtc::LLWebRTCIceCandidate &candidate)
+// callback from llwebrtc
+void LLVoiceWebRTCConnection::OnIceCandidate(const llwebrtc::LLWebRTCIceCandidate& candidate)
{
- LLMutexLock lock(&mVoiceStateMutex);
- mIceCandidates.push_back(candidate);
+ LL::WorkQueue::postMaybe(mMainQueue, [=] { mIceCandidates.push_back(candidate); });
}
void LLVoiceWebRTCConnection::onIceUpdateComplete(bool ice_completed, const LLSD &result)
@@ -2182,39 +2198,74 @@ void LLVoiceWebRTCConnection::processIceUpdates()
// and is passed to the simulator via a CAP, which then passes
// it on to the Secondlife WebRTC server.
+//
+// The LLWebRTCVoiceConnection object will not be deleted
+// before the webrtc connection itself is shut down, so
+// we shouldn't be getting this callback on a nonexistant
+// this pointer.
+
+// callback from llwebrtc
void LLVoiceWebRTCConnection::OnOfferAvailable(const std::string &sdp)
{
- LL_DEBUGS("Voice") << "On Offer Available." << LL_ENDL;
- LLMutexLock lock(&mVoiceStateMutex);
- mChannelSDP = sdp;
- if (mVoiceConnectionState == VOICE_STATE_WAIT_FOR_SESSION_START)
- {
- mVoiceConnectionState = VOICE_STATE_REQUEST_CONNECTION;
- }
+ LL::WorkQueue::postMaybe(mMainQueue,
+ [=] {
+ if (mShutDown)
+ {
+ return;
+ }
+ LL_DEBUGS("Voice") << "On Offer Available." << LL_ENDL;
+ mChannelSDP = sdp;
+ if (mVoiceConnectionState == VOICE_STATE_WAIT_FOR_SESSION_START)
+ {
+ mVoiceConnectionState = VOICE_STATE_REQUEST_CONNECTION;
+ }
+ });
}
-// Notifications from the webrtc library.
-void LLVoiceWebRTCConnection::OnAudioEstablished(llwebrtc::LLWebRTCAudioInterface *audio_interface)
-{
- LL_DEBUGS("Voice") << "On AudioEstablished." << LL_ENDL;
- mWebRTCAudioInterface = audio_interface;
- setVoiceConnectionState(VOICE_STATE_SESSION_ESTABLISHED);
+
+//
+// The LLWebRTCVoiceConnection object will not be deleted
+// before the webrtc connection itself is shut down, so
+// we shouldn't be getting this callback on a nonexistant
+// this pointer.
+// nor should audio_interface be invalid if the LLWebRTCVoiceConnection
+// is shut down.
+
+// callback from llwebrtc
+void LLVoiceWebRTCConnection::OnAudioEstablished(llwebrtc::LLWebRTCAudioInterface* audio_interface)
+{
+ LL::WorkQueue::postMaybe(mMainQueue,
+ [=] {
+ if (mShutDown)
+ {
+ return;
+ }
+ LL_DEBUGS("Voice") << "On AudioEstablished." << LL_ENDL;
+ mWebRTCAudioInterface = audio_interface;
+ setVoiceConnectionState(VOICE_STATE_SESSION_ESTABLISHED);
+ });
}
+
+//
+// The LLWebRTCVoiceConnection object will not be deleted
+// before the webrtc connection itself is shut down, so
+// we shouldn't be getting this callback on a nonexistant
+// this pointer.
+
+// callback from llwebrtc
void LLVoiceWebRTCConnection::OnRenegotiationNeeded()
{
- LL_DEBUGS("Voice") << "Voice channel requires renegotiation." << LL_ENDL;
- if (!mShutDown)
- {
- setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
- }
+ LL::WorkQueue::postMaybe(mMainQueue,
+ [=] {
+ LL_DEBUGS("Voice") << "Voice channel requires renegotiation." << LL_ENDL;
+ if (!mShutDown)
+ {
+ setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
+ }
+ });
}
-void LLVoiceWebRTCConnection::OnPeerConnectionShutdown()
-{
- setVoiceConnectionState(VOICE_STATE_SESSION_EXIT);
- mOutstandingRequests--; // shut down is an async call which is handled on a webrtc thread.
-}
void LLVoiceWebRTCConnection::setMuteMic(bool muted)
{
@@ -2284,7 +2335,7 @@ void LLVoiceWebRTCConnection::sendData(const std::string &data)
// Tell the simulator that we're shutting down a voice connection.
// The simulator will pass this on to the Secondlife WebRTC server.
-bool LLVoiceWebRTCConnection::breakVoiceConnection(bool corowait)
+void LLVoiceWebRTCConnection::breakVoiceConnection()
{
LL_DEBUGS("Voice") << "Disconnecting voice." << LL_ENDL;
if (mWebRTCDataInterface)
@@ -2297,96 +2348,53 @@ bool LLVoiceWebRTCConnection::breakVoiceConnection(bool corowait)
if (!regionp || !regionp->capabilitiesReceived())
{
LL_DEBUGS("Voice") << "no capabilities for voice provisioning; waiting " << LL_ENDL;
- setVoiceConnectionState(VOICE_STATE_SESSION_EXIT);
- return false;
+ return;
}
std::string url = regionp->getCapability("ProvisionVoiceAccountRequest");
if (url.empty())
{
- return false;
+ return;
}
LL_DEBUGS("Voice") << "region ready for voice break; url=" << url << LL_ENDL;
- LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
- LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("parcelVoiceInfoRequest", httpPolicy));
- LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
-
LLVoiceWebRTCStats::getInstance()->provisionAttemptStart();
LLSD body;
body["logout"] = TRUE;
body["viewer_session"] = mViewerSession;
body["voice_server_type"] = REPORTED_VOICE_SERVER_TYPE;
- LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(
- url,
- LLCore::HttpRequest::DEFAULT_POLICY_ID,
- body,
- boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceDisconnectionRequestSuccess, this, _1),
- boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceDisconnectionRequestFailure, this, url, 3, body, _1));
- setVoiceConnectionState(VOICE_STATE_WAIT_FOR_EXIT);
- mOutstandingRequests++;
- return true;
-}
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(
+ new LLCoreHttpUtil::HttpCoroutineAdapter("LLVoiceWebRTCAdHocConnection::breakVoiceConnection",
+ LLCore::HttpRequest::DEFAULT_POLICY_ID));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
-void LLVoiceWebRTCConnection::OnVoiceDisconnectionRequestSuccess(const LLSD &result)
-{
- mOutstandingRequests--;
- if (LLWebRTCVoiceClient::isShuttingDown())
- {
- return;
- }
+ httpOpts->setWantHeaders(true);
- if (mWebRTCPeerConnectionInterface)
- {
- if (mWebRTCPeerConnectionInterface->shutdownConnection())
- {
- mOutstandingRequests++;
- }
- }
- else
- {
- setVoiceConnectionState(VOICE_STATE_SESSION_EXIT);
- }
-}
+ mOutstandingRequests++;
+ setVoiceConnectionState(VOICE_STATE_WAIT_FOR_EXIT);
+
+ // tell the server to shut down the connection as a courtesy.
+ // shutdownConnection will drop the WebRTC connection which will
+ // also shut things down.
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, body, httpOpts);
-void LLVoiceWebRTCConnection::OnVoiceDisconnectionRequestFailure(std::string url, int retries, LLSD body, const LLSD &result)
-{
- if (LLWebRTCVoiceClient::isShuttingDown())
- {
- mOutstandingRequests--;
- return;
- }
- if (retries >= 0)
- {
- // retry a few times.
- LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(
- url,
- LLCore::HttpRequest::DEFAULT_POLICY_ID,
- body,
- boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceDisconnectionRequestSuccess, this, _1),
- boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceDisconnectionRequestFailure, this, url, retries - 1, body, _1));
- return;
- }
if (mWebRTCPeerConnectionInterface)
{
- mOutstandingRequests++;
mWebRTCPeerConnectionInterface->shutdownConnection();
}
- else
- {
- setVoiceConnectionState(VOICE_STATE_SESSION_EXIT);
- }
+ setVoiceConnectionState(VOICE_STATE_SESSION_EXIT);
+
mOutstandingRequests--;
}
-
// Tell the simulator to tell the Secondlife WebRTC server that we want a voice
// connection. The SDP is sent up as part of this, and the simulator will respond
// with an 'answer' which is in the form of another SDP. The webrtc library
// will use the offer and answer to negotiate the session.
-bool LLVoiceWebRTCSpatialConnection::requestVoiceConnection()
+void LLVoiceWebRTCSpatialConnection::requestVoiceConnection()
{
LLViewerRegion *regionp = LLWorld::instance().getRegionFromID(mRegionID);
@@ -2394,13 +2402,15 @@ bool LLVoiceWebRTCSpatialConnection::requestVoiceConnection()
if (!regionp || !regionp->capabilitiesReceived())
{
LL_DEBUGS("Voice") << "no capabilities for voice provisioning; waiting " << LL_ENDL;
- return false;
+ setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
+ return;
}
std::string url = regionp->getCapability("ProvisionVoiceAccountRequest");
if (url.empty())
{
- return false;
+ setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
+ return;
}
LL_DEBUGS("Voice") << "region ready for voice provisioning; url=" << url << LL_ENDL;
@@ -2410,7 +2420,6 @@ bool LLVoiceWebRTCSpatialConnection::requestVoiceConnection()
LLSD jsep;
jsep["type"] = "offer";
{
- LLMutexLock lock(&mVoiceStateMutex);
jsep["sdp"] = mChannelSDP;
}
body["jsep"] = jsep;
@@ -2420,27 +2429,42 @@ bool LLVoiceWebRTCSpatialConnection::requestVoiceConnection()
}
body["channel_type"] = "local";
body["voice_server_type"] = WEBRTC_VOICE_SERVER_TYPE;
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(
+ new LLCoreHttpUtil::HttpCoroutineAdapter("LLVoiceWebRTCAdHocConnection::requestVoiceConnection",
+ LLCore::HttpRequest::DEFAULT_POLICY_ID));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
- LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(
- url,
- LLCore::HttpRequest::DEFAULT_POLICY_ID,
- body,
- boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceConnectionRequestSuccess, this, _1),
- boost::bind(&LLVoiceWebRTCSpatialConnection::OnVoiceConnectionRequestFailure, this, url, 3, body, _1));
+ httpOpts->setWantHeaders(true);
mOutstandingRequests++;
- return true;
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, body, httpOpts);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
+ }
+ else
+ {
+ OnVoiceConnectionRequestSuccess(result);
+ }
+ mOutstandingRequests--;
}
void LLVoiceWebRTCConnection::OnVoiceConnectionRequestSuccess(const LLSD &result)
{
- mOutstandingRequests--;
if (LLWebRTCVoiceClient::isShuttingDown())
{
return;
}
LLVoiceWebRTCStats::getInstance()->provisionAttemptEnd(true);
- if (result.has("viewer_session") && result.has("jsep") && result["jsep"].has("type") && result["jsep"]["type"] == "answer" &&
+ if (result.has("viewer_session") &&
+ result.has("jsep") &&
+ result["jsep"].has("type") &&
+ result["jsep"]["type"] == "answer" &&
result["jsep"].has("sdp"))
{
mRemoteChannelSDP = result["jsep"]["sdp"].asString();
@@ -2455,35 +2479,9 @@ void LLVoiceWebRTCConnection::OnVoiceConnectionRequestSuccess(const LLSD &result
LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response"
<< " channel sdp " << mRemoteChannelSDP << LL_ENDL;
-
mWebRTCPeerConnectionInterface->AnswerAvailable(mRemoteChannelSDP);
}
-
-void LLVoiceWebRTCConnection::OnVoiceConnectionRequestFailure(std::string url, int retries, LLSD body, const LLSD &result)
-{
- if (LLWebRTCVoiceClient::isShuttingDown())
- {
- mOutstandingRequests--;
- return;
- }
- if (retries >= 0)
- {
- LL_WARNS("Voice") << "Failure connecting to voice, retrying." << body << " RESULT: " << result << LL_ENDL;
- LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(
- url,
- LLCore::HttpRequest::DEFAULT_POLICY_ID,
- body,
- boost::bind(&LLVoiceWebRTCConnection::OnVoiceConnectionRequestSuccess, this, _1),
- boost::bind(&LLVoiceWebRTCConnection::OnVoiceConnectionRequestFailure, this, url, retries - 1, body, _1));
- return;
- }
- LL_WARNS("Voice") << "Unable to connect voice." << body << " RESULT: " << result << LL_ENDL;
- setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
- mOutstandingRequests--;
-}
-
-
// Primary state machine for negotiating a single voice connection to the
// Secondlife WebRTC server.
bool LLVoiceWebRTCConnection::connectionStateMachine()
@@ -2530,14 +2528,9 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
// Ask the sim to ask the Secondlife WebRTC server for a connection to
// a given voice channel. On completion, we'll move on to the
// VOICE_STATE_SESSION_ESTABLISHED via a callback on a webrtc thread.
- if (!requestVoiceConnection())
- {
- setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
- }
- else
- {
- setVoiceConnectionState(VOICE_STATE_CONNECTION_WAIT);
- }
+ setVoiceConnectionState(VOICE_STATE_CONNECTION_WAIT);
+ LLCoros::getInstance()->launch("LLVoiceWebRTCConnection::requestVoiceConnectionCoro",
+ boost::bind(&LLVoiceWebRTCConnection::requestVoiceConnectionCoro, this));
break;
case VOICE_STATE_CONNECTION_WAIT:
@@ -2611,7 +2604,8 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
break;
case VOICE_STATE_DISCONNECT:
- breakVoiceConnection(true);
+ LLCoros::instance().launch("LLVoiceWebRTCConnection::breakVoiceConnection",
+ boost::bind(&LLVoiceWebRTCConnection::breakVoiceConnection, this));
break;
case VOICE_STATE_WAIT_FOR_EXIT:
@@ -2620,7 +2614,6 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
case VOICE_STATE_SESSION_EXIT:
{
{
- LLMutexLock lock(&mVoiceStateMutex);
if (!mShutDown)
{
mVoiceConnectionState = VOICE_STATE_START_SESSION;
@@ -2649,19 +2642,35 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
}
// Data has been received on the webrtc data channel
-void LLVoiceWebRTCConnection::OnDataReceived(const std::string &data, bool binary)
-{
- // incoming data will be a json structure (if it's not binary.) We may pack
- // binary for size reasons. Most of the keys in the json objects are
- // single or double characters for size reasons.
- // The primary element is:
- // An object where each key is an agent id. (in the future, we may allow
- // integer indices into an agentid list, populated on join commands. For size.
- // Each key will point to a json object with keys identifying what's updated.
- // 'p' - audio source power (level/volume) (int8 as int)
- // 'j' - object of join data (currently only a boolean 'p' marking a primary participant)
- // 'l' - boolean, always true if exists.
- // 'v' - boolean - voice activity has been detected.
+// incoming data will be a json structure (if it's not binary.) We may pack
+// binary for size reasons. Most of the keys in the json objects are
+// single or double characters for size reasons.
+// The primary element is:
+// An object where each key is an agent id. (in the future, we may allow
+// integer indices into an agentid list, populated on join commands. For size.
+// Each key will point to a json object with keys identifying what's updated.
+// 'p' - audio source power (level/volume) (int8 as int)
+// 'j' - object of join data (currently only a boolean 'p' marking a primary participant)
+// 'l' - boolean, always true if exists.
+// 'v' - boolean - voice activity has been detected.
+
+// llwebrtc callback
+void LLVoiceWebRTCConnection::OnDataReceived(const std::string& data, bool binary)
+{
+ LL::WorkQueue::postMaybe(mMainQueue, [=] { LLVoiceWebRTCConnection::OnDataReceivedImpl(data, binary); });
+}
+
+//
+// The LLWebRTCVoiceConnection object will not be deleted
+// before the webrtc connection itself is shut down, so
+// we shouldn't be getting this callback on a nonexistant
+// this pointer.
+void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool binary)
+{
+ if (mShutDown)
+ {
+ return;
+ }
if (binary)
{
@@ -2769,13 +2778,30 @@ void LLVoiceWebRTCConnection::OnDataReceived(const std::string &data, bool binar
}
}
+//
+// The LLWebRTCVoiceConnection object will not be deleted
+// before the webrtc connection itself is shut down, so
+// we shouldn't be getting this callback on a nonexistant
+// this pointer.
+// nor should data_interface be invalid if the LLWebRTCVoiceConnection
+// is shut down.
+
+// llwebrtc callback
void LLVoiceWebRTCConnection::OnDataChannelReady(llwebrtc::LLWebRTCDataInterface *data_interface)
{
- if (data_interface)
- {
- mWebRTCDataInterface = data_interface;
- mWebRTCDataInterface->setDataObserver(this);
- }
+ LL::WorkQueue::postMaybe(mMainQueue,
+ [=] {
+ if (mShutDown)
+ {
+ return;
+ }
+
+ if (data_interface)
+ {
+ mWebRTCDataInterface = data_interface;
+ mWebRTCDataInterface->setDataObserver(this);
+ }
+ });
}
// tell the Secondlife WebRTC server that
@@ -2872,7 +2898,7 @@ LLVoiceWebRTCAdHocConnection::~LLVoiceWebRTCAdHocConnection()
// as they go to a different set of Secondlife WebRTC servers.
// They also require credentials for the given channels.
// So, we have a separate requestVoiceConnection call.
-bool LLVoiceWebRTCAdHocConnection::requestVoiceConnection()
+void LLVoiceWebRTCAdHocConnection::requestVoiceConnection()
{
LLViewerRegion *regionp = LLWorld::instance().getRegionFromID(mRegionID);
@@ -2880,13 +2906,15 @@ bool LLVoiceWebRTCAdHocConnection::requestVoiceConnection()
if (!regionp || !regionp->capabilitiesReceived())
{
LL_DEBUGS("Voice") << "no capabilities for voice provisioning; waiting " << LL_ENDL;
- return false;
+ setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
+ return;
}
std::string url = regionp->getCapability("ProvisionVoiceAccountRequest");
if (url.empty())
{
- return false;
+ setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
+ return;
}
LLVoiceWebRTCStats::getInstance()->provisionAttemptStart();
@@ -2894,7 +2922,6 @@ bool LLVoiceWebRTCAdHocConnection::requestVoiceConnection()
LLSD jsep;
jsep["type"] = "offer";
{
- LLMutexLock lock(&mVoiceStateMutex);
jsep["sdp"] = mChannelSDP;
}
body["jsep"] = jsep;
@@ -2903,12 +2930,26 @@ bool LLVoiceWebRTCAdHocConnection::requestVoiceConnection()
body["channel_type"] = "multiagent";
body["voice_server_type"] = WEBRTC_VOICE_SERVER_TYPE;
- LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(
- url,
- LLCore::HttpRequest::DEFAULT_POLICY_ID,
- body,
- boost::bind(&LLVoiceWebRTCAdHocConnection::OnVoiceConnectionRequestSuccess, this, _1),
- boost::bind(&LLVoiceWebRTCAdHocConnection::OnVoiceConnectionRequestFailure, this, url, 3, body, _1));
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(
+ new LLCoreHttpUtil::HttpCoroutineAdapter("LLVoiceWebRTCAdHocConnection::requestVoiceConnection",
+ LLCore::HttpRequest::DEFAULT_POLICY_ID));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+ httpOpts->setWantHeaders(true);
mOutstandingRequests++;
- return true;
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, body, httpOpts);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ setVoiceConnectionState(VOICE_STATE_SESSION_RETRY);
+ }
+ else
+ {
+ OnVoiceConnectionRequestSuccess(result);
+ }
+ mOutstandingRequests--;
}
diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h
index b26bea27ce..21fc79420b 100644
--- a/indra/newview/llvoicewebrtc.h
+++ b/indra/newview/llvoicewebrtc.h
@@ -225,7 +225,8 @@ public:
void OnDevicesChanged(const llwebrtc::LLWebRTCVoiceDeviceList &render_devices,
const llwebrtc::LLWebRTCVoiceDeviceList &capture_devices) override;
//@}
-
+ void OnDevicesChangedImpl(const llwebrtc::LLWebRTCVoiceDeviceList &render_devices,
+ const llwebrtc::LLWebRTCVoiceDeviceList &capture_devices);
struct participantState
{
@@ -445,6 +446,8 @@ private:
/// Clean up objects created during a voice session.
void cleanUp();
+ LL::WorkQueue::weak_t mMainQueue;
+
bool mTuningMode;
F32 mTuningMicGain;
int mTuningSpeakerVolume;
@@ -585,7 +588,6 @@ class LLVoiceWebRTCConnection :
void OnOfferAvailable(const std::string &sdp) override;
void OnRenegotiationNeeded() override;
void OnAudioEstablished(llwebrtc::LLWebRTCAudioInterface *audio_interface) override;
- void OnPeerConnectionShutdown() override;
//@}
/////////////////////////
@@ -596,6 +598,8 @@ class LLVoiceWebRTCConnection :
void OnDataChannelReady(llwebrtc::LLWebRTCDataInterface *data_interface) override;
//@}
+ void OnDataReceivedImpl(const std::string &data, bool binary);
+
void sendJoin();
void sendData(const std::string &data);
@@ -618,12 +622,10 @@ class LLVoiceWebRTCConnection :
void shutDown()
{
- LLMutexLock lock(&mVoiceStateMutex);
mShutDown = true;
}
void OnVoiceConnectionRequestSuccess(const LLSD &body);
- void OnVoiceConnectionRequestFailure(std::string url, int retries, LLSD body, const LLSD &result);
protected:
typedef enum e_voice_connection_state
@@ -644,11 +646,10 @@ class LLVoiceWebRTCConnection :
} EVoiceConnectionState;
EVoiceConnectionState mVoiceConnectionState;
- LLMutex mVoiceStateMutex;
+ LL::WorkQueue::weak_t mMainQueue;
+
void setVoiceConnectionState(EVoiceConnectionState new_voice_connection_state)
{
- LLMutexLock lock(&mVoiceStateMutex);
-
if (new_voice_connection_state & VOICE_STATE_SESSION_STOPPING)
{
// the new state is shutdown or restart.
@@ -666,19 +667,13 @@ class LLVoiceWebRTCConnection :
}
EVoiceConnectionState getVoiceConnectionState()
{
- if (mVoiceStateMutex.isLocked())
- {
- LL_WARNS("Voice") << "LOCKED." << LL_ENDL;
- }
- LLMutexLock lock(&mVoiceStateMutex);
return mVoiceConnectionState;
}
- virtual bool requestVoiceConnection() = 0;
+ virtual void requestVoiceConnection() = 0;
+ void requestVoiceConnectionCoro() { requestVoiceConnection(); }
- bool breakVoiceConnection(bool wait);
- void OnVoiceDisconnectionRequestSuccess(const LLSD &body);
- void OnVoiceDisconnectionRequestFailure(std::string url, int retries, LLSD body, const LLSD &result);
+ void breakVoiceConnection();
LLUUID mRegionID;
LLUUID mViewerSession;
@@ -725,7 +720,7 @@ class LLVoiceWebRTCSpatialConnection :
protected:
- bool requestVoiceConnection() override;
+ void requestVoiceConnection() override;
S32 mParcelLocalID;
};
@@ -740,7 +735,7 @@ class LLVoiceWebRTCAdHocConnection : public LLVoiceWebRTCConnection
bool isSpatial() override { return false; }
protected:
- bool requestVoiceConnection() override;
+ void requestVoiceConnection() override;
std::string mCredentials;
};