summaryrefslogtreecommitdiff
path: root/indra/llmessage
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage')
-rw-r--r--indra/llmessage/llares.cpp17
-rw-r--r--indra/llmessage/llcurl.cpp34
-rw-r--r--indra/llmessage/llcurl.h10
-rw-r--r--indra/llmessage/lliohttpserver.cpp10
-rw-r--r--indra/llmessage/lliohttpserver.h2
-rw-r--r--indra/llmessage/lliosocket.cpp99
-rw-r--r--indra/llmessage/lliosocket.h37
-rw-r--r--indra/llmessage/llmail.cpp17
-rw-r--r--indra/llmessage/llmail.h4
-rw-r--r--indra/llmessage/llpacketring.cpp16
-rw-r--r--indra/llmessage/llpacketring.h3
-rw-r--r--indra/llmessage/llproxy.cpp106
-rw-r--r--indra/llmessage/llproxy.h107
-rw-r--r--indra/llmessage/llpumpio.cpp74
-rw-r--r--indra/llmessage/llpumpio.h31
-rw-r--r--indra/llmessage/llurlrequest.cpp25
-rw-r--r--indra/llmessage/message.cpp17
-rw-r--r--indra/llmessage/tests/networkio.h9
18 files changed, 375 insertions, 243 deletions
diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp
index fab9858b69..5a67035ed1 100644
--- a/indra/llmessage/llares.cpp
+++ b/indra/llmessage/llares.cpp
@@ -28,7 +28,6 @@
#include "linden_common.h"
#include "llares.h"
-#include "llscopedvolatileaprpool.h"
#include <ares_dns.h>
#include <ares_version.h>
@@ -465,6 +464,11 @@ void LLAres::search(const std::string &query, LLResType type,
bool LLAres::process(U64 timeout)
{
+ if (!gAPRPoolp)
+ {
+ ll_init_apr();
+ }
+
ares_socket_t socks[ARES_GETSOCK_MAXNUM];
apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM];
apr_int32_t nsds = 0;
@@ -478,7 +482,10 @@ bool LLAres::process(U64 timeout)
return nsds > 0;
}
- LLScopedVolatileAPRPool scoped_pool;
+ apr_status_t status;
+ LLAPRPool pool;
+ status = pool.getStatus() ;
+ ll_apr_assert_status(status);
for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++)
{
@@ -495,7 +502,7 @@ bool LLAres::process(U64 timeout)
apr_socket_t *aprSock = NULL;
- apr_status_t status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], scoped_pool);
+ status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], pool.getAPRPool());
if (status != APR_SUCCESS)
{
ll_apr_warn_status(status);
@@ -504,7 +511,7 @@ bool LLAres::process(U64 timeout)
aprFds[nactive].desc.s = aprSock;
aprFds[nactive].desc_type = APR_POLL_SOCKET;
- aprFds[nactive].p = scoped_pool;
+ aprFds[nactive].p = pool.getAPRPool();
aprFds[nactive].rtnevents = 0;
aprFds[nactive].client_data = &socks[i];
@@ -513,7 +520,7 @@ bool LLAres::process(U64 timeout)
if (nactive > 0)
{
- apr_status_t status = apr_poll(aprFds, nactive, &nsds, timeout);
+ status = apr_poll(aprFds, nactive, &nsds, timeout);
if (status != APR_SUCCESS && status != APR_TIMEUP)
{
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index a3de178d78..330028c926 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -222,7 +222,7 @@ namespace boost
std::set<CURL*> LLCurl::Easy::sFreeHandles;
std::set<CURL*> LLCurl::Easy::sActiveHandles;
LLMutex* LLCurl::Easy::sHandleMutex = NULL;
-
+LLMutex* LLCurl::Easy::sMultiMutex = NULL;
//static
CURL* LLCurl::Easy::allocEasyHandle()
@@ -499,7 +499,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,
//don't verify host name so urls with scrubbed host names will work (improves DNS performance)
setopt(CURLOPT_SSL_VERIFYHOST, 0);
- setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT);
+ setopt(CURLOPT_TIMEOUT, llmax(time_out, CURL_REQUEST_TIMEOUT));
setoptString(CURLOPT_URL, url);
@@ -531,7 +531,7 @@ LLCurl::Multi::Multi()
mThreaded = LLCurl::sMultiThreaded && LLThread::currentID() == sMainThreadID;
if (mThreaded)
{
- mSignal = new LLCondition();
+ mSignal = new LLCondition(NULL);
}
else
{
@@ -553,6 +553,11 @@ LLCurl::Multi::~Multi()
{
llassert(isStopped());
+ if (LLCurl::sMultiThreaded)
+ {
+ LLCurl::Easy::sMultiMutex->lock();
+ }
+
delete mSignal;
mSignal = NULL;
@@ -573,6 +578,11 @@ LLCurl::Multi::~Multi()
check_curl_multi_code(curl_multi_cleanup(mCurlMultiHandle));
--gCurlMultiCount;
+
+ if (LLCurl::sMultiThreaded)
+ {
+ LLCurl::Easy::sMultiMutex->unlock();
+ }
}
CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)
@@ -606,6 +616,7 @@ void LLCurl::Multi::run()
mPerformState = PERFORM_STATE_PERFORMING;
if (!mQuitting)
{
+ LLMutexLock lock(LLCurl::Easy::sMultiMutex);
doPerform();
}
}
@@ -1178,13 +1189,14 @@ void LLCurl::initClass(bool multi_threaded)
check_curl_code(code);
- Easy::sHandleMutex = new LLMutex();
+ Easy::sHandleMutex = new LLMutex(NULL);
+ Easy::sMultiMutex = new LLMutex(NULL);
#if SAFE_SSL
S32 mutex_count = CRYPTO_num_locks();
for (S32 i=0; i<mutex_count; i++)
{
- sSSLMutex.push_back(new LLMutex);
+ sSSLMutex.push_back(new LLMutex(NULL));
}
CRYPTO_set_id_callback(&LLCurl::ssl_thread_id);
CRYPTO_set_locking_callback(&LLCurl::ssl_locking_callback);
@@ -1200,6 +1212,8 @@ void LLCurl::cleanupClass()
delete Easy::sHandleMutex;
Easy::sHandleMutex = NULL;
+ delete Easy::sMultiMutex;
+ Easy::sMultiMutex = NULL;
for (std::set<CURL*>::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter)
{
@@ -1213,3 +1227,13 @@ void LLCurl::cleanupClass()
}
const unsigned int LLCurl::MAX_REDIRECTS = 5;
+
+// Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace.
+void LLCurlFF::check_easy_code(CURLcode code)
+{
+ check_curl_code(code);
+}
+void LLCurlFF::check_multi_code(CURLMcode code)
+{
+ check_curl_multi_code(code);
+}
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 5ab4dc35b9..87de202717 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -232,6 +232,7 @@ public:
private:
friend class LLCurl;
+ friend class LLCurl::Multi;
CURL* mCurlEasyHandle;
struct curl_slist* mHeaders;
@@ -251,6 +252,7 @@ private:
static std::set<CURL*> sFreeHandles;
static std::set<CURL*> sActiveHandles;
static LLMutex* sHandleMutex;
+ static LLMutex* sMultiMutex;
};
class LLCurl::Multi : public LLThread
@@ -371,7 +373,11 @@ private:
bool mResultReturned;
};
-void check_curl_code(CURLcode code);
-void check_curl_multi_code(CURLMcode code);
+// Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace.
+namespace LLCurlFF
+{
+ void check_easy_code(CURLcode code);
+ void check_multi_code(CURLMcode code);
+}
#endif // LL_LLCURL_H
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index 920a57ab55..73e8a69085 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -963,9 +963,13 @@ private:
// static
-LLHTTPNode& LLIOHTTPServer::create(LLPumpIO& pump, U16 port)
+LLHTTPNode& LLIOHTTPServer::create(
+ apr_pool_t* pool, LLPumpIO& pump, U16 port)
{
- LLSocket::ptr_t socket = LLSocket::create(LLSocket::STREAM_TCP, port);
+ LLSocket::ptr_t socket = LLSocket::create(
+ pool,
+ LLSocket::STREAM_TCP,
+ port);
if(!socket)
{
llerrs << "Unable to initialize socket" << llendl;
@@ -974,7 +978,7 @@ LLHTTPNode& LLIOHTTPServer::create(LLPumpIO& pump, U16 port)
LLHTTPResponseFactory* factory = new LLHTTPResponseFactory;
boost::shared_ptr<LLChainIOFactory> factory_ptr(factory);
- LLIOServerSocket* server = new LLIOServerSocket(socket, factory_ptr);
+ LLIOServerSocket* server = new LLIOServerSocket(pool, socket, factory_ptr);
LLPumpIO::chain_t chain;
chain.push_back(LLIOPipe::ptr_t(server));
diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h
index 2294e4b8ae..5c1b0531ff 100644
--- a/indra/llmessage/lliohttpserver.h
+++ b/indra/llmessage/lliohttpserver.h
@@ -50,7 +50,7 @@ class LLIOHTTPServer
public:
typedef void (*timing_callback_t)(const char* hashed_name, F32 time, void* data);
- static LLHTTPNode& create(LLPumpIO& pump, U16 port);
+ static LLHTTPNode& create(apr_pool_t* pool, LLPumpIO& pump, U16 port);
/**< Creates an HTTP wire server on the pump for the given TCP port.
*
* Returns the root node of the new server. Add LLHTTPNode instances
diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp
index a885ba8ee1..54ceab3422 100644
--- a/indra/llmessage/lliosocket.cpp
+++ b/indra/llmessage/lliosocket.cpp
@@ -35,7 +35,6 @@
#include "llhost.h"
#include "llmemtype.h"
#include "llpumpio.h"
-#include "llthread.h"
//
// constants
@@ -99,31 +98,51 @@ void ll_debug_socket(const char* msg, apr_socket_t* apr_sock)
///
// static
-LLSocket::ptr_t LLSocket::create(EType type, U16 port)
+LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
{
LLMemType m1(LLMemType::MTYPE_IO_TCP);
+ LLSocket::ptr_t rv;
+ apr_socket_t* socket = NULL;
+ apr_pool_t* new_pool = NULL;
apr_status_t status = APR_EGENERAL;
- LLSocket::ptr_t rv(new LLSocket);
+
+ // create a pool for the socket
+ status = apr_pool_create(&new_pool, pool);
+ if(ll_apr_warn_status(status))
+ {
+ if(new_pool) apr_pool_destroy(new_pool);
+ return rv;
+ }
if(STREAM_TCP == type)
{
- status = apr_socket_create(&rv->mSocket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, rv->mPool());
+ status = apr_socket_create(
+ &socket,
+ APR_INET,
+ SOCK_STREAM,
+ APR_PROTO_TCP,
+ new_pool);
}
else if(DATAGRAM_UDP == type)
{
- status = apr_socket_create(&rv->mSocket, APR_INET, SOCK_DGRAM, APR_PROTO_UDP, rv->mPool());
+ status = apr_socket_create(
+ &socket,
+ APR_INET,
+ SOCK_DGRAM,
+ APR_PROTO_UDP,
+ new_pool);
}
else
{
- rv.reset();
+ if(new_pool) apr_pool_destroy(new_pool);
return rv;
}
if(ll_apr_warn_status(status))
{
- rv->mSocket = NULL;
- rv.reset();
+ if(new_pool) apr_pool_destroy(new_pool);
return rv;
}
+ rv = ptr_t(new LLSocket(socket, new_pool));
if(port > 0)
{
apr_sockaddr_t* sa = NULL;
@@ -133,7 +152,7 @@ LLSocket::ptr_t LLSocket::create(EType type, U16 port)
APR_UNSPEC,
port,
0,
- rv->mPool());
+ new_pool);
if(ll_apr_warn_status(status))
{
rv.reset();
@@ -141,8 +160,8 @@ LLSocket::ptr_t LLSocket::create(EType type, U16 port)
}
// This allows us to reuse the address on quick down/up. This
// is unlikely to create problems.
- ll_apr_warn_status(apr_socket_opt_set(rv->mSocket, APR_SO_REUSEADDR, 1));
- status = apr_socket_bind(rv->mSocket, sa);
+ ll_apr_warn_status(apr_socket_opt_set(socket, APR_SO_REUSEADDR, 1));
+ status = apr_socket_bind(socket, sa);
if(ll_apr_warn_status(status))
{
rv.reset();
@@ -156,7 +175,7 @@ LLSocket::ptr_t LLSocket::create(EType type, U16 port)
// to keep a queue of incoming connections for ACCEPT.
lldebugs << "Setting listen state for socket." << llendl;
status = apr_socket_listen(
- rv->mSocket,
+ socket,
LL_DEFAULT_LISTEN_BACKLOG);
if(ll_apr_warn_status(status))
{
@@ -177,28 +196,21 @@ LLSocket::ptr_t LLSocket::create(EType type, U16 port)
}
// static
-LLSocket::ptr_t LLSocket::create(apr_status_t& status, LLSocket::ptr_t& listen_socket)
+LLSocket::ptr_t LLSocket::create(apr_socket_t* socket, apr_pool_t* pool)
{
LLMemType m1(LLMemType::MTYPE_IO_TCP);
- if (!listen_socket->getSocket())
- {
- status = APR_ENOSOCKET;
- return LLSocket::ptr_t();
- }
- LLSocket::ptr_t rv(new LLSocket);
- lldebugs << "accepting socket" << llendl;
- status = apr_socket_accept(&rv->mSocket, listen_socket->getSocket(), rv->mPool());
- if (status != APR_SUCCESS)
+ LLSocket::ptr_t rv;
+ if(!socket)
{
- rv->mSocket = NULL;
- rv.reset();
return rv;
}
+ rv = ptr_t(new LLSocket(socket, pool));
rv->mPort = PORT_EPHEMERAL;
rv->setNonBlocking();
return rv;
}
+
bool LLSocket::blockingConnect(const LLHost& host)
{
if(!mSocket) return false;
@@ -211,7 +223,7 @@ bool LLSocket::blockingConnect(const LLHost& host)
APR_UNSPEC,
host.getPort(),
0,
- mPool())))
+ mPool)))
{
return false;
}
@@ -222,11 +234,13 @@ bool LLSocket::blockingConnect(const LLHost& host)
return true;
}
-LLSocket::LLSocket() :
- mSocket(NULL),
- mPool(LLThread::tldata().mRootPool),
+LLSocket::LLSocket(apr_socket_t* socket, apr_pool_t* pool) :
+ mSocket(socket),
+ mPool(pool),
mPort(PORT_INVALID)
{
+ ll_debug_socket("Constructing wholely formed socket", mSocket);
+ LLMemType m1(LLMemType::MTYPE_IO_TCP);
}
LLSocket::~LLSocket()
@@ -239,6 +253,10 @@ LLSocket::~LLSocket()
apr_socket_close(mSocket);
mSocket = NULL;
}
+ if(mPool)
+ {
+ apr_pool_destroy(mPool);
+ }
}
// See http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-13.html#ss13.4
@@ -520,8 +538,10 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(
///
LLIOServerSocket::LLIOServerSocket(
+ apr_pool_t* pool,
LLIOServerSocket::socket_t listener,
factory_t factory) :
+ mPool(pool),
mListenSocket(listener),
mReactor(factory),
mInitialized(false),
@@ -583,15 +603,21 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
lldebugs << "accepting socket" << llendl;
PUMP_DEBUG;
- apr_status_t status;
- LLSocket::ptr_t llsocket(LLSocket::create(status, mListenSocket));
+ apr_pool_t* new_pool = NULL;
+ apr_status_t status = apr_pool_create(&new_pool, mPool);
+ apr_socket_t* socket = NULL;
+ status = apr_socket_accept(
+ &socket,
+ mListenSocket->getSocket(),
+ new_pool);
+ LLSocket::ptr_t llsocket(LLSocket::create(socket, new_pool));
//EStatus rv = STATUS_ERROR;
- if(llsocket && status == APR_SUCCESS)
+ if(llsocket)
{
PUMP_DEBUG;
apr_sockaddr_t* remote_addr;
- apr_socket_addr_get(&remote_addr, APR_REMOTE, llsocket->getSocket());
+ apr_socket_addr_get(&remote_addr, APR_REMOTE, socket);
char* remote_host_string;
apr_sockaddr_ip_get(&remote_host_string, remote_addr);
@@ -606,6 +632,7 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
{
chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(llsocket)));
pump->addChain(chain, mResponseTimeout);
+ status = STATUS_OK;
}
else
{
@@ -614,8 +641,7 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
}
else
{
- char buf[256];
- llwarns << "Unable to accept linden socket: " << apr_strerror(status, buf, sizeof(buf)) << llendl;
+ llwarns << "Unable to create linden socket." << llendl;
}
PUMP_DEBUG;
@@ -628,10 +654,11 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
#if 0
LLIODataSocket::LLIODataSocket(
U16 suggested_port,
- U16 start_discovery_port) :
+ U16 start_discovery_port,
+ apr_pool_t* pool) :
mSocket(NULL)
{
- if(PORT_INVALID == suggested_port) return;
+ if(!pool || (PORT_INVALID == suggested_port)) return;
if(ll_apr_warn_status(apr_socket_create(&mSocket, APR_INET, SOCK_DGRAM, APR_PROTO_UDP, pool))) return;
apr_sockaddr_t* sa = NULL;
if(ll_apr_warn_status(apr_sockaddr_info_get(&sa, APR_ANYADDR, APR_UNSPEC, suggested_port, 0, pool))) return;
diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h
index f0a6f25657..be0f7dfcc6 100644
--- a/indra/llmessage/lliosocket.h
+++ b/indra/llmessage/lliosocket.h
@@ -38,6 +38,7 @@
*/
#include "lliopipe.h"
+#include "apr_pools.h"
#include "apr_network_io.h"
#include "llchainio.h"
@@ -87,22 +88,34 @@ public:
* socket. If you intend the socket to be known to external
* clients without prior port notification, do not use
* PORT_EPHEMERAL.
+ * @param pool The apr pool to use. A child pool will be created
+ * and associated with the socket.
* @param type The type of socket to create
* @param port The port for the socket
* @return A valid socket shared pointer if the call worked.
*/
static ptr_t create(
+ apr_pool_t* pool,
EType type,
U16 port = PORT_EPHEMERAL);
/**
- * @brief Create a LLSocket by accepting a connection from a listen socket.
+ * @brief Create a LLSocket when you already have an apr socket.
*
- * @param status Output. Status of the accept if a valid listen socket was passed.
- * @param listen_socket The listen socket to use.
+ * This method assumes an ephemeral port. This is typically used
+ * by calls which spawn a socket such as a call to
+ * <code>accept()</code> as in the server socket. This call should
+ * not fail if you have a valid apr socket.
+ * Because of the nature of how accept() works, you are expected
+ * to create a new pool for the socket, use that pool for the
+ * accept, and pass it in here where it will be bound with the
+ * socket and destroyed at the same time.
+ * @param socket The apr socket to use
+ * @param pool The pool used to create the socket. *NOTE: The pool
+ * passed in will be DESTROYED.
* @return A valid socket shared pointer if the call worked.
*/
- static ptr_t create(apr_status_t& status, ptr_t& listen_socket);
+ static ptr_t create(apr_socket_t* socket, apr_pool_t* pool);
/**
* @brief Perform a blocking connect to a host. Do not use in production.
@@ -133,12 +146,6 @@ public:
apr_socket_t* getSocket() const { return mSocket; }
/**
- * @brief Protected constructor since should only make sockets
- * with one of the two <code>create()</code> calls.
- */
- LLSocket(void);
-
- /**
* @brief Set default socket options, with SO_NONBLOCK = 0 and a timeout in us.
* @param timeout Number of microseconds to wait on this socket. Any
* negative number means block-forever. TIMEOUT OF 0 IS NON-PORTABLE.
@@ -167,8 +174,8 @@ protected:
// The apr socket.
apr_socket_t* mSocket;
- // Our memory pool.
- LLAPRPool mPool;
+ // our memory pool
+ apr_pool_t* mPool;
// The port if we know it.
U16 mPort;
@@ -293,7 +300,7 @@ class LLIOServerSocket : public LLIOPipe
public:
typedef LLSocket::ptr_t socket_t;
typedef boost::shared_ptr<LLChainIOFactory> factory_t;
- LLIOServerSocket(socket_t listener, factory_t reactor);
+ LLIOServerSocket(apr_pool_t* pool, socket_t listener, factory_t reactor);
virtual ~LLIOServerSocket();
/**
@@ -325,6 +332,7 @@ protected:
//@}
protected:
+ apr_pool_t* mPool;
socket_t mListenSocket;
factory_t mReactor;
bool mInitialized;
@@ -358,7 +366,8 @@ public:
*/
LLIODataSocket(
U16 suggested_port,
- U16 start_discovery_port);
+ U16 start_discovery_port,
+ apr_pool_t* pool);
virtual ~LLIODataSocket();
protected:
diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp
index 8a898ab1b0..08b31e9c7a 100644
--- a/indra/llmessage/llmail.cpp
+++ b/indra/llmessage/llmail.cpp
@@ -50,7 +50,6 @@
#include "llstring.h"
#include "lluuid.h"
#include "net.h"
-#include "llaprpool.h"
//
// constants
@@ -58,7 +57,7 @@
const size_t LL_MAX_KNOWN_GOOD_MAIL_SIZE = 4096;
static bool gMailEnabled = true;
-static LLAPRPool gMailPool;
+static apr_pool_t* gMailPool;
static apr_sockaddr_t* gSockAddr;
static apr_socket_t* gMailSocket;
@@ -83,7 +82,7 @@ bool connect_smtp()
gSockAddr->sa.sin.sin_family,
SOCK_STREAM,
APR_PROTO_TCP,
- gMailPool());
+ gMailPool);
if(ll_apr_warn_status(status)) return false;
status = apr_socket_connect(gMailSocket, gSockAddr);
if(ll_apr_warn_status(status))
@@ -140,19 +139,19 @@ BOOL LLMail::send(
}
// static
-void LLMail::init(const std::string& hostname)
+void LLMail::init(const std::string& hostname, apr_pool_t* pool)
{
gMailSocket = NULL;
- if (hostname.empty())
+ if(hostname.empty() || !pool)
{
+ gMailPool = NULL;
gSockAddr = NULL;
- gMailPool.destroy();
}
else
{
- gMailPool.create();
+ gMailPool = pool;
- // Collect all the information into a sockaddr structure. the
+ // collect all the information into a socaddr sturcture. the
// documentation is a bit unclear, but I either have to
// specify APR_UNSPEC or not specify any flags. I am not sure
// which option is better.
@@ -162,7 +161,7 @@ void LLMail::init(const std::string& hostname)
APR_UNSPEC,
25,
APR_IPV4_ADDR_OK,
- gMailPool());
+ gMailPool);
ll_apr_warn_status(status);
}
}
diff --git a/indra/llmessage/llmail.h b/indra/llmessage/llmail.h
index 0a5c532088..3791714363 100644
--- a/indra/llmessage/llmail.h
+++ b/indra/llmessage/llmail.h
@@ -27,13 +27,15 @@
#ifndef LL_LLMAIL_H
#define LL_LLMAIL_H
+typedef struct apr_pool_t apr_pool_t;
+
#include "llsd.h"
class LLMail
{
public:
// if hostname is NULL, then the host is resolved as 'mail'
- static void init(const std::string& hostname);
+ static void init(const std::string& hostname, apr_pool_t* pool);
// Allow all email transmission to be disabled/enabled.
static void enable(bool mail_enabled);
diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp
index 7628984de4..fc6e9c5193 100644
--- a/indra/llmessage/llpacketring.cpp
+++ b/indra/llmessage/llpacketring.cpp
@@ -228,13 +228,13 @@ S32 LLPacketRing::receivePacket (S32 socket, char *datap)
if (LLProxy::isSOCKSProxyEnabled())
{
U8 buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];
- packet_size = receive_packet(socket, reinterpret_cast<char *>(buffer));
+ packet_size = receive_packet(socket, static_cast<char*>(static_cast<void*>(buffer)));
if (packet_size > SOCKS_HEADER_SIZE)
{
// *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6)
memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size - SOCKS_HEADER_SIZE);
- proxywrap_t * header = reinterpret_cast<proxywrap_t *>(buffer);
+ proxywrap_t * header = static_cast<proxywrap_t*>(static_cast<void*>(buffer));
mLastSender.setAddress(header->addr);
mLastSender.setPort(ntohs(header->port));
@@ -353,14 +353,20 @@ BOOL LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 bu
return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort());
}
- proxywrap_t *socks_header = reinterpret_cast<proxywrap_t *>(&mProxyWrappedSendBuffer);
+ char headered_send_buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];
+
+ proxywrap_t *socks_header = static_cast<proxywrap_t*>(static_cast<void*>(&headered_send_buffer));
socks_header->rsv = 0;
socks_header->addr = host.getAddress();
socks_header->port = htons(host.getPort());
socks_header->atype = ADDRESS_IPV4;
socks_header->frag = 0;
- memcpy(mProxyWrappedSendBuffer + SOCKS_HEADER_SIZE, send_buffer, buf_size);
+ memcpy(headered_send_buffer + SOCKS_HEADER_SIZE, send_buffer, buf_size);
- return send_packet(h_socket, (const char*) mProxyWrappedSendBuffer, buf_size + 10, LLProxy::getInstance()->getUDPProxy().getAddress(), LLProxy::getInstance()->getUDPProxy().getPort());
+ return send_packet( h_socket,
+ headered_send_buffer,
+ buf_size + SOCKS_HEADER_SIZE,
+ LLProxy::getInstance()->getUDPProxy().getAddress(),
+ LLProxy::getInstance()->getUDPProxy().getPort());
}
diff --git a/indra/llmessage/llpacketring.h b/indra/llmessage/llpacketring.h
index 7edcc834db..b214271e78 100644
--- a/indra/llmessage/llpacketring.h
+++ b/indra/llmessage/llpacketring.h
@@ -83,9 +83,6 @@ protected:
LLHost mLastSender;
LLHost mLastReceivingIF;
-
- U8 mProxyWrappedSendBuffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];
-
private:
BOOL sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host);
};
diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp
index 19f1fc6545..9988fcd9c0 100644
--- a/indra/llmessage/llproxy.cpp
+++ b/indra/llmessage/llproxy.cpp
@@ -43,13 +43,13 @@
bool LLProxy::sUDPProxyEnabled = false;
// 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 apr_status_t tcp_blocking_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(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
LLProxy::LLProxy():
mHTTPProxyEnabled(false),
- mProxyMutex(),
+ mProxyMutex(NULL),
mUDPProxy(),
mTCPProxy(),
mHTTPProxy(),
@@ -63,14 +63,13 @@ LLProxy::LLProxy():
LLProxy::~LLProxy()
{
stopSOCKSProxy();
- sUDPProxyEnabled = false;
- mHTTPProxyEnabled = false;
+ disableHTTPProxy();
}
/**
* @brief Open the SOCKS 5 TCP control channel.
*
- * Perform a SOCKS 5 authentication and UDP association to the proxy server.
+ * Perform a SOCKS 5 authentication and UDP association with 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.
@@ -83,11 +82,15 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
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 = getSelectedAuthMethod(); // Send only the selected method.
+ socks_auth_request.version = SOCKS_VERSION; // SOCKS version 5
+ socks_auth_request.num_methods = 1; // Sending 1 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));
+ result = tcp_blocking_handshake(mProxyControlChannel,
+ static_cast<char*>(static_cast<void*>(&socks_auth_request)),
+ sizeof(socks_auth_request),
+ static_cast<char*>(static_cast<void*>(&socks_auth_response)),
+ sizeof(socks_auth_response));
if (result != APR_SUCCESS)
{
LL_WARNS("Proxy") << "SOCKS authentication request failed, error on TCP control channel : " << result << LL_ENDL;
@@ -97,12 +100,12 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
if (socks_auth_response.method == AUTH_NOT_ACCEPTABLE)
{
- LL_WARNS("Proxy") << "SOCKS 5 server refused all our authentication methods" << LL_ENDL;
+ LL_WARNS("Proxy") << "SOCKS 5 server refused all our authentication methods." << LL_ENDL;
stopSOCKSProxy();
return SOCKS_NOT_ACCEPTABLE;
}
- // SOCKS 5 USERNAME/PASSWORD authentication
+ /* SOCKS 5 USERNAME/PASSWORD authentication */
if (socks_auth_response.method == METHOD_PASSWORD)
{
// The server has requested a username/password combination
@@ -114,11 +117,15 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
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());
+ memcpy(&password_auth[socks_username.size() + 3], socks_password.c_str(), socks_password.size());
authmethod_password_reply_t password_reply;
- result = tcp_handshake(mProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(password_reply));
+ result = tcp_blocking_handshake(mProxyControlChannel,
+ password_auth,
+ request_size,
+ static_cast<char*>(static_cast<void*>(&password_reply)),
+ sizeof(password_reply));
delete[] password_auth;
if (result != APR_SUCCESS)
@@ -150,7 +157,11 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
// "If the client is not in possession of the information at the time of the UDP ASSOCIATE,
// the client MUST use a port number and address of all zeros. RFC 1928"
- result = tcp_handshake(mProxyControlChannel, (char*)&connect_request, sizeof(connect_request), (char*)&connect_reply, sizeof(connect_reply));
+ result = tcp_blocking_handshake(mProxyControlChannel,
+ static_cast<char*>(static_cast<void*>(&connect_request)),
+ sizeof(connect_request),
+ static_cast<char*>(static_cast<void*>(&connect_reply)),
+ sizeof(connect_reply));
if (result != APR_SUCCESS)
{
LL_WARNS("Proxy") << "SOCKS connect request failed, error on TCP control channel : " << result << LL_ENDL;
@@ -169,6 +180,7 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
mUDPProxy.setAddress(proxy.getAddress());
// The connection was successful. We now have the UDP port to send requests that need forwarding to.
LL_INFOS("Proxy") << "SOCKS 5 UDP proxy connected on " << mUDPProxy << LL_ENDL;
+
return SOCKS_OK;
}
@@ -176,7 +188,8 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
* @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.
+ * and then negotiates the proxy connection with the server. Closes any existing SOCKS
+ * connection before proceeding. Also disables an HTTP proxy if it is using SOCKS as the proxy.
*
*
* @param host Socks server to connect to.
@@ -184,43 +197,37 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
*/
S32 LLProxy::startSOCKSProxy(LLHost host)
{
- S32 status = SOCKS_OK;
-
if (host.isOk())
{
mTCPProxy = host;
}
else
{
- status = SOCKS_INVALID_HOST;
+ return SOCKS_INVALID_HOST;
}
- if (mProxyControlChannel && status == SOCKS_OK)
- {
- tcp_close_channel(&mProxyControlChannel);
- }
+ // Close any running SOCKS connection.
+ stopSOCKSProxy();
- if (status == SOCKS_OK)
+ mProxyControlChannel = tcp_open_channel(mTCPProxy);
+ if (!mProxyControlChannel)
{
- mProxyControlChannel = tcp_open_channel(mTCPProxy);
- if (!mProxyControlChannel)
- {
- status = SOCKS_HOST_CONNECT_FAILED;
- }
+ return SOCKS_HOST_CONNECT_FAILED;
}
- if (status == SOCKS_OK)
- {
- status = proxyHandshake(mTCPProxy);
- }
- if (status == SOCKS_OK)
+ S32 status = proxyHandshake(mTCPProxy);
+
+ if (status != SOCKS_OK)
{
- sUDPProxyEnabled = true;
+ // Shut down the proxy if any of the above steps failed.
+ stopSOCKSProxy();
}
else
{
- stopSOCKSProxy();
+ // Connection was successful.
+ sUDPProxyEnabled = true;
}
+
return status;
}
@@ -241,7 +248,7 @@ void LLProxy::stopSOCKSProxy()
if (LLPROXY_SOCKS == getHTTPProxyType())
{
- void disableHTTPProxy();
+ disableHTTPProxy();
}
if (mProxyControlChannel)
@@ -350,16 +357,6 @@ void LLProxy::disableHTTPProxy()
}
/**
- * @brief Get the HTTP proxy address and port
- */
-//
-LLHost LLProxy::getHTTPProxy() const
-{
- LLMutexLock lock(&mProxyMutex);
- return mHTTPProxy;
-}
-
-/**
* @brief Get the currently selected HTTP proxy type
*/
LLHttpProxyType LLProxy::getHTTPProxyType() const
@@ -440,21 +437,21 @@ void LLProxy::applyProxySettings(CURL* handle)
// 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_PROXY, mHTTPProxy.getIPString().c_str()));
- check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort()));
+ LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str()));
+ LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort()));
if (mProxyType == LLPROXY_SOCKS)
{
- check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5));
+ LLCurlFF::check_easy_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()));
+ LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str()));
}
}
else
{
- check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP));
+ LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP));
}
}
}
@@ -473,7 +470,7 @@ void LLProxy::applyProxySettings(CURL* handle)
* @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)
+static apr_status_t tcp_blocking_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;
@@ -522,13 +519,12 @@ static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outl
*
* 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(LLHost host)
{
- LLSocket::ptr_t socket = LLSocket::create(LLSocket::STREAM_TCP);
+ LLSocket::ptr_t socket = LLSocket::create(NULL, LLSocket::STREAM_TCP);
bool connected = socket->blockingConnect(host);
if (!connected)
{
@@ -541,7 +537,7 @@ static LLSocket::ptr_t tcp_open_channel(LLHost host)
/**
* @brief Close the socket.
*
- * @param handle_ptr A pointer-to-pointer to avoid increasing the use count.
+ * @param handle_ptr The handle of the socket being closed. A pointer-to-pointer to avoid increasing the use count.
*/
static void tcp_close_channel(LLSocket::ptr_t* handle_ptr)
{
diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h
index 621debb61d..a919370540 100644
--- a/indra/llmessage/llproxy.h
+++ b/indra/llmessage/llproxy.h
@@ -36,7 +36,6 @@
#include <string>
// SOCKS error codes returned from the StartProxy method
-
#define SOCKS_OK 0
#define SOCKS_CONNECT_ERROR (-1)
#define SOCKS_NOT_PERMITTED (-2)
@@ -46,7 +45,6 @@
#define SOCKS_HOST_CONNECT_FAILED (-6)
#define SOCKS_INVALID_HOST (-7)
-
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN (255 + 1) /* socks5: 255, +1 for len. */
#endif
@@ -225,62 +223,71 @@ class LLProxy: public LLSingleton<LLProxy>
{
LOG_CLASS(LLProxy);
public:
- // METHODS THAT DO NOT LOCK mProxyMutex!
-
+ /*###########################################################################################
+ METHODS THAT DO NOT LOCK mProxyMutex!
+ ###########################################################################################*/
+ // Constructor, cannot have parameters due to LLSingleton parent class. Call from main thread only.
LLProxy();
- // static check for enabled status for UDP packets
+ // Static check for enabled status for UDP packets. Call from main thread only.
static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; }
- // check for enabled status for HTTP packets
- // mHTTPProxyEnabled is atomic, so no locking is required for thread safety.
- bool isHTTPProxyEnabled() const { return mHTTPProxyEnabled; }
-
- // Get the UDP proxy address and port
+ // Get the UDP proxy address and port. Call from main thread only.
LLHost getUDPProxy() const { return mUDPProxy; }
- // Get the SOCKS 5 TCP control channel address and port
- LLHost getTCPProxy() const { return mTCPProxy; }
+ /*###########################################################################################
+ END OF NON-LOCKING METHODS
+ ###########################################################################################*/
- // END OF NON-LOCKING METHODS
+ /*###########################################################################################
+ METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
+ ###########################################################################################*/
+ // Destructor, closes open connections. Do not call directly, use cleanupClass().
+ ~LLProxy();
- // METHODS THAT DO LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
+ // Delete LLProxy singleton. Allows the apr_socket used in the SOCKS 5 control channel to be
+ // destroyed before the call to apr_terminate. Call from main thread only.
+ static void cleanupClass();
- ~LLProxy();
+ // Apply the current proxy settings to a curl request. Doesn't do anything if mHTTPProxyEnabled is false.
+ // Safe to call from any thread.
+ void applyProxySettings(CURL* handle);
+ void applyProxySettings(LLCurl::Easy* handle);
+ void applyProxySettings(LLCurlEasyRequest* handle);
- // Start a connection to the SOCKS 5 proxy
+ // Start a connection to the SOCKS 5 proxy. Call from main thread only.
S32 startSOCKSProxy(LLHost host);
- // Disconnect and clean up any connection to the SOCKS 5 proxy
+ // Disconnect and clean up any connection to the SOCKS 5 proxy. Call from main thread only.
void stopSOCKSProxy();
- // Delete LLProxy singleton, destroying the APR pool used by the control channel.
- static void cleanupClass();
-
- // Set up to use Password auth when connecting to the SOCKS proxy
+ // Use Password auth when connecting to the SOCKS proxy. Call from main thread only.
bool setAuthPassword(const std::string &username, const std::string &password);
- // Set up to use No Auth when connecting to the SOCKS proxy
+ // Disable authentication when connecting to the SOCKS proxy. Call from main thread only.
void setAuthNone();
- // Get the currently selected auth method.
- LLSocks5AuthType getSelectedAuthMethod() const;
-
- // Proxy HTTP packets via httpHost, which can be a SOCKS 5 or a HTTP proxy
- // as specified in type
+ // Proxy HTTP packets via httpHost, which can be a SOCKS 5 or a HTTP proxy.
+ // as specified in type. Call from main thread only.
bool enableHTTPProxy(LLHost httpHost, LLHttpProxyType type);
bool enableHTTPProxy();
- // Stop proxying HTTP packets
+ // Stop proxying HTTP packets. Call from main thread only.
void disableHTTPProxy();
- // Apply the current proxy settings to a curl request. Doesn't do anything if mHTTPProxyEnabled is false.
- void applyProxySettings(CURL* handle);
- void applyProxySettings(LLCurl::Easy* handle);
- void applyProxySettings(LLCurlEasyRequest* handle);
+ /*###########################################################################################
+ END OF LOCKING METHODS
+ ###########################################################################################*/
+private:
+ /*###########################################################################################
+ METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
+ ###########################################################################################*/
- // Get the HTTP proxy address and port
- LLHost getHTTPProxy() const;
+ // Perform a SOCKS 5 authentication and UDP association with the proxy server.
+ S32 proxyHandshake(LLHost proxy);
+
+ // Get the currently selected auth method.
+ LLSocks5AuthType getSelectedAuthMethod() const;
// Get the currently selected HTTP proxy type
LLHttpProxyType getHTTPProxyType() const;
@@ -288,21 +295,21 @@ public:
std::string getSocksPwd() const;
std::string getSocksUser() const;
- // END OF LOCKING METHODS
-private:
- // Open a communication channel to the SOCKS 5 proxy proxy, at port messagePort
- S32 proxyHandshake(LLHost proxy);
+ /*###########################################################################################
+ END OF LOCKING METHODS
+ ###########################################################################################*/
private:
- // Is the HTTP proxy enabled?
- // Safe to read in any thread, do not write directly,
- // use enableHTTPProxy() and disableHTTPProxy() instead.
+ // Is the HTTP proxy enabled? Safe to read in any thread, but do not write directly.
+ // Instead use enableHTTPProxy() and disableHTTPProxy() instead.
mutable LLAtomic32<bool> mHTTPProxyEnabled;
- // Mutex to protect shared members in non-main thread calls to applyProxySettings()
+ // 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!
+ /*###########################################################################################
+ MEMBERS READ AND WRITTEN ONLY IN THE MAIN THREAD. DO NOT SHARE!
+ ###########################################################################################*/
// Is the UDP proxy enabled?
static bool sUDPProxyEnabled;
@@ -315,9 +322,13 @@ private:
// socket handle to proxy TCP control channel
LLSocket::ptr_t mProxyControlChannel;
- // END OF UNSHARED MEMBERS
+ /*###########################################################################################
+ END OF UNSHARED MEMBERS
+ ###########################################################################################*/
- // MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD. ONLY READ OR WRITE AFTER LOCKING mProxyMutex!
+ /*###########################################################################################
+ MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD. ONLY READ OR WRITE AFTER LOCKING mProxyMutex!
+ ###########################################################################################*/
// HTTP proxy address and port
LLHost mHTTPProxy;
@@ -325,7 +336,7 @@ private:
// Currently selected HTTP proxy type. Can be web or socks.
LLHttpProxyType mProxyType;
- // SOCKS 5 auth method selected
+ // SOCKS 5 selected authentication method.
LLSocks5AuthType mAuthMethodSelected;
// SOCKS 5 username
@@ -333,7 +344,9 @@ private:
// SOCKS 5 password
std::string mSocksPassword;
- // END OF SHARED MEMBERS
+ /*###########################################################################################
+ END OF SHARED MEMBERS
+ ###########################################################################################*/
};
#endif
diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp
index 89cfd66e1b..a8d2a0a224 100644
--- a/indra/llmessage/llpumpio.cpp
+++ b/indra/llmessage/llpumpio.cpp
@@ -37,7 +37,6 @@
#include "llmemtype.h"
#include "llstl.h"
#include "llstat.h"
-#include "llthread.h"
// These should not be enabled in production, but they can be
// intensely useful during development for finding certain kinds of
@@ -163,12 +162,14 @@ struct ll_delete_apr_pollset_fd_client_data
/**
* LLPumpIO
*/
-LLPumpIO::LLPumpIO(void) :
+LLPumpIO::LLPumpIO(apr_pool_t* pool) :
mState(LLPumpIO::NORMAL),
mRebuildPollset(false),
mPollset(NULL),
mPollsetClientID(0),
mNextLock(0),
+ mPool(NULL),
+ mCurrentPool(NULL),
mCurrentPoolReallocCount(0),
mChainsMutex(NULL),
mCallbackMutex(NULL),
@@ -177,24 +178,21 @@ LLPumpIO::LLPumpIO(void) :
mCurrentChain = mRunningChains.end();
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
- initialize();
+ initialize(pool);
}
LLPumpIO::~LLPumpIO()
{
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
-#if LL_THREADS_APR
- if (mChainsMutex) apr_thread_mutex_destroy(mChainsMutex);
- if (mCallbackMutex) apr_thread_mutex_destroy(mCallbackMutex);
-#endif
- mChainsMutex = NULL;
- mCallbackMutex = NULL;
- if(mPollset)
- {
-// lldebugs << "cleaning up pollset" << llendl;
- apr_pollset_destroy(mPollset);
- mPollset = NULL;
- }
+ cleanup();
+}
+
+bool LLPumpIO::prime(apr_pool_t* pool)
+{
+ LLMemType m1(LLMemType::MTYPE_IO_PUMP);
+ cleanup();
+ initialize(pool);
+ return ((pool == NULL) ? false : true);
}
bool LLPumpIO::addChain(const chain_t& chain, F32 timeout)
@@ -354,7 +352,8 @@ bool LLPumpIO::setConditional(LLIOPipe* pipe, const apr_pollfd_t* poll)
{
// each fd needs a pool to work with, so if one was
// not specified, use this pool.
- value.second.p = (*mCurrentChain).mDescriptorsPool->operator()();
+ // *FIX: Should it always be this pool?
+ value.second.p = mPool;
}
value.second.client_data = new S32(++mPollsetClientID);
(*mCurrentChain).mDescriptors.push_back(value);
@@ -826,15 +825,39 @@ void LLPumpIO::control(LLPumpIO::EControl op)
}
}
-void LLPumpIO::initialize(void)
+void LLPumpIO::initialize(apr_pool_t* pool)
{
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
- mPool.create();
+ if(!pool) return;
#if LL_THREADS_APR
// SJB: Windows defaults to NESTED and OSX defaults to UNNESTED, so use UNNESTED explicitly.
- apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, mPool());
- apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, mPool());
+ apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, pool);
+ apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, pool);
+#endif
+ mPool = pool;
+}
+
+void LLPumpIO::cleanup()
+{
+ LLMemType m1(LLMemType::MTYPE_IO_PUMP);
+#if LL_THREADS_APR
+ if(mChainsMutex) apr_thread_mutex_destroy(mChainsMutex);
+ if(mCallbackMutex) apr_thread_mutex_destroy(mCallbackMutex);
#endif
+ mChainsMutex = NULL;
+ mCallbackMutex = NULL;
+ if(mPollset)
+ {
+// lldebugs << "cleaning up pollset" << llendl;
+ apr_pollset_destroy(mPollset);
+ mPollset = NULL;
+ }
+ if(mCurrentPool)
+ {
+ apr_pool_destroy(mCurrentPool);
+ mCurrentPool = NULL;
+ }
+ mPool = NULL;
}
void LLPumpIO::rebuildPollset()
@@ -862,19 +885,21 @@ void LLPumpIO::rebuildPollset()
if(mCurrentPool
&& (0 == (++mCurrentPoolReallocCount % POLLSET_POOL_RECYCLE_COUNT)))
{
- mCurrentPool.destroy();
+ apr_pool_destroy(mCurrentPool);
+ mCurrentPool = NULL;
mCurrentPoolReallocCount = 0;
}
if(!mCurrentPool)
{
- mCurrentPool.create(mPool);
+ apr_status_t status = apr_pool_create(&mCurrentPool, mPool);
+ (void)ll_apr_warn_status(status);
}
// add all of the file descriptors
run_it = mRunningChains.begin();
LLChainInfo::conditionals_t::iterator fd_it;
LLChainInfo::conditionals_t::iterator fd_end;
- apr_pollset_create(&mPollset, size, mCurrentPool(), 0);
+ apr_pollset_create(&mPollset, size, mCurrentPool, 0);
for(; run_it != run_end; ++run_it)
{
fd_it = (*run_it).mDescriptors.begin();
@@ -1132,8 +1157,7 @@ bool LLPumpIO::handleChainError(
LLPumpIO::LLChainInfo::LLChainInfo() :
mInit(false),
mLock(0),
- mEOS(false),
- mDescriptorsPool(new LLAPRPool(LLThread::tldata().mRootPool))
+ mEOS(false)
{
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
mTimer.setTimerExpirySec(DEFAULT_CHAIN_EXPIRY_SECS);
diff --git a/indra/llmessage/llpumpio.h b/indra/llmessage/llpumpio.h
index 75c35ae7ab..9303c9d7fc 100644
--- a/indra/llmessage/llpumpio.h
+++ b/indra/llmessage/llpumpio.h
@@ -30,12 +30,11 @@
#define LL_LLPUMPIO_H
#include <set>
-#include <boost/shared_ptr.hpp>
#if LL_LINUX // needed for PATH_MAX in APR.
#include <sys/param.h>
#endif
-#include "llaprpool.h"
+#include "apr_pools.h"
#include "llbuffer.h"
#include "llframetimer.h"
#include "lliopipe.h"
@@ -59,8 +58,9 @@ extern const F32 NEVER_CHAIN_EXPIRY_SECS;
* <code>pump()</code> on a thread used for IO and call
* <code>respond()</code> on a thread that is expected to do higher
* level processing. You can call almost any other method from any
- * thread - see notes for each method for details.
- *
+ * thread - see notes for each method for details. In order for the
+ * threading abstraction to work, you need to call <code>prime()</code>
+ * with a valid apr pool.
* A pump instance manages much of the state for the pipe, including
* the list of pipes in the chain, the channel for each element in the
* chain, the buffer, and if any pipe has marked the stream or process
@@ -79,7 +79,7 @@ public:
/**
* @brief Constructor.
*/
- LLPumpIO(void);
+ LLPumpIO(apr_pool_t* pool);
/**
* @brief Destructor.
@@ -87,6 +87,17 @@ public:
~LLPumpIO();
/**
+ * @brief Prepare this pump for usage.
+ *
+ * If you fail to call this method prior to use, the pump will
+ * try to work, but will not come with any thread locking
+ * mechanisms.
+ * @param pool The apr pool to use.
+ * @return Returns true if the pump is primed.
+ */
+ bool prime(apr_pool_t* pool);
+
+ /**
* @brief Typedef for having a chain of pipes.
*/
typedef std::vector<LLIOPipe::ptr_t> chain_t;
@@ -357,7 +368,6 @@ protected:
typedef std::pair<LLIOPipe::ptr_t, apr_pollfd_t> pipe_conditional_t;
typedef std::vector<pipe_conditional_t> conditionals_t;
conditionals_t mDescriptors;
- boost::shared_ptr<LLAPRPool> mDescriptorsPool;
};
// All the running chains & info
@@ -376,9 +386,9 @@ protected:
callbacks_t mPendingCallbacks;
callbacks_t mCallbacks;
- // Memory pool for pollsets & mutexes.
- LLAPRPool mPool;
- LLAPRPool mCurrentPool;
+ // memory allocator for pollsets & mutexes.
+ apr_pool_t* mPool;
+ apr_pool_t* mCurrentPool;
S32 mCurrentPoolReallocCount;
#if LL_THREADS_APR
@@ -390,7 +400,8 @@ protected:
#endif
protected:
- void initialize();
+ void initialize(apr_pool_t* pool);
+ void cleanup();
/**
* @brief Given the internal state of the chains, rebuild the pollset
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 91a5a8ce2c..fa03bb7512 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -41,7 +41,6 @@
#include "llstring.h"
#include "apr_env.h"
#include "llapr.h"
-#include "llscopedvolatileaprpool.h"
static const U32 HTTP_STATUS_PIPE_ERROR = 499;
/**
@@ -212,31 +211,27 @@ void LLURLRequest::setCallback(LLURLRequestComplete* callback)
// is called with use_proxy = FALSE
void LLURLRequest::useProxy(bool use_proxy)
{
- static std::string env_proxy;
+ static char *env_proxy;
- if (use_proxy && env_proxy.empty())
+ if (use_proxy && (env_proxy == NULL))
{
- char* env_proxy_str;
- LLScopedVolatileAPRPool scoped_pool;
- apr_status_t status = apr_env_get(&env_proxy_str, "ALL_PROXY", scoped_pool);
+ apr_status_t status;
+ LLAPRPool pool;
+ status = apr_env_get(&env_proxy, "ALL_PROXY", pool.getAPRPool());
if (status != APR_SUCCESS)
{
- status = apr_env_get(&env_proxy_str, "http_proxy", scoped_pool);
+ status = apr_env_get(&env_proxy, "http_proxy", pool.getAPRPool());
}
if (status != APR_SUCCESS)
{
- use_proxy = false;
+ use_proxy = FALSE;
}
- else
- {
- // env_proxy_str is stored in the scoped_pool, so we have to make a copy.
- env_proxy = env_proxy_str;
- }
}
- LL_DEBUGS("Proxy") << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (!env_proxy.empty() ? env_proxy : "(null)") << LL_ENDL;
- if (use_proxy && !env_proxy.empty())
+ lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << llendl;
+
+ if (env_proxy && use_proxy)
{
mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, env_proxy);
}
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index 7d21e35f96..d0b0e178b8 100644
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -97,10 +97,8 @@ std::string get_shared_secret();
class LLMessagePollInfo
{
public:
- LLMessagePollInfo(void) : mPool(LLThread::tldata().mRootPool) { }
apr_socket_t *mAPRSocketp;
apr_pollfd_t mPollFD;
- LLAPRPool mPool;
};
namespace
@@ -289,13 +287,20 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port,
}
// LL_DEBUGS("Messaging") << << "*** port: " << mPort << llendl;
- mPollInfop = new LLMessagePollInfo;
-
+ //
+ // Create the data structure that we can poll on
+ //
+ if (!gAPRPoolp)
+ {
+ LL_ERRS("Messaging") << "No APR pool before message system initialization!" << llendl;
+ ll_init_apr();
+ }
apr_socket_t *aprSocketp = NULL;
- apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, mPollInfop->mPool());
+ apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, gAPRPoolp);
+ mPollInfop = new LLMessagePollInfo;
mPollInfop->mAPRSocketp = aprSocketp;
- mPollInfop->mPollFD.p = mPollInfop->mPool();
+ mPollInfop->mPollFD.p = gAPRPoolp;
mPollInfop->mPollFD.desc_type = APR_POLL_SOCKET;
mPollInfop->mPollFD.reqevents = APR_POLLIN;
mPollInfop->mPollFD.rtnevents = 0;
diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h
index 23e1c791f4..2aff90ca1e 100644
--- a/indra/llmessage/tests/networkio.h
+++ b/indra/llmessage/tests/networkio.h
@@ -30,6 +30,7 @@
#define LL_NETWORKIO_H
#include "llmemory.h" // LLSingleton
+#include "llapr.h"
#include "llares.h"
#include "llpumpio.h"
#include "llhttpclient.h"
@@ -47,8 +48,14 @@ public:
mServicePump(NULL),
mDone(false)
{
+ ll_init_apr();
+ if (! gAPRPoolp)
+ {
+ throw std::runtime_error("Can't initialize APR");
+ }
+
// Create IO Pump to use for HTTP Requests.
- mServicePump = new LLPumpIO;
+ mServicePump = new LLPumpIO(gAPRPoolp);
LLHTTPClient::setPump(*mServicePump);
if (ll_init_ares() == NULL || !gAres->isInitialized())
{