Skip to content

Commit b90495f

Browse files
committedJan 23, 2017
Correctly treat TCP ACKs that acknowledge both data and a FIN.
1 parent 2fedc76 commit b90495f

File tree

1 file changed

+48
-18
lines changed

1 file changed

+48
-18
lines changed
 

Diff for: ‎src/socket/tcp.rs

+48-18
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,18 @@ impl<'a> TcpSocket<'a> {
575575
if !self.remote_endpoint.addr.is_unspecified() &&
576576
self.remote_endpoint.addr != ip_repr.src_addr() { return Err(Error::Rejected) }
577577

578+
// Consider how much the sequence number space differs from the transmit buffer space.
579+
let (sent_syn, sent_fin) = match self.state {
580+
// In SYN-SENT or SYN-RECEIVED, we've just sent a SYN.
581+
State::SynSent | State::SynReceived => (true, false),
582+
// In FIN-WAIT-1, LAST-ACK, or CLOSING, we've just sent a FIN.
583+
State::FinWait1 | State::LastAck | State::Closing => (false, true),
584+
// In all other states we've already got acknowledgemetns for
585+
// all of the control flags we sent.
586+
_ => (false, false)
587+
};
588+
let control_len = (sent_syn as usize) + (sent_fin as usize);
589+
578590
// Reject unacceptable acknowledgements.
579591
match (self.state, repr) {
580592
// The initial SYN (or whatever) cannot contain an acknowledgement.
@@ -609,16 +621,7 @@ impl<'a> TcpSocket<'a> {
609621
return Err(Error::Malformed)
610622
}
611623
// Every acknowledgement must be for transmitted but unacknowledged data.
612-
(state, TcpRepr { ack_number: Some(ack_number), .. }) => {
613-
let control_len = match state {
614-
// In SYN-SENT or SYN-RECEIVED, we've just sent a SYN.
615-
State::SynSent | State::SynReceived => 1,
616-
// In FIN-WAIT-1, LAST-ACK, or CLOSING, we've just sent a FIN.
617-
State::FinWait1 | State::LastAck | State::Closing => 1,
618-
// In all other states we've already got acknowledgemetns for
619-
// all of the control flags we sent.
620-
_ => 0
621-
};
624+
(_, TcpRepr { ack_number: Some(ack_number), .. }) => {
622625
let unacknowledged = self.tx_buffer.len() + control_len;
623626
if !(ack_number >= self.local_seq_no &&
624627
ack_number <= (self.local_seq_no + unacknowledged)) {
@@ -708,7 +711,6 @@ impl<'a> TcpSocket<'a> {
708711

709712
// ACK packets in the SYN-RECEIVED state change it to ESTABLISHED.
710713
(State::SynReceived, TcpRepr { control: TcpControl::None, .. }) => {
711-
self.local_seq_no += 1;
712714
self.set_state(State::Established);
713715
self.retransmit.reset();
714716
}
@@ -725,7 +727,6 @@ impl<'a> TcpSocket<'a> {
725727

726728
// ACK packets in FIN-WAIT-1 state change it to FIN-WAIT-2.
727729
(State::FinWait1, TcpRepr { control: TcpControl::None, .. }) => {
728-
self.local_seq_no += 1;
729730
self.set_state(State::FinWait2);
730731
}
731732

@@ -745,7 +746,6 @@ impl<'a> TcpSocket<'a> {
745746

746747
// ACK packets in CLOSING state change it to TIME-WAIT.
747748
(State::Closing, TcpRepr { control: TcpControl::None, .. }) => {
748-
self.local_seq_no += 1;
749749
self.set_state(State::TimeWait);
750750
self.retransmit.reset();
751751
}
@@ -758,7 +758,6 @@ impl<'a> TcpSocket<'a> {
758758
// Clear the remote endpoint, or we'll send an RST there.
759759
self.set_state(State::Closed);
760760
self.remote_endpoint = IpEndpoint::default();
761-
self.local_seq_no += 1;
762761
}
763762

764763
_ => {
@@ -770,13 +769,23 @@ impl<'a> TcpSocket<'a> {
770769

771770
// Dequeue acknowledged octets.
772771
if let Some(ack_number) = repr.ack_number {
773-
let ack_length = ack_number - self.local_seq_no;
774-
if ack_length > 0 {
772+
let mut ack_len = ack_number - self.local_seq_no;
773+
// There could have been no data sent before the SYN, so we always remove it
774+
// from the sequence space.
775+
if sent_syn {
776+
ack_len -= 1
777+
}
778+
// We could've sent data before the FIN, so only remove FIN from the sequence
779+
// space if all of that data is acknowledged.
780+
if sent_fin && self.tx_buffer.len() + 1 == ack_len {
781+
ack_len -= 1
782+
}
783+
if ack_len > 0 {
775784
net_trace!("[{}]{}:{}: tx buffer: dequeueing {} octets (now {})",
776785
self.debug_id, self.local_endpoint, self.remote_endpoint,
777-
ack_length, self.tx_buffer.len() - ack_length);
786+
ack_len, self.tx_buffer.len() - ack_len);
778787
}
779-
self.tx_buffer.advance(ack_length);
788+
self.tx_buffer.advance(ack_len);
780789
self.local_seq_no = ack_number;
781790
}
782791

@@ -1962,6 +1971,27 @@ mod test {
19621971
}])
19631972
}
19641973

1974+
#[test]
1975+
fn test_mutual_close_with_data() {
1976+
let mut s = socket_established();
1977+
s.send_slice(b"abcdef").unwrap();
1978+
s.close();
1979+
assert_eq!(s.state, State::FinWait1);
1980+
recv!(s, [TcpRepr {
1981+
control: TcpControl::Fin,
1982+
seq_number: LOCAL_SEQ + 1,
1983+
ack_number: Some(REMOTE_SEQ + 1),
1984+
payload: &b"abcdef"[..],
1985+
..RECV_TEMPL
1986+
}]);
1987+
send!(s, TcpRepr {
1988+
control: TcpControl::Fin,
1989+
seq_number: REMOTE_SEQ + 1,
1990+
ack_number: Some(LOCAL_SEQ + 1 + 6 + 1),
1991+
..SEND_TEMPL
1992+
});
1993+
}
1994+
19651995
// =========================================================================================//
19661996
// Tests for retransmission on packet loss.
19671997
// =========================================================================================//

0 commit comments

Comments
 (0)
Please sign in to comment.