Accept TCP FIN packets in SYN-RECEIVED state.

v0.7.x
whitequark 2017-07-23 23:51:56 +00:00
parent ab4593ea6c
commit 38afc64f61
2 changed files with 45 additions and 4 deletions

View File

@ -1,6 +1,8 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![allow(unused_mut)]
#[cfg(feature = "std")]
use std as core;
#[macro_use]
extern crate log;
extern crate smoltcp;
@ -13,6 +15,7 @@ extern crate getopts;
#[allow(dead_code)]
mod utils;
use core::str;
use smoltcp::Error;
use smoltcp::phy::Loopback;
use smoltcp::wire::{EthernetAddress, IpAddress};
@ -126,13 +129,14 @@ fn main() {
let socket: &mut TcpSocket = socket_set.get_mut(server_handle).as_socket();
if !socket.is_active() && !socket.is_listening() {
if !did_listen {
debug!("listening");
socket.listen(1234).unwrap();
did_listen = true;
}
}
if socket.can_recv() {
debug!("got {:?}", socket.recv(32).unwrap());
debug!("got {:?}", str::from_utf8(socket.recv(32).unwrap()).unwrap());
socket.close();
done = true;
}
@ -142,6 +146,7 @@ fn main() {
let socket: &mut TcpSocket = socket_set.get_mut(client_handle).as_socket();
if !socket.is_open() {
if !did_connect {
debug!("connecting");
socket.connect((IpAddress::v4(127, 0, 0, 1), 1234),
(IpAddress::Unspecified, 65000)).unwrap();
did_connect = true;
@ -149,6 +154,7 @@ fn main() {
}
if socket.can_send() {
debug!("sending");
socket.send_slice(b"0123456789abcdef").unwrap();
socket.close();
}
@ -162,7 +168,9 @@ fn main() {
clock.advance(1);
}
if !done {
error!("this is taking too long, bailing out");
if done {
info!("done")
} else {
error!("this is taking too long, bailing out")
}
}

View File

@ -852,6 +852,15 @@ impl<'a> TcpSocket<'a> {
self.retransmit.reset();
}
// FIN packets in the SYN-RECEIVED state change it to CLOSE-WAIT.
// It's not obvious from RFC 793 that this is permitted, but
// 7th and 8th steps in the "SEGMENT ARRIVES" event describe this behavior.
(State::SynReceived, TcpRepr { control: TcpControl::Fin, .. }) => {
self.remote_seq_no += 1;
self.set_state(State::CloseWait);
self.retransmit.reset();
}
// SYN|ACK packets in the SYN-SENT state change it to ESTABLISHED.
(State::SynSent, TcpRepr {
control: TcpControl::Syn, seq_number, ack_number: Some(_),
@ -1498,7 +1507,7 @@ mod test {
}
#[test]
fn test_syn_received_syn_ack() {
fn test_syn_received_ack() {
let mut s = socket_syn_received();
recv!(s, [TcpRepr {
control: TcpControl::Syn,
@ -1516,6 +1525,30 @@ mod test {
sanity!(s, socket_established());
}
#[test]
fn test_syn_received_fin() {
let mut s = socket_syn_received();
recv!(s, [TcpRepr {
control: TcpControl::Syn,
seq_number: LOCAL_SEQ,
ack_number: Some(REMOTE_SEQ + 1),
max_seg_size: Some(1480),
..RECV_TEMPL
}]);
send!(s, TcpRepr {
control: TcpControl::Fin,
seq_number: REMOTE_SEQ + 1,
ack_number: Some(LOCAL_SEQ + 1),
payload: &b"abcdef"[..],
..SEND_TEMPL
});
assert_eq!(s.state, State::CloseWait);
sanity!(s, TcpSocket {
remote_last_ack: REMOTE_SEQ + 1,
..socket_close_wait()
});
}
#[test]
fn test_syn_received_rst() {
let mut s = socket_syn_received();