Always set proxy settings for every HTTP curl connection.
Move applyProxySettings to CurlEasyRequest and call it from applyDefaultOptions. Use AIThreadSafe for LLProxy for a more robust threadsafeness. (This forces correct locking, checks that the unshared vars are indeed unshared and made it easy to use read/write locking, which might be important in this case (we do a lot of read-only accesses to it).
This commit is contained in:
@@ -805,6 +805,39 @@ static int curl_debug_callback(CURL*, curl_infotype infotype, char* buf, size_t
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void CurlEasyRequest::applyProxySettings(void)
|
||||||
|
{
|
||||||
|
LLProxy& proxy = *LLProxy::getInstance();
|
||||||
|
|
||||||
|
// Do a faster unlocked check to see if we are supposed to proxy.
|
||||||
|
if (proxy.HTTPProxyEnabled())
|
||||||
|
{
|
||||||
|
// We think we should proxy, read lock the shared proxy members.
|
||||||
|
LLProxy::Shared_crat proxy_r(proxy.shared_lockobj());
|
||||||
|
|
||||||
|
// Now test again to verify that the proxy wasn't disabled between the first check and the lock.
|
||||||
|
if (proxy.HTTPProxyEnabled())
|
||||||
|
{
|
||||||
|
setopt(CURLOPT_PROXY, proxy.getHTTPProxy(proxy_r).getIPString().c_str());
|
||||||
|
setopt(CURLOPT_PROXYPORT, proxy.getHTTPProxy(proxy_r).getPort());
|
||||||
|
|
||||||
|
if (proxy.getHTTPProxyType(proxy_r) == LLPROXY_SOCKS)
|
||||||
|
{
|
||||||
|
setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
|
||||||
|
if (proxy.getSelectedAuthMethod(proxy_r) == METHOD_PASSWORD)
|
||||||
|
{
|
||||||
|
std::string auth_string = proxy.getSocksUser(proxy_r) + ":" + proxy.getSocksPwd(proxy_r);
|
||||||
|
setopt(CURLOPT_PROXYUSERPWD, auth_string.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CurlEasyRequest::applyDefaultOptions(void)
|
void CurlEasyRequest::applyDefaultOptions(void)
|
||||||
{
|
{
|
||||||
CertificateAuthority_rat CertificateAuthority_r(gCertificateAuthority);
|
CertificateAuthority_rat CertificateAuthority_r(gCertificateAuthority);
|
||||||
@@ -822,7 +855,7 @@ void CurlEasyRequest::applyDefaultOptions(void)
|
|||||||
// The old code did this for the 'buffered' version, but I think it's nonsense.
|
// The old code did this for the 'buffered' version, but I think it's nonsense.
|
||||||
//setopt(CURLOPT_DNS_CACHE_TIMEOUT, 0);
|
//setopt(CURLOPT_DNS_CACHE_TIMEOUT, 0);
|
||||||
// Set the CURL options for either Socks or HTTP proxy.
|
// Set the CURL options for either Socks or HTTP proxy.
|
||||||
LLProxy::getInstance()->applyProxySettings(this);
|
applyProxySettings();
|
||||||
Debug(
|
Debug(
|
||||||
if (dc::curl.is_on())
|
if (dc::curl.is_on())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -176,6 +176,10 @@ class CurlEasyRequest : public CurlEasyHandle {
|
|||||||
// Reset everything to the state it was in when this object was just created.
|
// Reset everything to the state it was in when this object was just created.
|
||||||
void resetState(void);
|
void resetState(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Called from applyDefaultOptions.
|
||||||
|
void applyProxySettings(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Set default options that we want applied to all curl easy handles.
|
// Set default options that we want applied to all curl easy handles.
|
||||||
void applyDefaultOptions(void);
|
void applyDefaultOptions(void);
|
||||||
|
|||||||
@@ -47,23 +47,22 @@ static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataou
|
|||||||
static LLSocket::ptr_t tcp_open_channel(LLHost host); // Open a TCP channel to a given host
|
static LLSocket::ptr_t tcp_open_channel(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 void tcp_close_channel(LLSocket::ptr_t* handle_ptr); // Close an open TCP channel
|
||||||
|
|
||||||
LLProxy::LLProxy():
|
ProxyShared::ProxyShared(void):
|
||||||
mHTTPProxyEnabled(false),
|
|
||||||
mProxyMutex(),
|
|
||||||
mUDPProxy(),
|
|
||||||
mTCPProxy(),
|
|
||||||
mHTTPProxy(),
|
|
||||||
mProxyType(LLPROXY_SOCKS),
|
mProxyType(LLPROXY_SOCKS),
|
||||||
mAuthMethodSelected(METHOD_NOAUTH),
|
mAuthMethodSelected(METHOD_NOAUTH)
|
||||||
mSocksUsername(),
|
{
|
||||||
mSocksPassword()
|
}
|
||||||
|
|
||||||
|
LLProxy::LLProxy():
|
||||||
|
mHTTPProxyEnabled(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
LLProxy::~LLProxy()
|
LLProxy::~LLProxy()
|
||||||
{
|
{
|
||||||
stopSOCKSProxy();
|
stopSOCKSProxy();
|
||||||
disableHTTPProxy();
|
Shared_wat shared_w(mShared);
|
||||||
|
disableHTTPProxy(shared_w);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,15 +77,18 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
|
|||||||
{
|
{
|
||||||
S32 result;
|
S32 result;
|
||||||
|
|
||||||
|
Unshared_rat unshared_r(mUnshared);
|
||||||
|
Shared_rat shared_r(mShared);
|
||||||
|
|
||||||
/* SOCKS 5 Auth request */
|
/* SOCKS 5 Auth request */
|
||||||
socks_auth_request_t socks_auth_request;
|
socks_auth_request_t socks_auth_request;
|
||||||
socks_auth_response_t socks_auth_response;
|
socks_auth_response_t socks_auth_response;
|
||||||
|
|
||||||
socks_auth_request.version = SOCKS_VERSION; // SOCKS version 5
|
socks_auth_request.version = SOCKS_VERSION; // SOCKS version 5
|
||||||
socks_auth_request.num_methods = 1; // Sending 1 method.
|
socks_auth_request.num_methods = 1; // Sending 1 method.
|
||||||
socks_auth_request.methods = getSelectedAuthMethod(); // Send only the selected method.
|
socks_auth_request.methods = getSelectedAuthMethod(shared_r); // Send only the selected method.
|
||||||
|
|
||||||
result = tcp_blocking_handshake(mProxyControlChannel,
|
result = tcp_blocking_handshake(unshared_r->mProxyControlChannel,
|
||||||
static_cast<char*>(static_cast<void*>(&socks_auth_request)),
|
static_cast<char*>(static_cast<void*>(&socks_auth_request)),
|
||||||
sizeof(socks_auth_request),
|
sizeof(socks_auth_request),
|
||||||
static_cast<char*>(static_cast<void*>(&socks_auth_response)),
|
static_cast<char*>(static_cast<void*>(&socks_auth_response)),
|
||||||
@@ -109,8 +111,8 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
|
|||||||
if (socks_auth_response.method == METHOD_PASSWORD)
|
if (socks_auth_response.method == METHOD_PASSWORD)
|
||||||
{
|
{
|
||||||
// The server has requested a username/password combination
|
// The server has requested a username/password combination
|
||||||
std::string socks_username(getSocksUser());
|
std::string socks_username(getSocksUser(shared_r));
|
||||||
std::string socks_password(getSocksPwd());
|
std::string socks_password(getSocksPwd(shared_r));
|
||||||
U32 request_size = socks_username.size() + socks_password.size() + 3;
|
U32 request_size = socks_username.size() + socks_password.size() + 3;
|
||||||
char * password_auth = new char[request_size];
|
char * password_auth = new char[request_size];
|
||||||
password_auth[0] = 0x01;
|
password_auth[0] = 0x01;
|
||||||
@@ -121,7 +123,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
|
|||||||
|
|
||||||
authmethod_password_reply_t password_reply;
|
authmethod_password_reply_t password_reply;
|
||||||
|
|
||||||
result = tcp_blocking_handshake(mProxyControlChannel,
|
result = tcp_blocking_handshake(unshared_r->mProxyControlChannel,
|
||||||
password_auth,
|
password_auth,
|
||||||
request_size,
|
request_size,
|
||||||
static_cast<char*>(static_cast<void*>(&password_reply)),
|
static_cast<char*>(static_cast<void*>(&password_reply)),
|
||||||
@@ -157,7 +159,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
|
|||||||
// "If the client is not in possession of the information at the time of the UDP ASSOCIATE,
|
// "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"
|
// the client MUST use a port number and address of all zeros. RFC 1928"
|
||||||
|
|
||||||
result = tcp_blocking_handshake(mProxyControlChannel,
|
result = tcp_blocking_handshake(unshared_r->mProxyControlChannel,
|
||||||
static_cast<char*>(static_cast<void*>(&connect_request)),
|
static_cast<char*>(static_cast<void*>(&connect_request)),
|
||||||
sizeof(connect_request),
|
sizeof(connect_request),
|
||||||
static_cast<char*>(static_cast<void*>(&connect_reply)),
|
static_cast<char*>(static_cast<void*>(&connect_reply)),
|
||||||
@@ -176,10 +178,14 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
|
|||||||
return SOCKS_UDP_FWD_NOT_GRANTED;
|
return SOCKS_UDP_FWD_NOT_GRANTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order
|
{
|
||||||
mUDPProxy.setAddress(proxy.getAddress());
|
// Write acccess type and read access type are really the same, so unshared_w must be simply a reference.
|
||||||
|
Unshared_wat& unshared_w = unshared_r;
|
||||||
|
unshared_w->mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order
|
||||||
|
unshared_w->mUDPProxy.setAddress(proxy.getAddress());
|
||||||
|
}
|
||||||
// The connection was successful. We now have the UDP port to send requests that need forwarding to.
|
// 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;
|
LL_INFOS("Proxy") << "SOCKS 5 UDP proxy connected on " << unshared_r->mUDPProxy << LL_ENDL;
|
||||||
|
|
||||||
return SOCKS_OK;
|
return SOCKS_OK;
|
||||||
}
|
}
|
||||||
@@ -197,9 +203,11 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
|
|||||||
*/
|
*/
|
||||||
S32 LLProxy::startSOCKSProxy(LLHost host)
|
S32 LLProxy::startSOCKSProxy(LLHost host)
|
||||||
{
|
{
|
||||||
|
Unshared_wat unshared_w(mUnshared);
|
||||||
|
|
||||||
if (host.isOk())
|
if (host.isOk())
|
||||||
{
|
{
|
||||||
mTCPProxy = host;
|
unshared_w->mTCPProxy = host;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -209,13 +217,13 @@ S32 LLProxy::startSOCKSProxy(LLHost host)
|
|||||||
// Close any running SOCKS connection.
|
// Close any running SOCKS connection.
|
||||||
stopSOCKSProxy();
|
stopSOCKSProxy();
|
||||||
|
|
||||||
mProxyControlChannel = tcp_open_channel(mTCPProxy);
|
unshared_w->mProxyControlChannel = tcp_open_channel(unshared_w->mTCPProxy);
|
||||||
if (!mProxyControlChannel)
|
if (!unshared_w->mProxyControlChannel)
|
||||||
{
|
{
|
||||||
return SOCKS_HOST_CONNECT_FAILED;
|
return SOCKS_HOST_CONNECT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
S32 status = proxyHandshake(mTCPProxy);
|
S32 status = proxyHandshake(unshared_w->mTCPProxy);
|
||||||
|
|
||||||
if (status != SOCKS_OK)
|
if (status != SOCKS_OK)
|
||||||
{
|
{
|
||||||
@@ -246,14 +254,16 @@ void LLProxy::stopSOCKSProxy()
|
|||||||
// then we must shut down any HTTP proxy operations. But it is allowable if web
|
// then we must shut down any HTTP proxy operations. But it is allowable if web
|
||||||
// proxy is being used to continue proxying HTTP.
|
// proxy is being used to continue proxying HTTP.
|
||||||
|
|
||||||
if (LLPROXY_SOCKS == getHTTPProxyType())
|
Shared_rat shared_r(mShared);
|
||||||
|
if (LLPROXY_SOCKS == getHTTPProxyType(shared_r))
|
||||||
{
|
{
|
||||||
disableHTTPProxy();
|
Shared_wat shared_w(shared_r);
|
||||||
|
disableHTTPProxy(shared_w);
|
||||||
}
|
}
|
||||||
|
Unshared_wat unshared_w(mUnshared);
|
||||||
if (mProxyControlChannel)
|
if (unshared_w->mProxyControlChannel)
|
||||||
{
|
{
|
||||||
tcp_close_channel(&mProxyControlChannel);
|
tcp_close_channel(&unshared_w->mProxyControlChannel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,9 +272,7 @@ void LLProxy::stopSOCKSProxy()
|
|||||||
*/
|
*/
|
||||||
void LLProxy::setAuthNone()
|
void LLProxy::setAuthNone()
|
||||||
{
|
{
|
||||||
LLMutexLock lock(&mProxyMutex);
|
Shared_wat(mShared)->mAuthMethodSelected = METHOD_NOAUTH;
|
||||||
|
|
||||||
mAuthMethodSelected = METHOD_NOAUTH;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -288,11 +296,10 @@ bool LLProxy::setAuthPassword(const std::string &username, const std::string &pa
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLMutexLock lock(&mProxyMutex);
|
Shared_wat shared_w(mShared);
|
||||||
|
shared_w->mAuthMethodSelected = METHOD_PASSWORD;
|
||||||
mAuthMethodSelected = METHOD_PASSWORD;
|
shared_w->mSocksUsername = username;
|
||||||
mSocksUsername = username;
|
shared_w->mSocksPassword = password;
|
||||||
mSocksPassword = password;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -314,12 +321,10 @@ bool LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLMutexLock lock(&mProxyMutex);
|
Shared_wat shared_w(mShared);
|
||||||
|
|
||||||
mHTTPProxy = httpHost;
|
|
||||||
mProxyType = type;
|
|
||||||
|
|
||||||
mHTTPProxyEnabled = true;
|
mHTTPProxyEnabled = true;
|
||||||
|
shared_w->mHTTPProxy = httpHost;
|
||||||
|
shared_w->mProxyType = type;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -335,9 +340,8 @@ bool LLProxy::enableHTTPProxy()
|
|||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
|
|
||||||
LLMutexLock lock(&mProxyMutex);
|
Shared_rat shared_r(mShared);
|
||||||
|
ok = (shared_r->mHTTPProxy.isOk());
|
||||||
ok = (mHTTPProxy.isOk());
|
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
mHTTPProxyEnabled = true;
|
mHTTPProxyEnabled = true;
|
||||||
@@ -346,54 +350,6 @@ bool LLProxy::enableHTTPProxy()
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Disable the HTTP proxy.
|
|
||||||
*/
|
|
||||||
void LLProxy::disableHTTPProxy()
|
|
||||||
{
|
|
||||||
LLMutexLock lock(&mProxyMutex);
|
|
||||||
|
|
||||||
mHTTPProxyEnabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the currently selected HTTP proxy type
|
|
||||||
*/
|
|
||||||
LLHttpProxyType LLProxy::getHTTPProxyType() const
|
|
||||||
{
|
|
||||||
LLMutexLock lock(&mProxyMutex);
|
|
||||||
return mProxyType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the SOCKS 5 password.
|
|
||||||
*/
|
|
||||||
std::string LLProxy::getSocksPwd() const
|
|
||||||
{
|
|
||||||
LLMutexLock lock(&mProxyMutex);
|
|
||||||
return mSocksPassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the SOCKS 5 username.
|
|
||||||
*/
|
|
||||||
std::string LLProxy::getSocksUser() const
|
|
||||||
{
|
|
||||||
LLMutexLock lock(&mProxyMutex);
|
|
||||||
return mSocksUsername;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the currently selected SOCKS 5 authentication method.
|
|
||||||
*
|
|
||||||
* @return Returns either none or password.
|
|
||||||
*/
|
|
||||||
LLSocks5AuthType LLProxy::getSelectedAuthMethod() const
|
|
||||||
{
|
|
||||||
LLMutexLock lock(&mProxyMutex);
|
|
||||||
return mAuthMethodSelected;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stop the LLProxy and make certain that any APR pools and classes are deleted before terminating APR.
|
* @brief Stop the LLProxy and make certain that any APR pools and classes are deleted before terminating APR.
|
||||||
*
|
*
|
||||||
@@ -406,47 +362,6 @@ void LLProxy::cleanupClass()
|
|||||||
deleteSingleton();
|
deleteSingleton();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Apply proxy settings to a CuRL request if an HTTP proxy is enabled.
|
|
||||||
*
|
|
||||||
* This method has been designed to be safe to call from
|
|
||||||
* any thread in the viewer. This allows requests in the
|
|
||||||
* texture fetch thread to be aware of the proxy settings.
|
|
||||||
* When the HTTP proxy is enabled, the proxy mutex will
|
|
||||||
* be locked every time this method is called.
|
|
||||||
*
|
|
||||||
* @param curlEasyRequest_w An already locked curl easy handle, before it has been performed.
|
|
||||||
*/
|
|
||||||
void LLProxy::applyProxySettings(AICurlEasyRequest_wat const& curlEasyRequest_w)
|
|
||||||
{
|
|
||||||
// Do a faster unlocked check to see if we are supposed to proxy.
|
|
||||||
if (mHTTPProxyEnabled)
|
|
||||||
{
|
|
||||||
// We think we should proxy, lock the proxy mutex.
|
|
||||||
LLMutexLock lock(&mProxyMutex);
|
|
||||||
// Now test again to verify that the proxy wasn't disabled between the first check and the lock.
|
|
||||||
if (mHTTPProxyEnabled)
|
|
||||||
{
|
|
||||||
curlEasyRequest_w->setopt(CURLOPT_PROXY, mHTTPProxy.getIPString().c_str());
|
|
||||||
curlEasyRequest_w->setopt(CURLOPT_PROXYPORT, mHTTPProxy.getPort());
|
|
||||||
|
|
||||||
if (mProxyType == LLPROXY_SOCKS)
|
|
||||||
{
|
|
||||||
curlEasyRequest_w->setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
|
|
||||||
if (mAuthMethodSelected == METHOD_PASSWORD)
|
|
||||||
{
|
|
||||||
std::string auth_string = mSocksUsername + ":" + mSocksPassword;
|
|
||||||
curlEasyRequest_w->setopt(CURLOPT_PROXYUSERPWD, auth_string.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
curlEasyRequest_w->setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send one TCP packet and receive one in return.
|
* @brief Send one TCP packet and receive one in return.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include "llmemory.h"
|
#include "llmemory.h"
|
||||||
#include "llsingleton.h"
|
#include "llsingleton.h"
|
||||||
#include "llthread.h"
|
#include "llthread.h"
|
||||||
|
#include "aithreadsafe.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// SOCKS error codes returned from the StartProxy method
|
// SOCKS error codes returned from the StartProxy method
|
||||||
@@ -211,28 +212,87 @@ enum LLSocks5AuthType
|
|||||||
* To ensure thread safety, all LLProxy members that relate to the HTTP
|
* To ensure thread safety, all LLProxy members that relate to the HTTP
|
||||||
* proxy require the LLProxyMutex to be locked before accessing.
|
* proxy require the LLProxyMutex to be locked before accessing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct ProxyUnshared
|
||||||
|
{
|
||||||
|
/*###########################################################################################
|
||||||
|
MEMBERS READ AND WRITTEN ONLY IN THE MAIN THREAD.
|
||||||
|
###########################################################################################*/
|
||||||
|
|
||||||
|
// UDP proxy address and port
|
||||||
|
LLHost mUDPProxy;
|
||||||
|
|
||||||
|
// TCP proxy control channel address and port
|
||||||
|
LLHost mTCPProxy;
|
||||||
|
|
||||||
|
// socket handle to proxy TCP control channel
|
||||||
|
LLSocket::ptr_t mProxyControlChannel;
|
||||||
|
|
||||||
|
/*###########################################################################################
|
||||||
|
END OF UNSHARED MEMBERS
|
||||||
|
###########################################################################################*/
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ProxyShared
|
||||||
|
{
|
||||||
|
ProxyShared(void);
|
||||||
|
|
||||||
|
/*###########################################################################################
|
||||||
|
MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD.
|
||||||
|
###########################################################################################*/
|
||||||
|
|
||||||
|
// HTTP proxy address and port
|
||||||
|
LLHost mHTTPProxy;
|
||||||
|
|
||||||
|
// Currently selected HTTP proxy type. Can be web or socks.
|
||||||
|
LLHttpProxyType mProxyType;
|
||||||
|
|
||||||
|
// SOCKS 5 selected authentication method.
|
||||||
|
LLSocks5AuthType mAuthMethodSelected;
|
||||||
|
|
||||||
|
// SOCKS 5 username
|
||||||
|
std::string mSocksUsername;
|
||||||
|
// SOCKS 5 password
|
||||||
|
std::string mSocksPassword;
|
||||||
|
|
||||||
|
/*###########################################################################################
|
||||||
|
END OF SHARED MEMBERS
|
||||||
|
###########################################################################################*/
|
||||||
|
};
|
||||||
|
|
||||||
class LLProxy: public LLSingleton<LLProxy>
|
class LLProxy: public LLSingleton<LLProxy>
|
||||||
{
|
{
|
||||||
LOG_CLASS(LLProxy);
|
LOG_CLASS(LLProxy);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
typedef AISTAccessConst<ProxyUnshared> Unshared_crat; // Constant Read Access Type for Unshared (cannot be converted to write access).
|
||||||
|
typedef AISTAccess<ProxyUnshared> Unshared_rat; // Read Access Type for Unshared (same as write access type, since we don't lock at all).
|
||||||
|
typedef AISTAccess<ProxyUnshared> Unshared_wat; // Write Access Type, for Unshared.
|
||||||
|
typedef AIReadAccessConst<ProxyShared> Shared_crat; // Constant Read Access Type for Shared (cannot be converted to write access).
|
||||||
|
typedef AIReadAccess<ProxyShared> Shared_rat; // Read Access Type for Shared.
|
||||||
|
typedef AIWriteAccess<ProxyShared> Shared_wat; // Write Access Type for Shared.
|
||||||
|
|
||||||
/*###########################################################################################
|
/*###########################################################################################
|
||||||
METHODS THAT DO NOT LOCK mProxyMutex!
|
Public methods that only access variables not shared between threads.
|
||||||
###########################################################################################*/
|
###########################################################################################*/
|
||||||
// Constructor, cannot have parameters due to LLSingleton parent class. Call from main thread only.
|
// Constructor, cannot have parameters due to LLSingleton parent class. Call from main thread only.
|
||||||
LLProxy();
|
LLProxy();
|
||||||
|
|
||||||
// Static check for enabled status for UDP packets. Call from main thread only.
|
// Static check for enabled status for UDP packets. Called from main thread only.
|
||||||
static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; }
|
static bool isSOCKSProxyEnabled(void) { llassert(is_main_thread()); return sUDPProxyEnabled; }
|
||||||
|
|
||||||
// Get the UDP proxy address and port. Call from main thread only.
|
// Get the UDP proxy address and port. Called from main thread only.
|
||||||
LLHost getUDPProxy() const { return mUDPProxy; }
|
LLHost getUDPProxy(void) const { return Unshared_crat(mUnshared)->mUDPProxy; }
|
||||||
|
|
||||||
/*###########################################################################################
|
/*###########################################################################################
|
||||||
END OF NON-LOCKING METHODS
|
End of methods that only access variables not shared between threads.
|
||||||
###########################################################################################*/
|
###########################################################################################*/
|
||||||
|
|
||||||
|
// Return true if there is a good chance that the HTTP proxy is currently enabled.
|
||||||
|
bool HTTPProxyEnabled(void) const { return mHTTPProxyEnabled; }
|
||||||
|
|
||||||
/*###########################################################################################
|
/*###########################################################################################
|
||||||
METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
|
Public methods that access variables shared between threads.
|
||||||
###########################################################################################*/
|
###########################################################################################*/
|
||||||
// Destructor, closes open connections. Do not call directly, use cleanupClass().
|
// Destructor, closes open connections. Do not call directly, use cleanupClass().
|
||||||
~LLProxy();
|
~LLProxy();
|
||||||
@@ -263,30 +323,37 @@ public:
|
|||||||
bool enableHTTPProxy();
|
bool enableHTTPProxy();
|
||||||
|
|
||||||
// Stop proxying HTTP packets. Call from main thread only.
|
// Stop proxying HTTP packets. Call from main thread only.
|
||||||
void disableHTTPProxy();
|
// Note that this needs shared_w to be passed because we want the shared members to be locked when this is reset to false.
|
||||||
|
void disableHTTPProxy(Shared_wat const& shared_w) { mHTTPProxyEnabled = false; }
|
||||||
|
void disableHTTPProxy(void) { disableHTTPProxy(Shared_wat(mShared)); }
|
||||||
|
|
||||||
|
// Get the currently selected HTTP proxy address and port
|
||||||
|
LLHost const& getHTTPProxy(Shared_crat const& shared_r) const { return shared_r->mHTTPProxy; }
|
||||||
|
|
||||||
|
// Get the currently selected HTTP proxy type
|
||||||
|
LLHttpProxyType getHTTPProxyType(Shared_crat const& shared_r) const { return shared_r->mProxyType; }
|
||||||
|
|
||||||
|
// Get the currently selected auth method.
|
||||||
|
LLSocks5AuthType getSelectedAuthMethod(Shared_crat const& shared_r) const { return shared_r->mAuthMethodSelected; }
|
||||||
|
|
||||||
|
// SOCKS 5 username and password accessors.
|
||||||
|
std::string getSocksUser(Shared_crat const& shared_r) const { return shared_r->mSocksUsername; }
|
||||||
|
std::string getSocksPwd(Shared_crat const& shared_r) const { return shared_r->mSocksPassword; }
|
||||||
|
|
||||||
/*###########################################################################################
|
/*###########################################################################################
|
||||||
END OF LOCKING METHODS
|
End of methods that access variables shared between threads.
|
||||||
###########################################################################################*/
|
###########################################################################################*/
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*###########################################################################################
|
/*###########################################################################################
|
||||||
METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
|
Private methods that access variables shared between threads.
|
||||||
###########################################################################################*/
|
###########################################################################################*/
|
||||||
|
|
||||||
// Perform a SOCKS 5 authentication and UDP association with the proxy server.
|
// Perform a SOCKS 5 authentication and UDP association with the proxy server.
|
||||||
S32 proxyHandshake(LLHost proxy);
|
S32 proxyHandshake(LLHost proxy);
|
||||||
|
|
||||||
// Get the currently selected auth method.
|
|
||||||
LLSocks5AuthType getSelectedAuthMethod() const;
|
|
||||||
|
|
||||||
// Get the currently selected HTTP proxy type
|
|
||||||
LLHttpProxyType getHTTPProxyType() const;
|
|
||||||
|
|
||||||
std::string getSocksPwd() const;
|
|
||||||
std::string getSocksUser() const;
|
|
||||||
|
|
||||||
/*###########################################################################################
|
/*###########################################################################################
|
||||||
END OF LOCKING METHODS
|
End of methods that access variables shared between threads.
|
||||||
###########################################################################################*/
|
###########################################################################################*/
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -294,49 +361,16 @@ private:
|
|||||||
// Instead use enableHTTPProxy() and disableHTTPProxy() instead.
|
// Instead use enableHTTPProxy() and disableHTTPProxy() instead.
|
||||||
mutable LLAtomic32<bool> mHTTPProxyEnabled;
|
mutable LLAtomic32<bool> mHTTPProxyEnabled;
|
||||||
|
|
||||||
// Mutex to protect shared members in non-main thread calls to applyProxySettings().
|
|
||||||
mutable LLMutex mProxyMutex;
|
|
||||||
|
|
||||||
/*###########################################################################################
|
|
||||||
MEMBERS READ AND WRITTEN ONLY IN THE MAIN THREAD. DO NOT SHARE!
|
|
||||||
###########################################################################################*/
|
|
||||||
|
|
||||||
// Is the UDP proxy enabled?
|
// Is the UDP proxy enabled?
|
||||||
static bool sUDPProxyEnabled;
|
static bool sUDPProxyEnabled;
|
||||||
|
|
||||||
// UDP proxy address and port
|
AIThreadSafeSingleThreadDC<ProxyUnshared> mUnshared;
|
||||||
LLHost mUDPProxy;
|
AIThreadSafeDC<ProxyShared> mShared;
|
||||||
// TCP proxy control channel address and port
|
|
||||||
LLHost mTCPProxy;
|
|
||||||
|
|
||||||
// socket handle to proxy TCP control channel
|
public:
|
||||||
LLSocket::ptr_t mProxyControlChannel;
|
// For thread-safe read access. Use the _crat access types with these.
|
||||||
|
AIThreadSafeSingleThreadDC<ProxyUnshared> const& unshared_lockobj(void) const { return mUnshared; }
|
||||||
/*###########################################################################################
|
AIThreadSafeDC<ProxyShared> const& shared_lockobj(void) const { return mShared; }
|
||||||
END OF UNSHARED MEMBERS
|
|
||||||
###########################################################################################*/
|
|
||||||
|
|
||||||
/*###########################################################################################
|
|
||||||
MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD. ONLY READ OR WRITE AFTER LOCKING mProxyMutex!
|
|
||||||
###########################################################################################*/
|
|
||||||
|
|
||||||
// HTTP proxy address and port
|
|
||||||
LLHost mHTTPProxy;
|
|
||||||
|
|
||||||
// Currently selected HTTP proxy type. Can be web or socks.
|
|
||||||
LLHttpProxyType mProxyType;
|
|
||||||
|
|
||||||
// SOCKS 5 selected authentication method.
|
|
||||||
LLSocks5AuthType mAuthMethodSelected;
|
|
||||||
|
|
||||||
// SOCKS 5 username
|
|
||||||
std::string mSocksUsername;
|
|
||||||
// SOCKS 5 password
|
|
||||||
std::string mSocksPassword;
|
|
||||||
|
|
||||||
/*###########################################################################################
|
|
||||||
END OF SHARED MEMBERS
|
|
||||||
###########################################################################################*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user