* 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
This commit is contained in:
parent
f466d35d9c
commit
8e0a418b70
@ -15,6 +15,7 @@
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <new>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -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);
|
||||
|
@ -151,6 +151,7 @@ private:
|
||||
tcp_sequence fSendUnacknowledged;
|
||||
tcp_sequence fSendNext;
|
||||
tcp_sequence fSendMax;
|
||||
tcp_sequence fSendUrgentOffset;
|
||||
uint32 fSendWindow;
|
||||
uint32 fSendMaxWindow;
|
||||
uint32 fSendMaxSegmentSize;
|
||||
|
Loading…
Reference in New Issue
Block a user