diff options
| -rw-r--r-- | indra/llmessage/llcurl.cpp | 125 | ||||
| -rw-r--r-- | indra/llmessage/llcurl.h | 103 | ||||
| -rw-r--r-- | indra/llmessage/llhttpassetstorage.cpp | 5 | ||||
| -rw-r--r-- | indra/llmessage/llhttpclient.cpp | 5 | ||||
| -rw-r--r-- | indra/llmessage/llproxy.cpp | 88 | ||||
| -rw-r--r-- | indra/llmessage/llproxy.h | 10 | ||||
| -rw-r--r-- | indra/llmessage/llurlrequest.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llxmlrpctransaction.cpp | 20 | 
8 files changed, 217 insertions, 141 deletions
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index a7ce4310c1..2b6d3e5dc4 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -46,8 +46,8 @@  #endif  #include "llbufferstream.h" -#include "llsdserialize.h"  #include "llproxy.h" +#include "llsdserialize.h"  #include "llstl.h"  #include "llthread.h"  #include "lltimer.h" @@ -216,73 +216,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; @@ -537,25 +470,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,  	setopt(CURLOPT_NOSIGNAL, 1);  	// Set the CURL options for either Socks or HTTP proxy -	if (LLProxy::getInstance()->isHTTPProxyEnabled()) -	{ -		std::string address = LLProxy::getInstance()->getHTTPProxy().getIPString(); -		U16 port = LLProxy::getInstance()->getHTTPProxy().getPort(); -		setoptString(CURLOPT_PROXY, address.c_str()); -		setopt(CURLOPT_PROXYPORT, port); -		if (LLProxy::getInstance()->getHTTPProxyType() == LLPROXY_SOCKS) -		{ -			setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); -			if (LLProxy::getInstance()->getSelectedAuthMethod() == METHOD_PASSWORD) -			{ -				setoptString(CURLOPT_PROXYUSERPWD, LLProxy::getInstance()->getProxyUserPwdCURL()); -			} -		} -		else -		{ -			setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP); -		} -	} +	LLProxy::getInstance()->applyProxySettings(this);  	mOutput.reset(new LLBufferArray);  	setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback); @@ -602,40 +517,6 @@ void LLCurl::Easy::prepRequest(const std::string& url,  //////////////////////////////////////////////////////////////////////////// -class LLCurl::Multi -{ -	LOG_CLASS(Multi); -public: -	 -	Multi(); -	~Multi(); - -	Easy* allocEasy(); -	bool addEasy(Easy* easy); -	 -	void removeEasy(Easy* easy); - -	S32 process(); -	S32 perform(); -	 -	CURLMsg* info_read(S32* msgs_in_queue); - -	S32 mQueued; -	S32 mErrorCount; -	 -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()  	: mQueued(0),  	  mErrorCount(0) @@ -981,6 +862,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 4ce3fa1078..5dd894d9b8 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -184,6 +184,106 @@ 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 +{ +	LOG_CLASS(Multi); +public: + +	Multi(); +	~Multi(); + +	Easy* allocEasy(); +	bool addEasy(Easy* easy); + +	void removeEasy(Easy* easy); + +	S32 process(); +	S32 perform(); + +	CURLMsg* info_read(S32* msgs_in_queue); + +	S32 mQueued; +	S32 mErrorCount; + +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 +350,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/llproxy.cpp b/indra/llmessage/llproxy.cpp index 11a5c480f0..6040472cba 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -28,9 +28,12 @@  #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" @@ -65,6 +68,10 @@ 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(mSOCKSAddrStrings.begin(), mSOCKSAddrStrings.end(), DeletePointerArray());  }  // Perform a SOCKS 5 authentication and UDP association to the proxy @@ -223,6 +230,11 @@ void LLProxy::setAuthPassword(const std::string &username, const std::string &pa  	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()); +	mSOCKSAuthStrings.push_back(curl_auth_string);  }  void LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type) @@ -230,6 +242,11 @@ void LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type)  	sHTTPProxyEnabled = true;  	mHTTPProxy        = httpHost;  	mProxyType        = type; + +	U32 size = httpHost.getIPString().length() + 1; +	char* socks_addr_string = new char[size]; +	strncpy(socks_addr_string, httpHost.getIPString().c_str(), size); +	mSOCKSAddrStrings.push_back(socks_addr_string);  }  //static @@ -238,6 +255,77 @@ void LLProxy::cleanupClass()  	LLProxy::getInstance()->stopProxy();  } +// Apply proxy settings to CuRL request if either type of HTTP proxy is enabled. +void LLProxy::applyProxySettings(LLCurl::Easy* handle) +{ +	if (LLProxy::getInstance()->isHTTPProxyEnabled()) +	{ +		std::string address = LLProxy::getInstance()->getHTTPProxy().getIPString(); +		U16 port = LLProxy::getInstance()->getHTTPProxy().getPort(); +		handle->setoptString(CURLOPT_PROXY, address.c_str()); +		handle->setopt(CURLOPT_PROXYPORT, port); +		if (LLProxy::getInstance()->getHTTPProxyType() == LLPROXY_SOCKS) +		{ +			handle->setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); +			if (LLProxy::getInstance()->getSelectedAuthMethod() == METHOD_PASSWORD) +			{ +				handle->setoptString(CURLOPT_PROXYUSERPWD, LLProxy::getInstance()->getProxyUserPwdCURL()); +			} +		} +		else +		{ +			handle->setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP); +		} +	} +} + +void LLProxy::applyProxySettings(LLCurlEasyRequest* handle) +{ +	if (LLProxy::getInstance()->isHTTPProxyEnabled()) +	{ +		std::string address = LLProxy::getInstance()->getHTTPProxy().getIPString(); +		U16 port = LLProxy::getInstance()->getHTTPProxy().getPort(); +		handle->setoptString(CURLOPT_PROXY, address.c_str()); +		handle->setopt(CURLOPT_PROXYPORT, port); +		if (LLProxy::getInstance()->getHTTPProxyType() == LLPROXY_SOCKS) +		{ +			handle->setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); +			if (LLProxy::getInstance()->getSelectedAuthMethod() == METHOD_PASSWORD) +			{ +				handle->setoptString(CURLOPT_PROXYUSERPWD, LLProxy::getInstance()->getProxyUserPwdCURL()); +			} +		} +		else +		{ +			handle->setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP); +		} +	} +} + +void LLProxy::applyProxySettings(CURL* handle) +{ +	if (LLProxy::getInstance()->isHTTPProxyEnabled()) +	{ +		check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, mSOCKSAddrStrings.back())); + +		U16 port = LLProxy::getInstance()->getHTTPProxy().getPort(); +		check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, port)); + +		if (LLProxy::getInstance()->getHTTPProxyType() == LLPROXY_SOCKS) +		{ +			check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5)); +			if (LLProxy::getInstance()->getSelectedAuthMethod() == 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)  { diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h index cf2dfdc60e..7d1431a4b3 100644 --- a/indra/llmessage/llproxy.h +++ b/indra/llmessage/llproxy.h @@ -27,6 +27,7 @@  #ifndef LL_PROXY_H  #define LL_PROXY_H +#include "llcurl.h"  #include "llhost.h"  #include "lliosocket.h"  #include "llmemory.h" @@ -211,6 +212,11 @@ public:  	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 @@ -242,6 +248,10 @@ private:  	// SOCKS 5 password  	std::string mSocksPassword; +	// Vectors to store valid pointers to string options that have been passed to CURL requests. +	std::vector<char*> mSOCKSAuthStrings; +	std::vector<char*> mSOCKSAddrStrings; +  	// APR pool for the socket  	apr_pool_t* mPool;  }; diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 28bd09fc4c..6fe9dce7d3 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" @@ -415,6 +416,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/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index c88e829527..fe5ceea81d 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -309,25 +309,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)  	}  	mErrorCert = NULL; -	if (LLProxy::getInstance()->isHTTPProxyEnabled()) -	{ -		std::string address = LLProxy::getInstance()->getHTTPProxy().getIPString(); -		U16 port = LLProxy::getInstance()->getHTTPProxy().getPort(); -		mCurlRequest->setoptString(CURLOPT_PROXY, address.c_str()); -		mCurlRequest->setopt(CURLOPT_PROXYPORT, port); -		if (LLProxy::getInstance()->getHTTPProxyType() == LLPROXY_SOCKS) -		{ -			mCurlRequest->setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); -			if (LLProxy::getInstance()->getSelectedAuthMethod()==METHOD_PASSWORD) -			{ -				mCurlRequest->setoptString(CURLOPT_PROXYUSERPWD,LLProxy::getInstance()->getProxyUserPwdCURL()); -			} -		} -		else -		{ -			mCurlRequest->setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP); -		} -	} +	LLProxy::getInstance()->applyProxySettings(mCurlRequest);  //	mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // useful for debugging  	mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);  | 
