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
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user