diff --git a/README.md b/README.md index 9f4e3d8..b8ab338 100644 --- a/README.md +++ b/README.md @@ -57,11 +57,11 @@ The TCP protocol is supported over IPv4. Server and client sockets are supported * TCP urgent pointer is **not** supported; any urgent octets will be received alongside data octets. * Reassembly of out-of-order segments is **not** supported. - * The status of TCP options is: + * The status of TCP options or extensions is: * Maximum segment size option is supported. * Window scaling is **not** supported, and the maximum buffer size is 65536. * Timestamping is **not** supported. - * Fast open is **not** supported. + * Fast open is **not** supported when smoltcp initiates connection. * Keepalive is **not** supported. ## Installation diff --git a/src/socket/tcp.rs b/src/socket/tcp.rs index 1793a6c..09e36b7 100644 --- a/src/socket/tcp.rs +++ b/src/socket/tcp.rs @@ -696,7 +696,6 @@ impl<'a> TcpSocket<'a> { src_port: repr.dst_port, dst_port: repr.src_port, control: TcpControl::None, - push: false, seq_number: TcpSeqNumber(0), ack_number: None, window_len: 0, @@ -1103,7 +1102,6 @@ impl<'a> TcpSocket<'a> { src_port: self.local_endpoint.port, dst_port: self.remote_endpoint.port, control: TcpControl::None, - push: false, seq_number: self.remote_next_seq, ack_number: Some(self.remote_seq_no + self.rx_buffer.len()), window_len: self.rx_buffer.window() as u16, @@ -1146,7 +1144,7 @@ impl<'a> TcpSocket<'a> { State::FinWait1 | State::LastAck => repr.control = TcpControl::Fin, State::Established | State::CloseWait => - repr.push = true, + repr.control = TcpControl::Psh, _ => () } } @@ -1190,7 +1188,8 @@ impl<'a> TcpSocket<'a> { (TcpControl::Syn, Some(_)) => "SYN|ACK", (TcpControl::Fin, Some(_)) => "FIN|ACK", (TcpControl::Rst, Some(_)) => "RST|ACK", - (TcpControl::None, _) => "ACK", + (TcpControl::Psh, Some(_)) => "PSH|ACK", + (TcpControl::None, Some(_)) => "ACK", _ => unreachable!() }; if repr.payload.len() > 0 { @@ -1346,14 +1345,14 @@ mod test { const SEND_TEMPL: TcpRepr<'static> = TcpRepr { src_port: REMOTE_PORT, dst_port: LOCAL_PORT, - control: TcpControl::None, push: false, + control: TcpControl::None, seq_number: TcpSeqNumber(0), ack_number: Some(TcpSeqNumber(0)), window_len: 256, max_seg_size: None, payload: &[] }; const RECV_TEMPL: TcpRepr<'static> = TcpRepr { src_port: LOCAL_PORT, dst_port: REMOTE_PORT, - control: TcpControl::None, push: false, + control: TcpControl::None, seq_number: TcpSeqNumber(0), ack_number: Some(TcpSeqNumber(0)), window_len: 64, max_seg_size: None, payload: &[] @@ -1426,10 +1425,15 @@ mod test { ($socket:ident, $result:expr) => (recv!($socket, time 0, $result)); ($socket:ident, time $time:expr, $result:expr) => - (recv(&mut $socket, $time, |repr| { + (recv(&mut $socket, $time, |result| { // Most of the time we don't care about the PSH flag. - let repr = repr.map(|r| TcpRepr { push: false, ..r }); - assert_eq!(repr, $result) + let result = result.map(|mut repr| { + if repr.control == TcpControl::Psh { + repr.control = TcpControl::None; + } + repr + }); + assert_eq!(result, $result) })); ($socket:ident, time $time:expr, $result:expr, exact) => (recv(&mut $socket, $time, |repr| assert_eq!(repr, $result))); @@ -2893,16 +2897,16 @@ mod test { s.send_slice(b"abcdef").unwrap(); s.send_slice(b"123456").unwrap(); recv!(s, time 0, Ok(TcpRepr { + control: TcpControl::None, seq_number: LOCAL_SEQ + 1, ack_number: Some(REMOTE_SEQ + 1), - push: false, payload: &b"abcdef"[..], ..RECV_TEMPL }), exact); recv!(s, time 0, Ok(TcpRepr { + control: TcpControl::Psh, seq_number: LOCAL_SEQ + 1 + 6, ack_number: Some(REMOTE_SEQ + 1), - push: true, payload: &b"123456"[..], ..RECV_TEMPL }), exact); diff --git a/src/wire/tcp.rs b/src/wire/tcp.rs index 5db52cf..02531d9 100644 --- a/src/wire/tcp.rs +++ b/src/wire/tcp.rs @@ -603,6 +603,7 @@ impl<'a> TcpOption<'a> { #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Control { None, + Psh, Syn, Fin, Rst @@ -613,7 +614,7 @@ impl Control { pub fn len(self) -> usize { match self { Control::Syn | Control::Fin => 1, - Control::Rst | Control::None => 0 + _ => 0 } } } @@ -624,7 +625,6 @@ pub struct Repr<'a> { pub src_port: u16, pub dst_port: u16, pub control: Control, - pub push: bool, pub seq_number: SeqNumber, pub ack_number: Option, pub window_len: u16, @@ -645,11 +645,12 @@ impl<'a> Repr<'a> { if !packet.verify_checksum(src_addr, dst_addr) { return Err(Error::Checksum) } let control = - match (packet.syn(), packet.fin(), packet.rst()) { - (false, false, false) => Control::None, - (true, false, false) => Control::Syn, - (false, true, false) => Control::Fin, - (false, false, true ) => Control::Rst, + match (packet.syn(), packet.fin(), packet.rst(), packet.psh()) { + (false, false, false, false) => Control::None, + (false, false, false, true) => Control::Psh, + (true, false, false, _) => Control::Syn, + (false, true, false, _) => Control::Fin, + (false, false, true , _) => Control::Rst, _ => return Err(Error::Malformed) }; let ack_number = @@ -680,7 +681,6 @@ impl<'a> Repr<'a> { src_port: packet.src_port(), dst_port: packet.dst_port(), control: control, - push: packet.psh(), seq_number: packet.seq_number(), ack_number: ack_number, window_len: packet.window_len(), @@ -716,11 +716,11 @@ impl<'a> Repr<'a> { packet.clear_flags(); match self.control { Control::None => (), + Control::Psh => packet.set_psh(true), Control::Syn => packet.set_syn(true), Control::Fin => packet.set_fin(true), Control::Rst => packet.set_rst(true) } - packet.set_psh(self.push); packet.set_ack(self.ack_number.is_some()); { let mut options = packet.options_mut(); @@ -795,11 +795,9 @@ impl<'a> fmt::Display for Repr<'a> { Control::Syn => write!(f, " syn")?, Control::Fin => write!(f, " fin")?, Control::Rst => write!(f, " rst")?, + Control::Psh => write!(f, " psh")?, Control::None => () } - if self.push { - write!(f, " psh")?; - } write!(f, " seq={}", self.seq_number)?; if let Some(ack_number) = self.ack_number { write!(f, " ack={}", ack_number)?; @@ -913,8 +911,8 @@ mod test { [0xbf, 0x00, 0x00, 0x50, 0x01, 0x23, 0x45, 0x67, 0x00, 0x00, 0x00, 0x00, - 0x50, 0x0a, 0x01, 0x23, - 0x7a, 0x85, 0x00, 0x00, + 0x50, 0x02, 0x01, 0x23, + 0x7a, 0x8d, 0x00, 0x00, 0xaa, 0x00, 0x00, 0xff]; fn packet_repr() -> Repr<'static> { @@ -925,7 +923,6 @@ mod test { ack_number: None, window_len: 0x0123, control: Control::Syn, - push: true, max_seg_size: None, payload: &PAYLOAD_BYTES }