bonefish + axeld:

* There was one incorrect check in BufferQueue::Get() that happened because
  the wrong operator was used due to the uint32 cast operator.
* Consequently, we removed the uint32 cast operator, and changed the code
  to deal with this. Fortunately, no other bugs were observed.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29928 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-04-05 12:00:36 +00:00
parent e2238bd923
commit c21f81c11a
4 changed files with 134 additions and 55 deletions
@@ -91,14 +91,15 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
} }
if (sequence < fFirstSequence) { if (sequence < fFirstSequence) {
// this buffer contains data that is already long gone - trim it // this buffer contains data that is already long gone - trim it
gBufferModule->remove_header(buffer, fFirstSequence - sequence); gBufferModule->remove_header(buffer,
(fFirstSequence - sequence).Number());
sequence = fFirstSequence; sequence = fFirstSequence;
} }
if (fList.IsEmpty() || sequence >= fLastSequence) { if (fList.IsEmpty() || sequence >= fLastSequence) {
// we usually just add the buffer to the end of the queue // we usually just add the buffer to the end of the queue
fList.Add(buffer); fList.Add(buffer);
buffer->sequence = sequence; buffer->sequence = sequence.Number();
if (sequence == fLastSequence if (sequence == fLastSequence
&& fLastSequence - fFirstSequence == fNumBytes) { && fLastSequence - fFirstSequence == fNumBytes) {
@@ -157,7 +158,7 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
> sequence) { > sequence) {
// We already have the first part of this buffer // We already have the first part of this buffer
gBufferModule->remove_header(buffer, gBufferModule->remove_header(buffer,
previous->sequence + previous->size - sequence); (previous->sequence + previous->size - sequence).Number());
sequence = previous->sequence + previous->size; sequence = previous->sequence + previous->size;
} }
} }
@@ -179,7 +180,7 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
} else if (tcp_sequence(next->sequence) > sequence) { } else if (tcp_sequence(next->sequence) > sequence) {
// We have the end of this buffer already // We have the end of this buffer already
gBufferModule->remove_trailer(buffer, gBufferModule->remove_trailer(buffer,
sequence + buffer->size - next->sequence); (sequence + buffer->size - next->sequence).Number());
} else { } else {
// We already have this data // We already have this data
gBufferModule->free(buffer); gBufferModule->free(buffer);
@@ -196,7 +197,7 @@ BufferQueue::Add(net_buffer *buffer, tcp_sequence sequence)
} }
fList.Insert(next, buffer); fList.Insert(next, buffer);
buffer->sequence = sequence; buffer->sequence = sequence.Number();
fNumBytes += buffer->size; fNumBytes += buffer->size;
// we might need to update the number of bytes available // we might need to update the number of bytes available
@@ -253,7 +254,7 @@ BufferQueue::RemoveUntil(tcp_sequence sequence)
gBufferModule->free(buffer); gBufferModule->free(buffer);
} else { } else {
// remove the header as far as needed // remove the header as far as needed
size_t size = sequence - buffer->sequence; size_t size = (sequence - buffer->sequence).Number();
gBufferModule->remove_header(buffer, size); gBufferModule->remove_header(buffer, size);
buffer->sequence += size; buffer->sequence += size;
@@ -290,7 +291,7 @@ BufferQueue::Get(net_buffer *buffer, tcp_sequence sequence, size_t bytes)
return B_BAD_VALUE; return B_BAD_VALUE;
} }
if (tcp_sequence(sequence + bytes) > fLastSequence) if (tcp_sequence(sequence + bytes) > fLastSequence)
bytes = fLastSequence - sequence; bytes = (fLastSequence - sequence).Number();
size_t bytesLeft = bytes; size_t bytesLeft = bytes;
@@ -305,14 +306,14 @@ BufferQueue::Get(net_buffer *buffer, tcp_sequence sequence, size_t bytes)
if (source == NULL) if (source == NULL)
panic("we should have had that data..."); panic("we should have had that data...");
if (source->sequence > sequence) { if (tcp_sequence(source->sequence) > sequence) {
panic("source %p, sequence = %lu (%lu)\n", source, source->sequence, panic("source %p, sequence = %lu (%lu)\n", source, source->sequence,
(uint32)sequence); sequence.Number());
} }
// clone the data // clone the data
uint32 offset = sequence - source->sequence; uint32 offset = (sequence - source->sequence).Number();
while (source != NULL && bytesLeft > 0) { while (source != NULL && bytesLeft > 0) {
size_t size = min_c(source->size - offset, bytesLeft); size_t size = min_c(source->size - offset, bytesLeft);
@@ -416,10 +417,10 @@ BufferQueue::Get(size_t bytes, bool remove, net_buffer **_buffer)
size_t size_t
BufferQueue::Available(tcp_sequence sequence) const BufferQueue::Available(tcp_sequence sequence) const
{ {
if (sequence > (uint32)fFirstSequence + fContiguousBytes) if (sequence > (fFirstSequence + fContiguousBytes).Number())
return 0; return 0;
return fContiguousBytes + fFirstSequence - sequence; return (fContiguousBytes + fFirstSequence - sequence).Number();
} }
@@ -76,8 +76,8 @@ 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 return fPushPointer != 0 && fPushPointer > fFirstSequence
&& fPushPointer > fFirstSequence ? fPushPointer - fFirstSequence : 0; ? (fPushPointer - fFirstSequence).Number() : 0;
} }
#endif // BUFFER_QUEUE_H #endif // BUFFER_QUEUE_H
@@ -1548,7 +1548,7 @@ TCPEndpoint::_Receive(tcp_segment_header& segment, net_buffer* buffer)
// 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 = fReceiveNext - segment.sequence; int32 drop = (int32)(fReceiveNext - segment.sequence).Number();
if (drop > 0) { if (drop > 0) {
if ((uint32)drop > buffer->size if ((uint32)drop > buffer->size
|| ((uint32)drop == buffer->size || ((uint32)drop == buffer->size
@@ -1566,7 +1566,8 @@ TCPEndpoint::_Receive(tcp_segment_header& segment, net_buffer* buffer)
int32 action = KEEP; int32 action = KEEP;
drop = segment.sequence + buffer->size - (fReceiveNext + fReceiveWindow); drop = (int32)(segment.sequence + buffer->size
- (fReceiveNext + fReceiveWindow)).Number();
if (drop > 0) { if (drop > 0) {
// remove data exceeding our window // remove data exceeding our window
if ((uint32)drop >= buffer->size) { if ((uint32)drop >= buffer->size) {
@@ -1844,7 +1845,7 @@ TCPEndpoint::_ShouldSendSegment(tcp_segment_header& segment, uint32 length,
if (segment.advertised_window > 0) { if (segment.advertised_window > 0) {
// correct the window to take into account what already has been advertised // correct the window to take into account what already has been advertised
uint32 window = (segment.advertised_window << fReceiveWindowShift) uint32 window = (segment.advertised_window << fReceiveWindowShift)
- (fReceiveMaxAdvertised - fReceiveNext); - (fReceiveMaxAdvertised - fReceiveNext).Number();
// if we can advertise a window larger than twice the maximum segment // if we can advertise a window larger than twice the maximum segment
// size, or half the maximum buffer size we send a window update // size, or half the maximum buffer size we send a window update
@@ -1912,14 +1913,14 @@ TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
else else
segment.advertised_window = min_c(TCP_MAX_WINDOW, availableBytes); segment.advertised_window = min_c(TCP_MAX_WINDOW, availableBytes);
segment.acknowledge = fReceiveNext; segment.acknowledge = fReceiveNext.Number();
// Process urgent data // Process urgent data
if (fSendUrgentOffset > fSendNext) { if (fSendUrgentOffset > fSendNext) {
segment.flags |= TCP_FLAG_URGENT; segment.flags |= TCP_FLAG_URGENT;
segment.urgent_offset = fSendUrgentOffset - fSendNext; segment.urgent_offset = (fSendUrgentOffset - fSendNext).Number();
} else { } else {
fSendUrgentOffset = fSendUnacknowledged; fSendUrgentOffset = fSendUnacknowledged.Number();
// Keep urgent offset updated, so that it doesn't reach into our // Keep urgent offset updated, so that it doesn't reach into our
// send window on overlap // send window on overlap
segment.urgent_offset = 0; segment.urgent_offset = 0;
@@ -1942,8 +1943,8 @@ TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
// reduced (by congestion for instance), so at some point in time flight // reduced (by congestion for instance), so at some point in time flight
// size may be larger than the currently calculated window. // size may be larger than the currently calculated window.
uint32 flightSize = fSendMax - fSendUnacknowledged; uint32 flightSize = (fSendMax - fSendUnacknowledged).Number();
uint32 consumedWindow = fSendNext - fSendUnacknowledged; uint32 consumedWindow = (fSendNext - fSendUnacknowledged).Number();
if (consumedWindow > sendWindow) { if (consumedWindow > sendWindow) {
sendWindow = 0; sendWindow = 0;
@@ -1998,7 +1999,7 @@ TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
PeerAddress().CopyTo(buffer->destination); PeerAddress().CopyTo(buffer->destination);
uint32 size = buffer->size; uint32 size = buffer->size;
segment.sequence = fSendNext; segment.sequence = fSendNext.Number();
TRACE("SendQueued(): buffer %p (%lu bytes) address %s to %s\n" TRACE("SendQueued(): buffer %p (%lu bytes) address %s to %s\n"
"\tflags 0x%x, seq %lu, ack %lu, rwnd %hu, cwnd %lu, ssthresh %lu\n" "\tflags 0x%x, seq %lu, ack %lu, rwnd %hu, cwnd %lu, ssthresh %lu\n"
@@ -2033,7 +2034,7 @@ TCPEndpoint::_SendQueued(bool force, uint32 sendWindow)
if (segment.flags & TCP_FLAG_FINISH) if (segment.flags & TCP_FLAG_FINISH)
size++; size++;
uint32 sendMax = fSendMax; uint32 sendMax = fSendMax.Number();
fSendNext += size; fSendNext += size;
if (fSendMax < fSendNext) if (fSendMax < fSendNext)
fSendMax = fSendNext; fSendMax = fSendNext;
@@ -2205,7 +2206,7 @@ TCPEndpoint::_UpdateRoundTripTime(int32 roundTripTime)
void void
TCPEndpoint::_ResetSlowStart() TCPEndpoint::_ResetSlowStart()
{ {
fSlowStartThreshold = max_c((fSendMax - fSendUnacknowledged) / 2, fSlowStartThreshold = max_c((fSendMax - fSendUnacknowledged).Number() / 2,
2 * fSendMaxSegmentSize); 2 * fSendMaxSegmentSize);
fCongestionWindow = fSendMaxSegmentSize; fCongestionWindow = fSendMaxSegmentSize;
} }
@@ -2300,11 +2301,11 @@ TCPEndpoint::Dump() const
kprintf(" accept sem: %ld\n", fAcceptSemaphore); kprintf(" accept sem: %ld\n", fAcceptSemaphore);
kprintf(" options: 0x%lx\n", (uint32)fOptions); kprintf(" options: 0x%lx\n", (uint32)fOptions);
kprintf(" send\n"); kprintf(" send\n");
kprintf(" window shift: %lu\n", (uint32)fSendWindowShift); kprintf(" window shift: %u\n", fSendWindowShift);
kprintf(" unacknowledged: %lu\n", (uint32)fSendUnacknowledged); kprintf(" unacknowledged: %lu\n", fSendUnacknowledged.Number());
kprintf(" next: %lu\n", (uint32)fSendNext); kprintf(" next: %lu\n", fSendNext.Number());
kprintf(" max: %lu\n", (uint32)fSendMax); kprintf(" max: %lu\n", fSendMax.Number());
kprintf(" urgent offset: %lu\n", (uint32)fSendUrgentOffset); kprintf(" urgent offset: %lu\n", fSendUrgentOffset.Number());
kprintf(" window: %lu\n", fSendWindow); kprintf(" window: %lu\n", fSendWindow);
kprintf(" max window: %lu\n", fSendMaxWindow); kprintf(" max window: %lu\n", fSendMaxWindow);
kprintf(" max segment size: %lu\n", fSendMaxSegmentSize); kprintf(" max segment size: %lu\n", fSendMaxSegmentSize);
@@ -2312,25 +2313,25 @@ TCPEndpoint::Dump() const
#if DEBUG_BUFFER_QUEUE #if DEBUG_BUFFER_QUEUE
fSendQueue.Dump(); fSendQueue.Dump();
#endif #endif
kprintf(" last acknowledge sent: %lu\n", (uint32)fLastAcknowledgeSent); kprintf(" last acknowledge sent: %lu\n", fLastAcknowledgeSent.Number());
kprintf(" initial sequence: %lu\n", (uint32)fInitialSendSequence); kprintf(" initial sequence: %lu\n", fInitialSendSequence.Number());
kprintf(" receive\n"); kprintf(" receive\n");
kprintf(" window shift: %lu\n", (uint32)fReceiveWindowShift); kprintf(" window shift: %u\n", fReceiveWindowShift);
kprintf(" next: %lu\n", (uint32)fReceiveNext); kprintf(" next: %lu\n", fReceiveNext.Number());
kprintf(" max advertised: %lu\n", (uint32)fReceiveMaxAdvertised); kprintf(" max advertised: %lu\n", fReceiveMaxAdvertised.Number());
kprintf(" window: %lu\n", (uint32)fReceiveWindow); kprintf(" window: %lu\n", fReceiveWindow);
kprintf(" max segment size: %lu\n", (uint32)fReceiveMaxSegmentSize); kprintf(" max segment size: %lu\n", fReceiveMaxSegmentSize);
kprintf(" queue: %lu / %lu\n", fReceiveQueue.Available(), kprintf(" queue: %lu / %lu\n", fReceiveQueue.Available(),
fReceiveQueue.Size()); fReceiveQueue.Size());
#if DEBUG_BUFFER_QUEUE #if DEBUG_BUFFER_QUEUE
fReceiveQueue.Dump(); fReceiveQueue.Dump();
#endif #endif
kprintf(" initial sequence: %lu\n", (uint32)fInitialReceiveSequence); kprintf(" initial sequence: %lu\n", fInitialReceiveSequence.Number());
kprintf(" duplicate acknowledge count: %lu\n", kprintf(" duplicate acknowledge count: %lu\n",
fDuplicateAcknowledgeCount); fDuplicateAcknowledgeCount);
kprintf(" round trip time: %ld (deviation %ld)\n", fRoundTripTime, kprintf(" round trip time: %ld (deviation %ld)\n", fRoundTripTime,
fRoundTripDeviation); fRoundTripDeviation);
kprintf(" retransmit timeout: %llu\n", (uint64)fRetransmitTimeout); kprintf(" retransmit timeout: %lld\n", fRetransmitTimeout);
kprintf(" congestion window: %lu\n", fCongestionWindow); kprintf(" congestion window: %lu\n", fCongestionWindow);
kprintf(" slow start threshold: %lu\n", fSlowStartThreshold); kprintf(" slow start threshold: %lu\n", fSlowStartThreshold);
} }
+93 -16
View File
@@ -73,29 +73,106 @@ struct tcp_header {
class tcp_sequence { class tcp_sequence {
public: public:
tcp_sequence() {} inline tcp_sequence() {}
tcp_sequence(uint32 sequence) : fNumber(sequence) {} inline tcp_sequence(uint32 sequence)
: fNumber(sequence)
{
}
operator uint32() const { return fNumber; } inline uint32 Number() const
{
return fNumber;
}
void operator=(uint32 sequence) { fNumber = sequence; } inline tcp_sequence& operator=(tcp_sequence sequence)
bool operator>(uint32 sequence) const {
{ return (int32)(fNumber - sequence) > 0; } fNumber = sequence.fNumber;
bool operator>=(uint32 sequence) const return *this;
{ return (int32)(fNumber - sequence) >= 0; } }
bool operator<(uint32 sequence) const
{ return (int32)(fNumber - sequence) < 0; }
bool operator<=(uint32 sequence) const
{ return (int32)(fNumber - sequence) <= 0; }
uint32& operator+=(uint32 sequence) { return fNumber += sequence; } inline tcp_sequence& operator+=(tcp_sequence sequence)
uint32& operator++() { return ++fNumber; } {
uint32 operator++(int _) { return fNumber++; } fNumber += sequence.fNumber;
return *this;
}
private: inline tcp_sequence& operator++()
{
fNumber++;
return *this;
}
inline tcp_sequence operator++(int _)
{
fNumber++;
return fNumber - 1;
}
// Conceptually private, but used in global operators.
//private:
uint32 fNumber; uint32 fNumber;
}; };
// Global tcp_sequence Operators
inline bool
operator>(tcp_sequence a, tcp_sequence b)
{
return (int32)(a.fNumber - b.fNumber) > 0;
}
inline bool
operator>=(tcp_sequence a, tcp_sequence b)
{
return (int32)(a.fNumber - b.fNumber) >= 0;
}
inline bool
operator<(tcp_sequence a, tcp_sequence b)
{
return (int32)(a.fNumber - b.fNumber) < 0;
}
inline bool
operator<=(tcp_sequence a, tcp_sequence b)
{
return (int32)(a.fNumber - b.fNumber) <= 0;
}
inline tcp_sequence
operator+(tcp_sequence a, tcp_sequence b)
{
return a.fNumber + b.fNumber;
}
inline tcp_sequence
operator-(tcp_sequence a, tcp_sequence b)
{
return a.fNumber - b.fNumber;
}
inline bool
operator!=(tcp_sequence a, tcp_sequence b)
{
return a.fNumber != b.fNumber;
}
inline bool
operator==(tcp_sequence a, tcp_sequence b)
{
return a.fNumber == b.fNumber;
}
// TCP flag constants // TCP flag constants
#define TCP_FLAG_FINISH 0x01 #define TCP_FLAG_FINISH 0x01
#define TCP_FLAG_SYNCHRONIZE 0x02 #define TCP_FLAG_SYNCHRONIZE 0x02