Merge pull request #977 from smoltcp-rs/tcp-fin-partially-out-of-window

tcp: do not ignore fin if segment is partially outside the window.
This commit is contained in:
Dario Nieuwenhuis 2024-09-10 21:42:42 +00:00 committed by GitHub
commit bc22929a7d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1710,9 +1710,9 @@ impl<'a> Socket<'a> {
let mut control = repr.control;
control = control.quash_psh();
// If a FIN is received at the end of the current segment but the start of the segment
// is not at the start of the receive window, disregard this FIN.
if control == TcpControl::Fin && window_start != segment_start {
// If a FIN is received at the end of the current segment, but
// we have a hole in the assembler before the current segment, disregard this FIN.
if control == TcpControl::Fin && window_start < segment_start {
tcp_trace!("ignoring FIN because we don't have full data yet. window_start={} segment_start={}", window_start, segment_start);
control = TcpControl::None;
}
@ -4237,6 +4237,50 @@ mod test {
.unwrap();
}
#[test]
fn test_established_receive_partially_outside_window_fin() {
let mut s = socket_established();
send!(
s,
TcpRepr {
seq_number: REMOTE_SEQ + 1,
ack_number: Some(LOCAL_SEQ + 1),
payload: &b"abc"[..],
..SEND_TEMPL
}
);
s.recv(|data| {
assert_eq!(data, b"abc");
(3, ())
})
.unwrap();
// Peer decides to retransmit (perhaps because the ACK was lost)
// and also pushed data, and sent a FIN.
send!(
s,
TcpRepr {
seq_number: REMOTE_SEQ + 1,
ack_number: Some(LOCAL_SEQ + 1),
control: TcpControl::Fin,
payload: &b"abcdef"[..],
..SEND_TEMPL
}
);
s.recv(|data| {
assert_eq!(data, b"def");
(3, ())
})
.unwrap();
// We should accept the FIN, because even though the last packet was partially
// outside the receive window, there is no hole after adding its data to the assembler.
assert_eq!(s.state, State::CloseWait);
}
#[test]
fn test_established_send_wrap() {
let mut s = socket_established();