summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llmessage/llcurl.cpp125
-rw-r--r--indra/llmessage/llcurl.h103
-rw-r--r--indra/llmessage/llhttpassetstorage.cpp5
-rw-r--r--indra/llmessage/llhttpclient.cpp5
-rw-r--r--indra/llmessage/llproxy.cpp88
-rw-r--r--indra/llmessage/llproxy.h10
-rw-r--r--indra/llmessage/llurlrequest.cpp2
-rw-r--r--indra/newview/llxmlrpctransaction.cpp20
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);