* BufferQueue::Free() no longer will return negative values. As is, the max
bytes restriction is only a soft limit. This fixes stalling TCP connections because everything received would be out of window once this happened. * Added a TODO to look into TCP's window management - it doesn't seem to be right. * Fixed build with tracing turned on. * Made the fNumber member of tcp_sequence private. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35468 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
10cb62616f
commit
965abdebd5
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@ -59,7 +59,8 @@ BufferQueue::SetMaxBytes(size_t maxBytes)
|
|||||||
void
|
void
|
||||||
BufferQueue::SetInitialSequence(tcp_sequence sequence)
|
BufferQueue::SetInitialSequence(tcp_sequence sequence)
|
||||||
{
|
{
|
||||||
TRACE(("BufferQueue@%p::SetInitialSequence(%lu)\n", this, (uint32)sequence));
|
TRACE(("BufferQueue@%p::SetInitialSequence(%lu)\n", this,
|
||||||
|
sequence.Number()));
|
||||||
|
|
||||||
fFirstSequence = fLastSequence = sequence;
|
fFirstSequence = fLastSequence = sequence;
|
||||||
}
|
}
|
||||||
@ -77,9 +78,9 @@ void
|
|||||||
BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
|
BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
|
||||||
{
|
{
|
||||||
TRACE(("BufferQueue@%p::Add(buffer %p, size %lu, sequence %lu)\n",
|
TRACE(("BufferQueue@%p::Add(buffer %p, size %lu, sequence %lu)\n",
|
||||||
this, buffer, buffer->size, (uint32)sequence));
|
this, buffer, buffer->size, sequence.Number()));
|
||||||
TRACE((" in: first: %lu, last: %lu, num: %lu, cont: %lu\n",
|
TRACE((" in: first: %lu, last: %lu, num: %lu, cont: %lu\n",
|
||||||
(uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes,
|
fFirstSequence.Number(), fLastSequence.Number(), fNumBytes,
|
||||||
fContiguousBytes));
|
fContiguousBytes));
|
||||||
VERIFY();
|
VERIFY();
|
||||||
|
|
||||||
@ -112,7 +113,7 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
|
|||||||
fNumBytes += buffer->size;
|
fNumBytes += buffer->size;
|
||||||
|
|
||||||
TRACE((" out0: first: %lu, last: %lu, num: %lu, cont: %lu\n",
|
TRACE((" out0: first: %lu, last: %lu, num: %lu, cont: %lu\n",
|
||||||
(uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes,
|
fFirstSequence.Number(), fLastSequence.Number(), fNumBytes,
|
||||||
fContiguousBytes));
|
fContiguousBytes));
|
||||||
VERIFY();
|
VERIFY();
|
||||||
return;
|
return;
|
||||||
@ -190,7 +191,7 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
|
|||||||
|
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
TRACE((" out1: first: %lu, last: %lu, num: %lu, cont: %lu\n",
|
TRACE((" out1: first: %lu, last: %lu, num: %lu, cont: %lu\n",
|
||||||
(uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes,
|
fFirstSequence.Number(), fLastSequence.Number(), fNumBytes,
|
||||||
fContiguousBytes));
|
fContiguousBytes));
|
||||||
VERIFY();
|
VERIFY();
|
||||||
return;
|
return;
|
||||||
@ -217,7 +218,8 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TRACE((" out2: first: %lu, last: %lu, num: %lu, cont: %lu\n",
|
TRACE((" out2: first: %lu, last: %lu, num: %lu, cont: %lu\n",
|
||||||
(uint32)fFirstSequence, (uint32)fLastSequence, fNumBytes, fContiguousBytes));
|
fFirstSequence.Number(), fLastSequence.Number(), fNumBytes,
|
||||||
|
fContiguousBytes));
|
||||||
VERIFY();
|
VERIFY();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +232,8 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
|
|||||||
status_t
|
status_t
|
||||||
BufferQueue::RemoveUntil(tcp_sequence sequence)
|
BufferQueue::RemoveUntil(tcp_sequence sequence)
|
||||||
{
|
{
|
||||||
TRACE(("BufferQueue@%p::RemoveUntil(sequence %lu)\n", this, (uint32)sequence));
|
TRACE(("BufferQueue@%p::RemoveUntil(sequence %lu)\n", this,
|
||||||
|
sequence.Number()));
|
||||||
VERIFY();
|
VERIFY();
|
||||||
|
|
||||||
if (sequence < fFirstSequence)
|
if (sequence < fFirstSequence)
|
||||||
@ -280,7 +283,7 @@ status_t
|
|||||||
BufferQueue::Get(net_buffer *buffer, tcp_sequence sequence, size_t bytes)
|
BufferQueue::Get(net_buffer *buffer, tcp_sequence sequence, size_t bytes)
|
||||||
{
|
{
|
||||||
TRACE(("BufferQueue@%p::Get(sequence %lu, bytes %lu)\n", this,
|
TRACE(("BufferQueue@%p::Get(sequence %lu, bytes %lu)\n", this,
|
||||||
(uint32)sequence, bytes));
|
sequence.Number(), bytes));
|
||||||
VERIFY();
|
VERIFY();
|
||||||
|
|
||||||
if (bytes == 0)
|
if (bytes == 0)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@ -23,61 +23,74 @@ typedef DoublyLinkedList<struct net_buffer,
|
|||||||
|
|
||||||
class BufferQueue {
|
class BufferQueue {
|
||||||
public:
|
public:
|
||||||
BufferQueue(size_t maxBytes);
|
BufferQueue(size_t maxBytes);
|
||||||
~BufferQueue();
|
~BufferQueue();
|
||||||
|
|
||||||
void SetMaxBytes(size_t maxBytes);
|
void SetMaxBytes(size_t maxBytes);
|
||||||
void SetInitialSequence(tcp_sequence sequence);
|
void SetInitialSequence(tcp_sequence sequence);
|
||||||
|
|
||||||
void Add(net_buffer* buffer);
|
void Add(net_buffer* buffer);
|
||||||
void Add(net_buffer* buffer, tcp_sequence sequence);
|
void Add(net_buffer* buffer, tcp_sequence sequence);
|
||||||
status_t RemoveUntil(tcp_sequence sequence);
|
status_t RemoveUntil(tcp_sequence sequence);
|
||||||
status_t Get(net_buffer* buffer, tcp_sequence sequence,
|
status_t Get(net_buffer* buffer, tcp_sequence sequence,
|
||||||
size_t bytes);
|
size_t bytes);
|
||||||
status_t Get(size_t bytes, bool remove,
|
status_t Get(size_t bytes, bool remove,
|
||||||
net_buffer** _buffer);
|
net_buffer** _buffer);
|
||||||
|
|
||||||
size_t Available() const { return fContiguousBytes; }
|
size_t Available() const { return fContiguousBytes; }
|
||||||
size_t Available(tcp_sequence sequence) const;
|
size_t Available(tcp_sequence sequence) const;
|
||||||
|
|
||||||
inline size_t PushedData() const;
|
inline size_t PushedData() const;
|
||||||
void SetPushPointer();
|
void SetPushPointer();
|
||||||
|
|
||||||
size_t Used() const { return fNumBytes; }
|
size_t Used() const { return fNumBytes; }
|
||||||
size_t Free() const { return fMaxBytes - fNumBytes; }
|
inline size_t Free() const;
|
||||||
size_t Size() const { return fMaxBytes; }
|
size_t Size() const { return fMaxBytes; }
|
||||||
|
|
||||||
bool IsContiguous() const
|
bool IsContiguous() const
|
||||||
{ return fNumBytes == fContiguousBytes; }
|
{ return fNumBytes == fContiguousBytes; }
|
||||||
|
|
||||||
tcp_sequence FirstSequence() const { return fFirstSequence; }
|
tcp_sequence FirstSequence() const { return fFirstSequence; }
|
||||||
tcp_sequence LastSequence() const { return fLastSequence; }
|
tcp_sequence LastSequence() const { return fLastSequence; }
|
||||||
tcp_sequence NextSequence() const
|
tcp_sequence NextSequence() const
|
||||||
{ return fFirstSequence + fContiguousBytes; }
|
{ return fFirstSequence + fContiguousBytes; }
|
||||||
|
|
||||||
#if DEBUG_BUFFER_QUEUE
|
#if DEBUG_BUFFER_QUEUE
|
||||||
void Verify() const;
|
void Verify() const;
|
||||||
void Dump() const;
|
void Dump() const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SegmentList fList;
|
SegmentList fList;
|
||||||
size_t fMaxBytes;
|
size_t fMaxBytes;
|
||||||
size_t fNumBytes;
|
size_t fNumBytes;
|
||||||
size_t fContiguousBytes;
|
size_t fContiguousBytes;
|
||||||
tcp_sequence fFirstSequence;
|
tcp_sequence fFirstSequence;
|
||||||
tcp_sequence fLastSequence;
|
tcp_sequence fLastSequence;
|
||||||
tcp_sequence fPushPointer;
|
tcp_sequence fPushPointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
BufferQueue::PushedData() const
|
BufferQueue::PushedData() const
|
||||||
{
|
{
|
||||||
// we must check if fPushPointer is not 0 here due to
|
// We must check if fPushPointer is not 0 here due to
|
||||||
// tcp_sequence's special handling of >
|
// tcp_sequence's special handling of >
|
||||||
return fPushPointer != 0 && fPushPointer > fFirstSequence
|
return fPushPointer != 0 && fPushPointer > fFirstSequence
|
||||||
? (fPushPointer - fFirstSequence).Number() : 0;
|
? (fPushPointer - fFirstSequence).Number() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t
|
||||||
|
BufferQueue::Free() const
|
||||||
|
{
|
||||||
|
// Max bytes is a soft limit, so it can be lower than the actual amount of
|
||||||
|
// data in the queue. TCP should never advertize a window outside the max
|
||||||
|
// buffer size, though.
|
||||||
|
if (fMaxBytes > fNumBytes)
|
||||||
|
return fMaxBytes - fNumBytes;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // BUFFER_QUEUE_H
|
#endif // BUFFER_QUEUE_H
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@ -411,7 +411,8 @@ WaitList::Signal()
|
|||||||
|
|
||||||
|
|
||||||
TCPEndpoint::TCPEndpoint(net_socket* socket)
|
TCPEndpoint::TCPEndpoint(net_socket* socket)
|
||||||
: ProtocolSocket(socket),
|
:
|
||||||
|
ProtocolSocket(socket),
|
||||||
fManager(NULL),
|
fManager(NULL),
|
||||||
fReceiveList("tcp receive"),
|
fReceiveList("tcp receive"),
|
||||||
fSendList("tcp send"),
|
fSendList("tcp send"),
|
||||||
@ -1301,7 +1302,7 @@ TCPEndpoint::_AddData(tcp_segment_header& segment, net_buffer* buffer)
|
|||||||
fReceiveNext = fReceiveQueue.NextSequence();
|
fReceiveNext = fReceiveQueue.NextSequence();
|
||||||
|
|
||||||
TRACE(" _AddData(): adding data, receive next = %lu. Now have %lu bytes.",
|
TRACE(" _AddData(): adding data, receive next = %lu. Now have %lu bytes.",
|
||||||
(uint32)fReceiveNext, fReceiveQueue.Available());
|
fReceiveNext.Number(), fReceiveQueue.Available());
|
||||||
|
|
||||||
if (segment.flags & TCP_FLAG_PUSH)
|
if (segment.flags & TCP_FLAG_PUSH)
|
||||||
fReceiveQueue.SetPushPointer();
|
fReceiveQueue.SetPushPointer();
|
||||||
@ -1515,8 +1516,8 @@ TCPEndpoint::_Receive(tcp_segment_header& segment, net_buffer* buffer)
|
|||||||
if (!segment_in_sequence(segment, segmentLength, fReceiveNext,
|
if (!segment_in_sequence(segment, segmentLength, fReceiveNext,
|
||||||
fReceiveWindow)) {
|
fReceiveWindow)) {
|
||||||
TRACE(" Receive(): segment out of window, next: %lu wnd: %lu",
|
TRACE(" Receive(): segment out of window, next: %lu wnd: %lu",
|
||||||
(uint32)fReceiveNext, fReceiveWindow);
|
fReceiveNext.Number(), fReceiveWindow);
|
||||||
if (segment.flags & TCP_FLAG_RESET) {
|
if ((segment.flags & TCP_FLAG_RESET) != 0) {
|
||||||
// TODO: this doesn't look right - review!
|
// TODO: this doesn't look right - review!
|
||||||
return DROP;
|
return DROP;
|
||||||
}
|
}
|
||||||
@ -1524,7 +1525,7 @@ TCPEndpoint::_Receive(tcp_segment_header& segment, net_buffer* buffer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (segment.flags & TCP_FLAG_RESET) {
|
if ((segment.flags & TCP_FLAG_RESET) != 0) {
|
||||||
// Is this a valid reset?
|
// Is this a valid reset?
|
||||||
// We generally ignore resets in time wait state (see RFC 1337)
|
// We generally ignore resets in time wait state (see RFC 1337)
|
||||||
if (fLastAcknowledgeSent <= segment.sequence
|
if (fLastAcknowledgeSent <= segment.sequence
|
||||||
@ -1556,9 +1557,11 @@ TCPEndpoint::_Receive(tcp_segment_header& segment, net_buffer* buffer)
|
|||||||
return DROP | RESET;
|
return DROP | RESET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Check this! Why do we advertize a window outside of what we should
|
||||||
|
// buffer?
|
||||||
fReceiveWindow = max_c(fReceiveQueue.Free(), fReceiveWindow);
|
fReceiveWindow = max_c(fReceiveQueue.Free(), fReceiveWindow);
|
||||||
// the window must not shrink
|
// the window must not shrink
|
||||||
|
|
||||||
// trim buffer to be within the receive window
|
// trim buffer to be within the receive window
|
||||||
int32 drop = (int32)(fReceiveNext - segment.sequence).Number();
|
int32 drop = (int32)(fReceiveNext - segment.sequence).Number();
|
||||||
if (drop > 0) {
|
if (drop > 0) {
|
||||||
@ -1959,7 +1962,7 @@ TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
|
|||||||
|
|
||||||
if (consumedWindow > sendWindow) {
|
if (consumedWindow > sendWindow) {
|
||||||
sendWindow = 0;
|
sendWindow = 0;
|
||||||
// TODO enter persist state? try to get a window update.
|
// TODO: enter persist state? try to get a window update.
|
||||||
} else
|
} else
|
||||||
sendWindow -= consumedWindow;
|
sendWindow -= consumedWindow;
|
||||||
|
|
||||||
@ -2019,8 +2022,8 @@ TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
|
|||||||
PrintAddress(buffer->destination), segment.flags, segment.sequence,
|
PrintAddress(buffer->destination), segment.flags, segment.sequence,
|
||||||
segment.acknowledge, segment.advertised_window,
|
segment.acknowledge, segment.advertised_window,
|
||||||
fCongestionWindow, fSlowStartThreshold, segmentLength,
|
fCongestionWindow, fSlowStartThreshold, segmentLength,
|
||||||
(uint32)fSendQueue.FirstSequence(),
|
fSendQueue.FirstSequence().Number(),
|
||||||
(uint32)fSendQueue.LastSequence());
|
fSendQueue.LastSequence().Number());
|
||||||
T(Send(this, segment, buffer, fSendQueue.FirstSequence(),
|
T(Send(this, segment, buffer, fSendQueue.FirstSequence(),
|
||||||
fSendQueue.LastSequence()));
|
fSendQueue.LastSequence()));
|
||||||
|
|
||||||
|
@ -108,8 +108,7 @@ public:
|
|||||||
return fNumber - 1;
|
return fNumber - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conceptually private, but used in global operators.
|
private:
|
||||||
//private:
|
|
||||||
uint32 fNumber;
|
uint32 fNumber;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -120,56 +119,56 @@ public:
|
|||||||
inline bool
|
inline bool
|
||||||
operator>(tcp_sequence a, tcp_sequence b)
|
operator>(tcp_sequence a, tcp_sequence b)
|
||||||
{
|
{
|
||||||
return (int32)(a.fNumber - b.fNumber) > 0;
|
return (int32)(a.Number() - b.Number()) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
operator>=(tcp_sequence a, tcp_sequence b)
|
operator>=(tcp_sequence a, tcp_sequence b)
|
||||||
{
|
{
|
||||||
return (int32)(a.fNumber - b.fNumber) >= 0;
|
return (int32)(a.Number() - b.Number()) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
operator<(tcp_sequence a, tcp_sequence b)
|
operator<(tcp_sequence a, tcp_sequence b)
|
||||||
{
|
{
|
||||||
return (int32)(a.fNumber - b.fNumber) < 0;
|
return (int32)(a.Number() - b.Number()) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
operator<=(tcp_sequence a, tcp_sequence b)
|
operator<=(tcp_sequence a, tcp_sequence b)
|
||||||
{
|
{
|
||||||
return (int32)(a.fNumber - b.fNumber) <= 0;
|
return (int32)(a.Number() - b.Number()) <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline tcp_sequence
|
inline tcp_sequence
|
||||||
operator+(tcp_sequence a, tcp_sequence b)
|
operator+(tcp_sequence a, tcp_sequence b)
|
||||||
{
|
{
|
||||||
return a.fNumber + b.fNumber;
|
return a.Number() + b.Number();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline tcp_sequence
|
inline tcp_sequence
|
||||||
operator-(tcp_sequence a, tcp_sequence b)
|
operator-(tcp_sequence a, tcp_sequence b)
|
||||||
{
|
{
|
||||||
return a.fNumber - b.fNumber;
|
return a.Number() - b.Number();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
operator!=(tcp_sequence a, tcp_sequence b)
|
operator!=(tcp_sequence a, tcp_sequence b)
|
||||||
{
|
{
|
||||||
return a.fNumber != b.fNumber;
|
return a.Number() != b.Number();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
operator==(tcp_sequence a, tcp_sequence b)
|
operator==(tcp_sequence a, tcp_sequence b)
|
||||||
{
|
{
|
||||||
return a.fNumber == b.fNumber;
|
return a.Number() == b.Number();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user