summaryrefslogtreecommitdiff
path: root/indra/llmessage/lliosocket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/lliosocket.cpp')
-rwxr-xr-x[-rw-r--r--]indra/llmessage/lliosocket.cpp114
1 files changed, 69 insertions, 45 deletions
diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp
index ca84fa8bb8..b7460df508 100644..100755
--- a/indra/llmessage/lliosocket.cpp
+++ b/indra/llmessage/lliosocket.cpp
@@ -32,14 +32,17 @@
#include "llapr.h"
#include "llbuffer.h"
+#include "llfasttimer.h"
#include "llhost.h"
-#include "llmemtype.h"
#include "llpumpio.h"
//
// constants
//
+const std::string CONTEXT_REMOTE_HOST("remote-host");
+const std::string CONTEXT_REMOTE_PORT("remote-port");
+
static const S32 LL_DEFAULT_LISTEN_BACKLOG = 10;
static const S32 LL_SEND_BUFFER_SIZE = 40000;
static const S32 LL_RECV_BUFFER_SIZE = 40000;
@@ -74,7 +77,7 @@ void ll_debug_socket(const char* msg, apr_socket_t* apr_sock)
#if LL_DEBUG_SOCKET_FILE_DESCRIPTORS
if(!apr_sock)
{
- lldebugs << "Socket -- " << (msg?msg:"") << ": no socket." << llendl;
+ LL_DEBUGS() << "Socket -- " << (msg?msg:"") << ": no socket." << LL_ENDL;
return;
}
// *TODO: Why doesn't this work?
@@ -82,13 +85,13 @@ void ll_debug_socket(const char* msg, apr_socket_t* apr_sock)
int os_sock;
if(APR_SUCCESS == apr_os_sock_get(&os_sock, apr_sock))
{
- lldebugs << "Socket -- " << (msg?msg:"") << " on fd " << os_sock
- << " at " << apr_sock << llendl;
+ LL_DEBUGS() << "Socket -- " << (msg?msg:"") << " on fd " << os_sock
+ << " at " << apr_sock << LL_ENDL;
}
else
{
- lldebugs << "Socket -- " << (msg?msg:"") << " no fd "
- << " at " << apr_sock << llendl;
+ LL_DEBUGS() << "Socket -- " << (msg?msg:"") << " no fd "
+ << " at " << apr_sock << LL_ENDL;
}
#endif
}
@@ -100,7 +103,6 @@ void ll_debug_socket(const char* msg, apr_socket_t* apr_sock)
// static
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;
@@ -167,13 +169,13 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
rv.reset();
return rv;
}
- lldebugs << "Bound " << ((DATAGRAM_UDP == type) ? "udp" : "tcp")
- << " socket to port: " << sa->port << llendl;
+ LL_DEBUGS() << "Bound " << ((DATAGRAM_UDP == type) ? "udp" : "tcp")
+ << " socket to port: " << sa->port << LL_ENDL;
if(STREAM_TCP == type)
{
// If it's a stream based socket, we need to tell the OS
// to keep a queue of incoming connections for ACCEPT.
- lldebugs << "Setting listen state for socket." << llendl;
+ LL_DEBUGS() << "Setting listen state for socket." << LL_ENDL;
status = apr_socket_listen(
socket,
LL_DEFAULT_LISTEN_BACKLOG);
@@ -191,14 +193,13 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
port = PORT_EPHEMERAL;
}
rv->mPort = port;
- rv->setOptions();
+ rv->setNonBlocking();
return rv;
}
// static
LLSocket::ptr_t LLSocket::create(apr_socket_t* socket, apr_pool_t* pool)
{
- LLMemType m1(LLMemType::MTYPE_IO_TCP);
LLSocket::ptr_t rv;
if(!socket)
{
@@ -206,7 +207,7 @@ LLSocket::ptr_t LLSocket::create(apr_socket_t* socket, apr_pool_t* pool)
}
rv = ptr_t(new LLSocket(socket, pool));
rv->mPort = PORT_EPHEMERAL;
- rv->setOptions();
+ rv->setNonBlocking();
return rv;
}
@@ -227,10 +228,10 @@ bool LLSocket::blockingConnect(const LLHost& host)
{
return false;
}
- apr_socket_timeout_set(mSocket, 1000);
+ setBlocking(1000);
ll_debug_socket("Blocking connect", mSocket);
if(ll_apr_warn_status(apr_socket_connect(mSocket, sa))) return false;
- setOptions();
+ setNonBlocking();
return true;
}
@@ -240,17 +241,16 @@ LLSocket::LLSocket(apr_socket_t* socket, apr_pool_t* pool) :
mPort(PORT_INVALID)
{
ll_debug_socket("Constructing wholely formed socket", mSocket);
- LLMemType m1(LLMemType::MTYPE_IO_TCP);
}
LLSocket::~LLSocket()
{
- LLMemType m1(LLMemType::MTYPE_IO_TCP);
// *FIX: clean up memory we are holding.
if(mSocket)
{
ll_debug_socket("Destroying socket", mSocket);
apr_socket_close(mSocket);
+ mSocket = NULL;
}
if(mPool)
{
@@ -258,11 +258,25 @@ LLSocket::~LLSocket()
}
}
-void LLSocket::setOptions()
+// See http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-13.html#ss13.4
+// for an explanation of how to get non-blocking sockets and timeouts with
+// consistent behavior across platforms.
+
+void LLSocket::setBlocking(S32 timeout)
+{
+ // set up the socket options
+ ll_apr_warn_status(apr_socket_timeout_set(mSocket, timeout));
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_NONBLOCK, 0));
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_SNDBUF, LL_SEND_BUFFER_SIZE));
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_RCVBUF, LL_RECV_BUFFER_SIZE));
+
+}
+
+void LLSocket::setNonBlocking()
{
- LLMemType m1(LLMemType::MTYPE_IO_TCP);
// set up the socket options
ll_apr_warn_status(apr_socket_timeout_set(mSocket, 0));
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_NONBLOCK, 1));
ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_SNDBUF, LL_SEND_BUFFER_SIZE));
ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_RCVBUF, LL_RECV_BUFFER_SIZE));
@@ -276,15 +290,15 @@ LLIOSocketReader::LLIOSocketReader(LLSocket::ptr_t socket) :
mSource(socket),
mInitialized(false)
{
- LLMemType m1(LLMemType::MTYPE_IO_TCP);
}
LLIOSocketReader::~LLIOSocketReader()
{
- LLMemType m1(LLMemType::MTYPE_IO_TCP);
- //lldebugs << "Destroying LLIOSocketReader" << llendl;
+ //LL_DEBUGS() << "Destroying LLIOSocketReader" << LL_ENDL;
}
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_SOCKET_READER("Socket Reader");
+
// virtual
LLIOPipe::EStatus LLIOSocketReader::process_impl(
const LLChannelDescriptors& channels,
@@ -293,8 +307,8 @@ LLIOPipe::EStatus LLIOSocketReader::process_impl(
LLSD& context,
LLPumpIO* pump)
{
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_SOCKET_READER);
PUMP_DEBUG;
- LLMemType m1(LLMemType::MTYPE_IO_TCP);
if(!mSource) return STATUS_PRECONDITION_NOT_MET;
if(!mInitialized)
{
@@ -305,8 +319,8 @@ LLIOPipe::EStatus LLIOSocketReader::process_impl(
if(pump)
{
PUMP_DEBUG;
- lldebugs << "Initializing poll descriptor for LLIOSocketReader."
- << llendl;
+ LL_DEBUGS() << "Initializing poll descriptor for LLIOSocketReader."
+ << LL_ENDL;
apr_pollfd_t poll_fd;
poll_fd.p = NULL;
poll_fd.desc_type = APR_POLL_SOCKET;
@@ -333,7 +347,7 @@ LLIOPipe::EStatus LLIOSocketReader::process_impl(
status = apr_socket_recv(mSource->getSocket(), read_buf, &len);
buffer->append(channels.out(), (U8*)read_buf, len);
} while((APR_SUCCESS == status) && (READ_BUFFER_SIZE == len));
- lldebugs << "socket read status: " << status << llendl;
+ LL_DEBUGS() << "socket read status: " << status << LL_ENDL;
LLIOPipe::EStatus rv = STATUS_OK;
PUMP_DEBUG;
@@ -376,15 +390,14 @@ LLIOSocketWriter::LLIOSocketWriter(LLSocket::ptr_t socket) :
mLastWritten(NULL),
mInitialized(false)
{
- LLMemType m1(LLMemType::MTYPE_IO_TCP);
}
LLIOSocketWriter::~LLIOSocketWriter()
{
- LLMemType m1(LLMemType::MTYPE_IO_TCP);
- //lldebugs << "Destroying LLIOSocketWriter" << llendl;
+ //LL_DEBUGS() << "Destroying LLIOSocketWriter" << LL_ENDL;
}
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_SOCKET_WRITER("Socket Writer");
// virtual
LLIOPipe::EStatus LLIOSocketWriter::process_impl(
const LLChannelDescriptors& channels,
@@ -393,8 +406,8 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(
LLSD& context,
LLPumpIO* pump)
{
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_SOCKET_WRITER);
PUMP_DEBUG;
- LLMemType m1(LLMemType::MTYPE_IO_TCP);
if(!mDestination) return STATUS_PRECONDITION_NOT_MET;
if(!mInitialized)
{
@@ -405,8 +418,8 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(
if(pump)
{
PUMP_DEBUG;
- lldebugs << "Initializing poll descriptor for LLIOSocketWriter."
- << llendl;
+ LL_DEBUGS() << "Initializing poll descriptor for LLIOSocketWriter."
+ << LL_ENDL;
apr_pollfd_t poll_fd;
poll_fd.p = NULL;
poll_fd.desc_type = APR_POLL_SOCKET;
@@ -423,6 +436,7 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(
// efficient - not only because writev() is better, but also
// because we won't have to do as much work to find the start
// address.
+ buffer->lock();
LLBufferArray::segment_iterator_t it;
LLBufferArray::segment_iterator_t end = buffer->endSegment();
LLSegment segment;
@@ -502,6 +516,8 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(
}
}
+ buffer->unlock();
+
PUMP_DEBUG;
if(done && eos)
{
@@ -525,13 +541,11 @@ LLIOServerSocket::LLIOServerSocket(
mInitialized(false),
mResponseTimeout(DEFAULT_CHAIN_EXPIRY_SECS)
{
- LLMemType m1(LLMemType::MTYPE_IO_TCP);
}
LLIOServerSocket::~LLIOServerSocket()
{
- LLMemType m1(LLMemType::MTYPE_IO_TCP);
- //lldebugs << "Destroying LLIOServerSocket" << llendl;
+ //LL_DEBUGS() << "Destroying LLIOServerSocket" << LL_ENDL;
}
void LLIOServerSocket::setResponseTimeout(F32 timeout_secs)
@@ -539,6 +553,7 @@ void LLIOServerSocket::setResponseTimeout(F32 timeout_secs)
mResponseTimeout = timeout_secs;
}
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_SERVER_SOCKET("Server Socket");
// virtual
LLIOPipe::EStatus LLIOServerSocket::process_impl(
const LLChannelDescriptors& channels,
@@ -547,11 +562,11 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
LLSD& context,
LLPumpIO* pump)
{
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_SERVER_SOCKET);
PUMP_DEBUG;
- LLMemType m1(LLMemType::MTYPE_IO_TCP);
if(!pump)
{
- llwarns << "Need a pump for server socket." << llendl;
+ LL_WARNS() << "Need a pump for server socket." << LL_ENDL;
return STATUS_ERROR;
}
if(!mInitialized)
@@ -560,8 +575,8 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
// This segment sets up the pump so that we do not call
// process again until we have an incoming read, aka connect()
// from a remote host.
- lldebugs << "Initializing poll descriptor for LLIOServerSocket."
- << llendl;
+ LL_DEBUGS() << "Initializing poll descriptor for LLIOServerSocket."
+ << LL_ENDL;
apr_pollfd_t poll_fd;
poll_fd.p = NULL;
poll_fd.desc_type = APR_POLL_SOCKET;
@@ -576,11 +591,20 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
// we are initialized, and told to process, so we must have a
// socket waiting for a connection.
- lldebugs << "accepting socket" << llendl;
+ LL_DEBUGS() << "accepting socket" << LL_ENDL;
PUMP_DEBUG;
apr_pool_t* new_pool = NULL;
apr_status_t status = apr_pool_create(&new_pool, mPool);
+ if(ll_apr_warn_status(status))
+ {
+ if(new_pool)
+ {
+ apr_pool_destroy(new_pool);
+ }
+ return STATUS_ERROR;
+ }
+
apr_socket_t* socket = NULL;
status = apr_socket_accept(
&socket,
@@ -599,8 +623,8 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
apr_sockaddr_ip_get(&remote_host_string, remote_addr);
LLSD context;
- context["remote-host"] = remote_host_string;
- context["remote-port"] = remote_addr->port;
+ context[CONTEXT_REMOTE_HOST] = remote_host_string;
+ context[CONTEXT_REMOTE_PORT] = remote_addr->port;
LLPumpIO::chain_t chain;
chain.push_back(LLIOPipe::ptr_t(new LLIOSocketReader(llsocket)));
@@ -612,12 +636,12 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
}
else
{
- llwarns << "Unable to build reactor to socket." << llendl;
+ LL_WARNS() << "Unable to build reactor to socket." << LL_ENDL;
}
}
else
{
- llwarns << "Unable to create linden socket." << llendl;
+ LL_WARNS() << "Unable to create linden socket." << LL_ENDL;
}
PUMP_DEBUG;
@@ -657,7 +681,7 @@ LLIODataSocket::LLIODataSocket(
if(ll_apr_warn_status(status)) return;
if(sa->port)
{
- lldebugs << "Bound datagram socket to port: " << sa->port << llendl;
+ LL_DEBUGS() << "Bound datagram socket to port: " << sa->port << LL_ENDL;
mPort = sa->port;
}
else