From 8e0a418b70d2599c9eaf2a410af2f48afd5563f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 29 Apr 2008 12:42:50 +0000 Subject: [PATCH] * Implemented sending of urgent data. Seems to work fine, but of course only if the other end is not a Haiku host (retrieving of urgent data is still missing). * Resolved TODO: SendData() now sends a SIGPIPE when trying to send on a closed connection. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25245 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../network/protocols/tcp/TCPEndpoint.cpp | 36 ++++++++++++++++--- .../network/protocols/tcp/TCPEndpoint.h | 1 + 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp index afa8650911..f18cd07613 100644 --- a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp +++ b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -375,6 +376,7 @@ TCPEndpoint::TCPEndpoint(net_socket* socket) fSendUnacknowledged(0), fSendNext(0), fSendMax(0), + fSendUrgentOffset(0), fSendWindow(0), fSendMaxWindow(0), fSendMaxSegmentSize(TCP_DEFAULT_MAX_SEGMENT_SIZE), @@ -721,7 +723,7 @@ TCPEndpoint::SendData(net_buffer *buffer) if (fState == FINISH_SENT || fState == FINISH_ACKNOWLEDGED || fState == CLOSING || fState == WAIT_FOR_FINISH_ACKNOWLEDGE || fState == TIME_WAIT) { - // TODO: send SIGPIPE signal to app? + send_signal(find_thread(NULL), SIGPIPE); return EPIPE; } @@ -749,8 +751,17 @@ TCPEndpoint::SendData(net_buffer *buffer) TRACE(" SendData(): %lu bytes used.", fSendQueue.Used()); + bool force = false; + if ((buffer->flags & MSG_OOB) != 0) { + fSendUrgentOffset = fSendQueue.LastSequence(); + // RFC 961 specifies that the urgent offset points to the last + // byte of urgent data. However, this is commonly implemented as + // here, ie. it points to the first byte after the urgent data. + force = true; + } + if (fState == ESTABLISHED || fState == FINISH_RECEIVED) - _SendQueued(); + _SendQueued(force); return B_OK; } @@ -1710,7 +1721,8 @@ TCPEndpoint::_ShouldSendSegment(tcp_segment_header& segment, uint32 length, // Avoid the silly window syndrome - we only send a segment in case: // - we have a full segment to send, or // - we're at the end of our buffer queue, or - // - the buffer is at least larger than half of the maximum send window, or + // - the buffer is at least larger than half of the maximum send window, + // or // - we're retransmitting data if (length == segmentMaxSize || (fOptions & TCP_NODELAY) != 0 @@ -1736,6 +1748,10 @@ TCPEndpoint::_ShouldSendSegment(tcp_segment_header& segment, uint32 length, | TCP_FLAG_RESET)) != 0) return true; + // We do have urgent data pending + if (fSendUrgentOffset > fSendNext) + return true; + // there is no reason to send a segment just now return false; } @@ -1788,7 +1804,17 @@ TCPEndpoint::_SendQueued(bool force, uint32 sendWindow) segment.advertised_window = min_c(TCP_MAX_WINDOW, availableBytes); segment.acknowledge = fReceiveNext; - segment.urgent_offset = 0; + + // Process urgent data + if (fSendUrgentOffset > fSendNext) { + segment.flags |= TCP_FLAG_URGENT; + segment.urgent_offset = fSendUrgentOffset - fSendNext; + } else { + fSendUrgentOffset = fSendUnacknowledged; + // Keep urgent offset updated, so that it doesn't reach into our + // send window on overlap + segment.urgent_offset = 0; + } if (fCongestionWindow > 0 && fCongestionWindow < sendWindow) sendWindow = fCongestionWindow; @@ -1964,6 +1990,7 @@ TCPEndpoint::_PrepareSendPath(const sockaddr* peer) fSendNext = fInitialSendSequence; fSendUnacknowledged = fInitialSendSequence; fSendMax = fInitialSendSequence; + fSendUrgentOffset = fInitialSendSequence; // we are counting the SYN here fSendQueue.SetInitialSequence(fSendNext + 1); @@ -2152,6 +2179,7 @@ TCPEndpoint::Dump() const kprintf(" unacknowledged: %lu\n", (uint32)fSendUnacknowledged); kprintf(" next: %lu\n", (uint32)fSendNext); kprintf(" max: %lu\n", (uint32)fSendMax); + kprintf(" urgent offset: %lu\n", (uint32)fSendUrgentOffset); kprintf(" window: %lu\n", fSendWindow); kprintf(" max window: %lu\n", fSendMaxWindow); kprintf(" max segment size: %lu\n", fSendMaxSegmentSize); diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h index 2fb8bb67b1..8ce4752f0b 100644 --- a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h +++ b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.h @@ -151,6 +151,7 @@ private: tcp_sequence fSendUnacknowledged; tcp_sequence fSendNext; tcp_sequence fSendMax; + tcp_sequence fSendUrgentOffset; uint32 fSendWindow; uint32 fSendMaxWindow; uint32 fSendMaxSegmentSize;