From 8107b1940338a62198e77f9d4c9007f048f00915 Mon Sep 17 00:00:00 2001 From: Hugo Santos Date: Tue, 10 Apr 2007 05:28:56 +0000 Subject: [PATCH] Fixed some more TCP issues. - Properly flag sockets using non-blocking connects() when in SYN SENT. - and when in LISTEN, we should use the socket's connection queue size. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20631 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/net/net_socket.h | 1 + .../network/protocols/tcp/TCPEndpoint.cpp | 25 ++++++++++++++++--- .../kernel/network/stack/net_socket.cpp | 17 +++++++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/headers/private/net/net_socket.h b/headers/private/net/net_socket.h index ef3fcd3b99..a9efc8ca4a 100644 --- a/headers/private/net/net_socket.h +++ b/headers/private/net/net_socket.h @@ -65,6 +65,7 @@ struct net_socket_module_info { status_t (*spawn_pending_socket)(net_socket *parent, net_socket **_socket); void (*delete_socket)(net_socket *socket); status_t (*dequeue_connected)(net_socket *parent, net_socket **_socket); + ssize_t (*count_connected)(net_socket *parent); status_t (*set_max_backlog)(net_socket *socket, uint32 backlog); status_t (*set_connected)(net_socket *socket); diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp index 5bdd57511b..a4e6960c2f 100644 --- a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp +++ b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp @@ -52,7 +52,7 @@ // the space after 'this' is important in order for this to work with cpp 2.95 # define TRACE(format, args...) dprintf("TCP:%p:" format "\n", this , ##args) #else -# define TRACE(args...) +# define TRACE(args...) do { } while (0) #endif // Initial estimate for packet round trip time (RTT) @@ -62,6 +62,9 @@ enum { FLAG_OPTION_WINDOW_SHIFT = 0x01, FLAG_OPTION_TIMESTAMP = 0x02, + // TODO: Should FLAG_NO_RECEIVE apply as well to received connections? + // That is, what is excepected from accept() after a shutdown() + // is performed on a listen()ing socket. FLAG_NO_RECEIVE = 0x04, }; @@ -334,13 +337,16 @@ TCPEndpoint::Connect(const struct sockaddr *address) // If we are running over Loopback, after _SendQueued() returns we // may be in ESTABLISHED already. - if (fState == ESTABLISHED) + if (fState == ESTABLISHED) { + TRACE(" Connect() completed after _SendQueued()"); return B_OK; + } // wait until 3-way handshake is complete (if needed) bigtime_t timeout = min_c(socket->send.timeout, TCP_CONNECTION_TIMEOUT); if (timeout == 0) { // we're a non-blocking socket + TRACE(" Connect() delayed, return EINPROGRESS"); return EINPROGRESS; } @@ -368,6 +374,8 @@ TCPEndpoint::Accept(struct net_socket **_acceptedSocket) return status; status = gSocketModule->dequeue_connected(socket, _acceptedSocket); + if (status == B_OK) + TRACE(" Accept() returning %p", (*_acceptedSocket)->first_protocol); } while (status < B_OK); return status; @@ -533,9 +541,8 @@ TCPEndpoint::SendData(net_buffer *buffer) ssize_t TCPEndpoint::SendAvailable() { - TRACE("SendAvailable()"); - RecursiveLocker locker(fLock); + TRACE("SendAvailable(): %li", fSendQueue.Free()); return fSendQueue.Free(); } @@ -767,6 +774,8 @@ TCPEndpoint::ListenReceive(tcp_segment_header &segment, net_buffer *buffer) } } + TRACE(" ListenReceive() created new endpoint %p", endpoint); + // send SYN+ACK status_t status = endpoint->_SendQueued(); @@ -1403,6 +1412,14 @@ TCPEndpoint::_ShutdownEgress(bool closing) ssize_t TCPEndpoint::_AvailableData() const { + // TODO: Refer to the FLAG_NO_RECEIVE comment above regarding + // the application of FLAG_NO_RECEIVE in listen()ing + // sockets. + if (fState == LISTEN) + return gSocketModule->count_connected(socket); + else if (fState == SYNCHRONIZE_SENT) + return 0; + ssize_t availableData = fReceiveQueue.Available(); if (availableData == 0 && !_ShouldReceive()) diff --git a/src/add-ons/kernel/network/stack/net_socket.cpp b/src/add-ons/kernel/network/stack/net_socket.cpp index 50c6db9124..e851a3d64b 100644 --- a/src/add-ons/kernel/network/stack/net_socket.cpp +++ b/src/add-ons/kernel/network/stack/net_socket.cpp @@ -372,6 +372,22 @@ socket_dequeue_connected(net_socket *_parent, net_socket **_socket) } +ssize_t +socket_count_connected(net_socket *_parent) +{ + net_socket_private *parent = (net_socket_private *)_parent; + + BenaphoreLocker _(parent->lock); + + int count = 0; + for (void *it = list_get_first_item(&parent->connected_children); + it != NULL; it = list_get_next_item(&parent->connected_children, it)) + count++; + + return count; +} + + status_t socket_set_max_backlog(net_socket *_socket, uint32 backlog) { @@ -1101,6 +1117,7 @@ net_socket_module_info gNetSocketModule = { socket_spawn_pending, socket_delete, socket_dequeue_connected, + socket_count_connected, socket_set_max_backlog, socket_connected,