* When receiving an out of sequence FIN we must ignore it until its part of

our available buffer (we might want to move this into the BufferQueue class).
* Now, _AddData() remembers the flag (and its position), and will alter the
  segment's flags field to reflect the current state.
* This fixes not being able to login into mmlr.dyndns.org.
* Fixed warnings when TCP_PROBE is defined.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36127 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2010-04-11 00:04:23 +00:00
parent d7acf4abc4
commit e572c32335
2 changed files with 26 additions and 8 deletions
@@ -72,9 +72,9 @@
# define PROBE(buffer, window) \
dprintf("TCP PROBE %llu %s %s %ld snxt %lu suna %lu cw %lu sst %lu win %lu swin %lu smax-suna %lu savail %lu sqused %lu rto %llu\n", \
system_time(), PrintAddress(buffer->source), \
PrintAddress(buffer->destination), buffer->size, (uint32)fSendNext, \
(uint32)fSendUnacknowledged, fCongestionWindow, fSlowStartThreshold, \
window, fSendWindow, (uint32)(fSendMax - fSendUnacknowledged), \
PrintAddress(buffer->destination), buffer->size, fSendNext.Number(), \
fSendUnacknowledged.Number(), fCongestionWindow, fSlowStartThreshold, \
window, fSendWindow, (fSendMax - fSendUnacknowledged).Number(), \
fSendQueue.Available(fSendNext), fSendQueue.Used(), fRetransmitTimeout)
#else
# define PROBE(buffer, window) do { } while (0)
@@ -1298,13 +1298,27 @@ TCPEndpoint::_NotifyReader()
bool
TCPEndpoint::_AddData(tcp_segment_header& segment, net_buffer* buffer)
{
if ((segment.flags & TCP_FLAG_FINISH) != 0) {
// Remember the position of the finish received flag
fFinishReceived = true;
fFinishReceivedAt = segment.sequence + buffer->size;
}
fReceiveQueue.Add(buffer, segment.sequence);
fReceiveNext = fReceiveQueue.NextSequence();
if (fFinishReceived) {
// Set or reset the finish flag on the current segment
if (fReceiveNext < fFinishReceivedAt)
segment.flags &= ~TCP_FLAG_FINISH;
else
segment.flags |= TCP_FLAG_FINISH;
}
TRACE(" _AddData(): adding data, receive next = %lu. Now have %lu bytes.",
fReceiveNext.Number(), fReceiveQueue.Available());
if (segment.flags & TCP_FLAG_PUSH)
if ((segment.flags & TCP_FLAG_PUSH) != 0)
fReceiveQueue.SetPushPointer();
return fReceiveQueue.Available() > 0;
@@ -1315,6 +1329,7 @@ void
TCPEndpoint::_PrepareReceivePath(tcp_segment_header& segment)
{
fInitialReceiveSequence = segment.sequence;
fFinishReceived = false;
// count the received SYN
segment.sequence++;
@@ -1686,7 +1701,8 @@ TCPEndpoint::_Receive(tcp_segment_header& segment, net_buffer* buffer)
bool notify = false;
if (buffer->size > 0 && _ShouldReceive())
if ((buffer->size > 0 || (segment.flags & TCP_FLAG_FINISH) != 0)
&& _ShouldReceive())
notify = _AddData(segment, buffer);
else {
if ((fFlags & FLAG_NO_RECEIVE) != 0)
@@ -1695,7 +1711,7 @@ TCPEndpoint::_Receive(tcp_segment_header& segment, net_buffer* buffer)
action = (action & ~KEEP) | DROP;
}
if (segment.flags & TCP_FLAG_FINISH) {
if ((segment.flags & TCP_FLAG_FINISH) != 0) {
segmentLength++;
if (fState != CLOSED && fState != LISTEN && fState != SYNCHRONIZE_SENT) {
TRACE("Receive(): peer is finishing connection!");
@@ -1989,7 +2005,7 @@ TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
// Determine if we should really send this segment
if (!force && !_ShouldSendSegment(segment, segmentLength,
segmentMaxSize, flightSize)) {
segmentMaxSize, flightSize)) {
if (fSendQueue.Available()
&& !gStackModule->is_timer_active(&fPersistTimer)
&& !gStackModule->is_timer_active(&fRetransmitTimer))
@@ -1,5 +1,5 @@
/*
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -170,6 +170,8 @@ private:
uint32 fReceiveWindow;
uint32 fReceiveMaxSegmentSize;
BufferQueue fReceiveQueue;
bool fFinishReceived;
tcp_sequence fFinishReceivedAt;
tcp_sequence fInitialReceiveSequence;
// round trip time and retransmit timeout computation