Explorar el Código

Implement the TCP FIN-WAIT-1 state.

whitequark hace 8 años
padre
commit
a058996e70
Se han modificado 1 ficheros con 82 adiciones y 7 borrados
  1. 82 7
      src/socket/tcp.rs

+ 82 - 7
src/socket/tcp.rs

@@ -581,14 +581,14 @@ impl<'a> TcpSocket<'a> {
                 self.remote_last_seq = self.local_seq_no + 1;
                 self.remote_seq_no   = seq_number + 1;
                 self.set_state(State::SynReceived);
-                self.retransmit.reset()
+                self.retransmit.reset();
             }
 
             // ACK packets in the SYN-RECEIVED state change it to ESTABLISHED.
             (State::SynReceived, TcpRepr { control: TcpControl::None, .. }) => {
                 self.local_seq_no   += 1;
                 self.set_state(State::Established);
-                self.retransmit.reset()
+                self.retransmit.reset();
             }
 
             // ACK packets in ESTABLISHED state do nothing.
@@ -598,7 +598,20 @@ impl<'a> TcpSocket<'a> {
             (State::Established, TcpRepr { control: TcpControl::Fin, .. }) => {
                 self.remote_seq_no  += 1;
                 self.set_state(State::CloseWait);
-                self.retransmit.reset()
+                self.retransmit.reset();
+            }
+
+            // ACK packets in FIN-WAIT-1 state change it to FIN-WAIT-2.
+            (State::FinWait1, TcpRepr { control: TcpControl::None, .. }) => {
+                self.local_seq_no   += 1;
+                self.set_state(State::FinWait2);
+            }
+
+            // FIN packets in FIN-WAIT-1 state change it to CLOSING.
+            (State::FinWait1, TcpRepr { control: TcpControl::Fin, .. })  => {
+                self.remote_seq_no  += 1;
+                self.set_state(State::Closing);
+                self.retransmit.reset();
             }
 
             // ACK packets in CLOSE-WAIT state do nothing.
@@ -1282,6 +1295,41 @@ mod test {
         s
     }
 
+    #[test]
+    fn test_fin_wait_1_fin_ack() {
+        let mut s = socket_fin_wait_1();
+        recv!(s, [TcpRepr {
+            control: TcpControl::Fin,
+            seq_number: LOCAL_SEQ + 1,
+            ack_number: Some(REMOTE_SEQ + 1),
+            ..RECV_TEMPL
+        }]);
+        send!(s, [TcpRepr {
+            seq_number: REMOTE_SEQ + 1,
+            ack_number: Some(LOCAL_SEQ + 1 + 1),
+            ..SEND_TEMPL
+        }]);
+        assert_eq!(s.state, State::FinWait2);
+    }
+
+    #[test]
+    fn test_fin_wait_1_fin_fin() {
+        let mut s = socket_fin_wait_1();
+        recv!(s, [TcpRepr {
+            control: TcpControl::Fin,
+            seq_number: LOCAL_SEQ + 1,
+            ack_number: Some(REMOTE_SEQ + 1),
+            ..RECV_TEMPL
+        }]);
+        send!(s, [TcpRepr {
+            control: TcpControl::Fin,
+            seq_number: REMOTE_SEQ + 1,
+            ack_number: Some(LOCAL_SEQ + 1),
+            ..SEND_TEMPL
+        }]);
+        assert_eq!(s.state, State::Closing);
+    }
+
     #[test]
     fn test_fin_wait_1_close() {
         let mut s = socket_fin_wait_1();
@@ -1423,10 +1471,7 @@ mod test {
 
     #[test]
     fn test_three_way_handshake() {
-        let mut s = socket();
-        s.state           = State::Listen;
-        s.local_endpoint  = IpEndpoint::new(IpAddress::default(), LOCAL_PORT);
-
+        let mut s = socket_listen();
         send!(s, [TcpRepr {
             control: TcpControl::Syn,
             seq_number: REMOTE_SEQ,
@@ -1451,4 +1496,34 @@ mod test {
         assert_eq!(s.local_seq_no, LOCAL_SEQ + 1);
         assert_eq!(s.remote_seq_no, REMOTE_SEQ + 1);
     }
+
+    #[test]
+    fn test_remote_close() {
+        let mut s = socket_established();
+        send!(s, [TcpRepr {
+            control: TcpControl::Fin,
+            seq_number: REMOTE_SEQ + 1,
+            ack_number: Some(LOCAL_SEQ + 1),
+            ..SEND_TEMPL
+        }]);
+        assert_eq!(s.state, State::CloseWait);
+        recv!(s, [TcpRepr {
+            seq_number: LOCAL_SEQ + 1,
+            ack_number: Some(REMOTE_SEQ + 1 + 1),
+            ..RECV_TEMPL
+        }]);
+        s.close();
+        assert_eq!(s.state, State::LastAck);
+        recv!(s, [TcpRepr {
+            control: TcpControl::Fin,
+            seq_number: LOCAL_SEQ + 1,
+            ack_number: Some(REMOTE_SEQ + 1 + 1),
+            ..RECV_TEMPL
+        }]);
+        send!(s, [TcpRepr {
+            seq_number: REMOTE_SEQ + 1 + 1,
+            ack_number: Some(LOCAL_SEQ + 1 + 1),
+            ..SEND_TEMPL
+        }]);
+    }
 }