diff options
Diffstat (limited to 'indra/llmessage')
-rw-r--r-- | indra/llmessage/llares.cpp | 17 | ||||
-rw-r--r-- | indra/llmessage/llcurl.cpp | 34 | ||||
-rw-r--r-- | indra/llmessage/llcurl.h | 10 | ||||
-rw-r--r-- | indra/llmessage/lliohttpserver.cpp | 10 | ||||
-rw-r--r-- | indra/llmessage/lliohttpserver.h | 2 | ||||
-rw-r--r-- | indra/llmessage/lliosocket.cpp | 99 | ||||
-rw-r--r-- | indra/llmessage/lliosocket.h | 37 | ||||
-rw-r--r-- | indra/llmessage/llmail.cpp | 17 | ||||
-rw-r--r-- | indra/llmessage/llmail.h | 4 | ||||
-rw-r--r-- | indra/llmessage/llpacketring.cpp | 16 | ||||
-rw-r--r-- | indra/llmessage/llpacketring.h | 3 | ||||
-rw-r--r-- | indra/llmessage/llproxy.cpp | 106 | ||||
-rw-r--r-- | indra/llmessage/llproxy.h | 107 | ||||
-rw-r--r-- | indra/llmessage/llpumpio.cpp | 74 | ||||
-rw-r--r-- | indra/llmessage/llpumpio.h | 31 | ||||
-rw-r--r-- | indra/llmessage/llurlrequest.cpp | 25 | ||||
-rw-r--r-- | indra/llmessage/message.cpp | 17 | ||||
-rw-r--r-- | indra/llmessage/tests/networkio.h | 9 |
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()) { |