Update remote_last_win for all ACKs

Only ACKs generated by `dispatch` were updating
`remote_last_win` but not the ACKs generated by
`process`, failing to keep track of the last
announced receive window. This left
`window_to_update` to return false in `dispatch`
after the RX buffer was emptied, thus not announcing
that the receive window is not zero anymore.

The change updates `remote_last_win` for immediate
ACKs generated by `process`.

Closes: #200
Approved by: whitequark
This commit is contained in:
Kai Lüke 2018-05-08 02:07:57 +09:00 committed by Homu
parent 879e3ea3cd
commit fada9d4e27
1 changed files with 62 additions and 1 deletions

View File

@ -782,7 +782,7 @@ impl<'a> TcpSocket<'a> {
(ip_reply_repr, reply_repr)
}
fn ack_reply(&self, ip_repr: &IpRepr, repr: &TcpRepr) -> (IpRepr, TcpRepr<'static>) {
fn ack_reply(&mut self, ip_repr: &IpRepr, repr: &TcpRepr) -> (IpRepr, TcpRepr<'static>) {
let (ip_reply_repr, mut reply_repr) = Self::reply(ip_repr, repr);
// From RFC 793:
@ -792,6 +792,7 @@ impl<'a> TcpSocket<'a> {
reply_repr.seq_number = self.remote_last_seq;
reply_repr.ack_number = self.remote_last_ack;
reply_repr.window_len = self.rx_buffer.window() as u16;
self.remote_last_win = reply_repr.window_len;
(ip_reply_repr, reply_repr)
}
@ -3340,6 +3341,66 @@ mod test {
}]);
}
#[test]
fn test_announce_window_after_read() {
let mut s = socket_established();
s.rx_buffer = SocketBuffer::new(vec![0; 6]);
s.assembler = Assembler::new(s.rx_buffer.capacity());
send!(s, TcpRepr {
seq_number: REMOTE_SEQ + 1,
ack_number: Some(LOCAL_SEQ + 1),
payload: &b"abc"[..],
..SEND_TEMPL
});
recv!(s, [TcpRepr {
seq_number: LOCAL_SEQ + 1,
ack_number: Some(REMOTE_SEQ + 1 + 3),
window_len: 3,
..RECV_TEMPL
}]);
// Test that `dispatch` updates `remote_last_win`
assert_eq!(s.remote_last_win, s.rx_buffer.window() as u16);
s.recv(|buffer| {
(buffer.len(), ())
}).unwrap();
assert!(s.window_to_update());
recv!(s, [TcpRepr {
seq_number: LOCAL_SEQ + 1,
ack_number: Some(REMOTE_SEQ + 1 + 3),
window_len: 6,
..RECV_TEMPL
}]);
assert_eq!(s.remote_last_win, s.rx_buffer.window() as u16);
// Provoke immediate ACK to test that `process` updates `remote_last_win`
send!(s, TcpRepr {
seq_number: REMOTE_SEQ + 1 + 6,
ack_number: Some(LOCAL_SEQ + 1),
payload: &b"def"[..],
..SEND_TEMPL
}, Ok(Some(TcpRepr {
seq_number: LOCAL_SEQ + 1,
ack_number: Some(REMOTE_SEQ + 1 + 3),
window_len: 6,
..RECV_TEMPL
})));
send!(s, TcpRepr {
seq_number: REMOTE_SEQ + 1 + 3,
ack_number: Some(LOCAL_SEQ + 1),
payload: &b"abc"[..],
..SEND_TEMPL
}, Ok(Some(TcpRepr {
seq_number: LOCAL_SEQ + 1,
ack_number: Some(REMOTE_SEQ + 1 + 9),
window_len: 0,
..RECV_TEMPL
})));
assert_eq!(s.remote_last_win, s.rx_buffer.window() as u16);
s.recv(|buffer| {
(buffer.len(), ())
}).unwrap();
assert!(s.window_to_update());
}
// =========================================================================================//
// Tests for timeouts.
// =========================================================================================//