tcp: send RST instead of FIN, when user closed and received data get lost
this is the abort way of closing a connection. tested with golang's http test TestTransportGzip. All TestTransport* pass. Change-Id: Ib79516eb8a16480d7a4425675748ff76554e9c6c Reviewed-on: https://review.haiku-os.org/c/haiku/+/10054 Reviewed-by: waddlesplash <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
5860e2c161
commit
9d587f4f3f
@@ -323,7 +323,8 @@ enum {
|
|||||||
FLAG_RECOVERY = 0x40,
|
FLAG_RECOVERY = 0x40,
|
||||||
FLAG_OPTION_SACK_PERMITTED = 0x80,
|
FLAG_OPTION_SACK_PERMITTED = 0x80,
|
||||||
FLAG_AUTO_RECEIVE_BUFFER_SIZE = 0x100,
|
FLAG_AUTO_RECEIVE_BUFFER_SIZE = 0x100,
|
||||||
FLAG_CAN_NOTIFY = 0x200
|
FLAG_CAN_NOTIFY = 0x200,
|
||||||
|
FLAG_USER_CLOSED = 0x400
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -821,7 +822,7 @@ TCPEndpoint::SendData(net_buffer *buffer)
|
|||||||
|
|
||||||
TRACE("SendData(buffer %p, size %" B_PRIu32 ", flags %#" B_PRIx32
|
TRACE("SendData(buffer %p, size %" B_PRIu32 ", flags %#" B_PRIx32
|
||||||
") [total %" B_PRIuSIZE " bytes, has %" B_PRIuSIZE "]", buffer,
|
") [total %" B_PRIuSIZE " bytes, has %" B_PRIuSIZE "]", buffer,
|
||||||
buffer->size, buffer->flags, fSendQueue.Size(), fSendQueue.Free());
|
buffer->size, buffer->msg_flags, fSendQueue.Size(), fSendQueue.Free());
|
||||||
T(APICall(this, "senddata"));
|
T(APICall(this, "senddata"));
|
||||||
|
|
||||||
const uint32 flags = buffer->msg_flags;
|
const uint32 flags = buffer->msg_flags;
|
||||||
@@ -1222,9 +1223,14 @@ TCPEndpoint::_Disconnect(bool closing)
|
|||||||
{
|
{
|
||||||
tcp_state previousState = fState;
|
tcp_state previousState = fState;
|
||||||
|
|
||||||
if (fState == SYNCHRONIZE_RECEIVED || fState == ESTABLISHED)
|
if (fState == SYNCHRONIZE_RECEIVED || fState == ESTABLISHED) {
|
||||||
|
// We "should send a RST if there is any unread received data,
|
||||||
|
// or if any new data is received" (RFC 2525 § 2.16). This
|
||||||
|
// isn't a TCP state, so use a flag.
|
||||||
|
if (closing && fReceiveQueue.Available() > 0)
|
||||||
|
fFlags |= FLAG_USER_CLOSED;
|
||||||
fState = FINISH_SENT;
|
fState = FINISH_SENT;
|
||||||
else if (fState == FINISH_RECEIVED)
|
} else if (fState == FINISH_RECEIVED)
|
||||||
fState = WAIT_FOR_FINISH_ACKNOWLEDGE;
|
fState = WAIT_FOR_FINISH_ACKNOWLEDGE;
|
||||||
else
|
else
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -1238,6 +1244,9 @@ TCPEndpoint::_Disconnect(bool closing)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((fFlags & FLAG_USER_CLOSED) != 0)
|
||||||
|
fState = CLOSED;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2344,7 +2353,7 @@ TCPEndpoint::_SendQueued(bool force)
|
|||||||
|
|
||||||
if ((fSendNext + segmentLength) == fSendQueue.LastSequence() && !force) {
|
if ((fSendNext + segmentLength) == fSendQueue.LastSequence() && !force) {
|
||||||
if (state_needs_finish(fState))
|
if (state_needs_finish(fState))
|
||||||
segment.flags |= TCP_FLAG_FINISH;
|
segment.flags |= (fFlags & FLAG_USER_CLOSED) != 0 ? TCP_FLAG_RESET : TCP_FLAG_FINISH;
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
segment.flags |= TCP_FLAG_PUSH;
|
segment.flags |= TCP_FLAG_PUSH;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user