Kaynağa Gözat

Fix the TCP ACK handling in FIN-WAIT-1 state with queued data.

whitequark 8 yıl önce
ebeveyn
işleme
9aebbff35d
1 değiştirilmiş dosya ile 44 ekleme ve 1 silme
  1. 44 1
      src/socket/tcp.rs

+ 44 - 1
src/socket/tcp.rs

@@ -720,10 +720,12 @@ impl<'a> TcpSocket<'a> {
             }
 
             // ACK packets in FIN-WAIT-1 state change it to FIN-WAIT-2, if we've already
-            // sent everything in the transmit buffer.
+            // sent everything in the transmit buffer, and reset the retransmit timer.
             (State::FinWait1, TcpRepr { control: TcpControl::None, .. }) => {
                 if self.tx_buffer.empty() {
                     self.set_state(State::FinWait2);
+                } else {
+                    self.retransmit.reset();
                 }
             }
 
@@ -2196,4 +2198,45 @@ mod test {
             ..RECV_TEMPL
         }));
     }
+
+    #[test]
+    fn test_fin_wait_1_retransmit_reset_after_ack() {
+        let mut s = socket_established();
+        s.remote_win_len = 6;
+        s.send_slice(b"abcdef").unwrap();
+        s.send_slice(b"123456").unwrap();
+        s.send_slice(b"ABCDEF").unwrap();
+        s.close();
+        recv!(s, time 1000, Ok(TcpRepr {
+            seq_number: LOCAL_SEQ + 1,
+            ack_number: Some(REMOTE_SEQ + 1),
+            payload:    &b"abcdef"[..],
+            ..RECV_TEMPL
+        }));
+        send!(s, time 1005, TcpRepr {
+            seq_number: REMOTE_SEQ + 1,
+            ack_number: Some(LOCAL_SEQ + 1 + 6),
+            window_len: 6,
+            ..SEND_TEMPL
+        });
+        recv!(s, time 1010, Ok(TcpRepr {
+            seq_number: LOCAL_SEQ + 1 + 6,
+            ack_number: Some(REMOTE_SEQ + 1),
+            payload:    &b"123456"[..],
+            ..RECV_TEMPL
+        }));
+        send!(s, time 1015, TcpRepr {
+            seq_number: REMOTE_SEQ + 1,
+            ack_number: Some(LOCAL_SEQ + 1 + 6 + 6),
+            window_len: 6,
+            ..SEND_TEMPL
+        });
+        recv!(s, time 1020, Ok(TcpRepr {
+            control:    TcpControl::Fin,
+            seq_number: LOCAL_SEQ + 1 + 6 + 6,
+            ack_number: Some(REMOTE_SEQ + 1),
+            payload:    &b"ABCDEF"[..],
+            ..RECV_TEMPL
+        }));
+    }
 }