From ab350d3cb38e1bcba0bbc50cf92408cb41d543fb Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Sun, 22 May 2011 02:23:05 +0200 Subject: revamp the voice client. * split the "voice" debug tag into several tags for usable filtering while debugging * remove debug-spam from user view by: * remove capability request spam by: * llstartup the voice client state engine when actually a region is present, and not the initial fake region. * don't request a capability to determine if (the very same) capability can be requested. * don't do it over and over as if a capability rezzed in like an avatar. Its available - or not (see llstartup). * unload the daemon if not used. * load vivox daemon depending on specific criteria in the caps * remove the partial implementation to load a specific daemon with via the openregion message or the login response. * discard obsolete caps. Tested and working on linux: Parcel changing, region changing, (SL) voice-disabled region private call, (SL) private call region changing, (OS) no voice <-> voice region changing, (OS) mumble <-> freeswitch region changing. To test: Mac, Win. Anything that needs to be tested and not mentioned above. --- linden/indra/newview/app_settings/logcontrol.xml | 5 + linden/indra/newview/app_settings/settings.xml | 17 +- linden/indra/newview/kowopenregionsettings.cpp | 8 +- linden/indra/newview/llstartup.cpp | 12 +- linden/indra/newview/llvoiceclient.cpp | 721 ++++++++++++++--------- linden/indra/newview/llvoiceclient.h | 20 +- 6 files changed, 474 insertions(+), 309 deletions(-) (limited to 'linden/indra') diff --git a/linden/indra/newview/app_settings/logcontrol.xml b/linden/indra/newview/app_settings/logcontrol.xml index c9e9127..f0db00f 100644 --- a/linden/indra/newview/app_settings/logcontrol.xml +++ b/linden/indra/newview/app_settings/logcontrol.xml @@ -90,7 +90,12 @@ + + + + + diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml index 24ff619..eac7674 100644 --- a/linden/indra/newview/app_settings/settings.xml +++ b/linden/indra/newview/app_settings/settings.xml @@ -39,16 +39,27 @@ Value 0 - VoiceModule + VoiceModuleMumble Comment - Executable file that runs voice. Platform specific parts (like .exe on windows) are added automatically. + Executable file that runs mumble voice . Platform specific parts (like .exe on windows) are added automatically, paths are stripped off if present. Defaults to mumble if empty Persist 1 Type String Value - SLVoice + + + VoiceModuleVivox + + Comment + Executable file that runs vivox voice. Platform specific parts (like .exe on windows) are added automatically, paths are stripped off if present. Defaults to SLVoice if empty. + Persist + 1 + Type + String + Value + diff --git a/linden/indra/newview/kowopenregionsettings.cpp b/linden/indra/newview/kowopenregionsettings.cpp index 0c4bb38..6257147 100644 --- a/linden/indra/newview/kowopenregionsettings.cpp +++ b/linden/indra/newview/kowopenregionsettings.cpp @@ -36,7 +36,6 @@ #include "llviewerobject.h" #include "llfloaterregioninfo.h" #include "llfloaterworldmap.h" -#include "llvoiceclient.h" #include "viewertime.h" //DEBUG includes @@ -205,12 +204,7 @@ class OpenRegionInfoUpdate : public LLHTTPNode { gHippoLimits->mAllowParcelWindLight = body["AllowParcelWindLight"].asInteger() == 1; } - if ( body.has("Voice") ) - { - gSavedSettings.setString("VoiceModule", body["Voice"].asString()); - //gVoiceClient->close(); - //gVoiceClient->start(); - } + if (limitschanged) gFloaterTools->updateToolsSizeLimits(); diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp index e29dc5a..b80a286 100644 --- a/linden/indra/newview/llstartup.cpp +++ b/linden/indra/newview/llstartup.cpp @@ -1884,8 +1884,7 @@ bool idle_startup() tmp = LLUserAuth::getInstance()->getResponse("max-agent-groups"); if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setMaxAgentGroups(atoi(tmp.c_str())); - tmp = LLUserAuth::getInstance()->getResponse("VoiceConnector"); - if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setVoiceConnector(tmp); + gHippoGridManager->saveFile(); gHippoLimits->setLimits(); @@ -1931,8 +1930,7 @@ bool idle_startup() } // else llwarns << "MapServerURL empty"<< llendl; - // Pass the user information to the voice chat server interface. - gVoiceClient->userAuthorized(firstname, lastname, gAgentID); + } else // if(successful_login) { @@ -2065,6 +2063,7 @@ bool idle_startup() LL_DEBUGS("AppInitStartupState") << "STATE_SEED_CAP_GRANTED" << LL_ENDL; update_texture_fetch(); + if ( gViewerWindow != NULL) { // This isn't the first logon attempt, so show the UI gViewerWindow->setNormalControlsVisible( TRUE ); @@ -2123,6 +2122,9 @@ bool idle_startup() // LL_INFOS("AppInit") << "Initializing communications..." << LL_ENDL; + // Pass the user information to the voice chat server interface. + gVoiceClient->userAuthorized(firstname, lastname, gAgentID); + // register callbacks for messages. . . do this after initial handshake to make sure that we don't catch any unwanted register_viewer_callbacks(gMessageSystem); @@ -2142,7 +2144,7 @@ bool idle_startup() gCacheName->addObserver(callback_cache_name); // Load stored cache if possible - LLAppViewer::instance()->loadNameCache(); + LLAppViewer::instance()->loadNameCache(); // Start cache in not-running state until we figure out if we have // capabilities for display name lookup diff --git a/linden/indra/newview/llvoiceclient.cpp b/linden/indra/newview/llvoiceclient.cpp index 2266aab..115f6e8 100644 --- a/linden/indra/newview/llvoiceclient.cpp +++ b/linden/indra/newview/llvoiceclient.cpp @@ -139,22 +139,23 @@ class LLViewerVoiceAccountProvisionResponder : public LLHTTPClient::Responder { public: - LLViewerVoiceAccountProvisionResponder(int retries) + LLViewerVoiceAccountProvisionResponder(int retries, LLUUID response_id) { mRetries = retries; + mResponseID = response_id; } virtual void error(U32 status, const std::string& reason) { if ( mRetries > 0 ) { - LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, retrying. status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL; + LL_DEBUGS("VoiceCaps") << "ProvisionVoiceAccountRequest returned an error, retrying. status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL; if ( gVoiceClient ) gVoiceClient->requestVoiceAccountProvision( mRetries - 1); } else { - LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, too many retries (giving up). status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL; + LL_DEBUGS("VoiceCaps") << "ProvisionVoiceAccountRequest returned an error, too many retries (giving up). status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL; if ( gVoiceClient ) gVoiceClient->giveUp(); } } @@ -166,7 +167,7 @@ public: std::string voice_sip_uri_hostname; std::string voice_account_server_uri; - LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << ll_pretty_print_sd(content) << LL_ENDL; + LL_DEBUGS("VoiceCaps") << "ProvisionVoiceAccountRequest response:" << ll_pretty_print_sd(content) << LL_ENDL; if(content.has("voice_sip_uri_hostname")) voice_sip_uri_hostname = content["voice_sip_uri_hostname"].asString(); @@ -179,12 +180,14 @@ public: content["username"].asString(), content["password"].asString(), voice_sip_uri_hostname, - voice_account_server_uri); + voice_account_server_uri, + mResponseID); } } private: int mRetries; + LLUUID mResponseID; }; /** @@ -364,7 +367,7 @@ LLIOPipe::EStatus LLVivoxProtocolParser::process_impl( // If this message isn't set to be squelched, output the raw XML received. if(!squelchDebugOutput) { - LL_DEBUGS("Voice") << "parsing: " << mInput.substr(start, delim - start) << LL_ENDL; + LL_DEBUGS("VivoxProtocolParser") << "parsing: " << mInput.substr(start, delim - start) << LL_ENDL; } start = delim + 3; @@ -378,7 +381,7 @@ LLIOPipe::EStatus LLVivoxProtocolParser::process_impl( if(!gVoiceClient->mConnected) { // If voice has been disabled, we just want to close the socket. This does so. - LL_INFOS("Voice") << "returning STATUS_STOP" << LL_ENDL; + LL_INFOS("VivoxProtocolParser") << "returning STATUS_STOP" << LL_ENDL; return STATUS_STOP; } @@ -1008,12 +1011,13 @@ static LLVoiceClientFriendsObserver *friendslist_listener = NULL; class LLVoiceClientCapResponder : public LLHTTPClient::Responder { public: - LLVoiceClientCapResponder(void){}; + LLVoiceClientCapResponder(LLUUID response_id):mResponseID(response_id) {}; virtual void error(U32 status, const std::string& reason); // called with bad status codes virtual void result(const LLSD& content); private: + LLUUID mResponseID; }; void LLVoiceClientCapResponder::error(U32 status, const std::string& reason) @@ -1027,7 +1031,7 @@ void LLVoiceClientCapResponder::result(const LLSD& content) { LLSD::map_const_iterator iter; - LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << ll_pretty_print_sd(content) << LL_ENDL; + LL_DEBUGS("VoiceCaps") << "ParcelVoiceInfoRequest response:\n" << ll_pretty_print_sd(content) << LL_ENDL; if ( content.has("voice_credentials") ) { @@ -1045,7 +1049,7 @@ void LLVoiceClientCapResponder::result(const LLSD& content) voice_credentials["channel_credentials"].asString(); } - gVoiceClient->setSpatialChannel(uri, credentials); + gVoiceClient->setSpatialChannel(uri, credentials, mResponseID); } } @@ -1126,6 +1130,8 @@ LLVoiceClient::LLVoiceClient() mAudioSessionChanged = false; // Initial dirty state + mAccountActive = false; + mVAPRequested = false; mSpatialCoordsDirty = false; mPTTDirty = true; mFriendsListDirty = true; @@ -1347,6 +1353,7 @@ void LLVoiceClient::userAuthorized(const std::string& firstName, const std::stri sConnectingToAgni = LLViewerLogin::getInstance()->isInProductionGrid(); mAccountName = nameFromID(agentID); + mAccountActive = true; } void LLVoiceClient::requestVoiceAccountProvision(S32 retries) @@ -1357,12 +1364,21 @@ void LLVoiceClient::requestVoiceAccountProvision(S32 retries) gAgent.getRegion()->getCapability( "ProvisionVoiceAccountRequest"); - if ( url == "" ) return; + if ( url.empty() ) + { + mVAPRequested = false; + mAccountActive = false; + setState(stateDisableCleanup); + } + + LL_DEBUGS("VoiceCaps") << "Got ProvisionVoiceAccountRequest capability: " + << url << llendl; + mVAPCapResponseID.generate(); LLHTTPClient::post( url, LLSD(), - new LLViewerVoiceAccountProvisionResponder(retries)); + new LLViewerVoiceAccountProvisionResponder(retries, mVAPCapResponseID)); } } @@ -1370,11 +1386,44 @@ void LLVoiceClient::login( const std::string& account_name, const std::string& password, const std::string& voice_sip_uri_hostname, - const std::string& voice_account_server_uri) + const std::string& voice_account_server_uri, + const LLUUID& response_id) { + if(response_id != mVAPCapResponseID) return; + + std::string new_scheme; + std::string old_scheme; + if(!voice_account_server_uri.empty()) + { + new_scheme = voice_account_server_uri.substr(0, voice_account_server_uri.find("://")); + } + if(!mDaemonScheme.empty()) + { + old_scheme = mDaemonScheme; + } + else + { + old_scheme = new_scheme; + } + mVoiceSIPURIHostName = voice_sip_uri_hostname; mVoiceAccountServerURI = voice_account_server_uri; + + LL_DEBUGS("VoiceCaps") << "new_scheme: \"" << new_scheme << "\"" + << "\nold_scheme: \"" << old_scheme << "\"" + << "\ngateway running: " << ( isGatewayRunning() ? "true" : "false" ) << llendl; + if(!isGatewayRunning() ) + { + loadDaemon(new_scheme); + } + else if(old_scheme != new_scheme) + { + mAccountActive = true; + setState(stateDisableCleanup); + } + + if(!mAccountHandle.empty()) { // Already logged in. @@ -1432,6 +1481,183 @@ void LLVoiceClient::login( } } +void LLVoiceClient::loadDaemon(const std::string& scheme) +{ + + // Launch the voice daemon + + + // *FIX:Mani - Using the executable dir instead + // of mAppRODataDir, the working directory from which the app + // is launched. + //std::string exe_path = gDirUtilp->getAppRODataDir(); + std::string exe_path = gDirUtilp->getExecutableDir(); + exe_path += gDirUtilp->getDirDelimiter(); + +#if LL_DARWIN + exe_path += "../Resources/"; +#endif + + //exe_path += gSavedSettings.getString("VoiceModule"); + llwarns << "Scheme: " << scheme << llendl; + + std::string module; + if (scheme == "tcp") + { + + module = gSavedSettings.getString("VoiceModuleMumble").empty() ? + "mumble" : gSavedSettings.getString("VoiceModuleMumble"); + } + else + { + module = gSavedSettings.getString("VoiceModuleVivox").empty() ? + "SLVoice" : gSavedSettings.getString("VoiceModuleVivox"); + } + + size_t pos_to_tst = module.find_last_of("/\\"); + if( pos_to_tst != std::string::npos ) + { + module = module.substr(pos_to_tst+1); + } + +#if LL_WINDOWS + std::string extension = ".exe"; + if ( module.rfind(extension) != module.length()-extension.length()) + { + module.append(extension); + } +#endif + + exe_path.append(module); + + // See if the vivox executable exists + llstat s; + if(!LLFile::stat(exe_path, &s)) + { + // vivox executable exists. Build the command line and launch the daemon. + // SLIM SDK: these arguments are no longer necessary. + // std::string args = " -p tcp -h -c"; + std::string args; + std::string cmd; + std::string loglevel = gSavedSettings.getString("VivoxDebugLevel"); + + if(loglevel.empty()) + { + loglevel = "-1"; // turn logging off completely + } + + args += " -ll "; + args += loglevel; + + llwarns << "Voice loaded from: " << exe_path << " " << args << LL_ENDL; + +#if LL_WINDOWS + PROCESS_INFORMATION pinfo; + STARTUPINFOA sinfo; + memset(&sinfo, 0, sizeof(sinfo)); + std::string exe_dir = gDirUtilp->getAppRODataDir(); + + + // So retarded. Windows requires that the second parameter to CreateProcessA be a writable (non-const) string... + char *args2 = new char[args.size() + 1]; + strcpy(args2, args.c_str()); + + if(!CreateProcessA(exe_path.c_str(), args2, NULL, NULL, FALSE, 0, NULL, exe_dir.c_str(), &sinfo, &pinfo)) + { + // DWORD dwErr = GetLastError(); + } + else + { + // foo = pinfo.dwProcessId; // get your pid here if you want to use it later on + // CloseHandle(pinfo.hProcess); // stops leaks - nothing else + sGatewayHandle = pinfo.hProcess; + CloseHandle(pinfo.hThread); // stops leaks - nothing else + } + + delete[] args2; +#else // LL_WINDOWS + // This should be the same for mac and linux + { + std::vector arglist; + arglist.push_back(exe_path); + + // Split the argument string into separate strings for each argument + typedef boost::tokenizer > tokenizer; + boost::char_separator sep(" "); + tokenizer tokens(args, sep); + tokenizer::iterator token_iter; + + for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) + { + arglist.push_back(*token_iter); + } + + // create an argv vector for the child process + char **fakeargv = new char*[arglist.size() + 1]; + int i; + for(i=0; i < arglist.size(); i++) + fakeargv[i] = const_cast(arglist[i].c_str()); + + fakeargv[i] = NULL; + + fflush(NULL); // flush all buffers before the child inherits them + pid_t id = vfork(); + if(id == 0) + { + // child + execv(exe_path.c_str(), fakeargv); + + // If we reach this point, the exec failed. + // Use _exit() instead of exit() per the vfork man page. + _exit(0); + } + + // parent + delete[] fakeargv; + sGatewayPID = id; + + } + +#endif // LL_WINDOWS + + mDaemonScheme = scheme; + mDaemonHost = LLHost(gSavedSettings.getString("VoiceHost").c_str(), gSavedSettings.getU32("VoicePort")); + + // Dirty the states we'll need to sync with the daemon when it comes up. + mPTTDirty = true; + mMicVolumeDirty = true; + mSpeakerVolumeDirty = true; + mSpeakerMuteDirty = true; + // These only need to be set if they're not default (i.e. empty string). + mCaptureDeviceDirty = !mCaptureDevice.empty(); + mRenderDeviceDirty = !mRenderDevice.empty(); + + mMainSessionGroupHandle.clear(); + + // kick in + + mUpdateTimer.start(); + mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS); + + setState(stateDaemonLaunched); + + //trigger parcel changed in the state engine + mCurrentRegionName.append("kick in"); + + + } + else + { + LL_WARNS("Voice") << exe_path << " not found." << LL_ENDL; + mAccountActive = false; + setState(stateDisableCleanup); + } + + // we are done, re-allow ProvisionVoiceAccountRequest + mVAPRequested = false; +} + + void LLVoiceClient::idle(void* user_data) { LLVoiceClient* self = (LLVoiceClient*)user_data; @@ -1537,11 +1763,20 @@ void LLVoiceClient::start() void LLVoiceClient::stateMachine() { + if( stateJail == getState()) + { + return; + } + + if(gSavedSettings.getBOOL("CmdLineDisableVoice")) + { + // Voice is locked out, we must not launch the vivox daemon. + setState(stateJail); + } // Disable voice as long as the viewer is disconnected from the sim (login/relog) setVoiceEnabled(!gDisconnected - && gSavedSettings.getBOOL("EnableVoiceChat") - && !gSavedSettings.getBOOL("CmdLineDisableVoice") ); + && gSavedSettings.getBOOL("EnableVoiceChat") ); if(mVoiceEnabled) { @@ -1560,12 +1795,8 @@ void LLVoiceClient::stateMachine() { // if voice was turned off after the daemon was launched but before we could connect to it, we may need to issue a kill. LL_WARNS("Voice") << "Disabling voice before connection to daemon, terminating." << LL_ENDL; - killGateway(); } - logout(); - connectorShutdown(); - setState(stateDisableCleanup); } } @@ -1580,42 +1811,23 @@ void LLVoiceClient::stateMachine() { S32 parcelLocalID = parcel->getLocalID(); std::string regionName = region->getName(); - std::string capURI = region->getCapability("ParcelVoiceInfoRequest"); - -// 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(/*getState() >= stateNoChannel &&*/ !regionName.empty()) { - if(!capURI.empty()) - { - if((parcelLocalID != mCurrentParcelLocalID) || (regionName != mCurrentRegionName)) - { - // We have changed parcels. Initiate a parcel channel lookup. - mCurrentParcelLocalID = parcelLocalID; - mCurrentRegionName = regionName; - - parcelChanged(); - } - } - else + + if((parcelLocalID != mCurrentParcelLocalID) || (regionName != mCurrentRegionName)) { - static int count = 0; - static int count2 = 0; - static int num = 1; - ++count; - if (count % num == 0) - { - LL_DEBUGS("Voice") << "region doesn't have ParcelVoiceInfoRequest capability. This is normal for a short time after teleporting, but bad if it persists for very long (" << count << ")." << LL_ENDL; - if (num < 1000 && ++count2 == 10) - { - num *= 10; - count2 = 0; - } - } + // We have changed parcels. Initiate a parcel channel lookup. + mCurrentParcelLocalID = parcelLocalID; + mCurrentRegionName = regionName; + + parcelChanged(); } + } } } @@ -1624,22 +1836,34 @@ void LLVoiceClient::stateMachine() { //MARK: stateDisableCleanup case stateDisableCleanup: - // Clean up and reset everything. + // Clean up and reset everything. + + mVAPCapResponseID.setNull(); + mPIRCapResponseID.setNull(); + + if(isGatewayRunning()) + { + killGateway(); + } + logoutSendMessage(); + mConnected = false; + + closeSocket(); deleteAllSessions(); - deleteAllBuddies(); + deleteAllBuddies(); mConnectorHandle.clear(); mAccountHandle.clear(); mAccountPassword.clear(); mVoiceAccountServerURI.clear(); - - setState(stateDisabled); + mVAPRequested = false; + setState(stateDisabled); break; //MARK: stateDisabled case stateDisabled: - if(mTuningMode || (mVoiceEnabled && !mAccountName.empty())) + if(mTuningMode || (mVoiceEnabled && mAccountActive && !mAccountName.empty())) { setState(stateStart); } @@ -1647,165 +1871,26 @@ void LLVoiceClient::stateMachine() //MARK: stateStart case stateStart: - if(gSavedSettings.getBOOL("CmdLineDisableVoice")) + { + bool have_region = (NULL != gAgent.getRegion() ); + if(mVoiceEnabled && !mVAPRequested && !mAccountName.empty() && have_region) { - // Voice is locked out, we must not launch the vivox daemon. - setState(stateJail); + mVAPRequested = true; + requestVoiceAccountProvision(); } - else if(!isGatewayRunning()) - { - if(true) - { - // Launch the voice daemon - - // *FIX:Mani - Using the executable dir instead - // of mAppRODataDir, the working directory from which the app - // is launched. - //std::string exe_path = gDirUtilp->getAppRODataDir(); - std::string exe_path = gDirUtilp->getExecutableDir(); - exe_path += gDirUtilp->getDirDelimiter(); -#if LL_DARWIN - exe_path += "../Resources/"; -#endif - exe_path += gSavedSettings.getString("VoiceModule"); -#if LL_WINDOWS - exe_path += ".exe"; -#endif - // See if the vivox executable exists - llstat s; - if(!LLFile::stat(exe_path, &s)) - { - // vivox executable exists. Build the command line and launch the daemon. - // SLIM SDK: these arguments are no longer necessary. -// std::string args = " -p tcp -h -c"; - std::string args; - std::string cmd; - std::string loglevel = gSavedSettings.getString("VivoxDebugLevel"); - - if(loglevel.empty()) - { - loglevel = "-1"; // turn logging off completely - } - - args += " -ll "; - args += loglevel; - - LL_DEBUGS("Voice") << "Args for SLVoice: " << args << LL_ENDL; - -#if LL_WINDOWS - PROCESS_INFORMATION pinfo; - STARTUPINFOA sinfo; - memset(&sinfo, 0, sizeof(sinfo)); - std::string exe_dir = gDirUtilp->getAppRODataDir(); - cmd = gSavedSettings.getString("VoiceModule"); - cmd += ".exe"; - cmd += args; - - // So retarded. Windows requires that the second parameter to CreateProcessA be a writable (non-const) string... - char *args2 = new char[args.size() + 1]; - strcpy(args2, args.c_str()); - - if(!CreateProcessA(exe_path.c_str(), args2, NULL, NULL, FALSE, 0, NULL, exe_dir.c_str(), &sinfo, &pinfo)) - { -// DWORD dwErr = GetLastError(); - } - else - { - // foo = pinfo.dwProcessId; // get your pid here if you want to use it later on - // CloseHandle(pinfo.hProcess); // stops leaks - nothing else - sGatewayHandle = pinfo.hProcess; - CloseHandle(pinfo.hThread); // stops leaks - nothing else - } - - delete[] args2; -#else // LL_WINDOWS - // This should be the same for mac and linux - { - std::vector arglist; - arglist.push_back(exe_path); - - // Split the argument string into separate strings for each argument - typedef boost::tokenizer > tokenizer; - boost::char_separator sep(" "); - tokenizer tokens(args, sep); - tokenizer::iterator token_iter; - - for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) - { - arglist.push_back(*token_iter); - } - - // create an argv vector for the child process - char **fakeargv = new char*[arglist.size() + 1]; - int i; - for(i=0; i < arglist.size(); i++) - fakeargv[i] = const_cast(arglist[i].c_str()); - - fakeargv[i] = NULL; - - fflush(NULL); // flush all buffers before the child inherits them - pid_t id = vfork(); - if(id == 0) - { - // child - execv(exe_path.c_str(), fakeargv); - - // If we reach this point, the exec failed. - // Use _exit() instead of exit() per the vfork man page. - _exit(0); - } - - // parent - delete[] fakeargv; - sGatewayPID = id; - } -#endif // LL_WINDOWS - mDaemonHost = LLHost(gSavedSettings.getString("VoiceHost").c_str(), gSavedSettings.getU32("VoicePort")); - } - else - { - LL_WARNS("Voice") << exe_path << " not found." << LL_ENDL; - mVoiceEnabled = false; - } - } - else - { - // SLIM SDK: port changed from 44124 to 44125. - // We can connect to a client gateway running on another host. This is useful for testing. - // To do this, launch the gateway on a nearby host like this: - // vivox-gw.exe -p tcp -i 0.0.0.0:44125 - // and put that host's IP address here. - mDaemonHost = LLHost(gSavedSettings.getString("VoiceHost"), gSavedSettings.getU32("VoicePort")); - } - - mUpdateTimer.start(); - mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS); - - setState(stateDaemonLaunched); - - // Dirty the states we'll need to sync with the daemon when it comes up. - mPTTDirty = true; - mMicVolumeDirty = true; - mSpeakerVolumeDirty = true; - mSpeakerMuteDirty = true; - // These only need to be set if they're not default (i.e. empty string). - mCaptureDeviceDirty = !mCaptureDevice.empty(); - mRenderDeviceDirty = !mRenderDevice.empty(); - - mMainSessionGroupHandle.clear(); - } - break; + } break; //MARK: stateDaemonLaunched case stateDaemonLaunched: if(mUpdateTimer.hasExpired()) { - LL_DEBUGS("Voice") << "Connecting to vivox daemon" << LL_ENDL; - + mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS); if(!mSocket) { + LL_DEBUGS("VoiceDaemon") << "Connecting to voice daemon. Protocol: " + << mDaemonScheme << LL_ENDL; mSocket = LLSocket::create(LLSocket::STREAM_TCP); } @@ -1817,6 +1902,7 @@ void LLVoiceClient::stateMachine() else { // If the connect failed, the socket may have been put into a bad state. Delete it. + LL_DEBUGS("VoiceDaemon") << "voice daemon not ready yet, retrying" << LL_ENDL; closeSocket(); } } @@ -1871,24 +1957,16 @@ void LLVoiceClient::stateMachine() } else if(!mAccountName.empty() && mVoiceEnabled) { - LLViewerRegion *region = gAgent.getRegion(); - - if(region) + if ( mAccountPassword.empty() ) { - if ( region->getCapability("ProvisionVoiceAccountRequest") != "" ) - { - if ( mAccountPassword.empty() ) - { - requestVoiceAccountProvision(); - } - setState(stateConnectorStart); - } - else - { - LL_DEBUGS("Voice") << "region doesn't have ProvisionVoiceAccountRequest capability!" << LL_ENDL; - } + requestVoiceAccountProvision(); + } + else + { + setState(stateConnectorStart); } } + break; //MARK: stateMicTuningStart @@ -2025,7 +2103,8 @@ void LLVoiceClient::stateMachine() if(mLoginRetryCount > MAX_LOGIN_RETRIES) { LL_WARNS("Voice") << "too many login retries, giving up." << LL_ENDL; - setState(stateLoginFailed); + mAccountActive = false; + setState(stateDisableCleanup); } else { @@ -2569,7 +2648,7 @@ void LLVoiceClient::sessionGroupCreateSendMessage() void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAudio, bool startText) { - LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL; + LL_DEBUGS("VoiceSession") << "requesting create: " << session->mSIPURI << LL_ENDL; session->mCreateInProgress = true; if(startAudio) @@ -2605,7 +2684,7 @@ void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAu void LLVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio, bool startText) { - LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL; + LL_DEBUGS("VoiceSession") << "requesting create: " << session->mSIPURI << LL_ENDL; session->mCreateInProgress = true; if(startAudio) @@ -2642,7 +2721,7 @@ void LLVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session, boo void LLVoiceClient::sessionMediaConnectSendMessage(sessionState *session) { - LL_DEBUGS("Voice") << "connecting audio to session handle: " << session->mHandle << LL_ENDL; + LL_DEBUGS("VoiceSession") << "connecting audio to session handle: " << session->mHandle << LL_ENDL; session->mMediaConnectInProgress = true; @@ -2660,7 +2739,7 @@ void LLVoiceClient::sessionMediaConnectSendMessage(sessionState *session) void LLVoiceClient::sessionTextConnectSendMessage(sessionState *session) { - LL_DEBUGS("Voice") << "connecting text to session handle: " << session->mHandle << LL_ENDL; + LL_DEBUGS("VoiceSession") << "connecting text to session handle: " << session->mHandle << LL_ENDL; std::ostringstream stream; @@ -2689,7 +2768,7 @@ void LLVoiceClient::leaveAudioSession() { if(mAudioSession) { - LL_DEBUGS("Voice") << "leaving session: " << mAudioSession->mSIPURI << LL_ENDL; + LL_DEBUGS("VoiceSession") << "leaving session: " << mAudioSession->mSIPURI << LL_ENDL; switch(getState()) { @@ -2724,7 +2803,7 @@ void LLVoiceClient::leaveAudioSession() } else { - LL_WARNS("Voice") << "called with no session handle" << LL_ENDL; + LL_WARNS("VoiceSession") << "called with no session handle" << LL_ENDL; setState(stateSessionTerminated); } break; @@ -2734,13 +2813,13 @@ void LLVoiceClient::leaveAudioSession() break; default: - LL_WARNS("Voice") << "called from unknown state" << LL_ENDL; + LL_WARNS("VoiceSession") << "called from unknown state" << LL_ENDL; break; } } else { - LL_WARNS("Voice") << "called with no active session" << LL_ENDL; + LL_WARNS("VoiceSession") << "called with no active session" << LL_ENDL; setState(stateSessionTerminated); } } @@ -2749,7 +2828,7 @@ void LLVoiceClient::sessionTerminateSendMessage(sessionState *session) { std::ostringstream stream; - LL_DEBUGS("Voice") << "Sending Session.Terminate with handle " << session->mHandle << LL_ENDL; + LL_DEBUGS("VoiceSession") << "Sending Session.Terminate with handle " << session->mHandle << LL_ENDL; stream << "" << "" << session->mHandle << "" @@ -2762,7 +2841,7 @@ void LLVoiceClient::sessionGroupTerminateSendMessage(sessionState *session) { std::ostringstream stream; - LL_DEBUGS("Voice") << "Sending SessionGroup.Terminate with handle " << session->mGroupHandle << LL_ENDL; + LL_DEBUGS("VoiceSession") << "Sending SessionGroup.Terminate with handle " << session->mGroupHandle << LL_ENDL; stream << "" << "" << session->mGroupHandle << "" @@ -2775,7 +2854,7 @@ void LLVoiceClient::sessionMediaDisconnectSendMessage(sessionState *session) { std::ostringstream stream; - LL_DEBUGS("Voice") << "Sending Session.MediaDisconnect with handle " << session->mHandle << LL_ENDL; + LL_DEBUGS("VoiceSession") << "Sending Session.MediaDisconnect with handle " << session->mHandle << LL_ENDL; stream << "" << "" << session->mGroupHandle << "" @@ -2791,7 +2870,7 @@ void LLVoiceClient::sessionTextDisconnectSendMessage(sessionState *session) { std::ostringstream stream; - LL_DEBUGS("Voice") << "Sending Session.TextDisconnect with handle " << session->mHandle << LL_ENDL; + LL_DEBUGS("VoiceSession") << "Sending Session.TextDisconnect with handle " << session->mHandle << LL_ENDL; stream << "" << "" << session->mGroupHandle << "" @@ -2823,13 +2902,13 @@ void LLVoiceClient::getRenderDevicesSendMessage() void LLVoiceClient::clearCaptureDevices() { - LL_DEBUGS("Voice") << "called" << LL_ENDL; + LL_DEBUGS("VoiceDevice") << "called" << LL_ENDL; mCaptureDevices.clear(); } void LLVoiceClient::addCaptureDevice(const std::string& name) { - LL_DEBUGS("Voice") << name << LL_ENDL; + LL_DEBUGS("VoiceDevice") << name << LL_ENDL; mCaptureDevices.push_back(name); } @@ -2861,13 +2940,13 @@ void LLVoiceClient::setCaptureDevice(const std::string& name) void LLVoiceClient::clearRenderDevices() { - LL_DEBUGS("Voice") << "called" << LL_ENDL; + LL_DEBUGS("VoiceDevice") << "called" << LL_ENDL; mRenderDevices.clear(); } void LLVoiceClient::addRenderDevice(const std::string& name) { - LL_DEBUGS("Voice") << name << LL_ENDL; + LL_DEBUGS("VoiceDevice") << name << LL_ENDL; mRenderDevices.push_back(name); } @@ -2951,7 +3030,7 @@ void LLVoiceClient::tuningRenderStopSendMessage() void LLVoiceClient::tuningCaptureStartSendMessage(int duration) { - LL_DEBUGS("Voice") << "sending CaptureAudioStart" << LL_ENDL; + LL_DEBUGS("VoiceDevice") << "sending CaptureAudioStart" << LL_ENDL; std::ostringstream stream; stream @@ -2964,7 +3043,7 @@ void LLVoiceClient::tuningCaptureStartSendMessage(int duration) void LLVoiceClient::tuningCaptureStopSendMessage() { - LL_DEBUGS("Voice") << "sending CaptureAudioStop" << LL_ENDL; + LL_DEBUGS("VoiceDevice") << "sending CaptureAudioStop" << LL_ENDL; std::ostringstream stream; stream @@ -3038,12 +3117,8 @@ void LLVoiceClient::daemonDied() void LLVoiceClient::giveUp() { - // All has failed. Clean up and stop trying. - closeSocket(); - deleteAllSessions(); - deleteAllBuddies(); - - setState(stateJail); + mAccountActive = false; + setState(stateDisableCleanup); } static void oldSDKTransform (LLVector3 &left, LLVector3 &up, LLVector3 &at, LLVector3d &pos, LLVector3 &vel) @@ -3378,7 +3453,7 @@ void LLVoiceClient::buildSetCaptureDevice(std::ostringstream &stream) { if(mCaptureDeviceDirty) { - LL_DEBUGS("Voice") << "Setting input device = \"" << mCaptureDevice << "\"" << LL_ENDL; + LL_DEBUGS("VoiceDevice") << "Setting input device = \"" << mCaptureDevice << "\"" << LL_ENDL; stream << "" @@ -4099,29 +4174,29 @@ void LLVoiceClient::reapSession(sessionState *session) { if(!session->mHandle.empty()) { - LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (non-null session handle)" << LL_ENDL; + LL_DEBUGS("VoiceSession") << "NOT deleting session " << session->mSIPURI << " (non-null session handle)" << LL_ENDL; } else if(session->mCreateInProgress) { - LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (create in progress)" << LL_ENDL; + LL_DEBUGS("VoiceSession") << "NOT deleting session " << session->mSIPURI << " (create in progress)" << LL_ENDL; } else if(session->mMediaConnectInProgress) { - LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (connect in progress)" << LL_ENDL; + LL_DEBUGS("VoiceSession") << "NOT deleting session " << session->mSIPURI << " (connect in progress)" << LL_ENDL; } else if(session == mAudioSession) { - LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the current session)" << LL_ENDL; + LL_DEBUGS("VoiceSession") << "NOT deleting session " << session->mSIPURI << " (it's the current session)" << LL_ENDL; } else if(session == mNextAudioSession) { - LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the next session)" << LL_ENDL; + LL_DEBUGS("VoiceSession") << "NOT deleting session " << session->mSIPURI << " (it's the next session)" << LL_ENDL; } else { // TODO: Question: Should we check for queued text messages here? // We don't have a reason to keep tracking this session, so just delete it. - LL_DEBUGS("Voice") << "deleting session " << session->mSIPURI << LL_ENDL; + LL_DEBUGS("VoiceSession") << "deleting session " << session->mSIPURI << LL_ENDL; deleteSession(session); session = NULL; } @@ -4179,17 +4254,17 @@ void LLVoiceClient::leftAudioSession( case stateJoinSessionFailed: case stateJoinSessionFailedWaiting: // normal transition - LL_DEBUGS("Voice") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL; + LL_DEBUGS("VoiceSession") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL; setState(stateSessionTerminated); break; case stateSessionTerminated: // this will happen sometimes -- there are cases where we send the terminate and then go straight to this state. - LL_WARNS("Voice") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL; + LL_WARNS("VoiceSession") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL; break; default: - LL_WARNS("Voice") << "unexpected SessionStateChangeEvent (left session) in state " << state2string(getState()) << LL_ENDL; + LL_WARNS("VoiceSession") << "unexpected SessionStateChangeEvent (left session) in state " << state2string(getState()) << LL_ENDL; setState(stateSessionTerminated); break; } @@ -4249,7 +4324,7 @@ void LLVoiceClient::mediaStreamUpdatedEvent( { sessionState *session = findSession(sessionHandle); - LL_DEBUGS("Voice") << "session " << sessionHandle << ", status code " << statusCode << ", string \"" << statusString << "\"" << LL_ENDL; + LL_DEBUGS("VoiceSession") << "session " << sessionHandle << ", status code " << statusCode << ", string \"" << statusString << "\"" << LL_ENDL; if(session) { @@ -4314,7 +4389,7 @@ void LLVoiceClient::mediaStreamUpdatedEvent( } else { - LL_WARNS("Voice") << "session " << sessionHandle << "not found"<< LL_ENDL; + LL_WARNS("VoiceSession") << "session " << sessionHandle << "not found"<< LL_ENDL; } } @@ -4435,7 +4510,7 @@ void LLVoiceClient::participantRemovedEvent( } else { - LL_DEBUGS("Voice") << "unknown session " << sessionHandle << LL_ENDL; + LL_DEBUGS("VoiceSession") << "unknown session " << sessionHandle << LL_ENDL; } } @@ -4479,7 +4554,7 @@ void LLVoiceClient::participantUpdatedEvent( } else { - LL_WARNS("Voice") << "unknown session " << sessionHandle << LL_ENDL; + LL_WARNS("VoiceSession") << "unknown session " << sessionHandle << LL_ENDL; } } @@ -5058,22 +5133,34 @@ LLVoiceClient::participantState* LLVoiceClient::findParticipantByID(const LLUUID void LLVoiceClient::parcelChanged() { - if(getState() >= stateNoChannel) + if( (getState() >= stateNoChannel) && !inNonSpatialChannel() ) { - // If the user is logged in, start a channel lookup. - LL_DEBUGS("Voice") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << LL_ENDL; + // If the user is logged in, start a channel lookup, + // but not if already in a private call/conference. + mAccountActive = true; std::string url = gAgent.getRegion()->getCapability("ParcelVoiceInfoRequest"); - LLSD data; - LLHTTPClient::post( - url, - data, - new LLVoiceClientCapResponder); + LL_DEBUGS("VoiceCaps") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << " cap url:" << url << LL_ENDL; + if(! url.empty() ) + { + mPIRCapResponseID.generate(); + LLSD data; + LLHTTPClient::post( + url, + data, + new LLVoiceClientCapResponder(mPIRCapResponseID)); + } + else + { + mAccountActive = false; + setState(stateDisableCleanup); + } } else { + mAccountActive = true; // The transition to stateNoChannel needs to kick this off again. - LL_WARNS("Voice") << "not logged in yet, deferring" << LL_ENDL; + LL_DEBUGS("Voice") << "not logged in yet, deferring" << LL_ENDL; } } @@ -5086,12 +5173,40 @@ void LLVoiceClient::switchChannel( { bool needsSwitch = false; - LL_DEBUGS("Voice") - << "called in state " << state2string(getState()) + LL_DEBUGS("VoiceSession") + << "Switch channel called in state " << state2string(getState()) << " with uri \"" << uri << "\"" << (spatial?", spatial is true":", spatial is false") << LL_ENDL; - + + size_t new_uri_find_sip = std::string::npos; + size_t old_uri_find_sip = std::string::npos; + if(!uri.empty()) + { + new_uri_find_sip = uri.find("sip:"); + } + + if( mNextAudioSession + && !( mNextAudioSession->mSIPURI.empty() ) + && (mNextAudioSession->mSIPURI != uri) ) + { + old_uri_find_sip = mNextAudioSession->mSIPURI.find("sip:"); + } + else + { + + // just logged in or voice disabled land in SL, + // anyway right daemon is already up + old_uri_find_sip = new_uri_find_sip; + } + + if(old_uri_find_sip != new_uri_find_sip) + { + mAccountActive = true; + setState(stateDisableCleanup); + return; + } + switch(getState()) { case stateJoinSessionFailed: @@ -5148,7 +5263,7 @@ void LLVoiceClient::switchChannel( if(uri.empty()) { // Leave any channel we may be in - LL_DEBUGS("Voice") << "leaving channel" << LL_ENDL; + LL_DEBUGS("VoiceSession") << "leaving channel" << LL_ENDL; sessionState *oldSession = mNextAudioSession; mNextAudioSession = NULL; @@ -5160,7 +5275,7 @@ void LLVoiceClient::switchChannel( } else { - LL_DEBUGS("Voice") << "switching to channel " << uri << LL_ENDL; + LL_DEBUGS("VoiceSession") << "switching to channel " << uri << LL_ENDL; mNextAudioSession = addSession(uri); mNextAudioSession->mHash = hash; @@ -5205,8 +5320,14 @@ void LLVoiceClient::setNonSpatialChannel( void LLVoiceClient::setSpatialChannel( const std::string &uri, - const std::string &credentials) + const std::string &credentials, + const LLUUID& response_id) { + if (response_id != mPIRCapResponseID) + { + return; + } + mSpatialSessionURI = uri; mSpatialSessionCredentials = credentials; mAreaVoiceDisabled = mSpatialSessionURI.empty(); @@ -5282,7 +5403,7 @@ bool LLVoiceClient::sendTextMessage(const LLUUID& participant_id, const std::str } else { - LL_DEBUGS("Voice") << "Session not found for participant ID " << participant_id << LL_ENDL; + LL_DEBUGS("VoiceSession") << "Session not found for participant ID " << participant_id << LL_ENDL; } return result; @@ -5331,7 +5452,7 @@ void LLVoiceClient::endUserIMSession(const LLUUID &uuid) } else { - LL_DEBUGS("Voice") << "Session not found for participant ID " << uuid << LL_ENDL; + LL_DEBUGS("VoiceSession") << "Session not found for participant ID " << uuid << LL_ENDL; } } @@ -5452,7 +5573,7 @@ void LLVoiceClient::declineInvite(std::string &sessionHandle) void LLVoiceClient::leaveNonSpatialChannel() { - LL_DEBUGS("Voice") + LL_DEBUGS("VoiceSession") << "called in state " << state2string(getState()) << LL_ENDL; @@ -5644,6 +5765,18 @@ bool LLVoiceClient::inSpatialChannel(void) return result; } +bool LLVoiceClient::inNonSpatialChannel(void) +{ + bool result = false; + + if(mAudioSession) + result = !(mAudioSession->mIsSpatial); + if(mNextAudioSession) + result |= !(mNextAudioSession->mIsSpatial); + + return result; +} + std::string LLVoiceClient::getAudioSessionURI() { std::string result; @@ -6397,7 +6530,7 @@ LLVoiceClient::sessionState *LLVoiceClient::addSession(const std::string &uri, c { // No existing session found. - LL_DEBUGS("Voice") << "adding new session: handle " << handle << " URI " << uri << LL_ENDL; + LL_DEBUGS("VoiceSession") << "adding new session: handle " << handle << " URI " << uri << LL_ENDL; result = new sessionState(); result->mSIPURI = uri; result->mHandle = handle; @@ -6416,7 +6549,7 @@ LLVoiceClient::sessionState *LLVoiceClient::addSession(const std::string &uri, c if(uri != result->mSIPURI) { // TODO: Should this be an internal error? - LL_DEBUGS("Voice") << "changing uri from " << result->mSIPURI << " to " << uri << LL_ENDL; + LL_DEBUGS("VoiceSession") << "changing uri from " << result->mSIPURI << " to " << uri << LL_ENDL; setSessionURI(result, uri); } @@ -6425,17 +6558,17 @@ LLVoiceClient::sessionState *LLVoiceClient::addSession(const std::string &uri, c if(handle.empty()) { // There's at least one race condition where where addSession was clearing an existing session handle, which caused things to break. - LL_DEBUGS("Voice") << "NOT clearing handle " << result->mHandle << LL_ENDL; + LL_DEBUGS("VoiceSession") << "NOT clearing handle " << result->mHandle << LL_ENDL; } else { // TODO: Should this be an internal error? - LL_DEBUGS("Voice") << "changing handle from " << result->mHandle << " to " << handle << LL_ENDL; + LL_DEBUGS("VoiceSession") << "changing handle from " << result->mHandle << " to " << handle << LL_ENDL; setSessionHandle(result, handle); } } - LL_DEBUGS("Voice") << "returning existing session: handle " << handle << " URI " << uri << LL_ENDL; + LL_DEBUGS("VoiceSession") << "returning existing session: handle " << handle << " URI " << uri << LL_ENDL; } verifySessionState(); @@ -6455,14 +6588,14 @@ void LLVoiceClient::setSessionHandle(sessionState *session, const std::string &h { if(iter->second != session) { - LL_ERRS("Voice") << "Internal error: session mismatch!" << LL_ENDL; + LL_ERRS("VoiceSession") << "Internal error: session mismatch!" << LL_ENDL; } mSessionsByHandle.erase(iter); } else { - LL_ERRS("Voice") << "Internal error: session handle not found in map!" << LL_ENDL; + LL_ERRS("VoiceSession") << "Internal error: session handle not found in map!" << LL_ENDL; } } @@ -6494,7 +6627,7 @@ void LLVoiceClient::deleteSession(sessionState *session) { if(iter->second != session) { - LL_ERRS("Voice") << "Internal error: session mismatch" << LL_ENDL; + LL_ERRS("VoiceSession") << "Internal error: session mismatch" << LL_ENDL; } mSessionsByHandle.erase(iter); } @@ -6525,7 +6658,7 @@ void LLVoiceClient::deleteSession(sessionState *session) void LLVoiceClient::deleteAllSessions() { - LL_DEBUGS("Voice") << "called" << LL_ENDL; + LL_DEBUGS("VoiceSession") << "called" << LL_ENDL; while(!mSessions.empty()) { @@ -6534,20 +6667,20 @@ void LLVoiceClient::deleteAllSessions() if(!mSessionsByHandle.empty()) { - LL_ERRS("Voice") << "Internal error: empty session map, non-empty handle map" << LL_ENDL; + LL_ERRS("VoiceSession") << "Internal error: empty session map, non-empty handle map" << LL_ENDL; } } void LLVoiceClient::verifySessionState(void) { // This is mostly intended for debugging problems with session state management. - LL_DEBUGS("Voice") << "Total session count: " << mSessions.size() << " , session handle map size: " << mSessionsByHandle.size() << LL_ENDL; + LL_DEBUGS("VoiceSession") << "Total session count: " << mSessions.size() << " , session handle map size: " << mSessionsByHandle.size() << LL_ENDL; for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++) { sessionState *session = *iter; - LL_DEBUGS("Voice") << "session " << session << ": handle " << session->mHandle << ", URI " << session->mSIPURI << LL_ENDL; + LL_DEBUGS("VoiceSession") << "session " << session << ": handle " << session->mHandle << ", URI " << session->mSIPURI << LL_ENDL; if(!session->mHandle.empty()) { @@ -6555,13 +6688,13 @@ void LLVoiceClient::verifySessionState(void) sessionMap::iterator i2 = mSessionsByHandle.find(&(session->mHandle)); if(i2 == mSessionsByHandle.end()) { - LL_ERRS("Voice") << "internal error (handle " << session->mHandle << " not found in session map)" << LL_ENDL; + LL_ERRS("VoiceSession") << "internal error (handle " << session->mHandle << " not found in session map)" << LL_ENDL; } else { if(i2->second != session) { - LL_ERRS("Voice") << "internal error (handle " << session->mHandle << " in session map points to another session)" << LL_ENDL; + LL_ERRS("VoiceSession") << "internal error (handle " << session->mHandle << " in session map points to another session)" << LL_ENDL; } } } @@ -6574,13 +6707,13 @@ void LLVoiceClient::verifySessionState(void) sessionIterator i2 = mSessions.find(session); if(i2 == mSessions.end()) { - LL_ERRS("Voice") << "internal error (session for handle " << session->mHandle << " not found in session map)" << LL_ENDL; + LL_ERRS("VoiceSession") << "internal error (session for handle " << session->mHandle << " not found in session map)" << LL_ENDL; } else { if(session->mHandle != (*i2)->mHandle) { - LL_ERRS("Voice") << "internal error (session for handle " << session->mHandle << " points to session with different handle " << (*i2)->mHandle << ")" << LL_ENDL; + LL_ERRS("VoiceSession") << "internal error (session for handle " << session->mHandle << " points to session with different handle " << (*i2)->mHandle << ")" << LL_ENDL; } } } @@ -7010,6 +7143,8 @@ class LLViewerParcelVoiceInfo : public LLHTTPNode { LLSD body = input["body"]; + LL_DEBUGS("VoiceCaps") << "ParcelVoiceInfo response: " + << ll_pretty_print_sd(input) << LL_ENDL; //body has "region_name" (str), "parcel_local_id"(int), //"voice_credentials" (map). @@ -7036,7 +7171,10 @@ class LLViewerParcelVoiceInfo : public LLHTTPNode voice_credentials["channel_credentials"].asString(); } - gVoiceClient->setSpatialChannel(uri, credentials); + LLUUID response_id; + response_id.generate(); + gVoiceClient->setPIRCapResponseID(response_id); + gVoiceClient->setSpatialChannel(uri, credentials, response_id); } } } @@ -7050,10 +7188,13 @@ class LLViewerRequiredVoiceVersion : public LLHTTPNode const LLSD& context, const LLSD& input) const { + //You received this messsage (most likely on region cross or //teleport) if ( input.has("body") && input["body"].has("major_version") ) { + LL_DEBUGS("VoiceCaps") << "RequiredVoiceVersion response: " + << ll_pretty_print_sd(input)<< LL_ENDL; int major_voice_version = input["body"]["major_version"].asInteger(); // int minor_voice_version = diff --git a/linden/indra/newview/llvoiceclient.h b/linden/indra/newview/llvoiceclient.h index 9ef3be9..fb59b4e 100644 --- a/linden/indra/newview/llvoiceclient.h +++ b/linden/indra/newview/llvoiceclient.h @@ -424,11 +424,15 @@ static void updatePosition(void); const std::string& account_name, const std::string& password, const std::string& voice_sip_uri_hostname, - const std::string& voice_account_server_uri); + const std::string& voice_account_server_uri, + const LLUUID& response_id); + void loginSendMessage(); void logout(); void logoutSendMessage(); + void loadDaemon(const std::string& scheme); + void accountListBlockRulesSendMessage(); void accountListAutoAcceptRulesSendMessage(); @@ -474,7 +478,8 @@ static void updatePosition(void); const std::string &credentials); void setSpatialChannel( const std::string &uri, - const std::string &credentials); + const std::string &credentials, + const LLUUID& response_id); // start a voice session with the specified user void callUser(const LLUUID &uuid); @@ -519,7 +524,7 @@ static void updatePosition(void); void close(); void start(); - + void setPIRCapResponseID(const LLUUID& response_id){ mPIRCapResponseID = response_id; } private: // internal state for a simple state machine. This is used to deal with the asynchronous nature of some of the messages. @@ -595,7 +600,13 @@ static void updatePosition(void); std::string mAccountDisplayName; std::string mAccountFirstName; std::string mAccountLastName; - + + bool mAccountActive; + bool mVAPRequested; + std::string mDaemonScheme; + LLUUID mVAPCapResponseID; + LLUUID mPIRCapResponseID; + bool mTuningMode; float mTuningEnergy; std::string mTuningAudioFile; @@ -667,6 +678,7 @@ static std::string displayNameFromAvatar(LLVOAvatar *avatar); static std::string nameFromsipURI(const std::string &uri); bool inSpatialChannel(void); + bool inNonSpatialChannel(void); std::string getAudioSessionURI(); std::string getAudioSessionHandle(); -- cgit v1.1