From 7717b6f647feb250c0b94d038f72a640a7888915 Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Tue, 28 Jun 2011 19:54:53 -0400 Subject: STORM-1112 More cleanup of SOCKS 5 proxy code. Renamed llsocks5.cpp to llproxy.cpp. --- indra/llmessage/llproxy.cpp | 294 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 indra/llmessage/llproxy.cpp (limited to 'indra/llmessage/llproxy.cpp') diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp new file mode 100644 index 0000000000..6bc9e8b62b --- /dev/null +++ b/indra/llmessage/llproxy.cpp @@ -0,0 +1,294 @@ +/** + * @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 + +#include "llapr.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); // Close an open TCP channel +static int 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) +{ +} + +LLProxy::~LLProxy() +{ + tcp_close_channel(mProxyControlChannel); + sUDPProxyEnabled = false; + sHTTPProxyEnabled = false; +} + +// Perform a SOCKS 5 authentication and UDP association to the proxy +// specified by proxy, and associate UDP port message_port +int LLProxy::proxyHandshake(LLHost proxy, U32 message_port) +{ + int 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) + { + llwarns << "SOCKS authentication request failed, error on TCP control channel : " << result << llendl; + stopProxy(); + return SOCKS_CONNECT_ERROR; + } + + if (socks_auth_response.method == AUTH_NOT_ACCEPTABLE) + { + llwarns << "SOCKS 5 server refused all our authentication methods" << llendl; + 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(authmethod_password_reply_t)); + delete[] password_auth; + + if (result != 0) + { + llwarns << "SOCKS authentication failed, error on TCP control channel : " << result << llendl; + stopProxy(); + return SOCKS_CONNECT_ERROR; + } + + if (password_reply.status != AUTH_SUCCESS) + { + llwarns << "SOCKS authentication failed" << llendl; + 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(socks_command_request_t), (char*)&connect_reply, sizeof(socks_command_response_t)); + if (result != 0) + { + llwarns << "SOCKS connect request failed, error on TCP control channel : " << result << llendl; + stopProxy(); + return SOCKS_CONNECT_ERROR; + } + + if (connect_reply.reply != REPLY_REQUEST_GRANTED) + { + //Something went wrong + llwarns << "Connection to SOCKS 5 server failed, UDP forward request not granted" << llendl; + stopProxy(); + return SOCKS_UDP_FWD_NOT_GRANTED; + } + + mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order + mUDPProxy.setAddress(proxy.getAddress()); + // All good now we have been given the UDP port to send requests that need forwarding. + llinfos << "SOCKS 5 UDP proxy connected on " << mUDPProxy << llendl; + return SOCKS_OK; +} + +int LLProxy::startProxy(std::string host, U32 port) +{ + mTCPProxy.setHostByName(host); + mTCPProxy.setPort(port); + + int 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) + { + sHTTPProxyEnabled = false; + } + + 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; +} + +void LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type) +{ + sHTTPProxyEnabled = true; + mHTTPProxy = httpHost; + mProxyType = type; +} + +static int 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_size_t expected_len = outlen; + + apr_socket_opt_set(apr_socket, APR_SO_NONBLOCK, -5); // Blocking connection, 5 second timeout + apr_socket_timeout_set(apr_socket, (APR_USEC_PER_SEC * 5)); + + rv = apr_socket_send(apr_socket, dataout, &outlen); + if (rv != APR_SUCCESS || expected_len != outlen) + { + llwarns << "Error sending data to proxy control channel" << llendl; + ll_apr_warn_status(rv); + return -1; + } + + expected_len = maxinlen; + do + { + rv = apr_socket_recv(apr_socket, datain, &maxinlen); + llinfos << "Receiving packets." << llendl; + llwarns << "Proxy control channel status: " << rv << llendl; + } while (APR_STATUS_IS_EAGAIN(rv)); + + if (rv != APR_SUCCESS) + { + llwarns << "Error receiving data from proxy control channel, status: " << rv << llendl; + llwarns << "Received " << maxinlen << " bytes." << llendl; + ll_apr_warn_status(rv); + return rv; + } + else if (expected_len != maxinlen) + { + llwarns << "Incorrect data received length in proxy control channel" << llendl; + return -1; + } + + return 0; +} + +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; +} + +static void tcp_close_channel(LLSocket::ptr_t handle) +{ + handle.reset(); +} -- cgit v1.2.3 From 975975029d7f248cdf917da670ffd6c6b98d40c1 Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Tue, 5 Jul 2011 16:55:43 -0400 Subject: STORM-1112 Fixed crash on quit. Other minor fixes: * Reordered HTTP proxy choices in settings dialog * Now using setBlocking and setNonBlocking LLSocket methods during TCP handshakes. * Made those LLSocket methods available outside the class. --- indra/llmessage/llproxy.cpp | 93 ++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 43 deletions(-) (limited to 'indra/llmessage/llproxy.cpp') diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index 6bc9e8b62b..6278751c31 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -45,9 +45,8 @@ 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); // Close an open TCP channel -static int tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen); // Do a TCP data handshake - +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), @@ -63,16 +62,16 @@ LLProxy::LLProxy(): LLProxy::~LLProxy() { - tcp_close_channel(mProxyControlChannel); + stopProxy(); sUDPProxyEnabled = false; sHTTPProxyEnabled = false; } // Perform a SOCKS 5 authentication and UDP association to the proxy // specified by proxy, and associate UDP port message_port -int LLProxy::proxyHandshake(LLHost proxy, U32 message_port) +S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) { - int result; + S32 result; /* SOCKS 5 Auth request */ socks_auth_request_t socks_auth_request; @@ -153,7 +152,6 @@ int LLProxy::proxyHandshake(LLHost proxy, U32 message_port) if (connect_reply.reply != REPLY_REQUEST_GRANTED) { - //Something went wrong llwarns << "Connection to SOCKS 5 server failed, UDP forward request not granted" << llendl; stopProxy(); return SOCKS_UDP_FWD_NOT_GRANTED; @@ -161,21 +159,21 @@ int LLProxy::proxyHandshake(LLHost proxy, U32 message_port) mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order mUDPProxy.setAddress(proxy.getAddress()); - // All good now we have been given the UDP port to send requests that need forwarding. + // The connection was successful. We now have the UDP port to send requests that need forwarding to. llinfos << "SOCKS 5 UDP proxy connected on " << mUDPProxy << llendl; return SOCKS_OK; } -int LLProxy::startProxy(std::string host, U32 port) +S32 LLProxy::startProxy(std::string host, U32 port) { mTCPProxy.setHostByName(host); mTCPProxy.setPort(port); - int status; + S32 status; if (mProxyControlChannel) { - tcp_close_channel(mProxyControlChannel); + tcp_close_channel(&mProxyControlChannel); } mProxyControlChannel = tcp_open_channel(mPool, mTCPProxy); @@ -200,9 +198,9 @@ 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 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) { @@ -211,7 +209,7 @@ void LLProxy::stopProxy() if (mProxyControlChannel) { - tcp_close_channel(mProxyControlChannel); + tcp_close_channel(&mProxyControlChannel); } } @@ -234,46 +232,53 @@ void LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type) mProxyType = type; } -static int tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen) +//static +void LLProxy::cleanupClass() { + LLProxy::getInstance()->stopProxy(); +} + +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_status_t rv = APR_SUCCESS; apr_size_t expected_len = outlen; - apr_socket_opt_set(apr_socket, APR_SO_NONBLOCK, -5); // Blocking connection, 5 second timeout - apr_socket_timeout_set(apr_socket, (APR_USEC_PER_SEC * 5)); + handle->setBlocking(1000); - rv = apr_socket_send(apr_socket, dataout, &outlen); - if (rv != APR_SUCCESS || expected_len != outlen) + rv = apr_socket_send(apr_socket, dataout, &outlen); + if (APR_SUCCESS != rv || expected_len != outlen) { llwarns << "Error sending data to proxy control channel" << llendl; ll_apr_warn_status(rv); - return -1; } - - expected_len = maxinlen; - do - { - rv = apr_socket_recv(apr_socket, datain, &maxinlen); - llinfos << "Receiving packets." << llendl; - llwarns << "Proxy control channel status: " << rv << llendl; - } while (APR_STATUS_IS_EAGAIN(rv)); - - if (rv != APR_SUCCESS) + else if (expected_len != outlen) { - llwarns << "Error receiving data from proxy control channel, status: " << rv << llendl; - llwarns << "Received " << maxinlen << " bytes." << llendl; - ll_apr_warn_status(rv); - return rv; + llwarns << "Error sending data to proxy control channel" << llendl; + rv = -1; } - else if (expected_len != maxinlen) + + if (APR_SUCCESS == rv) { - llwarns << "Incorrect data received length in proxy control channel" << llendl; - return -1; + expected_len = maxinlen; + rv = apr_socket_recv(apr_socket, datain, &maxinlen); + if (rv != APR_SUCCESS) + { + llwarns << "Error receiving data from proxy control channel, status: " << rv << llendl; + ll_apr_warn_status(rv); + } + else if (expected_len != maxinlen) + { + llwarns << "Received incorrect amount of data in proxy control channel" << llendl; + rv = -1; + } } - return 0; + handle->setNonBlocking(); + + return rv; } static LLSocket::ptr_t tcp_open_channel(apr_pool_t* pool, LLHost host) @@ -282,13 +287,15 @@ static LLSocket::ptr_t tcp_open_channel(apr_pool_t* pool, LLHost host) bool connected = socket->blockingConnect(host); if (!connected) { - tcp_close_channel(socket); + tcp_close_channel(&socket); } return socket; } -static void tcp_close_channel(LLSocket::ptr_t handle) +// Pass a pointer-to-pointer to avoid changing use_count(). +static void tcp_close_channel(LLSocket::ptr_t* handle_ptr) { - handle.reset(); + lldebugs << "Resetting proxy LLSocket handle, use_count == " << handle_ptr->use_count() << llendl; + handle_ptr->reset(); } -- cgit v1.2.3 From f630f997c0d1ceb52872304474160850c0abde72 Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Wed, 6 Jul 2011 18:49:22 -0400 Subject: Changed lllog messages in llproxy.cpp to new macros. --- indra/llmessage/llproxy.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'indra/llmessage/llproxy.cpp') diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index 6278751c31..0143803f2b 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -84,14 +84,14 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) result = tcp_handshake(mProxyControlChannel, (char*)&socks_auth_request, sizeof(socks_auth_request), (char*)&socks_auth_response, sizeof(socks_auth_response)); if (result != 0) { - llwarns << "SOCKS authentication request failed, error on TCP control channel : " << result << llendl; + 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) { - llwarns << "SOCKS 5 server refused all our authentication methods" << llendl; + LL_WARNS("Proxy") << "SOCKS 5 server refused all our authentication methods" << LL_ENDL; stopProxy(); return SOCKS_NOT_ACCEPTABLE; } @@ -115,14 +115,14 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) if (result != 0) { - llwarns << "SOCKS authentication failed, error on TCP control channel : " << result << llendl; + 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) { - llwarns << "SOCKS authentication failed" << llendl; + LL_WARNS("Proxy") << "SOCKS authentication failed" << LL_ENDL; stopProxy(); return SOCKS_AUTH_FAIL; } @@ -145,14 +145,14 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) result = tcp_handshake(mProxyControlChannel, (char*)&connect_request, sizeof(socks_command_request_t), (char*)&connect_reply, sizeof(socks_command_response_t)); if (result != 0) { - llwarns << "SOCKS connect request failed, error on TCP control channel : " << result << llendl; + 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) { - llwarns << "Connection to SOCKS 5 server failed, UDP forward request not granted" << llendl; + LL_WARNS("Proxy") << "Connection to SOCKS 5 server failed, UDP forward request not granted" << LL_ENDL; stopProxy(); return SOCKS_UDP_FWD_NOT_GRANTED; } @@ -160,7 +160,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) 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. - llinfos << "SOCKS 5 UDP proxy connected on " << mUDPProxy << llendl; + LL_INFOS("Proxy") << "SOCKS 5 UDP proxy connected on " << mUDPProxy << LL_ENDL; return SOCKS_OK; } @@ -251,12 +251,12 @@ static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outl rv = apr_socket_send(apr_socket, dataout, &outlen); if (APR_SUCCESS != rv || expected_len != outlen) { - llwarns << "Error sending data to proxy control channel" << llendl; + LL_WARNS("Proxy") << "Error sending data to proxy control channel" << LL_ENDL; ll_apr_warn_status(rv); } else if (expected_len != outlen) { - llwarns << "Error sending data to proxy control channel" << llendl; + LL_WARNS("Proxy") << "Error sending data to proxy control channel" << LL_ENDL; rv = -1; } @@ -266,12 +266,12 @@ static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outl rv = apr_socket_recv(apr_socket, datain, &maxinlen); if (rv != APR_SUCCESS) { - llwarns << "Error receiving data from proxy control channel, status: " << rv << llendl; + LL_WARNS("Proxy") << "Error receiving data from proxy control channel, status: " << rv << LL_ENDL; ll_apr_warn_status(rv); } else if (expected_len != maxinlen) { - llwarns << "Received incorrect amount of data in proxy control channel" << llendl; + LL_WARNS("Proxy") << "Received incorrect amount of data in proxy control channel" << LL_ENDL; rv = -1; } } @@ -296,6 +296,6 @@ static LLSocket::ptr_t tcp_open_channel(apr_pool_t* pool, LLHost host) // Pass a pointer-to-pointer to avoid changing use_count(). static void tcp_close_channel(LLSocket::ptr_t* handle_ptr) { - lldebugs << "Resetting proxy LLSocket handle, use_count == " << handle_ptr->use_count() << llendl; + LL_DEBUGS("Proxy") << "Resetting proxy LLSocket handle, use_count == " << handle_ptr->use_count() << LL_ENDL; handle_ptr->reset(); } -- cgit v1.2.3 From cb24dff9e36a963af280be1aead9424be8a678b6 Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Wed, 13 Jul 2011 16:46:36 -0400 Subject: Code cleanup for the SOCKS 5 proxy viewer. --- indra/llmessage/llproxy.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llmessage/llproxy.cpp') diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index 0143803f2b..11a5c480f0 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -110,7 +110,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) authmethod_password_reply_t password_reply; - result = tcp_handshake(mProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(authmethod_password_reply_t)); + result = tcp_handshake(mProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(password_reply)); delete[] password_auth; if (result != 0) @@ -142,7 +142,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) // "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(socks_command_request_t), (char*)&connect_reply, sizeof(socks_command_response_t)); + 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; @@ -202,7 +202,7 @@ void LLProxy::stopProxy() // 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) + if (LLPROXY_SOCKS == mProxyType) { sHTTPProxyEnabled = false; } -- cgit v1.2.3 From 792667ff8ef13e16823d96b490ea9a4f498425ea Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Tue, 19 Jul 2011 14:20:21 -0400 Subject: STORM-1112 Added LLProxy::applyProxySettings() to apply proxy settings to curl handles. Added call to that function everywhere curl handles are created in the viewer. --- indra/llmessage/llproxy.cpp | 88 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) (limited to 'indra/llmessage/llproxy.cpp') 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 #include +#include #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) { -- cgit v1.2.3 From 859dc52c30a8c750047323399caa4fec18adfb2d Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Thu, 21 Jul 2011 15:16:54 -0400 Subject: STORM-1112 Protected LLProxy members during cross-thread calls to LLProxy::applyProxySettings() --- indra/llmessage/llproxy.cpp | 72 +++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 25 deletions(-) (limited to 'indra/llmessage/llproxy.cpp') diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index 6040472cba..d34ad1a811 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -59,7 +59,10 @@ LLProxy::LLProxy(): mAuthMethodSelected(METHOD_NOAUTH), mSocksUsername(), mSocksPassword(), - mPool(gAPRPoolp) + mPool(gAPRPoolp), + mSOCKSAuthStrings(), + mHTTPProxyAddrStrings(), + mProxyMutex(0) { } @@ -71,7 +74,7 @@ LLProxy::~LLProxy() // Delete c_str versions of the addresses and credentials. for_each(mSOCKSAuthStrings.begin(), mSOCKSAuthStrings.end(), DeletePointerArray()); - for_each(mSOCKSAddrStrings.begin(), mSOCKSAddrStrings.end(), DeletePointerArray()); + for_each(mHTTPProxyAddrStrings.begin(), mHTTPProxyAddrStrings.end(), DeletePointerArray()); } // Perform a SOCKS 5 authentication and UDP association to the proxy @@ -211,7 +214,7 @@ void LLProxy::stopProxy() if (LLPROXY_SOCKS == mProxyType) { - sHTTPProxyEnabled = false; + void disableHTTPProxy(); } if (mProxyControlChannel) @@ -234,42 +237,61 @@ void LLProxy::setAuthPassword(const std::string &username, const std::string &pa 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* socks_addr_string = new char[size]; - strncpy(socks_addr_string, httpHost.getIPString().c_str(), size); - mSOCKSAddrStrings.push_back(socks_addr_string); + 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() { - LLProxy::getInstance()->stopProxy(); + getInstance()->stopProxy(); + deleteSingleton(); } // Apply proxy settings to CuRL request if either type of HTTP proxy is enabled. void LLProxy::applyProxySettings(LLCurl::Easy* handle) { - if (LLProxy::getInstance()->isHTTPProxyEnabled()) + if (sHTTPProxyEnabled) { - std::string address = LLProxy::getInstance()->getHTTPProxy().getIPString(); - U16 port = LLProxy::getInstance()->getHTTPProxy().getPort(); + std::string address = mHTTPProxy.getIPString(); + U16 port = mHTTPProxy.getPort(); handle->setoptString(CURLOPT_PROXY, address.c_str()); handle->setopt(CURLOPT_PROXYPORT, port); - if (LLProxy::getInstance()->getHTTPProxyType() == LLPROXY_SOCKS) + if (mProxyType == LLPROXY_SOCKS) { handle->setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); - if (LLProxy::getInstance()->getSelectedAuthMethod() == METHOD_PASSWORD) + if (mAuthMethodSelected == METHOD_PASSWORD) { - handle->setoptString(CURLOPT_PROXYUSERPWD, LLProxy::getInstance()->getProxyUserPwdCURL()); + handle->setoptString(CURLOPT_PROXYUSERPWD, getProxyUserPwdCURL()); } } else @@ -281,18 +303,18 @@ void LLProxy::applyProxySettings(LLCurl::Easy* handle) void LLProxy::applyProxySettings(LLCurlEasyRequest* handle) { - if (LLProxy::getInstance()->isHTTPProxyEnabled()) + if (sHTTPProxyEnabled) { - std::string address = LLProxy::getInstance()->getHTTPProxy().getIPString(); - U16 port = LLProxy::getInstance()->getHTTPProxy().getPort(); + std::string address = mHTTPProxy.getIPString(); + U16 port = mHTTPProxy.getPort(); handle->setoptString(CURLOPT_PROXY, address.c_str()); handle->setopt(CURLOPT_PROXYPORT, port); - if (LLProxy::getInstance()->getHTTPProxyType() == LLPROXY_SOCKS) + if (mProxyType == LLPROXY_SOCKS) { handle->setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); - if (LLProxy::getInstance()->getSelectedAuthMethod() == METHOD_PASSWORD) + if (mAuthMethodSelected == METHOD_PASSWORD) { - handle->setoptString(CURLOPT_PROXYUSERPWD, LLProxy::getInstance()->getProxyUserPwdCURL()); + handle->setoptString(CURLOPT_PROXYUSERPWD, getProxyUserPwdCURL()); } } else @@ -304,17 +326,17 @@ void LLProxy::applyProxySettings(LLCurlEasyRequest* handle) void LLProxy::applyProxySettings(CURL* handle) { - if (LLProxy::getInstance()->isHTTPProxyEnabled()) + LLMutexLock lock(&mProxyMutex); + if (sHTTPProxyEnabled) { - 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_PROXY, mHTTPProxyAddrStrings.back())); + U16 port = mHTTPProxy.getPort(); check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, port)); - if (LLProxy::getInstance()->getHTTPProxyType() == LLPROXY_SOCKS) + if (mProxyType == LLPROXY_SOCKS) { check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5)); - if (LLProxy::getInstance()->getSelectedAuthMethod() == METHOD_PASSWORD) + if (mAuthMethodSelected == METHOD_PASSWORD) { check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, mSOCKSAuthStrings.back())); } -- cgit v1.2.3 From f15d28a636da7b6d2784d9301e7a030b5bd38a8c Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Thu, 28 Jul 2011 13:47:20 -0400 Subject: Proxy cleanup in llstartup.cpp and llproxy.cpp. --- indra/llmessage/llproxy.cpp | 45 +++++---------------------------------------- 1 file changed, 5 insertions(+), 40 deletions(-) (limited to 'indra/llmessage/llproxy.cpp') diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index d34ad1a811..e1970f1368 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -278,50 +278,15 @@ void LLProxy::cleanupClass() } // Apply proxy settings to CuRL request if either type of HTTP proxy is enabled. -void LLProxy::applyProxySettings(LLCurl::Easy* handle) +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); - } - } + applyProxySettings(handle->getEasy()); } -void LLProxy::applyProxySettings(LLCurlEasyRequest* handle) + +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); - } - } + applyProxySettings(handle->getCurlHandle()); } void LLProxy::applyProxySettings(CURL* handle) -- cgit v1.2.3 From d2c72cb7e92896cb414e357ef262d91b0498a6b7 Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Fri, 29 Jul 2011 15:38:20 -0400 Subject: STORM-1112 Input sanitization of proxy options. --- indra/llmessage/llproxy.cpp | 79 +++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 24 deletions(-) (limited to 'indra/llmessage/llproxy.cpp') diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index e1970f1368..381308fb2a 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -68,7 +68,7 @@ LLProxy::LLProxy(): LLProxy::~LLProxy() { - stopProxy(); + stopSOCKSProxy(); sUDPProxyEnabled = false; sHTTPProxyEnabled = false; @@ -95,14 +95,14 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) if (result != 0) { LL_WARNS("Proxy") << "SOCKS authentication request failed, error on TCP control channel : " << result << LL_ENDL; - stopProxy(); + stopSOCKSProxy(); 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(); + stopSOCKSProxy(); return SOCKS_NOT_ACCEPTABLE; } @@ -126,14 +126,14 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) if (result != 0) { LL_WARNS("Proxy") << "SOCKS authentication failed, error on TCP control channel : " << result << LL_ENDL; - stopProxy(); + stopSOCKSProxy(); return SOCKS_CONNECT_ERROR; } if (password_reply.status != AUTH_SUCCESS) { LL_WARNS("Proxy") << "SOCKS authentication failed" << LL_ENDL; - stopProxy(); + stopSOCKSProxy(); return SOCKS_AUTH_FAIL; } } @@ -156,14 +156,14 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) if (result != 0) { LL_WARNS("Proxy") << "SOCKS connect request failed, error on TCP control channel : " << result << LL_ENDL; - stopProxy(); + stopSOCKSProxy(); 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(); + stopSOCKSProxy(); return SOCKS_UDP_FWD_NOT_GRANTED; } @@ -174,37 +174,49 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) return SOCKS_OK; } -S32 LLProxy::startProxy(std::string host, U32 port) +S32 LLProxy::startSOCKSProxy(LLHost host) { - mTCPProxy.setHostByName(host); - mTCPProxy.setPort(port); + S32 status = SOCKS_OK; - S32 status; + if (host.isOk()) + { + mTCPProxy = host; + } + else + { + status = SOCKS_INVALID_HOST; + } - if (mProxyControlChannel) + if (mProxyControlChannel && status == SOCKS_OK) { tcp_close_channel(&mProxyControlChannel); } - mProxyControlChannel = tcp_open_channel(mPool, mTCPProxy); - if (!mProxyControlChannel) + if (status == SOCKS_OK) + { + mProxyControlChannel = tcp_open_channel(mPool, mTCPProxy); + if (!mProxyControlChannel) + { + status = SOCKS_HOST_CONNECT_FAILED; + } + } + + if (status == SOCKS_OK) { - return SOCKS_HOST_CONNECT_FAILED; + status = proxyHandshake(mTCPProxy, (U32)gMessageSystem->mPort); } - status = proxyHandshake(mTCPProxy, (U32)gMessageSystem->mPort); if (status == SOCKS_OK) { sUDPProxyEnabled = true; } else { - stopProxy(); + stopSOCKSProxy(); } return status; - } -void LLProxy::stopProxy() +void LLProxy::stopSOCKSProxy() { sUDPProxyEnabled = false; @@ -228,8 +240,15 @@ void LLProxy::setAuthNone() mAuthMethodSelected = METHOD_NOAUTH; } -void LLProxy::setAuthPassword(const std::string &username, const std::string &password) +bool LLProxy::setAuthPassword(const std::string &username, const std::string &password) { + if (username.length() > SOCKSMAXUSERNAMELEN || password.length() > SOCKSMAXPASSWORDLEN || + username.length() < SOCKSMINUSERNAMELEN || password.length() < SOCKSMINPASSWORDLEN) + { + LL_WARNS("Proxy") << "Invalid SOCKS 5 password or username length." << LL_ENDL; + return false; + } + mAuthMethodSelected = METHOD_PASSWORD; mSocksUsername = username; mSocksPassword = password; @@ -240,10 +259,18 @@ void LLProxy::setAuthPassword(const std::string &username, const std::string &pa LLMutexLock lock(&mProxyMutex); mSOCKSAuthStrings.push_back(curl_auth_string); + + return true; } -void LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type) -{ +bool LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type) +{ + if (httpHost.isOk()) + { + LL_WARNS("Proxy") << "Invalid SOCKS 5 Server" << LL_ENDL; + return false; + } + LLMutexLock lock(&mProxyMutex); sHTTPProxyEnabled = true; @@ -254,13 +281,17 @@ void LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type) char* http_addr_string = new char[size]; strncpy(http_addr_string, httpHost.getIPString().c_str(), size); mHTTPProxyAddrStrings.push_back(http_addr_string); + + return true; } -void LLProxy::enableHTTPProxy() +bool LLProxy::enableHTTPProxy() { LLMutexLock lock(&mProxyMutex); sHTTPProxyEnabled = true; + + return true; } void LLProxy::disableHTTPProxy() @@ -273,7 +304,7 @@ void LLProxy::disableHTTPProxy() //static void LLProxy::cleanupClass() { - getInstance()->stopProxy(); + getInstance()->stopSOCKSProxy(); deleteSingleton(); } -- cgit v1.2.3 From 97bedac2a1274f26a6a346afccea7596f1d13923 Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Tue, 2 Aug 2011 11:08:07 -0400 Subject: Proxy: Improved mutex usage in LLProxy. Introduced an LLAtomic member to track the status of the http proxy that can be checked without locking a mutex. --- indra/llmessage/llproxy.cpp | 129 ++++++++++++++++++++++++++------------------ 1 file changed, 78 insertions(+), 51 deletions(-) (limited to 'indra/llmessage/llproxy.cpp') diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index 381308fb2a..b224757673 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -1,6 +1,6 @@ /** - * @file llsocks5.cpp - * @brief SOCKS 5 implementation + * @file llproxy.cpp + * @brief UDP and HTTP proxy communications * * $LicenseInfo:firstyear=2011&license=viewerlgpl$ * Second Life Viewer Source Code @@ -28,7 +28,6 @@ #include "llproxy.h" -#include #include #include @@ -44,7 +43,6 @@ // 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 @@ -52,17 +50,16 @@ static void tcp_close_channel(LLSocket::ptr_t* handle_ptr); // Close an open TCP 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), + mHTTPProxyEnabled(false), + mProxyMutex(0), mUDPProxy(), mTCPProxy(), + mPool(gAPRPoolp), mHTTPProxy(), + mProxyType(LLPROXY_SOCKS), mAuthMethodSelected(METHOD_NOAUTH), mSocksUsername(), - mSocksPassword(), - mPool(gAPRPoolp), - mSOCKSAuthStrings(), - mHTTPProxyAddrStrings(), - mProxyMutex(0) + mSocksPassword() { } @@ -70,11 +67,7 @@ LLProxy::~LLProxy() { stopSOCKSProxy(); 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()); + mHTTPProxyEnabled = false; } // Perform a SOCKS 5 authentication and UDP association to the proxy @@ -89,7 +82,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) 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. + socks_auth_request.methods = getSelectedAuthMethod(); // 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) @@ -110,13 +103,15 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) if (socks_auth_response.method == METHOD_PASSWORD) { // The server has requested a username/password combination - U32 request_size = mSocksUsername.size() + mSocksPassword.size() + 3; + std::string socks_username(getSocksUser()); + std::string socks_password(getSocksPwd()); + U32 request_size = socks_username.size() + socks_password.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()); + password_auth[1] = socks_username.size(); + memcpy(&password_auth[2], socks_username.c_str(), socks_username.size()); + password_auth[socks_username.size() + 2] = socks_password.size(); + memcpy(&password_auth[socks_username.size()+3], socks_password.c_str(), socks_password.size()); authmethod_password_reply_t password_reply; @@ -224,7 +219,7 @@ void LLProxy::stopSOCKSProxy() // 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) + if (LLPROXY_SOCKS == getHTTPProxyType()) { void disableHTTPProxy(); } @@ -237,6 +232,8 @@ void LLProxy::stopSOCKSProxy() void LLProxy::setAuthNone() { + LLMutexLock lock(&mProxyMutex); + mAuthMethodSelected = METHOD_NOAUTH; } @@ -249,23 +246,18 @@ bool LLProxy::setAuthPassword(const std::string &username, const std::string &pa return false; } + LLMutexLock lock(&mProxyMutex); + 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); - return true; } bool LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type) { - if (httpHost.isOk()) + if (!httpHost.isOk()) { LL_WARNS("Proxy") << "Invalid SOCKS 5 Server" << LL_ENDL; return false; @@ -273,14 +265,10 @@ bool 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); + mHTTPProxyEnabled = true; return true; } @@ -289,7 +277,7 @@ bool LLProxy::enableHTTPProxy() { LLMutexLock lock(&mProxyMutex); - sHTTPProxyEnabled = true; + mHTTPProxyEnabled = true; return true; } @@ -298,7 +286,40 @@ void LLProxy::disableHTTPProxy() { LLMutexLock lock(&mProxyMutex); - sHTTPProxyEnabled = false; + mHTTPProxyEnabled = false; +} + +// Get the HTTP proxy address and port +LLHost LLProxy::getHTTPProxy() const +{ + LLMutexLock lock(&mProxyMutex); + return mHTTPProxy; +} + +// Get the currently selected HTTP proxy type +LLHttpProxyType LLProxy::getHTTPProxyType() const +{ + LLMutexLock lock(&mProxyMutex); + return mProxyType; +} + +std::string LLProxy::getSocksPwd() const +{ + LLMutexLock lock(&mProxyMutex); + return mSocksPassword; +} + +std::string LLProxy::getSocksUser() const +{ + LLMutexLock lock(&mProxyMutex); + return mSocksUsername; +} + +// get the currently selected auth method +LLSocks5AuthType LLProxy::getSelectedAuthMethod() const +{ + LLMutexLock lock(&mProxyMutex); + return mAuthMethodSelected; } //static @@ -322,24 +343,30 @@ void LLProxy::applyProxySettings(LLCurl::Easy* handle) void LLProxy::applyProxySettings(CURL* handle) { - LLMutexLock lock(&mProxyMutex); - if (sHTTPProxyEnabled) + // Do a faster unlocked check to see if we are supposed to proxy. + if (mHTTPProxyEnabled) { - 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) + // 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) { - check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5)); - if (mAuthMethodSelected == METHOD_PASSWORD) + check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str())); + check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort())); + + if (mProxyType == LLPROXY_SOCKS) { - check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, mSOCKSAuthStrings.back())); + check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5)); + if (mAuthMethodSelected == METHOD_PASSWORD) + { + std::string auth_string = mSocksUsername + ":" + mSocksPassword; + check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str())); + } + } + else + { + check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP)); } - } - else - { - check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP)); } } } -- cgit v1.2.3 From d3b4cc34a8d388ab66ef2ca717ee0d814d87ff3d Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Tue, 2 Aug 2011 17:18:54 -0400 Subject: LLProxy cleanup. * Removed early returns in LLStartup::handleSocksProxy * Corrected some cases that would result in handleSocksProxy not being called again during login if settings changed * Allowed for short replies in tcp_handshake in LLProxy.cpp * Renamed LLProxy::isEnabled() to LLProxy::isSocksProxyEnabled() to clarify its use. --- indra/llmessage/llproxy.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'indra/llmessage/llproxy.cpp') diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index b224757673..d2e64e60ac 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -382,14 +382,15 @@ static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outl handle->setBlocking(1000); rv = apr_socket_send(apr_socket, dataout, &outlen); - if (APR_SUCCESS != rv || expected_len != outlen) + if (APR_SUCCESS != rv) { - LL_WARNS("Proxy") << "Error sending data to proxy control channel" << LL_ENDL; + LL_WARNS("Proxy") << "Error sending data to proxy control channel, status: " << rv << LL_ENDL; ll_apr_warn_status(rv); } else if (expected_len != outlen) { - LL_WARNS("Proxy") << "Error sending data to proxy control channel" << LL_ENDL; + LL_WARNS("Proxy") << "Incorrect data length sent. Expected: " << expected_len << + " Sent: " << outlen << LL_ENDL; rv = -1; } @@ -402,9 +403,10 @@ static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outl LL_WARNS("Proxy") << "Error receiving data from proxy control channel, status: " << rv << LL_ENDL; ll_apr_warn_status(rv); } - else if (expected_len != maxinlen) + else if (expected_len < maxinlen) { - LL_WARNS("Proxy") << "Received incorrect amount of data in proxy control channel" << LL_ENDL; + LL_WARNS("Proxy") << "Incorrect data length received. Expected: " << expected_len << + " Received: " << maxinlen << LL_ENDL; rv = -1; } } -- cgit v1.2.3 From 37f88470850cf572f30b0d1dae2f46a8e3b43977 Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Thu, 4 Aug 2011 11:17:03 -0400 Subject: LLProxy: Added another attempt to download gpu and feature tables after successfully setting up a proxy. Other minor changes: Clarified why we are using SOCKS5 as the "grid" argument to store proxy credentials. Added class wide logging to the LLProxy class. --- indra/llmessage/llproxy.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'indra/llmessage/llproxy.cpp') diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index d2e64e60ac..bdffa34fbc 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -85,7 +85,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) socks_auth_request.methods = getSelectedAuthMethod(); // 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) + if (result != APR_SUCCESS) { LL_WARNS("Proxy") << "SOCKS authentication request failed, error on TCP control channel : " << result << LL_ENDL; stopSOCKSProxy(); @@ -118,7 +118,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) result = tcp_handshake(mProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(password_reply)); delete[] password_auth; - if (result != 0) + if (result != APR_SUCCESS) { LL_WARNS("Proxy") << "SOCKS authentication failed, error on TCP control channel : " << result << LL_ENDL; stopSOCKSProxy(); @@ -148,7 +148,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) // 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) + if (result != APR_SUCCESS) { LL_WARNS("Proxy") << "SOCKS connect request failed, error on TCP control channel : " << result << LL_ENDL; stopSOCKSProxy(); @@ -335,7 +335,6 @@ void LLProxy::applyProxySettings(LLCurlEasyRequest* handle) applyProxySettings(handle->getEasy()); } - void LLProxy::applyProxySettings(LLCurl::Easy* handle) { applyProxySettings(handle->getCurlHandle()); @@ -373,7 +372,6 @@ void LLProxy::applyProxySettings(CURL* handle) 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; -- cgit v1.2.3 From 5915da89f06106d0e811c6655144df93d35144f8 Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Mon, 8 Aug 2011 15:53:06 -0400 Subject: LLProxy cleanup. Made the socks proxy start first in llstartup.cpp Moved initialization of the proxy to before the HTTP table fetch Added Doxygen comments to LLProxy methods. Removed call to applyProxySettings in llxmlrpctransaction.cpp since the ctor of LLCurlEasyRequest will apply the proxy settings. --- indra/llmessage/llproxy.cpp | 149 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 133 insertions(+), 16 deletions(-) (limited to 'indra/llmessage/llproxy.cpp') diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index bdffa34fbc..3f4a6accbf 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -34,8 +34,6 @@ #include "llapr.h" #include "llcurl.h" #include "llhost.h" -#include "message.h" -#include "net.h" // Static class variable instances @@ -44,10 +42,10 @@ // member is also static bool LLProxy::sUDPProxyEnabled = false; -// Some helpful TCP functions +// Some helpful TCP static functions. +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 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(): mHTTPProxyEnabled(false), @@ -70,9 +68,15 @@ LLProxy::~LLProxy() mHTTPProxyEnabled = false; } -// 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) +/** + * @brief Open the SOCKS 5 TCP control channel. + * + * Perform a SOCKS 5 authentication and UDP association to the proxy server. + * + * @param proxy The SOCKS 5 server to connect to. + * @return SOCKS_OK if successful, otherwise a socks error code from llproxy.h. + */ +S32 LLProxy::proxyHandshake(LLHost proxy) { S32 result; @@ -169,6 +173,16 @@ S32 LLProxy::proxyHandshake(LLHost proxy, U32 message_port) return SOCKS_OK; } +/** + * @brief Initiates a SOCKS 5 proxy session. + * + * Performs basic checks on host to verify that it is a valid address. Opens the control channel + * and then negotiates the proxy connection with the server. + * + * + * @param host Socks server to connect to. + * @return SOCKS_OK if successful, otherwise a SOCKS error code defined in llproxy.h. + */ S32 LLProxy::startSOCKSProxy(LLHost host) { S32 status = SOCKS_OK; @@ -198,7 +212,7 @@ S32 LLProxy::startSOCKSProxy(LLHost host) if (status == SOCKS_OK) { - status = proxyHandshake(mTCPProxy, (U32)gMessageSystem->mPort); + status = proxyHandshake(mTCPProxy); } if (status == SOCKS_OK) { @@ -211,6 +225,13 @@ S32 LLProxy::startSOCKSProxy(LLHost host) return status; } +/** + * @brief Stop using the SOCKS 5 proxy. + * + * This will stop sending UDP packets through the SOCKS 5 proxy + * and will also stop the HTTP proxy if it is configured to use SOCKS. + * The proxy control channel will also be disconnected. + */ void LLProxy::stopSOCKSProxy() { sUDPProxyEnabled = false; @@ -230,6 +251,9 @@ void LLProxy::stopSOCKSProxy() } } +/** + * @brief Set the proxy's SOCKS authentication method to none. + */ void LLProxy::setAuthNone() { LLMutexLock lock(&mProxyMutex); @@ -237,6 +261,18 @@ void LLProxy::setAuthNone() mAuthMethodSelected = METHOD_NOAUTH; } +/** + * @brief Set the proxy's SOCKS authentication method to password. + * + * Check whether the lengths of the supplied username + * and password conform to the lengths allowed by the + * SOCKS protocol. + * + * @param username The SOCKS username to send. + * @param password The SOCKS password to send. + * @return Return true if applying the settings was successful. No changes are made if false. + * + */ bool LLProxy::setAuthPassword(const std::string &username, const std::string &password) { if (username.length() > SOCKSMAXUSERNAMELEN || password.length() > SOCKSMAXPASSWORDLEN || @@ -255,6 +291,15 @@ bool LLProxy::setAuthPassword(const std::string &username, const std::string &pa return true; } +/** + * @brief Enable the HTTP proxy for either SOCKS or HTTP. + * + * Check the supplied host to see if it is a valid IP and port. + * + * @param httpHost Proxy server to connect to. + * @param type Is the host a SOCKS or HTTP proxy. + * @return Return true if applying the setting was successful. No changes are made if false. + */ bool LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type) { if (!httpHost.isOk()) @@ -273,15 +318,31 @@ bool LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type) return true; } +/** + * @brief Enable the HTTP proxy without changing the proxy settings. + * + * This should not be called unless the proxy has already been set up. + * + * @return Return true only if the current settings are valid and the proxy was enabled. + */ bool LLProxy::enableHTTPProxy() { + bool ok; + LLMutexLock lock(&mProxyMutex); - mHTTPProxyEnabled = true; + ok = (mHTTPProxy.isOk()); + if (ok) + { + mHTTPProxyEnabled = true; + } - return true; + return ok; } +/** + * @brief Disable the HTTP proxy. + */ void LLProxy::disableHTTPProxy() { LLMutexLock lock(&mProxyMutex); @@ -289,39 +350,59 @@ void LLProxy::disableHTTPProxy() mHTTPProxyEnabled = false; } -// Get the HTTP proxy address and port +/** + * @brief Get the HTTP proxy address and port + */ +// LLHost LLProxy::getHTTPProxy() const { LLMutexLock lock(&mProxyMutex); return mHTTPProxy; } -// Get the currently selected HTTP proxy type +/** + * @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; } -// get the currently selected auth method +/** + * @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. + * + * Deletes the LLProxy singleton, destroying the APR pool used by the control channel as well as . + */ //static void LLProxy::cleanupClass() { @@ -329,7 +410,6 @@ void LLProxy::cleanupClass() deleteSingleton(); } -// Apply proxy settings to CuRL request if either type of HTTP proxy is enabled. void LLProxy::applyProxySettings(LLCurlEasyRequest* handle) { applyProxySettings(handle->getEasy()); @@ -340,6 +420,17 @@ void LLProxy::applyProxySettings(LLCurl::Easy* handle) applyProxySettings(handle->getCurlHandle()); } +/** + * @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 handle A pointer to a valid CURL request, before it has been performed. + */ void LLProxy::applyProxySettings(CURL* handle) { // Do a faster unlocked check to see if we are supposed to proxy. @@ -370,6 +461,19 @@ void LLProxy::applyProxySettings(CURL* handle) } } +/** + * @brief Send one TCP packet and receive one in return. + * + * This operation is done synchronously with a 1000ms timeout. Therefore, it should not be used when a blocking + * operation would impact the operation of the viewer. + * + * @param handle_ptr Pointer to a connected LLSocket of type STREAM_TCP. + * @param dataout Data to send. + * @param outlen Length of dataout. + * @param datain Buffer for received data. Undefined if return value is not APR_SUCCESS. + * @param maxinlen Maximum possible length of received data. Short reads are allowed. + * @return Indicates APR status code of exchange. APR_SUCCESS if exchange was successful, -1 if invalid data length was received. + */ 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(); @@ -414,9 +518,18 @@ static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outl return rv; } +/** + * @brief Open a LLSocket and do a blocking connect to the chosen host. + * + * Checks for a successful connection, and makes sure the connection is closed if it fails. + * + * @param pool APR pool to pass into the LLSocket. + * @param host The host to open the connection to. + * @return The created socket. Will evaluate as NULL if the connection is unsuccessful. + */ static LLSocket::ptr_t tcp_open_channel(apr_pool_t* pool, LLHost host) { - LLSocket::ptr_t socket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); + LLSocket::ptr_t socket = LLSocket::create(pool, LLSocket::STREAM_TCP); bool connected = socket->blockingConnect(host); if (!connected) { @@ -426,7 +539,11 @@ static LLSocket::ptr_t tcp_open_channel(apr_pool_t* pool, LLHost host) return socket; } -// Pass a pointer-to-pointer to avoid changing use_count(). +/** + * @brief Close the socket. + * + * @param handle_ptr A pointer-to-pointer to avoid increasing the 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; -- cgit v1.2.3