From 92fde3d18bd6fe525103efad8fd7ccea93d3e131 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 23 Jan 2017 12:07:07 +0000 Subject: [PATCH] Don't send TCP FIN flag yet if next segment will also have data. --- src/socket/tcp.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/socket/tcp.rs b/src/socket/tcp.rs index e948e84..3cc8911 100644 --- a/src/socket/tcp.rs +++ b/src/socket/tcp.rs @@ -901,8 +901,12 @@ impl<'a> TcpSocket<'a> { self.remote_last_seq += data.len(); should_send = true; } + // The FIN control flag occupies the place in the sequence space after + // the data in the current segment. If we still have some data left for the next + // segment (e.g. the receiver window is too small), then don't send FIN just yet. + let all_data_sent = self.tx_buffer.len() == offset + size; match self.state { - State::FinWait1 | State::LastAck => { + State::FinWait1 | State::LastAck if all_data_sent => { // We should notify the other side that we've closed the transmit half // of the connection. net_trace!("[{}]{}:{}: sending FIN|ACK", @@ -1619,6 +1623,20 @@ mod test { sanity!(s, socket_closing()); } + #[test] + fn test_fin_wait_1_fin_with_data_queued() { + let mut s = socket_established(); + s.remote_win_len = 6; + s.send_slice(b"abcdef123456").unwrap(); + s.close(); + recv!(s, [TcpRepr { + seq_number: LOCAL_SEQ + 1, + ack_number: Some(REMOTE_SEQ + 1), + payload: &b"abcdef"[..], + ..RECV_TEMPL + }]); + } + #[test] fn test_fin_wait_1_close() { let mut s = socket_fin_wait_1();