From 74d9bf0d5525426feae4ea21e2a81034ddcf4d7f Mon Sep 17 00:00:00 2001 From: Robin Cornelius Date: Mon, 28 Mar 2011 11:20:06 +0100 Subject: VWR-20801 Implement SOCKS 5 Proxy for the viewer --- indra/newview/app_settings/settings.xml | 77 ++++++ indra/newview/llfloaterpreference.cpp | 171 +++++++++++++ indra/newview/llfloaterpreference.h | 30 +++ indra/newview/llstartup.cpp | 123 ++++++++- indra/newview/llstartup.h | 2 + indra/newview/llviewerfloaterreg.cpp | 1 + indra/newview/llxmlrpctransaction.cpp | 21 +- .../default/xui/en/floater_preferences_proxy.xml | 274 +++++++++++++++++++++ .../newview/skins/default/xui/en/notifications.xml | 70 ++++++ .../default/xui/en/panel_preferences_setup.xml | 85 +++---- 10 files changed, 791 insertions(+), 63 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/floater_preferences_proxy.xml (limited to 'indra/newview') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f0e28d4ae3..2b7b7b8484 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -774,6 +774,83 @@ Value 5 + Socks5ProxyEnabled + + Comment + Use Socks5 Proxy + Persist + 1 + Type + Boolean + Value + 1 + + Socks5HttpProxyType + + Comment + Proxy type to use for HTTP operations + Persist + 1 + Type + String + Value + Socks + + Socks5ProxyHost + + Comment + Socks 5 Proxy Host + Persist + 1 + Type + String + Value + 64.79.219.97 + + Socks5ProxyPort + + Comment + Socks 5 Proxy Port + Persist + 1 + Type + U32 + Value + 1080 + + Socks5Username + + Comment + Socks 5 Username + Persist + 1 + Type + String + Value + + + Socks5Password + + Comment + Socks 5 Password + Persist + 1 + Type + String + Value + + + Socks5AuthType + + Comment + Selected Auth mechanism for Socks5 + Persist + 1 + Type + String + Value + None + BuildAxisDeadZone0 Comment diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 724096b443..a0d3852d30 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -103,6 +103,7 @@ #include "llviewermedia.h" #include "llpluginclassmedia.h" #include "llteleporthistorystorage.h" +#include "llsocks5.h" #include "lllogininstance.h" // to check if logged in yet #include "llsdserialize.h" @@ -325,6 +326,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.getUIColor", boost::bind(&LLFloaterPreference::getUIColor, this ,_1, _2)); mCommitCallbackRegistrar.add("Pref.MaturitySettings", boost::bind(&LLFloaterPreference::onChangeMaturity, this)); mCommitCallbackRegistrar.add("Pref.BlockList", boost::bind(&LLFloaterPreference::onClickBlockList, this)); + mCommitCallbackRegistrar.add("Pref.Proxy", boost::bind(&LLFloaterPreference::onClickProxySettings, this)); sSkin = gSavedSettings.getString("SkinCurrent"); @@ -603,6 +605,12 @@ void LLFloaterPreference::cancel() updateDoubleClickControls(); mDoubleClickActionDirty = false; } + LLFloaterPreferenceProxy * advanced_socks_settings = LLFloaterReg::findTypedInstance("prefs_socks5_advanced"); + if(advanced_socks_settings) + { + advanced_socks_settings->cancel(); + } + } void LLFloaterPreference::onOpen(const LLSD& key) @@ -1497,6 +1505,11 @@ void LLFloaterPreference::updateDoubleClickSettings() } } +void LLFloaterPreference::onClickProxySettings() +{ + LLFloaterReg::showInstance("prefs_proxy"); +} + void LLFloaterPreference::updateDoubleClickControls() { // check is one of double-click actions settings enabled @@ -1805,3 +1818,161 @@ void LLPanelPreferenceGraphics::setHardwareDefaults() resetDirtyChilds(); LLPanelPreference::setHardwareDefaults(); } + + +/* ------------------------------------------------------------ */ + +LLFloaterPreferenceProxy::LLFloaterPreferenceProxy(const LLSD& key) + : LLFloater(key), + mSocksSettingsDirty(false) +{ + mCommitCallbackRegistrar.add("Proxy.OK", boost::bind(&LLFloaterPreferenceProxy::onBtnOk, this)); + mCommitCallbackRegistrar.add("Proxy.Cancel", boost::bind(&LLFloaterPreferenceProxy::onBtnCancel, this)); + mCommitCallbackRegistrar.add("Proxy.Change", boost::bind(&LLFloaterPreferenceProxy::onChangeSocksSettings, this)); +} + +LLFloaterPreferenceProxy::~LLFloaterPreferenceProxy() +{ +} + +BOOL LLFloaterPreferenceProxy::postBuild() +{ + LLLineEditor* edit = getChild("socks_password_editor"); + if (edit) edit->setDrawAsterixes(TRUE); + + LLRadioGroup* socksAuth = getChild("socks5_auth_type"); + if(socksAuth->getSelectedValue().asString() == "None") + { + getChild("socks5_username")->setEnabled(false); + getChild("socks5_password")->setEnabled(false); + } + + center(); + return TRUE; +} + +void LLFloaterPreferenceProxy::onOpen(const LLSD& key) +{ + saveSettings(); +} + +void LLFloaterPreferenceProxy::onClose(bool app_quitting) +{ + if(mSocksSettingsDirty) + { + + // If the user plays with the Socks proxy settings after login, its only fair we let them know + // it will not be updated untill next restart. + if(LLStartUp::getStartupState()>STATE_LOGIN_WAIT) + { + if(this->mSocksSettingsDirty == true ) + { + LLNotifications::instance().add("ChangeSocks5Settings",LLSD(),LLSD()); + mSocksSettingsDirty = false; // we have notified the user now be quiet again + } + } + } +} + +void LLFloaterPreferenceProxy::saveSettings() +{ + // Save the value of all controls in the hierarchy + mSavedValues.clear(); + std::list view_stack; + view_stack.push_back(this); + while(!view_stack.empty()) + { + // Process view on top of the stack + LLView* curview = view_stack.front(); + view_stack.pop_front(); + + LLUICtrl* ctrl = dynamic_cast(curview); + if (ctrl) + { + LLControlVariable* control = ctrl->getControlVariable(); + if (control) + { + mSavedValues[control] = control->getValue(); + } + } + + // Push children onto the end of the work stack + for (child_list_t::const_iterator iter = curview->getChildList()->begin(); + iter != curview->getChildList()->end(); ++iter) + { + view_stack.push_back(*iter); + } + } + +} + +void LLFloaterPreferenceProxy::onBtnOk() +{ + // commit any outstanding text entry + if (hasFocus()) + { + LLUICtrl* cur_focus = dynamic_cast(gFocusMgr.getKeyboardFocus()); + if (cur_focus && cur_focus->acceptsTextInput()) + { + cur_focus->onCommit(); + } + } + closeFloater(false); +} + +void LLFloaterPreferenceProxy::onBtnCancel() +{ + if (hasFocus()) + { + LLUICtrl* cur_focus = dynamic_cast(gFocusMgr.getKeyboardFocus()); + if (cur_focus && cur_focus->acceptsTextInput()) + { + cur_focus->onCommit(); + } + refresh(); + } + + cancel(); + +} +void LLFloaterPreferenceProxy::cancel() +{ + + for (control_values_map_t::iterator iter = mSavedValues.begin(); + iter != mSavedValues.end(); ++iter) + { + LLControlVariable* control = iter->first; + LLSD ctrl_value = iter->second; + control->set(ctrl_value); + } + + closeFloater(); +} + +void LLFloaterPreferenceProxy::onChangeSocksSettings() +{ + mSocksSettingsDirty = true; + + LLRadioGroup* socksAuth = getChild("socks5_auth_type"); + if(socksAuth->getSelectedValue().asString() == "None") + { + getChild("socks5_username")->setEnabled(false); + getChild("socks5_password")->setEnabled(false); + } + else + { + getChild("socks5_username")->setEnabled(true); + getChild("socks5_password")->setEnabled(true); + } + + //Check for invalid states for the other http proxy radio + LLRadioGroup* otherHttpProxy = getChild("other_http_proxy_selection"); + if( (otherHttpProxy->getSelectedValue().asString() == "Socks" && + getChild("socks_proxy_enabled")->get() == FALSE )||( + otherHttpProxy->getSelectedValue().asString() == "Web" && + getChild("web_proxy_enabled")->get() == FALSE ) ) + { + otherHttpProxy->selectFirstItem(); + } + +}; \ No newline at end of file diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 46014804ec..fd5454ebcf 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -154,6 +154,7 @@ public: void applyResolution(); void onChangeMaturity(); void onClickBlockList(); + void onClickProxySettings(); void applyUIColor(LLUICtrl* ctrl, const LLSD& param); void getUIColor(LLUICtrl* ctrl, const LLSD& param); @@ -225,4 +226,33 @@ protected: }; +class LLFloaterPreferenceProxy : public LLFloater +{ +public: + LLFloaterPreferenceProxy(const LLSD& key); + ~LLFloaterPreferenceProxy(); + + /// show off our menu + static void show(); + void cancel(); + +protected: + BOOL postBuild(); + void onOpen(const LLSD& key); + void onClose(bool app_quitting); + void saveSettings(); + void onBtnOk(); + void onBtnCancel(); + + void onChangeSocksSettings(); + +private: + + bool mSocksSettingsDirty; + typedef std::map control_values_map_t; + control_values_map_t mSavedValues; + +}; + + #endif // LL_LLPREFERENCEFLOATER_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 8fccb35886..f054bd11b8 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -191,6 +191,8 @@ #include "llevents.h" #include "llstartuplistener.h" +#include "llsocks5.h" + #if LL_WINDOWS #include "lldxhardware.h" #endif @@ -393,7 +395,7 @@ bool idle_startup() gSavedSettings.setS32("LastGPUClass", LLFeatureManager::getInstance()->getGPUClass()); // load dynamic GPU/feature tables from website (S3) - LLFeatureManager::getInstance()->fetchHTTPTables(); + //LLFeatureManager::getInstance()->fetchHTTPTables(); std::string xml_file = LLUI::locateSkin("xui_version.xml"); LLXMLNodePtr root; @@ -595,6 +597,15 @@ bool idle_startup() LL_INFOS("AppInit") << "Message System Initialized." << LL_ENDL; + //------------------------------------------------- + // Init the socks 5 proxy and open the control TCP + // connection if the user is using SOCKS5 + // We need to do this early incase the user is using + // socks for http so we get the login screen via socks + //------------------------------------------------- + + LLStartUp::handleSocksProxy(false); + //------------------------------------------------- // Init audio, which may be needed for prefs dialog // or audio cues in connection UI. @@ -809,6 +820,27 @@ bool idle_startup() if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState()) { + // Post login screen, we should see if any settings have changed that may + // require us to either start/stop or change the socks proxy. As various communications + // past this point may require the proxy to be up. + if ( gSavedSettings.getBOOL("Socks5ProxyEnabled") ) + { + if (!LLStartUp::handleSocksProxy(true)) + { + // Proxy start up failed, we should now bail the state machine + // HandleSocksProxy() will have reported an error to the user + // already, so we just go back to the login screen. The user + // could then change the preferences to fix the issue. + LLStartUp::setStartupState(STATE_LOGIN_SHOW); + return FALSE; + } + } + else + { + LLSocks::getInstance()->stopProxy(); + } + + //reset the values that could have come in from a slurl // DEV-42215: Make sure they're not empty -- gUserCredential // might already have been set from gSavedSettings, and it's too bad @@ -2746,6 +2778,95 @@ void LLStartUp::setStartSLURL(const LLSLURL& slurl) } } +bool LLStartUp::handleSocksProxy(bool reportOK) +{ + std::string httpProxyType = gSavedSettings.getString("Socks5HttpProxyType"); + + // Determine the http proxy type (if any) + if ((httpProxyType.compare("Web") == 0) && gSavedSettings.getBOOL("BrowserProxyEnabled")) + { + LLHost httpHost; + httpHost.setHostByName(gSavedSettings.getString("BrowserProxyAddress")); + httpHost.setPort(gSavedSettings.getS32("BrowserProxyPort")); + LLSocks::getInstance()->EnableHttpProxy(httpHost,LLPROXY_HTTP); + } + else if ((httpProxyType.compare("Socks") == 0) && gSavedSettings.getBOOL("Socks5ProxyEnabled")) + { + LLHost httpHost; + httpHost.setHostByName(gSavedSettings.getString("Socks5ProxyHost")); + httpHost.setPort(gSavedSettings.getU32("Socks5ProxyPort")); + LLSocks::getInstance()->EnableHttpProxy(httpHost,LLPROXY_SOCKS); + } + else + { + LLSocks::getInstance()->DisableHttpProxy(); + } + + bool use_socks_proxy = gSavedSettings.getBOOL("Socks5ProxyEnabled"); + if (use_socks_proxy) + { + + // Determine and update LLSocks with the saved authentication system + std::string auth_type = gSavedSettings.getString("Socks5AuthType"); + + if (auth_type.compare("None") == 0) + { + LLSocks::getInstance()->setAuthNone(); + } + + if (auth_type.compare("UserPass") == 0) + { + LLSocks::getInstance()->setAuthPassword(gSavedSettings.getString("Socks5Username"),gSavedSettings.getString("Socks5Password")); + } + + // Start the proxy and check for errors + int status = LLSocks::getInstance()->startProxy(gSavedSettings.getString("Socks5ProxyHost"), gSavedSettings.getU32("Socks5ProxyPort")); + LLSD subs; + LLSD payload; + subs["HOST"] = gSavedSettings.getString("Socks5ProxyHost"); + subs["PORT"] = (S32)gSavedSettings.getU32("Socks5ProxyPort"); + + switch(status) + { + case SOCKS_OK: + return true; + break; + + case SOCKS_CONNECT_ERROR: // TCP Fail + LLNotifications::instance().add("SOCKS_CONNECT_ERROR", subs,payload); + break; + + case SOCKS_NOT_PERMITTED: // Socks5 server rule set refused connection + LLNotifications::instance().add("SOCKS_NOT_PERMITTED", subs,payload); + break; + + case SOCKS_NOT_ACCEPTABLE: // Selected authentication is not acceptable to server + LLNotifications::instance().add("SOCKS_NOT_ACCEPTABLE", subs,payload); + break; + + case SOCKS_AUTH_FAIL: // Authentication failed + LLNotifications::instance().add("SOCKS_AUTH_FAIL", subs,payload); + break; + + case SOCKS_UDP_FWD_NOT_GRANTED: // UDP forward request failed + LLNotifications::instance().add("SOCKS_UDP_FWD_NOT_GRANTED", subs,payload); + break; + + case SOCKS_HOST_CONNECT_FAILED: // Failed to open a TCP channel to the socks server + LLNotifications::instance().add("SOCKS_HOST_CONNECT_FAILED", subs,payload); + break; + } + + return false; + } + else + { + LLSocks::getInstance()->stopProxy(); //ensure no UDP proxy is running and its all cleaned up + } + + return true; +} + bool login_alert_done(const LLSD& notification, const LLSD& response) { LLPanelLogin::giveFocus(); diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index b3d9ef1dcc..a512ec7bff 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -113,6 +113,8 @@ public: static void setStartSLURL(const LLSLURL& slurl); static LLSLURL& getStartSLURL() { return sStartSLURL; } + static bool handleSocksProxy(bool reportOK); //handle kicking the socks 5 proxy code at startup time + private: static LLSLURL sStartSLURL; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index dca1e33e60..976dc76b50 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -202,6 +202,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("postcard", "floater_postcard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("prefs_hardware_settings", "floater_hardware_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("perm_prefs", "floater_perm_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 257884d921..b3d899c61a 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -41,6 +41,8 @@ #include "llappviewer.h" #include "lltrans.h" +#include "llsocks5.h" + // Static instance of LLXMLRPCListener declared here so that every time we // bring in this code, we instantiate a listener. If we put the static // instance of LLXMLRPCListener into llxmlrpclistener.cpp, the linker would @@ -307,16 +309,23 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) } mErrorCert = NULL; - if (gSavedSettings.getBOOL("BrowserProxyEnabled")) + if (LLSocks::getInstance()->isHttpProxyEnabled()) { - mProxyAddress = gSavedSettings.getString("BrowserProxyAddress"); - S32 port = gSavedSettings.getS32 ( "BrowserProxyPort" ); - - // tell curl about the settings - mCurlRequest->setoptString(CURLOPT_PROXY, mProxyAddress); + std::string address = LLSocks::getInstance()->getHTTPProxy().getIPString(); + U16 port = LLSocks::getInstance()->getHTTPProxy().getPort(); + mCurlRequest->setoptString(CURLOPT_PROXY, address.c_str()); mCurlRequest->setopt(CURLOPT_PROXYPORT, port); + if (LLSocks::getInstance()->getHttpProxyType() == LLPROXY_SOCKS) + { + mCurlRequest->setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); + if(LLSocks::getInstance()->getSelectedAuthMethod()==METHOD_PASSWORD) + mCurlRequest->setoptString(CURLOPT_PROXYUSERPWD,LLSocks::getInstance()->getProxyUserPwd()); + } + else + { mCurlRequest->setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP); } + } // mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // usefull for debugging mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1); diff --git a/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml b/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml new file mode 100644 index 0000000000..bb9ade067b --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml @@ -0,0 +1,274 @@ + + + + + + Other Http traffic proxy: + + + + + + + + HTTP Proxy: + + + + + SOCKS 5 Proxy: + + + + + Authentication: + + + + width="120" /> + + width="120" /> + + + Username: + + + + Password: + + + -- cgit v1.2.3