diff options
Diffstat (limited to 'indra')
32 files changed, 1770 insertions, 277 deletions
| diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 7aee1bb85f..00757be277 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -100,12 +100,6 @@ private:  		DELETED  	} EInitState; -	static void deleteSingleton() -	{ -		delete getData().mSingletonInstance; -		getData().mSingletonInstance = NULL; -	} -	  	// stores pointer to singleton instance  	// and tracks initialization state of singleton  	struct SingletonInstanceData @@ -120,7 +114,11 @@ private:  		~SingletonInstanceData()  		{ -			deleteSingleton(); +			SingletonInstanceData& data = getData(); +			if (data.mInitState != DELETED) +			{ +				deleteSingleton(); +			}  		}  	}; @@ -132,6 +130,14 @@ public:  		data.mInitState = DELETED;  	} +	// Can be used to control when the singleton is deleted.  Not normally needed. +	static void deleteSingleton() +	{ +		delete getData().mSingletonInstance; +		getData().mSingletonInstance = NULL; +		getData().mInitState = DELETED; +	} +  	static SingletonInstanceData& getData()  	{  		// this is static to cache the lookup results diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index c5f82cf052..0f40a670fa 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -65,6 +65,7 @@ set(llmessage_SOURCE_FILES      llpacketbuffer.cpp      llpacketring.cpp      llpartdata.cpp +    llproxy.cpp      llpumpio.cpp      llregionpresenceverifier.cpp      llsdappservices.cpp @@ -161,6 +162,7 @@ set(llmessage_HEADER_FILES      llpacketring.h      llpartdata.h      llpumpio.h +    llproxy.h      llqueryflags.h      llregionflags.h      llregionhandle.h diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 0735842dcd..7a041239bc 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -46,8 +46,9 @@  #endif  #include "llbufferstream.h" -#include "llstl.h" +#include "llproxy.h"  #include "llsdserialize.h" +#include "llstl.h"  #include "llthread.h"  #include "lltimer.h" @@ -204,7 +205,7 @@ namespace boost  	void intrusive_ptr_release(LLCurl::Responder* p)  	{ -		if(p && 0 == --p->mReferenceCount) +		if (p && 0 == --p->mReferenceCount)  		{  			delete p;  		} @@ -214,73 +215,6 @@ namespace boost  ////////////////////////////////////////////////////////////////////////////// - -class LLCurl::Easy -{ -	LOG_CLASS(Easy); - -private: -	Easy(); -	 -public: -	static Easy* getEasy(); -	~Easy(); - -	CURL* getCurlHandle() const { return mCurlEasyHandle; } - -	void setErrorBuffer(); -	void setCA(); -	 -	void setopt(CURLoption option, S32 value); -	// These assume the setter does not free value! -	void setopt(CURLoption option, void* value); -	void setopt(CURLoption option, char* value); -	// Copies the string so that it is gauranteed to stick around -	void setoptString(CURLoption option, const std::string& value); -	 -	void slist_append(const char* str); -	void setHeaders(); -	 -	U32 report(CURLcode); -	void getTransferInfo(LLCurl::TransferInfo* info); - -	void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, bool post = false); -	 -	const char* getErrorBuffer(); - -	std::stringstream& getInput() { return mInput; } -	std::stringstream& getHeaderOutput() { return mHeaderOutput; } -	LLIOPipe::buffer_ptr_t& getOutput() { return mOutput; } -	const LLChannelDescriptors& getChannels() { return mChannels; } -	 -	void resetState(); - -	static CURL* allocEasyHandle(); -	static void releaseEasyHandle(CURL* handle); - -private:	 -	friend class LLCurl; - -	CURL*				mCurlEasyHandle; -	struct curl_slist*	mHeaders; -	 -	std::stringstream	mRequest; -	LLChannelDescriptors mChannels; -	LLIOPipe::buffer_ptr_t mOutput; -	std::stringstream	mInput; -	std::stringstream	mHeaderOutput; -	char				mErrorBuffer[CURL_ERROR_SIZE]; - -	// Note: char*'s not strings since we pass pointers to curl -	std::vector<char*>	mStrings; -	 -	ResponderPtr		mResponder; - -	static std::set<CURL*> sFreeHandles; -	static std::set<CURL*> sActiveHandles; -	static LLMutex* sHandleMutex; -}; -  std::set<CURL*> LLCurl::Easy::sFreeHandles;  std::set<CURL*> LLCurl::Easy::sActiveHandles;  LLMutex* LLCurl::Easy::sHandleMutex = NULL; @@ -404,11 +338,11 @@ const char* LLCurl::Easy::getErrorBuffer()  void LLCurl::Easy::setCA()  { -	if(!sCAPath.empty()) +	if (!sCAPath.empty())  	{  		setoptString(CURLOPT_CAPATH, sCAPath);  	} -	if(!sCAFile.empty()) +	if (!sCAFile.empty())  	{  		setoptString(CURLOPT_CAINFO, sCAFile);  	} @@ -531,9 +465,12 @@ void LLCurl::Easy::prepRequest(const std::string& url,  	if (post) setoptString(CURLOPT_ENCODING, ""); -	//setopt(CURLOPT_VERBOSE, 1); // usefull for debugging +	//setopt(CURLOPT_VERBOSE, 1); // useful for debugging  	setopt(CURLOPT_NOSIGNAL, 1); +	// Set the CURL options for either Socks or HTTP proxy +	LLProxy::getInstance()->applyProxySettings(this); +  	mOutput.reset(new LLBufferArray);  	setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback);  	setopt(CURLOPT_WRITEDATA, (void*)this); @@ -545,7 +482,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,  	setopt(CURLOPT_HEADERDATA, (void*)this);  	// Allow up to five redirects -	if(responder && responder->followRedir()) +	if (responder && responder->followRedir())  	{  		setopt(CURLOPT_FOLLOWLOCATION, 1);  		setopt(CURLOPT_MAXREDIRS, MAX_REDIRECTS); @@ -579,54 +516,6 @@ void LLCurl::Easy::prepRequest(const std::string& url,  //////////////////////////////////////////////////////////////////////////// -class LLCurl::Multi : public LLThread -{ -	LOG_CLASS(Multi); -public: - -	typedef enum -	{ -		PERFORM_STATE_READY=0, -		PERFORM_STATE_PERFORMING=1, -		PERFORM_STATE_COMPLETED=2 -	} ePerformState; - -	Multi(); -	~Multi(); - -	Easy* allocEasy(); -	bool addEasy(Easy* easy); -	 -	void removeEasy(Easy* easy); - -	S32 process(); -	void perform(); -	 -	virtual void run(); - -	CURLMsg* info_read(S32* msgs_in_queue); - -	S32 mQueued; -	S32 mErrorCount; -	 -	S32 mPerformState; - -	LLCondition* mSignal; -	bool mQuitting; - -private: -	void easyFree(Easy*); -	 -	CURLM* mCurlMultiHandle; - -	typedef std::set<Easy*> easy_active_list_t; -	easy_active_list_t mEasyActiveList; -	typedef std::map<CURL*, Easy*> easy_active_map_t; -	easy_active_map_t mEasyActiveMap; -	typedef std::set<Easy*> easy_free_list_t; -	easy_free_list_t mEasyFreeList; -}; -  LLCurl::Multi::Multi()  	: LLThread("Curl Multi"),  	  mQueued(0), @@ -1025,6 +914,8 @@ LLCurlEasyRequest::LLCurlEasyRequest()  	{  		mEasy->setErrorBuffer();  		mEasy->setCA(); +		// Set proxy settings if configured to do so. +		LLProxy::getInstance()->applyProxySettings(mEasy);  	}  } diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 2f951d6ab8..79f5eeb927 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -41,6 +41,7 @@  #include "llbuffer.h"  #include "lliopipe.h"  #include "llsd.h" +#include "llthread.h"  class LLMutex; @@ -184,6 +185,120 @@ private:  	static const unsigned int MAX_REDIRECTS;  }; +class LLCurl::Easy +{ +	LOG_CLASS(Easy); + +private: +	Easy(); + +public: +	static Easy* getEasy(); +	~Easy(); + +	CURL* getCurlHandle() const { return mCurlEasyHandle; } + +	void setErrorBuffer(); +	void setCA(); + +	void setopt(CURLoption option, S32 value); +	// These assume the setter does not free value! +	void setopt(CURLoption option, void* value); +	void setopt(CURLoption option, char* value); +	// Copies the string so that it is guaranteed to stick around +	void setoptString(CURLoption option, const std::string& value); + +	void slist_append(const char* str); +	void setHeaders(); + +	U32 report(CURLcode); +	void getTransferInfo(LLCurl::TransferInfo* info); + +	void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, bool post = false); + +	const char* getErrorBuffer(); + +	std::stringstream& getInput() { return mInput; } +	std::stringstream& getHeaderOutput() { return mHeaderOutput; } +	LLIOPipe::buffer_ptr_t& getOutput() { return mOutput; } +	const LLChannelDescriptors& getChannels() { return mChannels; } + +	void resetState(); + +	static CURL* allocEasyHandle(); +	static void releaseEasyHandle(CURL* handle); + +private: +	friend class LLCurl; + +	CURL*				mCurlEasyHandle; +	struct curl_slist*	mHeaders; + +	std::stringstream	mRequest; +	LLChannelDescriptors mChannels; +	LLIOPipe::buffer_ptr_t mOutput; +	std::stringstream	mInput; +	std::stringstream	mHeaderOutput; +	char				mErrorBuffer[CURL_ERROR_SIZE]; + +	// Note: char*'s not strings since we pass pointers to curl +	std::vector<char*>	mStrings; + +	ResponderPtr		mResponder; + +	static std::set<CURL*> sFreeHandles; +	static std::set<CURL*> sActiveHandles; +	static LLMutex* sHandleMutex; +}; + +class LLCurl::Multi : public LLThread +{ +	LOG_CLASS(Multi); +public: + +	typedef enum +	{ +		PERFORM_STATE_READY=0, +		PERFORM_STATE_PERFORMING=1, +		PERFORM_STATE_COMPLETED=2 +	} ePerformState; + +	Multi(); +	~Multi(); + +	Easy* allocEasy(); +	bool addEasy(Easy* easy); + +	void removeEasy(Easy* easy); + +	S32 process(); +	void perform(); + +	virtual void run(); + +	CURLMsg* info_read(S32* msgs_in_queue); + +	S32 mQueued; +	S32 mErrorCount; + +	S32 mPerformState; + +	LLCondition* mSignal; +	bool mQuitting; + +private: +	void easyFree(Easy*); + +	CURLM* mCurlMultiHandle; + +	typedef std::set<Easy*> easy_active_list_t; +	easy_active_list_t mEasyActiveList; +	typedef std::map<CURL*, Easy*> easy_active_map_t; +	easy_active_map_t mEasyActiveMap; +	typedef std::set<Easy*> easy_free_list_t; +	easy_free_list_t mEasyFreeList; +}; +  namespace boost  {  	void intrusive_ptr_add_ref(LLCurl::Responder* p); @@ -250,4 +365,7 @@ private:  	bool mResultReturned;  }; +void check_curl_code(CURLcode code); +void check_curl_multi_code(CURLMcode code); +  #endif // LL_LLCURL_H diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp index 5a38b7fd9f..2bca517e97 100644 --- a/indra/llmessage/llhttpassetstorage.cpp +++ b/indra/llmessage/llhttpassetstorage.cpp @@ -33,6 +33,7 @@  #include "indra_constants.h"  #include "message.h" +#include "llproxy.h"  #include "llvfile.h"  #include "llvfs.h" @@ -232,6 +233,10 @@ void LLHTTPAssetRequest::setupCurlHandle()  {  	// *NOTE: Similar code exists in mapserver/llcurlutil.cpp  JC  	mCurlHandle = curl_easy_init(); + +	// Apply proxy settings if configured to do so +	LLProxy::getInstance()->applyProxySettings(mCurlHandle); +  	curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1);  	curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1);  	curl_easy_setopt(mCurlHandle, CURLOPT_URL, mURLBuffer.c_str()); diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 0e5206a520..dd4e3a6300 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -428,6 +428,9 @@ static LLSD blocking_request(  	std::string body_str;  	// other request method checks root cert first, we skip? + +	// Apply configured proxy settings +	LLProxy::getInstance()->applyProxySettings(curlp);  	// * Set curl handle options  	curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1);	// don't use SIGALRM for timeouts @@ -436,7 +439,7 @@ static LLSD blocking_request(  	curl_easy_setopt(curlp, CURLOPT_WRITEDATA, &http_buffer);  	curl_easy_setopt(curlp, CURLOPT_URL, url.c_str());  	curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curl_error_buffer); -	 +  	// * Setup headers (don't forget to free them after the call!)  	curl_slist* headers_list = NULL;  	if (headers.isMap()) diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index b717e321bf..ee9379f205 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -251,10 +251,12 @@ LLSocket::~LLSocket()  	{  		ll_debug_socket("Destroying socket", mSocket);  		apr_socket_close(mSocket); +		mSocket = NULL;  	}  	if(mPool)  	{  		apr_pool_destroy(mPool); +		mPool = NULL;  	}  } diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h index e0f6c1e34d..be0f7dfcc6 100644 --- a/indra/llmessage/lliosocket.h +++ b/indra/llmessage/lliosocket.h @@ -145,13 +145,6 @@ public:  	 */  	apr_socket_t* getSocket() const { return mSocket; } -protected: -	/**  -	 * @brief Protected constructor since should only make sockets -	 * with one of the two <code>create()</code> calls. -	 */ -	LLSocket(apr_socket_t* socket, apr_pool_t* pool); -  	/**   	 * @brief Set default socket options, with SO_NONBLOCK = 0 and a timeout in us.  	 * @param timeout Number of microseconds to wait on this socket. Any @@ -164,6 +157,13 @@ protected:  	 */  	void setNonBlocking(); +protected: +	/** +	 * @brief Protected constructor since should only make sockets +	 * with one of the two <code>create()</code> calls. +	 */ +	LLSocket(apr_socket_t* socket, apr_pool_t* pool); +  public:  	/**   	 * @brief Do not call this directly. diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp index 8999dec64a..ba82957b47 100644 --- a/indra/llmessage/llpacketring.cpp +++ b/indra/llmessage/llpacketring.cpp @@ -28,11 +28,20 @@  #include "llpacketring.h" +#if LL_WINDOWS +	#include <winsock2.h> +#else +	#include <sys/socket.h> +	#include <netinet/in.h> +#endif +  // linden library includes  #include "llerror.h"  #include "lltimer.h" -#include "timing.h" +#include "llproxy.h"  #include "llrand.h" +#include "message.h" +#include "timing.h"  #include "u64.h"  /////////////////////////////////////////////////////////// @@ -216,8 +225,32 @@ S32 LLPacketRing::receivePacket (S32 socket, char *datap)  	else  	{  		// no delay, pull straight from net -		packet_size = receive_packet(socket, datap);		 -		mLastSender = ::get_sender(); +		if (LLProxy::isEnabled()) +		{ +			U8 buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; +			packet_size = receive_packet(socket, reinterpret_cast<char *>(buffer)); +			 +			if (packet_size > SOCKS_HEADER_SIZE) +			{ +				// *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6) +				memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size - SOCKS_HEADER_SIZE); +				proxywrap_t * header = reinterpret_cast<proxywrap_t *>(buffer); +				mLastSender.setAddress(header->addr); +				mLastSender.setPort(ntohs(header->port)); + +				packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size +			} +			else +			{ +				packet_size = 0; +			} +		} +		else +		{ +			packet_size = receive_packet(socket, datap); +			mLastSender = ::get_sender(); +		} +  		mLastReceivingIF = ::get_receiving_interface();  		if (packet_size)  // did we actually get a packet? @@ -243,7 +276,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL  	BOOL status = TRUE;  	if (!mUseOutThrottle)  	{ -		return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() ); +		return sendPacketImpl(h_socket, send_buffer, buf_size, host );  	}  	else  	{ @@ -264,7 +297,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL  				mOutBufferLength -= packetp->getSize();  				packet_size = packetp->getSize(); -				status = send_packet(h_socket, packetp->getData(), packet_size, packetp->getHost().getAddress(), packetp->getHost().getPort()); +				status = sendPacketImpl(h_socket, packetp->getData(), packet_size, packetp->getHost());  				delete packetp;  				// Update the throttle @@ -273,7 +306,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL  			else  			{  				// If the queue's empty, we can just send this packet right away. -				status = send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() ); +				status =  sendPacketImpl(h_socket, send_buffer, buf_size, host );  				packet_size = buf_size;  				// Update the throttle @@ -311,3 +344,23 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL  	return status;  } + +BOOL LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host) +{ +	 +	if (!LLProxy::isEnabled()) +	{ +		return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort()); +	} + +	proxywrap_t *socks_header = reinterpret_cast<proxywrap_t *>(&mProxyWrappedSendBuffer); +	socks_header->rsv   = 0; +	socks_header->addr  = host.getAddress(); +	socks_header->port  = htons(host.getPort()); +	socks_header->atype = ADDRESS_IPV4; +	socks_header->frag  = 0; + +	memcpy(mProxyWrappedSendBuffer + SOCKS_HEADER_SIZE, send_buffer, buf_size); + +	return send_packet(h_socket, (const char*) mProxyWrappedSendBuffer, buf_size + 10, LLProxy::getInstance()->getUDPProxy().getAddress(), LLProxy::getInstance()->getUDPProxy().getPort()); +} diff --git a/indra/llmessage/llpacketring.h b/indra/llmessage/llpacketring.h index e6409d2048..7edcc834db 100644 --- a/indra/llmessage/llpacketring.h +++ b/indra/llmessage/llpacketring.h @@ -30,11 +30,11 @@  #include <queue> -#include "llpacketbuffer.h"  #include "llhost.h" -#include "net.h" +#include "llpacketbuffer.h" +#include "llproxy.h"  #include "llthrottle.h" - +#include "net.h"  class LLPacketRing  { @@ -82,6 +82,12 @@ protected:  	LLHost mLastSender;  	LLHost mLastReceivingIF; + + +	U8 mProxyWrappedSendBuffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; + +private: +	BOOL sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host);  }; diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp new file mode 100644 index 0000000000..d34ad1a811 --- /dev/null +++ b/indra/llmessage/llproxy.cpp @@ -0,0 +1,411 @@ +/** + * @file llsocks5.cpp + * @brief SOCKS 5 implementation + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llproxy.h" + +#include <algorithm> +#include <string> +#include <curl/curl.h> + +#include "llapr.h" +#include "llcurl.h" +#include "llhost.h" +#include "message.h" +#include "net.h" + +// Static class variable instances + +// We want this to be static to avoid excessive indirection on every +// incoming packet just to do a simple bool test. The getter for this +// member is also static +bool LLProxy::sUDPProxyEnabled = false; +bool LLProxy::sHTTPProxyEnabled = false; + +// Some helpful TCP functions +static LLSocket::ptr_t tcp_open_channel(apr_pool_t* pool, LLHost host); // Open a TCP channel to a given host +static void tcp_close_channel(LLSocket::ptr_t* handle_ptr); // Close an open TCP channel +static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen); // Do a TCP data handshake + +LLProxy::LLProxy(): +		mProxyType(LLPROXY_SOCKS), +		mUDPProxy(), +		mTCPProxy(), +		mHTTPProxy(), +		mAuthMethodSelected(METHOD_NOAUTH), +		mSocksUsername(), +		mSocksPassword(), +		mPool(gAPRPoolp), +		mSOCKSAuthStrings(), +		mHTTPProxyAddrStrings(), +		mProxyMutex(0) +{ +} + +LLProxy::~LLProxy() +{ +	stopProxy(); +	sUDPProxyEnabled  = false; +	sHTTPProxyEnabled = false; + +	// Delete c_str versions of the addresses and credentials. +	for_each(mSOCKSAuthStrings.begin(), mSOCKSAuthStrings.end(), DeletePointerArray()); +	for_each(mHTTPProxyAddrStrings.begin(), mHTTPProxyAddrStrings.end(), DeletePointerArray()); +} + +// Perform a SOCKS 5 authentication and UDP association to the proxy +// specified by proxy, and associate UDP port message_port +S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) +{ +	S32 result; + +	/* SOCKS 5 Auth request */ +	socks_auth_request_t  socks_auth_request; +	socks_auth_response_t socks_auth_response; + +	socks_auth_request.version     = SOCKS_VERSION;       // SOCKS version 5 +	socks_auth_request.num_methods = 1;                   // Sending 1 method. +	socks_auth_request.methods     = mAuthMethodSelected; // Send only the selected method. + +	result = tcp_handshake(mProxyControlChannel, (char*)&socks_auth_request, sizeof(socks_auth_request), (char*)&socks_auth_response, sizeof(socks_auth_response)); +	if (result != 0) +	{ +		LL_WARNS("Proxy") << "SOCKS authentication request failed, error on TCP control channel : " << result << LL_ENDL; +		stopProxy(); +		return SOCKS_CONNECT_ERROR; +	} + +	if (socks_auth_response.method == AUTH_NOT_ACCEPTABLE) +	{ +		LL_WARNS("Proxy") << "SOCKS 5 server refused all our authentication methods" << LL_ENDL; +		stopProxy(); +		return SOCKS_NOT_ACCEPTABLE; +	} + +	// SOCKS 5 USERNAME/PASSWORD authentication +	if (socks_auth_response.method == METHOD_PASSWORD) +	{ +		// The server has requested a username/password combination +		U32 request_size = mSocksUsername.size() + mSocksPassword.size() + 3; +		char * password_auth = new char[request_size]; +		password_auth[0] = 0x01; +		password_auth[1] = mSocksUsername.size(); +		memcpy(&password_auth[2], mSocksUsername.c_str(), mSocksUsername.size()); +		password_auth[mSocksUsername.size() + 2] = mSocksPassword.size(); +		memcpy(&password_auth[mSocksUsername.size()+3], mSocksPassword.c_str(), mSocksPassword.size()); + +		authmethod_password_reply_t password_reply; + +		result = tcp_handshake(mProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(password_reply)); +		delete[] password_auth; + +		if (result != 0) +		{ +			LL_WARNS("Proxy") << "SOCKS authentication failed, error on TCP control channel : " << result << LL_ENDL; +			stopProxy(); +			return SOCKS_CONNECT_ERROR; +		} + +		if (password_reply.status != AUTH_SUCCESS) +		{ +			LL_WARNS("Proxy") << "SOCKS authentication failed" << LL_ENDL; +			stopProxy(); +			return SOCKS_AUTH_FAIL; +		} +	} + +	/* SOCKS5 connect request */ + +	socks_command_request_t  connect_request; +	socks_command_response_t connect_reply; + +	connect_request.version		= SOCKS_VERSION;         // SOCKS V5 +	connect_request.command		= COMMAND_UDP_ASSOCIATE; // Associate UDP +	connect_request.reserved	= FIELD_RESERVED; +	connect_request.atype		= ADDRESS_IPV4; +	connect_request.address		= htonl(0); // 0.0.0.0 +	connect_request.port		= htons(0); // 0 +	// "If the client is not in possession of the information at the time of the UDP ASSOCIATE, +	//  the client MUST use a port number and address of all zeros. RFC 1928" + +	result = tcp_handshake(mProxyControlChannel, (char*)&connect_request, sizeof(connect_request), (char*)&connect_reply, sizeof(connect_reply)); +	if (result != 0) +	{ +		LL_WARNS("Proxy") << "SOCKS connect request failed, error on TCP control channel : " << result << LL_ENDL; +		stopProxy(); +		return SOCKS_CONNECT_ERROR; +	} + +	if (connect_reply.reply != REPLY_REQUEST_GRANTED) +	{ +		LL_WARNS("Proxy") << "Connection to SOCKS 5 server failed, UDP forward request not granted" << LL_ENDL; +		stopProxy(); +		return SOCKS_UDP_FWD_NOT_GRANTED; +	} + +	mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order +	mUDPProxy.setAddress(proxy.getAddress()); +	// The connection was successful. We now have the UDP port to send requests that need forwarding to. +	LL_INFOS("Proxy") << "SOCKS 5 UDP proxy connected on " << mUDPProxy << LL_ENDL; +	return SOCKS_OK; +} + +S32 LLProxy::startProxy(std::string host, U32 port) +{ +	mTCPProxy.setHostByName(host); +	mTCPProxy.setPort(port); + +	S32 status; + +	if (mProxyControlChannel) +	{ +		tcp_close_channel(&mProxyControlChannel); +	} + +	mProxyControlChannel = tcp_open_channel(mPool, mTCPProxy); +	if (!mProxyControlChannel) +	{ +		return SOCKS_HOST_CONNECT_FAILED; +	} +	status = proxyHandshake(mTCPProxy, (U32)gMessageSystem->mPort); +	if (status == SOCKS_OK) +	{ +		sUDPProxyEnabled = true; +	} +	else +	{ +		stopProxy(); +	} +	return status; + +} + +void LLProxy::stopProxy() +{ +	sUDPProxyEnabled = false; + +	// If the SOCKS proxy is requested to stop and we are using that for HTTP as well +	// then we must shut down any HTTP proxy operations. But it is allowable if web +	// proxy is being used to continue proxying HTTP. + +	if (LLPROXY_SOCKS == mProxyType) +	{ +		void disableHTTPProxy(); +	} + +	if (mProxyControlChannel) +	{ +		tcp_close_channel(&mProxyControlChannel); +	} +} + +void LLProxy::setAuthNone() +{ +	mAuthMethodSelected = METHOD_NOAUTH; +} + +void LLProxy::setAuthPassword(const std::string &username, const std::string &password) +{ +	mAuthMethodSelected = METHOD_PASSWORD; +	mSocksUsername      = username; +	mSocksPassword      = password; + +	U32 size = username.length() + password.length() + 2; +	char* curl_auth_string  = new char[size]; +	snprintf(curl_auth_string, size, "%s:%s", username.c_str(), password.c_str()); + +	LLMutexLock lock(&mProxyMutex); +	mSOCKSAuthStrings.push_back(curl_auth_string); +} + +void LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type) +{  +	LLMutexLock lock(&mProxyMutex); + +	sHTTPProxyEnabled = true; +	mHTTPProxy        = httpHost; +	mProxyType        = type; + +	U32 size = httpHost.getIPString().length() + 1; +	char* http_addr_string = new char[size]; +	strncpy(http_addr_string, httpHost.getIPString().c_str(), size); +	mHTTPProxyAddrStrings.push_back(http_addr_string); +} + +void LLProxy::enableHTTPProxy() +{ +	LLMutexLock lock(&mProxyMutex); + +	sHTTPProxyEnabled = true; +} + +void LLProxy::disableHTTPProxy() +{ +	LLMutexLock lock(&mProxyMutex); + +	sHTTPProxyEnabled = false; +} + +//static +void LLProxy::cleanupClass() +{ +	getInstance()->stopProxy(); +	deleteSingleton(); +} + +// Apply proxy settings to CuRL request if either type of HTTP proxy is enabled. +void LLProxy::applyProxySettings(LLCurl::Easy* handle) +{ +	if (sHTTPProxyEnabled) +	{ +		std::string address = mHTTPProxy.getIPString(); +		U16 port = mHTTPProxy.getPort(); +		handle->setoptString(CURLOPT_PROXY, address.c_str()); +		handle->setopt(CURLOPT_PROXYPORT, port); +		if (mProxyType == LLPROXY_SOCKS) +		{ +			handle->setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); +			if (mAuthMethodSelected == METHOD_PASSWORD) +			{ +				handle->setoptString(CURLOPT_PROXYUSERPWD, getProxyUserPwdCURL()); +			} +		} +		else +		{ +			handle->setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP); +		} +	} +} + +void LLProxy::applyProxySettings(LLCurlEasyRequest* handle) +{ +	if (sHTTPProxyEnabled) +	{ +		std::string address = mHTTPProxy.getIPString(); +		U16 port = mHTTPProxy.getPort(); +		handle->setoptString(CURLOPT_PROXY, address.c_str()); +		handle->setopt(CURLOPT_PROXYPORT, port); +		if (mProxyType == LLPROXY_SOCKS) +		{ +			handle->setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); +			if (mAuthMethodSelected == METHOD_PASSWORD) +			{ +				handle->setoptString(CURLOPT_PROXYUSERPWD, getProxyUserPwdCURL()); +			} +		} +		else +		{ +			handle->setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP); +		} +	} +} + +void LLProxy::applyProxySettings(CURL* handle) +{ +	LLMutexLock lock(&mProxyMutex); +	if (sHTTPProxyEnabled) +	{ +		check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxyAddrStrings.back())); +		U16 port = mHTTPProxy.getPort(); +		check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, port)); + +		if (mProxyType == LLPROXY_SOCKS) +		{ +			check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5)); +			if (mAuthMethodSelected == METHOD_PASSWORD) +			{ +				check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, mSOCKSAuthStrings.back())); +			} +		} +		else +		{ +			check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP)); +		} +	} +} + +static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen) +{ + +	apr_socket_t* apr_socket = handle->getSocket(); +	apr_status_t rv = APR_SUCCESS; + +	apr_size_t expected_len = outlen; + +	handle->setBlocking(1000); + +  	rv = apr_socket_send(apr_socket, dataout, &outlen); +	if (APR_SUCCESS != rv || expected_len != outlen) +	{ +		LL_WARNS("Proxy") << "Error sending data to proxy control channel" << LL_ENDL; +		ll_apr_warn_status(rv); +	} +	else if (expected_len != outlen) +	{ +		LL_WARNS("Proxy") << "Error sending data to proxy control channel" << LL_ENDL; +		rv = -1; +	} + +	if (APR_SUCCESS == rv) +	{ +		expected_len = maxinlen; +		rv = apr_socket_recv(apr_socket, datain, &maxinlen); +		if (rv != APR_SUCCESS) +		{ +			LL_WARNS("Proxy") << "Error receiving data from proxy control channel, status: " << rv << LL_ENDL; +			ll_apr_warn_status(rv); +		} +		else if (expected_len != maxinlen) +		{ +			LL_WARNS("Proxy") << "Received incorrect amount of data in proxy control channel" << LL_ENDL; +			rv = -1; +		} +	} + +	handle->setNonBlocking(); + +	return rv; +} + +static LLSocket::ptr_t tcp_open_channel(apr_pool_t* pool, LLHost host) +{ +	LLSocket::ptr_t socket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); +	bool connected = socket->blockingConnect(host); +	if (!connected) +	{ +		tcp_close_channel(&socket); +	} + +	return socket; +} + +// Pass a pointer-to-pointer to avoid changing use_count(). +static void tcp_close_channel(LLSocket::ptr_t* handle_ptr) +{ +	LL_DEBUGS("Proxy") << "Resetting proxy LLSocket handle, use_count == " << handle_ptr->use_count() << LL_ENDL; +	handle_ptr->reset(); +} diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h new file mode 100644 index 0000000000..df1ec9121e --- /dev/null +++ b/indra/llmessage/llproxy.h @@ -0,0 +1,266 @@ +/** + * @file llsocks5.h + * @brief Socks 5 implementation + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_PROXY_H +#define LL_PROXY_H + +#include "llcurl.h" +#include "llhost.h" +#include "lliosocket.h" +#include "llmemory.h" +#include "llsingleton.h" +#include "llthread.h" +#include <string> + +// Error codes returned from the StartProxy method + +#define SOCKS_OK 0 +#define SOCKS_CONNECT_ERROR (-1) +#define SOCKS_NOT_PERMITTED (-2) +#define SOCKS_NOT_ACCEPTABLE (-3) +#define SOCKS_AUTH_FAIL (-4) +#define SOCKS_UDP_FWD_NOT_GRANTED (-5) +#define SOCKS_HOST_CONNECT_FAILED (-6) + +#ifndef MAXHOSTNAMELEN +#define	MAXHOSTNAMELEN (255 + 1) /* socks5: 255, +1 for len. */ +#endif + +#define SOCKS_VERSION 0x05 // we are using SOCKS 5 + +#define SOCKS_HEADER_SIZE 10 + +// SOCKS 5 address/hostname types +#define ADDRESS_IPV4     0x01 +#define ADDRESS_HOSTNAME 0x03 +#define ADDRESS_IPV6     0x04 + +// Lets just use our own ipv4 struct rather than dragging in system +// specific headers +union ipv4_address_t { +	U8		octets[4]; +	U32		addr32; +}; + +// SOCKS 5 control channel commands +#define COMMAND_TCP_STREAM    0x01 +#define COMMAND_TCP_BIND      0x02 +#define COMMAND_UDP_ASSOCIATE 0x03 + +// SOCKS 5 command replies +#define REPLY_REQUEST_GRANTED     0x00 +#define REPLY_GENERAL_FAIL        0x01 +#define REPLY_RULESET_FAIL        0x02 +#define REPLY_NETWORK_UNREACHABLE 0x03 +#define REPLY_HOST_UNREACHABLE    0x04 +#define REPLY_CONNECTION_REFUSED  0x05 +#define REPLY_TTL_EXPIRED         0x06 +#define REPLY_PROTOCOL_ERROR      0x07 +#define REPLY_TYPE_NOT_SUPPORTED  0x08 + +#define FIELD_RESERVED 0x00 + +// The standard SOCKS 5 request packet +// Push current alignment to stack and set alignment to 1 byte boundary +// This enabled us to use structs directly to set up and receive network packets +// into the correct fields, without fear of boundary alignment causing issues +#pragma pack(push,1) + +// SOCKS 5 command packet +struct socks_command_request_t { +	U8		version; +	U8		command; +	U8		reserved; +	U8		atype; +	U32		address; +	U16		port; +}; + +// Standard SOCKS 5 reply packet +struct socks_command_response_t { +	U8		version; +	U8		reply; +	U8		reserved; +	U8		atype; +	U8		add_bytes[4]; +	U16		port; +}; + +#define AUTH_NOT_ACCEPTABLE 0xFF // reply if preferred methods are not available +#define AUTH_SUCCESS        0x00 // reply if authentication successful + +// SOCKS 5 authentication request, stating which methods the client supports +struct socks_auth_request_t { +	U8		version; +	U8		num_methods; +	U8		methods; // We are only using a single method currently +}; + +// SOCKS 5 authentication response packet, stating server preferred method +struct socks_auth_response_t { +	U8		version; +	U8		method; +}; + +// SOCKS 5 password reply packet +struct authmethod_password_reply_t { +	U8		version; +	U8		status; +}; + +// SOCKS 5 UDP packet header +struct proxywrap_t { +	U16		rsv; +	U8		frag; +	U8		atype; +	U32		addr; +	U16		port; +}; + +#pragma pack(pop) /* restore original alignment from stack */ + + +// Currently selected HTTP proxy type +enum LLHttpProxyType +{ +	LLPROXY_SOCKS = 0, +	LLPROXY_HTTP  = 1 +}; + +// Auth types +enum LLSocks5AuthType +{ +	METHOD_NOAUTH   = 0x00,	// Client supports no auth +	METHOD_GSSAPI   = 0x01,	// Client supports GSSAPI (Not currently supported) +	METHOD_PASSWORD = 0x02 	// Client supports username/password +}; + +class LLProxy: public LLSingleton<LLProxy> +{ +public: +	LLProxy(); +	~LLProxy(); + +	// Start a connection to the SOCKS 5 proxy +	S32 startProxy(std::string host, U32 port); + +	// Disconnect and clean up any connection to the SOCKS 5 proxy +	void stopProxy(); + +	// Delete LLProxy singleton, destroying the APR pool used by the control channel. +	static void cleanupClass(); + +	// Set up to use Password auth when connecting to the SOCKS proxy +	void setAuthPassword(const std::string &username, const std::string &password); + +	// Set up to use No Auth when connecting to the SOCKS proxy +	void setAuthNone(); + +	// get the currently selected auth method +	LLSocks5AuthType getSelectedAuthMethod() const { return mAuthMethodSelected; } + +	// static check for enabled status for UDP packets +	static bool isEnabled() { return sUDPProxyEnabled; } + +	// static check for enabled status for http packets +	static bool isHTTPProxyEnabled() { return sHTTPProxyEnabled; } + +	// Proxy HTTP packets via httpHost, which can be a SOCKS 5 or a HTTP proxy +	// as specified in type +	void enableHTTPProxy(LLHost httpHost, LLHttpProxyType type); +	void enableHTTPProxy(); + +	// Stop proxying HTTP packets +	void disableHTTPProxy(); + +	// Get the UDP proxy address and port +	LLHost getUDPProxy() const { return mUDPProxy; } + +	// Get the SOCKS 5 TCP control channel address and port +	LLHost getTCPProxy() const { return mTCPProxy; } + +	// Get the HTTP proxy address and port +	LLHost getHTTPProxy() const { return mHTTPProxy; } + +	// Get the currently selected HTTP proxy type +	LLHttpProxyType getHTTPProxyType() const { return mProxyType; } + +	// Get the username password in a curl compatible format +	std::string getProxyUserPwdCURL() const { return (mSocksUsername + ":" + mSocksPassword); } + +	std::string getSocksPwd() const { return mSocksPassword; } +	std::string getSocksUser() const { return mSocksUsername; } + +	// Apply the current proxy settings to a curl request. Doesn't do anything if sHTTPProxyEnabled is false. +	void applyProxySettings(CURL* handle); +	void applyProxySettings(LLCurl::Easy* handle); +	void applyProxySettings(LLCurlEasyRequest* handle); + +private: +	// Open a communication channel to the SOCKS 5 proxy proxy, at port messagePort +	S32 proxyHandshake(LLHost proxy, U32 messagePort); + +private: +	// socket handle to proxy TCP control channel +	LLSocket::ptr_t mProxyControlChannel; + +	// Is the UDP proxy enabled? +	static bool sUDPProxyEnabled; +	// Is the HTTP proxy enabled?  +	// Do not toggle directly, use enableHTTPProxy() and disableHTTPProxy() +	static bool sHTTPProxyEnabled; + +	// currently selected http proxy type +	LLHttpProxyType mProxyType; + +	// UDP proxy address and port +	LLHost mUDPProxy; +	// TCP proxy control channel address and port +	LLHost mTCPProxy; +	// HTTP proxy address and port +	LLHost mHTTPProxy; + +	// SOCKS 5 auth method selected +	LLSocks5AuthType mAuthMethodSelected; + +	// SOCKS 5 username +	std::string mSocksUsername; +	// SOCKS 5 password +	std::string mSocksPassword; + +	// Vectors to store valid pointers to string options that might have been set on CURL requests. +	// This results in a behavior similar to LLCurl::Easy::setoptstring() +	std::vector<char*> mSOCKSAuthStrings; +	std::vector<char*> mHTTPProxyAddrStrings; + +	// Mutex to protect members in cross-thread calls to applyProxySettings() +	LLMutex mProxyMutex; + +	// APR pool for the socket +	apr_pool_t* mPool; +}; + +#endif diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index e8e35d00a2..a186596582 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -35,6 +35,7 @@  #include "llcurl.h"  #include "llioutil.h"  #include "llmemtype.h" +#include "llproxy.h"  #include "llpumpio.h"  #include "llsd.h"  #include "llstring.h" @@ -227,8 +228,7 @@ void LLURLRequest::useProxy(bool use_proxy)          }      } - -    lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << llendl; +    LL_DEBUGS("Proxy") << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << LL_ENDL;      if (env_proxy && use_proxy)      { @@ -438,6 +438,7 @@ void LLURLRequest::initialize()  	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);  	mState = STATE_INITIALIZED;  	mDetail = new LLURLRequestDetail; +	LLProxy::getInstance()->applyProxySettings(mDetail->mCurlRequest);  	mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);  	mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);  	mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this); diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp index 97611c3b51..85aef5da00 100644 --- a/indra/llmessage/net.cpp +++ b/indra/llmessage/net.cpp @@ -50,7 +50,6 @@  #include "lltimer.h"  #include "indra_constants.h" -  // Globals  #if LL_WINDOWS @@ -174,7 +173,7 @@ U32 ip_string_to_u32(const char* ip_string)  	// use wildcard addresses. -Ambroff  	U32 ip = inet_addr(ip_string);  	if (ip == INADDR_NONE  -	    && strncmp(ip_string, BROADCAST_ADDRESS_STRING, MAXADDRSTR) != 0) +			&& strncmp(ip_string, BROADCAST_ADDRESS_STRING, MAXADDRSTR) != 0)  	{  		llwarns << "ip_string_to_u32() failed, Error: Invalid IP string '" << ip_string << "'" << llendl;  		return INVALID_HOST_IP_ADDRESS; @@ -188,11 +187,11 @@ U32 ip_string_to_u32(const char* ip_string)  //////////////////////////////////////////////////////////////////////////////////////////  #if LL_WINDOWS -  +  S32 start_net(S32& socket_out, int& nPort)   {			  	// Create socket, make non-blocking -    // Init WinSock  +	// Init WinSock  	int nRet;  	int hSocket; @@ -201,7 +200,7 @@ S32 start_net(S32& socket_out, int& nPort)  	int buff_size = 4;  	// Initialize windows specific stuff -	if(WSAStartup(0x0202, &stWSAData)) +	if (WSAStartup(0x0202, &stWSAData))  	{  		S32 err = WSAGetLastError();  		WSACleanup(); @@ -210,8 +209,8 @@ S32 start_net(S32& socket_out, int& nPort)  	}  	// Get a datagram socket -    hSocket = (int)socket(AF_INET, SOCK_DGRAM, 0); -    if (hSocket == INVALID_SOCKET) +	hSocket = (int)socket(AF_INET, SOCK_DGRAM, 0); +	if (hSocket == INVALID_SOCKET)  	{  		S32 err = WSAGetLastError();  		WSACleanup(); @@ -304,7 +303,7 @@ S32 start_net(S32& socket_out, int& nPort)  	//  Setup a destination address  	stDstAddr.sin_family =      AF_INET;  	stDstAddr.sin_addr.s_addr = INVALID_HOST_IP_ADDRESS; -    stDstAddr.sin_port =        htons(nPort); +	stDstAddr.sin_port =        htons(nPort);  	socket_out = hSocket;  	return 0; @@ -393,10 +392,10 @@ S32 start_net(S32& socket_out, int& nPort)  	int rec_size = RECEIVE_BUFFER_SIZE;  	socklen_t buff_size = 4; -     +  	//  Create socket -    hSocket = socket(AF_INET, SOCK_DGRAM, 0); -    if (hSocket < 0) +	hSocket = socket(AF_INET, SOCK_DGRAM, 0); +	if (hSocket < 0)  	{  		llwarns << "socket() failed" << llendl;  		return 1; @@ -429,7 +428,7 @@ S32 start_net(S32& socket_out, int& nPort)  	}  	else  	{ -	    // Name the socket (assign the local port number to receive on) +		// Name the socket (assign the local port number to receive on)  		stLclAddr.sin_family      = AF_INET;  		stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);  		stLclAddr.sin_port        = htons(nPort); @@ -474,7 +473,7 @@ S32 start_net(S32& socket_out, int& nPort)  		nPort = attempt_port;  	}  	// Set socket to be non-blocking - 	fcntl(hSocket, F_SETFL, O_NONBLOCK); +	fcntl(hSocket, F_SETFL, O_NONBLOCK);  	// set a large receive buffer  	nRet = setsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, buff_size);  	if (nRet) @@ -510,8 +509,8 @@ S32 start_net(S32& socket_out, int& nPort)  	//  Setup a destination address  	char achMCAddr[MAXADDRSTR] = "127.0.0.1";	/* Flawfinder: ignore */   	stDstAddr.sin_family =      AF_INET; -        stDstAddr.sin_addr.s_addr = ip_string_to_u32(achMCAddr); -        stDstAddr.sin_port =        htons(nPort); +	stDstAddr.sin_addr.s_addr = ip_string_to_u32(achMCAddr); +	stDstAddr.sin_port =        htons(nPort);  	socket_out = hSocket;  	return 0; @@ -537,7 +536,7 @@ static int recvfrom_destip( int socket, void *buf, int len, struct sockaddr *fro  	iov[0].iov_base = buf;  	iov[0].iov_len = len; -	memset( &msg, 0, sizeof msg ); +	memset(&msg, 0, sizeof msg);  	msg.msg_name = from;  	msg.msg_namelen = *fromlen;  	msg.msg_iov = iov; @@ -545,14 +544,14 @@ static int recvfrom_destip( int socket, void *buf, int len, struct sockaddr *fro  	msg.msg_control = &cmsg;  	msg.msg_controllen = sizeof(cmsg); -	size = recvmsg( socket, &msg, 0 ); +	size = recvmsg(socket, &msg, 0); -	if( size == -1 ) +	if (size == -1)  	{  		return -1;  	} -	for( cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR( &msg, cmsgptr ) ) +	for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR( &msg, cmsgptr))  	{  		if( cmsgptr->cmsg_level == SOL_IP && cmsgptr->cmsg_type == IP_PKTINFO )  		{ @@ -650,7 +649,7 @@ BOOL send_packet(int hSocket, const char * sendBuffer, int size, U32 recipient,  			}  		}  	} -	while ( resend && send_attempts < 3); +	while (resend && send_attempts < 3);  	if (send_attempts >= 3)  	{ diff --git a/indra/llmessage/net.h b/indra/llmessage/net.h index 9f4f5c5821..0f2437479d 100644 --- a/indra/llmessage/net.h +++ b/indra/llmessage/net.h @@ -46,10 +46,10 @@ S32		receive_packet(int hSocket, char * receiveBuffer);  BOOL	send_packet(int hSocket, const char *sendBuffer, int size, U32 recipient, int nPort);	// Returns TRUE on success.  //void	get_sender(char * tmp); -LLHost  get_sender(); +LLHost	get_sender();  U32		get_sender_port();  U32		get_sender_ip(void); -LLHost  get_receiving_interface(); +LLHost	get_receiving_interface();  U32		get_receiving_interface_ip(void);  const char*	u32_to_ip_string(U32 ip);					// Returns pointer to internal string buffer, "(bad IP addr)" on failure, cannot nest calls  diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h index 752c7df7ee..899cc3a326 100644 --- a/indra/llui/llfunctorregistry.h +++ b/indra/llui/llfunctorregistry.h @@ -103,7 +103,7 @@ public:  		}  		else  		{ -			llwarns << "tried to find '" << name << "' in LLFunctorRegistry, but it wasn't there." << llendl; +			lldebugs << "tried to find '" << name << "' in LLFunctorRegistry, but it wasn't there." << llendl;  			return mMap[LOGFUNCTOR];  		}  	} @@ -115,7 +115,7 @@ private:  	static void log_functor(const LLSD& notification, const LLSD& payload)  	{ -		llwarns << "log_functor called with payload: " << payload << llendl; +		lldebugs << "log_functor called with payload: " << payload << llendl;  	}  	static void do_nothing(const LLSD& notification, const LLSD& payload) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 9bb320d882..b18538a42b 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -796,6 +796,61 @@        <key>Value</key>        <integer>5</integer>      </map> +    <key>Socks5ProxyEnabled</key> +    <map> +      <key>Comment</key> +      <string>Use Socks5 Proxy</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map> +    <key>Socks5HttpProxyType</key> +    <map> +      <key>Comment</key> +      <string>Proxy type to use for HTTP operations</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>Socks</string> +    </map> +    <key>Socks5ProxyHost</key> +    <map> +      <key>Comment</key> +      <string>Socks 5 Proxy Host</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string></string> +    </map> +    <key>Socks5ProxyPort</key> +    <map> +      <key>Comment</key> +      <string>Socks 5 Proxy Port</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>U32</string> +      <key>Value</key> +      <integer>1080</integer> +    </map> +    <key>Socks5AuthType</key> +    <map> +      <key>Comment</key> +      <string>Selected Auth mechanism for Socks5</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>None</string> +    </map>      <key>BuildAxisDeadZone0</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b65933f8a1..27e72ad7ca 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -137,6 +137,7 @@  #include "lltoolmgr.h"  #include "llassetstorage.h"  #include "llpolymesh.h" +#include "llproxy.h"  #include "llaudioengine.h"  #include "llstreamingaudio.h"  #include "llviewermenu.h" @@ -1840,6 +1841,8 @@ bool LLAppViewer::cleanup()  		LLWeb::loadURLExternal( gLaunchFileOnQuit, false );  		llinfos << "File launched." << llendflush;  	} +	llinfos << "Cleaning up LLProxy." << llendl; +	LLProxy::cleanupClass();  	LLMainLoopRepeater::instance().stop(); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 5fd262a720..84547ec38a 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -105,6 +105,7 @@  #include "llviewermedia.h"  #include "llpluginclassmedia.h"  #include "llteleporthistorystorage.h" +#include "llproxy.h"  #include "lllogininstance.h"        // to check if logged in yet  #include "llsdserialize.h" @@ -158,7 +159,7 @@ BOOL LLVoiceSetKeyDialog::handleKeyHere(KEY key, MASK mask)  {  	BOOL result = TRUE; -	if(key == 'Q' && mask == MASK_CONTROL) +	if (key == 'Q' && mask == MASK_CONTROL)  	{  		result = FALSE;  	} @@ -343,6 +344,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"); @@ -457,7 +459,7 @@ BOOL LLFloaterPreference::postBuild()  void LLFloaterPreference::onBusyResponseChanged()  {  	// set "BusyResponseChanged" TRUE if user edited message differs from default, FALSE otherwise -	if(LLTrans::getString("BusyModeResponseDefault") != getChild<LLUICtrl>("busy_response")->getValue().asString()) +	if (LLTrans::getString("BusyModeResponseDefault") != getChild<LLUICtrl>("busy_response")->getValue().asString())  	{  		gSavedPerAccountSettings.setBOOL("BusyResponseChanged", TRUE );  	} @@ -539,7 +541,7 @@ void LLFloaterPreference::apply()  	LLViewerMedia::setCookiesEnabled(getChild<LLUICtrl>("cookies_enabled")->getValue()); -	if(hasChild("web_proxy_enabled") &&hasChild("web_proxy_editor") && hasChild("web_proxy_port")) +	if (hasChild("web_proxy_enabled") &&hasChild("web_proxy_editor") && hasChild("web_proxy_port"))  	{  		bool proxy_enable = getChild<LLUICtrl>("web_proxy_enabled")->getValue();  		std::string proxy_address = getChild<LLUICtrl>("web_proxy_editor")->getValue(); @@ -552,13 +554,13 @@ void LLFloaterPreference::apply()  	gSavedSettings.setBOOL("PlainTextChatHistory", getChild<LLUICtrl>("plain_text_chat_history")->getValue().asBoolean()); -	if(mGotPersonalInfo) +	if (mGotPersonalInfo)  	{   //		gSavedSettings.setString("BusyModeResponse2", std::string(wstring_to_utf8str(busy_response)));  		bool new_im_via_email = getChild<LLUICtrl>("send_im_to_email")->getValue().asBoolean();  		bool new_hide_online = getChild<LLUICtrl>("online_visibility")->getValue().asBoolean();		 -		if((new_im_via_email != mOriginalIMViaEmail) +		if ((new_im_via_email != mOriginalIMViaEmail)  			||(new_hide_online != mOriginalHideOnlineStatus))  		{  			// This hack is because we are representing several different 	  @@ -566,13 +568,13 @@ void LLFloaterPreference::apply()  			// can only select between 2 values, we represent it as a 	   			// checkbox. This breaks down a little bit for liaisons, but 	   			// works out in the end. 	  -			if(new_hide_online != mOriginalHideOnlineStatus) 	  -			{ 	  -				if(new_hide_online) mDirectoryVisibility = VISIBILITY_HIDDEN; +			if (new_hide_online != mOriginalHideOnlineStatus) +			{ +				if (new_hide_online) mDirectoryVisibility = VISIBILITY_HIDDEN;  				else mDirectoryVisibility = VISIBILITY_DEFAULT;  			 //Update showonline value, otherwise multiple applys won't work  				mOriginalHideOnlineStatus = new_hide_online; -			} 	  +			}  			gAgent.sendAgentUpdateUserInfo(new_im_via_email,mDirectoryVisibility);  		}  	} @@ -616,6 +618,11 @@ void LLFloaterPreference::cancel()  		updateDoubleClickControls();  		mDoubleClickActionDirty = false;  	} +	LLFloaterPreferenceProxy * advanced_socks_settings = LLFloaterReg::findTypedInstance<LLFloaterPreferenceProxy>("prefs_socks5_advanced"); +	if (advanced_socks_settings) +	{ +		advanced_socks_settings->cancel(); +	}  }  void LLFloaterPreference::onOpen(const LLSD& key) @@ -799,7 +806,7 @@ void LLFloaterPreference::onBtnCancel()  void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email)  {  	LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); -	if(instance) +	if (instance)  	{  		instance->setPersonalInfo(visibility, im_via_email, email);	  	} @@ -809,7 +816,7 @@ void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_  void LLFloaterPreference::refreshEnabledGraphics()  {  	LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); -	if(instance) +	if (instance)  	{  		instance->refresh();  		//instance->refreshEnabledState(); @@ -1096,7 +1103,7 @@ void LLFloaterPreference::disableUnavailableSettings()  	LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF");  	// if vertex shaders off, disable all shader related products -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable"))  	{  		ctrl_shader_enable->setEnabled(FALSE);  		ctrl_shader_enable->setValue(FALSE); @@ -1127,7 +1134,7 @@ void LLFloaterPreference::disableUnavailableSettings()  	}  	// disabled windlight -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"))  	{  		ctrl_wind_light->setEnabled(FALSE);  		ctrl_wind_light->setValue(FALSE); @@ -1164,28 +1171,28 @@ void LLFloaterPreference::disableUnavailableSettings()  	}  	// disabled deferred SSAO -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO"))  	{  		ctrl_ssao->setEnabled(FALSE);  		ctrl_ssao->setValue(FALSE);  	}  	// disabled deferred shadows -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail"))  	{  		ctrl_shadows->setEnabled(FALSE);  		ctrl_shadows->setValue(0);  	}  	// disabled reflections -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail"))  	{  		ctrl_reflections->setEnabled(FALSE);  		ctrl_reflections->setValue(FALSE);  	}  	// disabled av -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP"))  	{  		ctrl_avatar_vp->setEnabled(FALSE);  		ctrl_avatar_vp->setValue(FALSE); @@ -1208,14 +1215,14 @@ void LLFloaterPreference::disableUnavailableSettings()  	}  	// disabled cloth -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth"))  	{  		ctrl_avatar_cloth->setEnabled(FALSE);  		ctrl_avatar_cloth->setValue(FALSE);  	}  	// disabled impostors -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderUseImpostors")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderUseImpostors"))  	{  		ctrl_avatar_impostors->setEnabled(FALSE);  		ctrl_avatar_impostors->setValue(FALSE); @@ -1381,12 +1388,12 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im  	mOriginalIMViaEmail = im_via_email;  	mDirectoryVisibility = visibility; -	if(visibility == VISIBILITY_DEFAULT) +	if (visibility == VISIBILITY_DEFAULT)  	{  		mOriginalHideOnlineStatus = false;  		getChildView("online_visibility")->setEnabled(TRUE); 	   	} -	else if(visibility == VISIBILITY_HIDDEN) +	else if (visibility == VISIBILITY_HIDDEN)  	{  		mOriginalHideOnlineStatus = true;  		getChildView("online_visibility")->setEnabled(TRUE); 	  @@ -1434,7 +1441,7 @@ void LLFloaterPreference::onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name)  {  	std::string ctrl_name = name.asString(); -	if((ctrl_name =="" )|| !hasChild(ctrl_name, true)) +	if ((ctrl_name =="" )|| !hasChild(ctrl_name, true))  		return;  	LLTextBox* text_box = getChild<LLTextBox>(name.asString()); @@ -1444,7 +1451,7 @@ void LLFloaterPreference::onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name)  void LLFloaterPreference::updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box)  { -	if(text_box == NULL || ctrl== NULL) +	if (text_box == NULL || ctrl== NULL)  		return;  	// get range and points when text should change @@ -1457,7 +1464,7 @@ void LLFloaterPreference::updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_b  	F32 highPoint = min + (2.0f * range / 3.0f);  	// choose the right text -	if(value < midPoint) +	if (value < midPoint)  	{  		text_box->setText(LLTrans::getString("GraphicsQualityLow"));  	}  @@ -1541,6 +1548,11 @@ void LLFloaterPreference::updateDoubleClickSettings()  	}  } +void LLFloaterPreference::onClickProxySettings() +{ +	LLFloaterReg::showInstance("prefs_proxy"); +} +  void LLFloaterPreference::updateDoubleClickControls()  {  	// check is one of double-click actions settings enabled @@ -1637,7 +1649,7 @@ BOOL LLPanelPreference::postBuild()  {  	////////////////////// PanelVoice /////////////////// -	if(hasChild("voice_unavailable")) +	if (hasChild("voice_unavailable"))  	{  		BOOL voice_disabled = gSavedSettings.getBOOL("CmdLineDisableVoice");  		getChildView("voice_unavailable")->setVisible( voice_disabled); @@ -1659,7 +1671,7 @@ BOOL LLPanelPreference::postBuild()  	} -	if(hasChild("online_visibility") && hasChild("send_im_to_email")) +	if (hasChild("online_visibility") && hasChild("send_im_to_email"))  	{  		getChild<LLUICtrl>("email_address")->setValue(getString("log_in_to_change") );  //		getChild<LLUICtrl>("busy_response")->setValue(getString("log_in_to_change"));		 @@ -1788,7 +1800,7 @@ void LLPanelPreference::cancel()  		 iter != mSavedColors.end(); ++iter)  	{  		LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>(iter->first); -		if(color_swatch) +		if (color_swatch)  		{  			color_swatch->set(iter->second);  			color_swatch->onCommit(); @@ -1832,7 +1844,7 @@ void LLPanelPreferenceGraphics::draw()  	LLButton* button_apply = findChild<LLButton>("Apply"); -	if(button_apply && button_apply->getVisible()) +	if (button_apply && button_apply->getVisible())  	{  		bool enable = hasDirtyChilds(); @@ -1852,7 +1864,7 @@ bool LLPanelPreferenceGraphics::hasDirtyChilds()  		LLUICtrl* ctrl = dynamic_cast<LLUICtrl*>(curview);  		if (ctrl)  		{ -			if(ctrl->isDirty()) +			if (ctrl->isDirty())  				return true;  		}  		// Push children onto the end of the work stack @@ -1908,3 +1920,181 @@ 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() +{ +	LLRadioGroup* socksAuth = getChild<LLRadioGroup>("socks5_auth_type"); +	if (socksAuth->getSelectedValue().asString() == "None") +	{ +		getChild<LLLineEditor>("socks5_username")->setEnabled(false); +		getChild<LLLineEditor>("socks5_password")->setEnabled(false); +	} +	else +	{ +		// Populate the SOCKS 5 credential fields with protected values. +		LLPointer<LLCredential> socks_cred = gSecAPIHandler->loadCredential("SOCKS5"); +		getChild<LLLineEditor>("socks5_username")->setValue(socks_cred->getIdentifier()["username"].asString()); +		getChild<LLLineEditor>("socks5_password")->setValue(socks_cred->getAuthenticator()["creds"].asString()); +	} + +	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, it's only fair we let them know +		// it will not be updated until next restart. +		if (LLStartUp::getStartupState()>STATE_LOGIN_WAIT) +		{ +			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<LLView*> 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<LLUICtrl*>(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<LLUICtrl*>(gFocusMgr.getKeyboardFocus()); +		if (cur_focus && cur_focus->acceptsTextInput()) +		{ +			cur_focus->onCommit(); +		} +	} + +	// Save SOCKS proxy credentials securely if password auth is enabled +	LLRadioGroup* socksAuth = getChild<LLRadioGroup>("socks5_auth_type"); +	if (socksAuth->getSelectedValue().asString() == "UserPass") +	{ +		LLSD socks_id = LLSD::emptyMap(); +		socks_id["type"] = "SOCKS5"; +		socks_id["username"] = getChild<LLLineEditor>("socks5_username")->getValue().asString(); + +		LLSD socks_authenticator = LLSD::emptyMap(); +		socks_authenticator["type"] = "SOCKS5"; +		socks_authenticator["creds"] = getChild<LLLineEditor>("socks5_password")->getValue().asString(); + +		LLPointer<LLCredential> socks_cred = gSecAPIHandler->createCredential("SOCKS5", socks_id, socks_authenticator); +		gSecAPIHandler->saveCredential(socks_cred, true); +	} +	else +	{ +		// Clear SOCKS5 credentials since they are no longer needed. +		LLPointer<LLCredential> socks_cred = new LLCredential("SOCKS5"); +		gSecAPIHandler->deleteCredential(socks_cred); +	} + +	closeFloater(false); +} + +void LLFloaterPreferenceProxy::onBtnCancel() +{ +	if (hasFocus()) +	{ +		LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(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<LLRadioGroup>("socks5_auth_type"); +	if (socksAuth->getSelectedValue().asString() == "None") +	{ +		getChild<LLLineEditor>("socks5_username")->setEnabled(false); +		getChild<LLLineEditor>("socks5_password")->setEnabled(false); +	} +	else +	{ +		getChild<LLLineEditor>("socks5_username")->setEnabled(true); +		getChild<LLLineEditor>("socks5_password")->setEnabled(true); +	} + +	// Check for invalid states for the other HTTP proxy radio +	LLRadioGroup* otherHttpProxy = getChild<LLRadioGroup>("other_http_proxy_selection"); +	if ((otherHttpProxy->getSelectedValue().asString() == "Socks" && +			getChild<LLCheckBoxCtrl>("socks_proxy_enabled")->get() == FALSE )||( +					otherHttpProxy->getSelectedValue().asString() == "Web" && +					getChild<LLCheckBoxCtrl>("web_proxy_enabled")->get() == FALSE ) ) +	{ +		otherHttpProxy->selectFirstItem(); +	} + +}; diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 61f2c78640..ef9bc2dd53 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -156,6 +156,7 @@ public:  	void applyResolution();  	void onChangeMaturity();  	void onClickBlockList(); +	void onClickProxySettings();  	void applyUIColor(LLUICtrl* ctrl, const LLSD& param);  	void getUIColor(LLUICtrl* ctrl, const LLSD& param); @@ -229,4 +230,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<LLControlVariable*, LLSD> control_values_map_t; +	control_values_map_t mSavedValues; + +}; + +  #endif  // LL_LLPREFERENCEFLOATER_H diff --git a/indra/newview/llloginhandler.cpp b/indra/newview/llloginhandler.cpp index 48be251611..9b4f146332 100644 --- a/indra/newview/llloginhandler.cpp +++ b/indra/newview/llloginhandler.cpp @@ -30,13 +30,13 @@  // viewer includes  #include "llsecapi.h" -#include "lllogininstance.h"        // to check if logged in yet -#include "llpanellogin.h"			// save_password_to_disk() +#include "lllogininstance.h"		// to check if logged in yet +#include "llpanellogin.h"  #include "llstartup.h"				// getStartupState()  #include "llslurl.h"  #include "llviewercontrol.h"		// gSavedSettings  #include "llviewernetwork.h"		// EGridInfo -#include "llviewerwindow.h"                    // getWindow() +#include "llviewerwindow.h"			// getWindow()  // library includes  #include "llmd5.h" diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index 11273453ba..b1390a483a 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -115,7 +115,4 @@ private:  	static BOOL		sCapslockDidNotification;  }; -std::string load_password_from_disk(void); -void save_password_to_disk(const char* hashed_password); -  #endif diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index b65cf37e7f..812a539324 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -286,8 +286,8 @@ bool operator!=(const LLCertificateVector::iterator& _lhs, const LLCertificateVe  #define CRED_AUTHENTICATOR_TYPE_HASH   "hash"  //  // LLCredential - interface for credentials providing the following functionality: -// * persistance of credential information based on grid (for saving username/password) -// * serialization to an OGP identifier/authenticator pair +// * Persistence of credential information based on grid (for saving username/password) +// * Serialization to an OGP identifier/authenticator pair  //   class LLCredential  : public LLRefCount  { diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 4dfcb85295..1fe241a8ce 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -126,6 +126,7 @@  #include "llpanelgroupnotices.h"  #include "llpreview.h"  #include "llpreviewscript.h" +#include "llproxy.h"  #include "llproductinforequest.h"  #include "llsecondlifeurls.h"  #include "llselectmgr.h" @@ -593,6 +594,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 SOCKS 5 +		// We need to do this early in case the user is using +		// socks for HTTP so we get the login screen via SOCKS +		//------------------------------------------------- + +		LLStartUp::handleSocksProxy(); + +		//-------------------------------------------------  		// Init audio, which may be needed for prefs dialog  		// or audio cues in connection UI.  		//------------------------------------------------- @@ -807,6 +817,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()) +			{ +				// 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 +		{ +			LLProxy::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 @@ -2738,6 +2769,111 @@ void LLStartUp::setStartSLURL(const LLSLURL& slurl)      }  } +bool LLStartUp::handleSocksProxy() +{ +	std::string httpProxyType = gSavedSettings.getString("Socks5HttpProxyType"); + +	// Determine the HTTP proxy type (if any) +	if ((httpProxyType.compare("Web") == 0) && gSavedSettings.getBOOL("BrowserProxyEnabled")) +	{ +		LLHost http_host; +		http_host.setHostByName(gSavedSettings.getString("BrowserProxyAddress")); +		http_host.setPort(gSavedSettings.getS32("BrowserProxyPort")); +		LLProxy::getInstance()->enableHTTPProxy(http_host, LLPROXY_HTTP); +	} +	else if ((httpProxyType.compare("Socks") == 0) && gSavedSettings.getBOOL("Socks5ProxyEnabled")) +	{ +		LLHost socks_host; +		socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost")); +		socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort")); +		LLProxy::getInstance()->enableHTTPProxy(socks_host, LLPROXY_SOCKS); +	} +	else +	{ +		LLProxy::getInstance()->disableHTTPProxy(); +	} +	 +	bool use_socks_proxy = gSavedSettings.getBOOL("Socks5ProxyEnabled"); +	if (use_socks_proxy) +	{	 + +		// Determine and update LLProxy with the saved authentication system +		std::string auth_type = gSavedSettings.getString("Socks5AuthType"); + +		if (auth_type.compare("UserPass") == 0) +		{ +			LLPointer<LLCredential> socks_cred = gSecAPIHandler->loadCredential("SOCKS5"); +			std::string socks_user = socks_cred->getIdentifier()["username"].asString(); +			std::string socks_password = socks_cred->getAuthenticator()["creds"].asString(); +			LLProxy::getInstance()->setAuthPassword(socks_user, socks_password); +		} +		else if (auth_type.compare("None") == 0) +		{ +			LLProxy::getInstance()->setAuthNone(); +		} +		else +		{ +			// Unknown or missing setting. +			gSavedSettings.setString("Socks5AuthType", "None"); + +			// Clear the SOCKS credentials. +			LLPointer<LLCredential> socks_cred = new LLCredential("SOCKS5"); +			gSecAPIHandler->deleteCredential(socks_cred); + +			LLProxy::getInstance()->setAuthNone(); +		} + +		// Start the proxy and check for errors +		// If status != SOCKS_OK, stopProxy() will already have been called when startProxy() returns. +		int status = LLProxy::getInstance()->startProxy(gSavedSettings.getString("Socks5ProxyHost"), gSavedSettings.getU32("Socks5ProxyPort")); +		LLSD subs; +		subs["HOST"] = gSavedSettings.getString("Socks5ProxyHost"); +		subs["PORT"] = (S32)gSavedSettings.getU32("Socks5ProxyPort"); + +		std::string error_string; + +		switch(status) +		{ +			case SOCKS_OK: +				return true; +				break; + +			case SOCKS_CONNECT_ERROR: // TCP Fail +				error_string = "SOCKS_CONNECT_ERROR"; +				break; + +			case SOCKS_NOT_PERMITTED: // SOCKS 5 server rule set refused connection +				error_string = "SOCKS_NOT_PERMITTED"; +				break; +					 +			case SOCKS_NOT_ACCEPTABLE: // Selected authentication is not acceptable to server +				error_string = "SOCKS_NOT_ACCEPTABLE"; +				break; + +			case SOCKS_AUTH_FAIL: // Authentication failed +				error_string = "SOCKS_AUTH_FAIL"; +				break; + +			case SOCKS_UDP_FWD_NOT_GRANTED: // UDP forward request failed +				error_string = "SOCKS_UDP_FWD_NOT_GRANTED"; +				break; + +			case SOCKS_HOST_CONNECT_FAILED: // Failed to open a TCP channel to the socks server +				error_string = "SOCKS_HOST_CONNECT_FAILED"; +				break; +		} + +		LLNotificationsUtil::add(error_string, subs); +		return false; +	} +	else +	{ +		LLProxy::getInstance()->stopProxy(); // ensure no UDP proxy is running and it's 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..7292e4d68c 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(); // Initialize the SOCKS 5 proxy +  private:  	static LLSLURL sStartSLURL; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 6ae8e79be4..068dddfbb9 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -232,6 +232,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("postcard", "floater_postcard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostcard>);  	LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>); +	LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceProxy>);  	LLFloaterReg::add("prefs_hardware_settings", "floater_hardware_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHardwareSettings>);  	LLFloaterReg::add("perm_prefs", "floater_perm_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPerms>);  	LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>); diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index bd1d2ed7a7..7683d4feb5 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -41,6 +41,8 @@  #include "llappviewer.h"  #include "lltrans.h" +#include "llproxy.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,18 +309,9 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)  	}  	mErrorCert = NULL; -	if (gSavedSettings.getBOOL("BrowserProxyEnabled")) -	{ -		mProxyAddress = gSavedSettings.getString("BrowserProxyAddress"); -		S32 port = gSavedSettings.getS32 ( "BrowserProxyPort" ); - -		// tell curl about the settings -		mCurlRequest->setoptString(CURLOPT_PROXY, mProxyAddress); -		mCurlRequest->setopt(CURLOPT_PROXYPORT, port); -		mCurlRequest->setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP); -	} +	LLProxy::getInstance()->applyProxySettings(mCurlRequest); -//	mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // usefull for debugging +//	mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // useful for debugging  	mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);  	mCurlRequest->setWriteCallback(&curlDownloadCallback, (void*)this);  	BOOL vefifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert"); 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..020ee52c18 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml @@ -0,0 +1,273 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + height="500" + layout="topleft" + name="Proxy Settings Floater" + help_topic="proxy_settings_floater" + title="Proxy Settings" + width="500"> +	<check_box +	 control_name="BrowserProxyEnabled" +	 top="38" +	 enabled="true" +	 follows="left|top" +	 height="14" +	 initial_value="false" +	 commit_callback.function="Proxy.Change" +	 label="Use HTTP Proxy for Web pages" +	 left="22" +	 mouse_opaque="true" +	 name="web_proxy_enabled" +	 radio_style="false" +	 width="400" +	 top_pad="5" /> +	<text +	 type="string" +	 length="1" +	 follows="left|top" +	 height="10" +	 left_delta="23" +	 layout="topleft" +	 name="Proxy location" +	 top_pad="10" +	 width="300"> +	    HTTP Proxy: +	</text> +	<line_editor +	 control_name="BrowserProxyAddress" +	 enabled_control="BrowserProxyEnabled" +	 follows="left|top" +	 font="SansSerif" +	 height="23" +	 layout="topleft" +	 left_delta="0" +	 name="web_proxy_editor" +	 tool_tip="The DNS name or IP address of the HTTP proxy you would like to use." +	 top_pad="4" +	 width="200" /> +	<spinner +	 control_name="BrowserProxyPort" +	 enabled_control="BrowserProxyEnabled" +     decimal_digits="0" +	 follows="left|top" +	 height="23" +	 increment="1" +	 initial_value="80" +	 label="Port number:" +	 label_width="95" +	 layout="topleft" +	 left_delta="210" +	 max_val="12000" +	 min_val="10" +	 name="web_proxy_port" +	 top_delta="0" +	 tool_tip="The port of the HTTP proxy you would like to use." +	 width="145" /> +	<check_box +	 control_name="Socks5ProxyEnabled" +	 height="16" +	 label="Use SOCKS 5 Proxy for UDP traffic" +	 layout="topleft" +	 left="22" +	 name="socks_proxy_enabled" +	 top_pad="32" +	 width="256" +	 commit_callback.function="Proxy.Change" /> +	<text +	 type="string" +	 length="1" +	 follows="left|top" +	 height="10" +	 layout="topleft" +	 left_delta="23" +	 name="Proxy location" +	 top_pad="10" +	 width="300"> +	    SOCKS 5 Proxy: +	</text> +	<line_editor +	 control_name="Socks5ProxyHost" +	 enabled_control="Socks5ProxyEnabled" +	 follows="left|top" +	 font="SansSerif" +	 height="23" +	 layout="topleft" +	 left_delta="0" +	 name="socks_proxy_editor" +	 tool_tip="The DNS name or IP address of the SOCKS 5 proxy you would like to use." +	 top_pad="4" +	 width="200" +	 commit_callback.function="Proxy.Change" /> +	<spinner +	 control_name="Socks5ProxyPort" +	 enabled_control="Socks5ProxyEnabled" +	 decimal_digits="0" +	 follows="left|top" +	 height="23" +	 increment="1" +	 initial_value="80" +	 label="Port number:" +	 label_width="95" +	 layout="topleft" +	 left_delta="210" +	 max_val="12000" +	 min_val="10" +	 name="socks_proxy_port" +	 top_delta="0" +	 width="145" +	 tool_tip="The port of the SOCKS 5 proxy you would like to use." +	 commit_callback.function="Proxy.Change" /> +	<text +	 type="string" +	 length="1" +	 follows="left|top" +	 height="10" +	 layout="topleft" +	 left="40" +	 name="Proxy location" +	 top_pad="15" +	 width="300"> +	    SOCKS Authentication: +	</text> +	<radio_group +	 control_name="Socks5AuthType" +	 enabled_control="Socks5ProxyEnabled" +	 height="50" +	 layout="topleft" +	 name="socks5_auth_type" +	 top_pad="10" +	 width="120" +	 border="1" +	 commit_callback.function="Proxy.Change" > +		<radio_item +		 height="16" +		 label="No Authentication" +		 layout="topleft" +		 name="Socks5NoAuth" +		 value="None" +		 tool_tip="Socks5 proxy requires no authentication." +		 width="120" /> +		<radio_item +		 height="16" +		 label="Username/Password" +		 layout="topleft" +		 name="Socks5UserPass" +		 value="UserPass" +		 tool_tip="Socks5 proxy requires username/password authentication." +		 width="120" /> +	</radio_group> +	<text +	 type="string" +	 length="1" +	 follows="left|top" +	 height="10" +	 layout="topleft" +	 left_delta="20" +	 top_delta="50" +	 width="200"> +	    Username: +	</text> +	<text +	 type="string" +	 length="1" +	 follows="left|top" +	 height="10" +	 left_pad="15" +	 layout="topleft" +	 width="200"> +	    Password: +	</text> +	<line_editor +	 follows="left|top" +	 font="SansSerif" +	 height="23" +	 layout="topleft" +	 left="60" +	 name="socks5_username" +	 tool_tip="The username used to authenticate with your SOCKS 5 server" +	 top_pad="4" +	 width="200" +	 commit_callback.function="Proxy.Change" /> +	<line_editor +	 follows="left|top" +	 font="SansSerif" +	 height="23" +	 layout="topleft" +	 left_pad="15" +	 name="socks5_password" +	 tool_tip="The password used to authenticate with your SOCKS 5 server" +	 top_delta="0" +	 width="200" +	 is_password="true" +	 commit_callback.function="Proxy.Change" /> +	<text +	 type="string" +	 length="1" +	 follows="left|top" +	 height="10" +	 layout="topleft" +	 left="25" +	 name="Proxy location" +	 top_pad="18" +	 width="300"> +	   Other HTTP traffic proxy: +	</text> +	<radio_group +	 control_name="Socks5HttpProxyType" +	 height="60" +	 layout="topleft" +	 top_pad="9" +	 width="120" +	 border="1" +	 left_delta="15"  +	 commit_callback.function="Proxy.Change" > +		<radio_item +		 height="16" +		 label="Do not proxy" +		 layout="topleft" +		 value="None" +		 width="120" +		 tool_tip="Non-web HTTP traffic will NOT be sent to any proxy."/> +		<radio_item +		 height="16" +		 label="Use HTTP Proxy" +		 layout="topleft" +		 value="Web" +		 width="120" +		 enabled_control="BrowserProxyEnabled" +		 tool_tip="Non-web HTTP will be sent through the configured Web proxy." /> +		<radio_item +		 height="16" +		 label="Use SOCKS 5 Proxy" +		 layout="topleft" +		 value="Socks" +		 width="120" +		 enabled_control="Socks5ProxyEnabled" +		 tool_tip="Non-web HTTP traffic will be sent through the configured Socks 5 proxy."/> +	</radio_group> +	<button +	 follows="left|top" +	 height="22" +	 label="OK" +	 label_selected="OK" +	 layout="topleft" +	 left="282" +	 name="OK" +	 top_pad="36" +	 width="90" +	 commit_callback.function="Proxy.OK" /> +	<button +	 follows="left|top" +	 height="22" +	 label="Cancel" +	 label_selected="Cancel" +	 layout="topleft" +	 left_pad="10" +	 name="Cancel" +	 top_delta="0" +	 width="90" +	 commit_callback.function="Proxy.Cancel" /> +	  +	  +</floater> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 661165069e..78685dbd79 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -7143,6 +7143,83 @@ Click and drag anywhere on the world to rotate your view    </notification>    <notification +   icon="alertmodal.tga" +   name="SOCKS_NOT_PERMITTED" +   type="alertmodal"> +	The SOCKS 5 proxy "[HOST]:[PORT]" refused the connection, not allowed by rule set +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="SOCKS_CONNECT_ERROR" +   type="alertmodal"> +	The SOCKS 5 proxy "[HOST]:[PORT]" refused the connection, could not open TCP channel +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/>	  +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="SOCKS_NOT_ACCEPTABLE" +   type="alertmodal"> +	The SOCKS 5 proxy "[HOST]:[PORT]" refused the selected authentication system +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="SOCKS_AUTH_FAIL" +   type="alertmodal"> +	The SOCKS 5 proxy "[HOST]:[PORT]" reported your credentials are invalid +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="SOCKS_UDP_FWD_NOT_GRANTED" +   type="alertmodal"> +	The SOCKS 5 proxy "[HOST]:[PORT]" refused the UDP associate request +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="SOCKS_HOST_CONNECT_FAILED" +   type="alertmodal"> +	Could not connect to SOCKS 5 proxy server "[HOST]:[PORT]" +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="ChangeSocks5Settings" +   type="alert"> +	SOCKS 5 proxy settings take effect after you restart [APP_NAME]. +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification    name="AuthRequest"    type="browser">  The site at '<nolink>[HOST_NAME]</nolink>' in realm '[REALM]' requires a user name and password. diff --git a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml index 9e70706603..beea53437a 100644 --- a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml +++ b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml @@ -52,7 +52,7 @@               multi_select="true"               name="list_attachments"               top="0" -             width="311"/> +			 width="311" />          </accordion_tab>          <accordion_tab           layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index 30be5bc853..47236c1a48 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -139,7 +139,7 @@       height="16"       label="Add datestamp to log file name."       layout="topleft" -     left_detla="5" +     left_delta="5"       name="logfile_name_datestamp"       top_pad="10"       width="350"/> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index e639f0dc9d..a7078ce2e1 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -70,7 +70,7 @@     layout="topleft"     left="77"     name="connection_port_enabled" -   top_pad="20" +   top_pad="10"     width="256">      <check_box.commit_callback       function="Notification.Show" @@ -79,7 +79,7 @@    <spinner     control_name="ConnectionPort"     enabled_control="ConnectionPortEnabled" - decimal_digits="0" +   decimal_digits="0"     follows="left|top"     height="23"     increment="1" @@ -195,60 +195,6 @@      name="media_popup_enabled"      width="400"                 top_pad="5"/> -  <check_box -    top_delta="4" -    enabled="true" -    follows="left|top" -    height="14" -    initial_value="false" -    control_name="BrowserProxyEnabled" -    label="Enable Web Proxy" -    left_delta="0" -    mouse_opaque="true" -    name="web_proxy_enabled" -    radio_style="false" -    width="400"           top_pad="5"/> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="10" -   layout="topleft" -   left_delta="20" -   name="Proxy location" -   top_delta="16" -   width="300"> -    Proxy location: -  </text> -  <line_editor -   control_name="BrowserProxyAddress" -   enabled_control="BrowserProxyEnabled" - follows="left|top" -   font="SansSerif" -   height="23" -   layout="topleft" -   left_delta="0" -   name="web_proxy_editor" -   tool_tip="The name or IP address of the proxy you would like to use" -   top_pad="4" -   width="200" /> -  <spinner -   control_name="BrowserProxyPort" -   enabled_control="BrowserProxyEnabled" - decimal_digits="0" -   follows="left|top" -   height="23" -   increment="1" -   initial_value="80" -   label="Port number:" -   label_width="95" -   layout="topleft" -   left_delta="210" -   max_val="12000" -   min_val="10" -   name="web_proxy_port" -   top_delta="0" -   width="145" />    <text       type="string"       length="1" @@ -286,4 +232,31 @@           name="Install_manual"           value="0" />    </combo_box> +  <text +     type="string" +     length="1" +     follows="left|top" +     height="10" +     layout="topleft" +     left="30" +     name="Proxy Settings:" +     mouse_opaque="false" +     top_pad="5" +     width="300"> +		Proxy Settings: +  </text> +  <button +	label="Adjust proxy settings" +    follows="left|top" +    height="23" +	width="140"  +    label_selected="Browse" +    layout="topleft" +    left_delta="50" +    name="set_proxy" +    top_pad="5" +    > +		<button.commit_callback +		  function="Pref.Proxy" /> +  </button>  </panel> | 
