tcp: fixed an issue where the socket could be waken from ReadData() even when no new data was added to the queue (due to lost packets). Also make sure we only break from the receive loop where there is at least a byte of data to be consumed.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21248 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Hugo Santos
2007-05-27 03:38:22 +00:00
parent cad7120f0c
commit 34c53bacf4
2 changed files with 14 additions and 13 deletions
@@ -648,18 +648,18 @@ TCPEndpoint::ReadData(size_t numBytes, uint32 flags, net_buffer** _buffer)
return B_OK; return B_OK;
} }
if (fReceiveQueue.Available() > 0) {
if (fReceiveQueue.Available() >= dataNeeded || if (fReceiveQueue.Available() >= dataNeeded ||
((fReceiveQueue.PushedData() > 0) ((fReceiveQueue.PushedData() > 0)
&& (fReceiveQueue.PushedData() >= fReceiveQueue.Available()))) && (fReceiveQueue.PushedData() >= fReceiveQueue.Available())))
break; break;
} else if (fState == FINISH_RECEIVED) {
if (fState == FINISH_RECEIVED) {
// ``If no text is awaiting delivery, the RECEIVE will // ``If no text is awaiting delivery, the RECEIVE will
// get a Connection closing''. // get a Connection closing''.
return B_OK; return B_OK;
} }
if (flags & MSG_DONTWAIT) if ((flags & MSG_DONTWAIT) || (socket->receive.timeout == 0))
return B_WOULD_BLOCK; return B_WOULD_BLOCK;
status_t status = fReceiveList.Wait(locker, timeout, false); status_t status = fReceiveList.Wait(locker, timeout, false);
@@ -1024,7 +1024,7 @@ TCPEndpoint::_SegmentReceived(tcp_segment_header &segment, net_buffer *buffer)
&& fReceiveQueue.IsContiguous() && fReceiveQueue.IsContiguous()
&& fReceiveQueue.Free() >= buffer->size && fReceiveQueue.Free() >= buffer->size
&& !(fFlags & FLAG_NO_RECEIVE)) { && !(fFlags & FLAG_NO_RECEIVE)) {
_AddData(segment, buffer); if (_AddData(segment, buffer))
_NotifyReader(); _NotifyReader();
return KEEP | ((segment.flags & TCP_FLAG_PUSH) ? return KEEP | ((segment.flags & TCP_FLAG_PUSH) ?
IMMEDIATE_ACKNOWLEDGE : ACKNOWLEDGE); IMMEDIATE_ACKNOWLEDGE : ACKNOWLEDGE);
@@ -1544,10 +1544,9 @@ TCPEndpoint::_Receive(tcp_segment_header &segment, net_buffer *buffer)
bool notify = false; bool notify = false;
if (buffer->size > 0 && _ShouldReceive()) { if (buffer->size > 0 && _ShouldReceive())
_AddData(segment, buffer); notify = _AddData(segment, buffer);
notify = true; else
} else
action = (action & ~KEEP) | DROP; action = (action & ~KEEP) | DROP;
if (segment.flags & TCP_FLAG_FINISH) { if (segment.flags & TCP_FLAG_FINISH) {
@@ -1639,7 +1638,7 @@ TCPEndpoint::_WaitForEstablished(MutexLocker &locker, bigtime_t timeout)
} }
void bool
TCPEndpoint::_AddData(tcp_segment_header &segment, net_buffer *buffer) TCPEndpoint::_AddData(tcp_segment_header &segment, net_buffer *buffer)
{ {
fReceiveQueue.Add(buffer, segment.sequence); fReceiveQueue.Add(buffer, segment.sequence);
@@ -1650,6 +1649,8 @@ TCPEndpoint::_AddData(tcp_segment_header &segment, net_buffer *buffer)
if (segment.flags & TCP_FLAG_PUSH) if (segment.flags & TCP_FLAG_PUSH)
fReceiveQueue.SetPushPointer(); fReceiveQueue.SetPushPointer();
return fReceiveQueue.Available() > 0;
} }
@@ -108,7 +108,7 @@ class TCPEndpoint : public net_protocol, public ProtocolSocket {
size_t segmentLength); size_t segmentLength);
void _MarkEstablished(); void _MarkEstablished();
status_t _WaitForEstablished(MutexLocker &lock, bigtime_t timeout); status_t _WaitForEstablished(MutexLocker &lock, bigtime_t timeout);
void _AddData(tcp_segment_header &segment, net_buffer *buffer); bool _AddData(tcp_segment_header &segment, net_buffer *buffer);
void _PrepareReceivePath(tcp_segment_header &segment); void _PrepareReceivePath(tcp_segment_header &segment);
status_t _PrepareSendPath(const sockaddr *peer); status_t _PrepareSendPath(const sockaddr *peer);
void _Acknowledged(tcp_segment_header &segment); void _Acknowledged(tcp_segment_header &segment);