Do not send window updates in states that shouldn't do so.

Previously, the window update was sent anytime it changed. This is
not desirable for 2 reasons:

- It would send window updates in TimeWait or Closed states, which is incorrect.
- It would send window updates in states where we've already received the
  remote side's FIN, such as CloseWait. This is not necessarily incorrect, but
  is useless, since the remote side is not going to send us more data, therefore
  it's not interested in our window size anymore.
v0.7.x
Dario Nieuwenhuis 2020-06-25 01:51:33 +02:00 committed by whitequark
parent f6a55fa3c7
commit 4cfe8dafdb
1 changed files with 59 additions and 2 deletions

View File

@ -1417,8 +1417,11 @@ impl<'a> TcpSocket<'a> {
}
fn window_to_update(&self) -> bool {
(self.rx_buffer.window() >> self.remote_win_shift) as u16 >
self.remote_last_win
match self.state {
State::SynSent | State::SynReceived | State::Established | State::FinWait1 | State::FinWait2 =>
(self.rx_buffer.window() >> self.remote_win_shift) as u16 > self.remote_last_win,
_ => false,
}
}
pub(crate) fn dispatch<F>(&mut self, timestamp: Instant, caps: &DeviceCapabilities,
@ -4083,6 +4086,60 @@ mod test {
}));
}
#[test]
fn test_close_wait_no_window_update() {
let mut s = socket_established();
send!(s, TcpRepr {
control: TcpControl::Fin,
seq_number: REMOTE_SEQ + 1,
ack_number: Some(LOCAL_SEQ + 1),
payload: &[1,2,3,4],
..SEND_TEMPL
});
assert_eq!(s.state, State::CloseWait);
// we ack the FIN, with the reduced window size.
recv!(s, Ok(TcpRepr {
seq_number: LOCAL_SEQ + 1,
ack_number: Some(REMOTE_SEQ + 6),
window_len: 60,
..RECV_TEMPL
}));
let rx_buf = &mut [0; 32];
assert_eq!(s.recv_slice(rx_buf), Ok(4));
// check that we do NOT send a window update even if it has changed.
recv!(s, Err(Error::Exhausted));
}
#[test]
fn test_time_wait_no_window_update() {
let mut s = socket_fin_wait_2();
send!(s, TcpRepr {
control: TcpControl::Fin,
seq_number: REMOTE_SEQ + 1,
ack_number: Some(LOCAL_SEQ + 2),
payload: &[1,2,3,4],
..SEND_TEMPL
});
assert_eq!(s.state, State::TimeWait);
// we ack the FIN, with the reduced window size.
recv!(s, Ok(TcpRepr {
seq_number: LOCAL_SEQ + 2,
ack_number: Some(REMOTE_SEQ + 6),
window_len: 60,
..RECV_TEMPL
}));
let rx_buf = &mut [0; 32];
assert_eq!(s.recv_slice(rx_buf), Ok(4));
// check that we do NOT send a window update even if it has changed.
recv!(s, Err(Error::Exhausted));
}
// =========================================================================================//
// Tests for flow control.
// =========================================================================================//