diff options
| author | chenzizhan <[email protected]> | 2023-09-11 14:13:03 +0800 |
|---|---|---|
| committer | chenzizhan <[email protected]> | 2023-09-11 14:13:03 +0800 |
| commit | 1658c7e4839cc23bcf08d0fcec215f63b28a3cda (patch) | |
| tree | 963af8945eec2d9f9879a322a8d7ee38b46047ac | |
| parent | e0e50c85bb3ef1a483b73fc2b596ed280e5593aa (diff) | |
more ack number test
| -rw-r--r-- | src/session/tcp_reassembly.rs | 330 |
1 files changed, 192 insertions, 138 deletions
diff --git a/src/session/tcp_reassembly.rs b/src/session/tcp_reassembly.rs index 412c942..2d7505e 100644 --- a/src/session/tcp_reassembly.rs +++ b/src/session/tcp_reassembly.rs @@ -6,7 +6,6 @@ use std::vec::IntoIter; use super::duration::Duration; use crate::protocol::ipv4::IPv4Header; use crate::protocol::ipv6::IPv6Header; -use crate::protocol::ip::IPProtocol; use crate::protocol::udp::UdpHeader; use crate::protocol::ethernet::EthernetFrame; use crate::protocol::tcp::{TcpHeader, TcpOption}; @@ -32,14 +31,16 @@ pub enum TcpSessionErr { DiscardedSegment, // todo /// new a connection failed, because the packet is not a SYN packet, but the packet is valid NewConnectionFailed, + UnexpectedAckNumber, } -#[derive(Debug, Eq, PartialEq)] -pub enum TcpSessionOk { - EstablishedSession, - ClosingSession, - ClosedSession, - Other, +#[allow(non_snake_case)] +pub mod TcpSessionOk { // use as enum + pub const ESTABLISHED: u32 = 0x01; + pub const CLOSING: u32 = 0x02; + pub const CLOSED: u32 = 0x04; + pub const ACK_SEGMENT: u32 = 0x08; + pub const OTHER: u32 = 0x0; } #[derive(Debug, Eq, PartialEq, Clone)] @@ -565,7 +566,7 @@ impl TcpStream { // if there is a ACK, check & send segments on the *other* side let ret = if has_ack { - send_peer_segments(destination, rel_ack) + send_peer_segments(destination, rel_ack)? } else { None }; @@ -597,7 +598,7 @@ impl TcpStream { let ret = if has_ack { println!("ACKing segments up to {}", rel_ack); - send_peer_segments(destination, rel_ack) + send_peer_segments(destination, rel_ack)? } else { if tcp.get_acknowledgement() != 0 { println!( @@ -733,7 +734,7 @@ fn queue_segment(peer: &mut TcpPeer, segment: TcpSegment) { peer.insert_sorted(segment); } -fn send_peer_segments(peer: &mut TcpPeer, rel_ack: Wrapping<u32>) -> Option<Vec<TcpSegment>> { +fn send_peer_segments(peer: &mut TcpPeer, rel_ack: Wrapping<u32>) -> Result<Option<Vec<TcpSegment>>, TcpSessionErr> { // todo: window println!( "Trying to send segments for {}:{} up to {} (last ack: {})", @@ -744,16 +745,16 @@ fn send_peer_segments(peer: &mut TcpPeer, rel_ack: Wrapping<u32>) -> Option<Vec< ); if rel_ack == peer.last_rel_ack { println!("re-acking last data, doing nothing"); - return None; + return Ok(None); } if peer.segments.is_empty() { - return None; + return Ok(None); } // is ACK acceptable? if rel_ack < peer.last_rel_ack { println!("ACK request for already ACKed data (ack < last_ack)"); - return None; + return Err(TcpSessionErr::UnexpectedAckNumber); } // check consistency of segment ACK numbers + order and/or missing fragments and/or overlap @@ -762,17 +763,6 @@ fn send_peer_segments(peer: &mut TcpPeer, rel_ack: Wrapping<u32>) -> Option<Vec< while !peer.segments.is_empty() { let segment = &peer.segments[0]; - println!( - "segment: rel_seq={} len={}", - segment.rel_seq, - segment.payload.len() - ); - println!( - " origin.next_rel_seq {} ack {}", - peer.next_rel_seq, - rel_ack - ); - if rel_ack <= segment.rel_seq { // if packet is in the past (strictly less), we don't care break; @@ -800,11 +790,6 @@ fn send_peer_segments(peer: &mut TcpPeer, rel_ack: Wrapping<u32>) -> Option<Vec< handle_overlap_linux(peer, &mut segment); adjust_seq_numbers(peer, &segment); - println!( - "ACKed: pushing segment: rel_seq={} len={}", - segment.rel_seq, - segment.payload.len(), - ); if !segment.payload.is_empty() { acked.push(segment); } @@ -820,7 +805,7 @@ fn send_peer_segments(peer: &mut TcpPeer, rel_ack: Wrapping<u32>) -> Option<Vec< } peer.last_rel_ack = rel_ack; - Some(acked) + Ok(Some(acked)) } const FIRST_WINS: bool = false; @@ -886,7 +871,7 @@ impl TcpConnection { Self::_try_new(simple_packet) } - pub(crate) fn update(&mut self, packet: &RawPacket) -> Result<TcpSessionOk, TcpSessionErr> { + pub(crate) fn update(&mut self, packet: &RawPacket) -> Result<u32, TcpSessionErr> { let simple_packet = raw_packet_convert_to_my_packet(packet)?; self._update(simple_packet) } @@ -931,7 +916,7 @@ impl TcpConnection { Ok(connection) } - fn _update(&mut self, tcp: TcpPacket) -> Result<TcpSessionOk, TcpSessionErr> { + fn _update(&mut self, tcp: TcpPacket) -> Result<u32, TcpSessionErr> { let stream = &mut self.stream; println!("stream state: {:?}", stream.status); @@ -981,33 +966,36 @@ impl TcpConnection { _ => stream.handle_closing_connection(tcp, to_server), }?; - let mut ok_ret = TcpSessionOk::Other; + let mut ok_ret = TcpSessionOk::OTHER; + if let Some(sent_packet) = sent_packet { + if !to_server { // ack packet, so the previous packet if from the other side. Like a ack packet from server, so the sent packets are from client + self.packets_sent_by_client.push(sent_packet.into_iter().map(|s| s.raw_packet).collect()); + } else { + self.packets_sent_by_server.push(sent_packet.into_iter().map(|s| s.raw_packet).collect()); + } + ok_ret = ok_ret | TcpSessionOk::ACK_SEGMENT; + } + if client_status_before != stream.client.status || server_status_before != stream.server.status { println!("status changed: {:?} -> {:?} / {:?} -> {:?}", client_status_before, stream.client.status, server_status_before, stream.server.status ); if stream.client.status == TcpStatus::Established { println!("handshake completed"); - ok_ret = TcpSessionOk::EstablishedSession; + ok_ret = ok_ret | TcpSessionOk::ESTABLISHED; } else if stream.client.status == TcpStatus::Closed || stream.server.status == TcpStatus::Closed { println!("connection closed"); - ok_ret = TcpSessionOk::ClosedSession; + ok_ret |= TcpSessionOk::CLOSED; } else if client_status_before == TcpStatus::Established { println!("connection closed"); - ok_ret = TcpSessionOk::ClosingSession; - } - } - - if let Some(sent_packet) = sent_packet { - if !to_server { // ack packet, so the previous packet if from the other side. Like a ack packet from server, so the sent packets are from client - self.packets_sent_by_client.push(sent_packet.into_iter().map(|s| s.raw_packet).collect()); - } else { - self.packets_sent_by_server.push(sent_packet.into_iter().map(|s| s.raw_packet).collect()); + ok_ret = TcpSessionOk::CLOSING; } } Ok(ok_ret) } + // todo: refresh (删除所有的数据包,但是保留状态) + } impl fmt::Debug for TcpPeer { @@ -1035,6 +1023,7 @@ impl fmt::Debug for TcpPeer { #[cfg(test)] mod tests { use std::vec; + use crate::protocol::ip::IPProtocol; use super::*; @@ -1053,8 +1042,6 @@ mod tests { role: PeerRole, } - - fn new_raw<'a>(from: &PeerInTest, to: &PeerInTest, seq_num: u32, ack_num: u32, has_ack: bool, has_syn: bool, has_rst: bool, has_fin: bool, segment: &'a [u8]) -> RawPacket<'a> { @@ -1126,22 +1113,23 @@ mod tests { let ret = connection.update(&packet_handshake2).unwrap(); assert!(connection.stream.client.status == TcpStatus::SynSent); assert!(connection.stream.server.status == TcpStatus::SynRcv); - assert!(ret == TcpSessionOk::Other); + assert!(ret == TcpSessionOk::OTHER); let packet_handshake3 = new_raw(&client, &server, 1, 1, true, false, false, false, &[]); let ret = connection.update(&packet_handshake3).unwrap(); assert!(connection.stream.client.status == TcpStatus::Established); assert!(connection.stream.server.status == TcpStatus::Established); - assert!(ret == TcpSessionOk::EstablishedSession); + assert!(ret == TcpSessionOk::ESTABLISHED); let packet_established_from_client = new_raw(&client, &server, 1, 1, true, false, false, false, &[1, 2, 3]); let ret = connection.update(&packet_established_from_client).unwrap(); - assert!(ret == TcpSessionOk::Other); + assert!(ret == TcpSessionOk::OTHER); assert!(connection.stream.client.segments.len() == 1); let packet_established_server_response = new_raw(&server, &client, 1, 4, true, false, false, false, &[]); - connection.update(&packet_established_server_response).unwrap(); + let ret = connection.update(&packet_established_server_response).unwrap(); assert!(connection.stream.client.segments.len() == 0); + assert!(ret == TcpSessionOk::ACK_SEGMENT); let seg: Vec<_> = connection.iter(true).collect(); assert!(seg.len() == 1); assert!(raw_packet_convert_to_my_packet(&seg[0].1).unwrap().payload == [1, 2, 3]); @@ -1149,10 +1137,11 @@ mod tests { let packet_established_from_server = new_raw(&server, &client, 1, 4, true, false, false, false, &[4]); let ret = connection.update(&packet_established_from_server).unwrap(); assert!(connection.stream.server.segments.len() == 1); - assert!(ret == TcpSessionOk::Other); + assert!(ret == TcpSessionOk::OTHER); let packet_established_client_response = new_raw(&client, &server, 4, 2, true, false, false, false, &[]); - connection.update(&packet_established_client_response).unwrap(); + let ret = connection.update(&packet_established_client_response).unwrap(); + assert!(ret == TcpSessionOk::ACK_SEGMENT); let seg: Vec<_> = connection.iter(false).collect(); assert!(seg.len() == 1); assert!(raw_packet_convert_to_my_packet(&seg[0].1).unwrap().payload == [4]); @@ -1163,109 +1152,174 @@ mod tests { let ret = connection.update(&packet_close_by_client).unwrap(); assert!(connection.stream.client.status == TcpStatus::FinWait1); assert!(connection.stream.server.status == TcpStatus::CloseWait); - assert!(ret == TcpSessionOk::ClosingSession); + assert!(ret == TcpSessionOk::CLOSING); let packet_close_response_by_server = new_raw(&server, &client, 2, 5, true, false, false, false, &[]); let ret = connection.update(&packet_close_response_by_server).unwrap(); assert!(connection.stream.client.status == TcpStatus::FinWait2); assert!(connection.stream.server.status == TcpStatus::CloseWait); - assert!(ret == TcpSessionOk::Other); + assert!(ret == TcpSessionOk::OTHER); let packet_close_by_server = new_raw(&server, &client, 2, 5, true, false, false, true, &[]); let ret = connection.update(&packet_close_by_server).unwrap(); assert!(connection.stream.client.status == TcpStatus::TimeWait); assert!(connection.stream.server.status == TcpStatus::LastAck); - assert!(ret == TcpSessionOk::Other); + assert!(ret == TcpSessionOk::OTHER); let packet_close_response_by_client = new_raw(&client, &server, 5, 3, true, false, false, false, &[]); let ret = connection.update(&packet_close_response_by_client).unwrap(); assert!(connection.stream.client.status == TcpStatus::Closed); assert!(connection.stream.server.status == TcpStatus::Closed); - assert!(ret == TcpSessionOk::ClosedSession); - + assert!(ret == TcpSessionOk::CLOSED); } - // #[test] - // fn several_ordered_segments_in_one_ack() { - // let client = PeerInTest { - // addr: Ipv4Addr::new(192, 168, 1, 1), - // port: 1234, - // role: PeerRole::Client, - // }; - // let server = PeerInTest { - // addr: Ipv4Addr::new(192, 168, 1, 2), - // port: 80, - // role: PeerRole::Server, - // }; - - // // standard handshake - // let packet_handshake1 = new_raw(&client, &server, 0, 0, false, true, false, false, &[]); - // let mut connection = TcpConnection::_try_new(packet_handshake1).unwrap(); - // let packet_handshake2 = new_raw(&server, &client, 0, 1, true, true, false, false, &[]); - // connection.update(&packet_handshake2).unwrap(); - // let packet_handshake3 = new_raw(&client, &server, 1, 1, true, false, false, false, &[]); - // connection.update(&packet_handshake3).unwrap(); - - // // send 3 segments from client - // let packet_established_from_client1 = new_raw(&client, &server, 1, 1, true, false, false, false, &[1, 2, 3]); - // let ret = connection.update(&packet_established_from_client1).unwrap(); - // assert!(ret == TcpSessionOk::Other); - // let packet_established_from_client2 = new_raw(&client, &server, 4, 1, true, false, false, false, &[4, 5, 6]); - // let ret = connection.update(&packet_established_from_client2).unwrap(); - // assert!(ret == TcpSessionOk::Other); - // let packet_established_from_client3 = new_raw(&client, &server, 7, 1, true, false, false, false, &[7, 8, 9]); - // let ret = connection.update(&packet_established_from_client3).unwrap(); - // assert!(ret == TcpSessionOk::Other); - - // // server ack - // let packet_established_server_responce = new_raw(&server, &client, 1, 10, true, false, false, false, &[]); - // let ret = connection.update(&packet_established_server_responce).unwrap(); - // println!("czzzz"); - // for s in connection.iter(true) { - // println!("s: {:?}", s); - // } - // // assert!(ret.as_ref().unwrap().len() == 3); - // // assert!(ret.as_ref().unwrap()[0].payload.as_slice() == &[1, 2, 3]); - // // assert!(ret.as_ref().unwrap()[1].payload.as_slice() == &[4, 5, 6]); - // // assert!(ret.as_ref().unwrap()[2].payload.as_slice() == &[7, 8, 9]); - // } + #[test] + fn several_ordered_segments_in_one_ack() { + let client = PeerInTest { + addr: Ipv4Addr::new(192, 168, 1, 1), + port: 1234, + role: PeerRole::Client, + }; + let server = PeerInTest { + addr: Ipv4Addr::new(192, 168, 1, 2), + port: 80, + role: PeerRole::Server, + }; + + // standard handshake + let packet_handshake1 = new_raw(&client, &server, 0, 0, false, true, false, false, &[]); + let mut connection = TcpConnection::try_new(&packet_handshake1).unwrap(); + let packet_handshake2 = new_raw(&server, &client, 0, 1, true, true, false, false, &[]); + connection.update(&packet_handshake2).unwrap(); + let packet_handshake3 = new_raw(&client, &server, 1, 1, true, false, false, false, &[]); + connection.update(&packet_handshake3).unwrap(); + + // send 3 segments from client + let packet_established_from_client1 = new_raw(&client, &server, 1, 1, true, false, false, false, &[1, 2, 3]); + let ret = connection.update(&packet_established_from_client1).unwrap(); + assert!(ret == TcpSessionOk::OTHER); + let packet_established_from_client2 = new_raw(&client, &server, 4, 1, true, false, false, false, &[4, 5, 6]); + let ret = connection.update(&packet_established_from_client2).unwrap(); + assert!(ret == TcpSessionOk::OTHER); + let packet_established_from_client3 = new_raw(&client, &server, 7, 1, true, false, false, false, &[7, 8, 9]); + let ret = connection.update(&packet_established_from_client3).unwrap(); + assert!(ret == TcpSessionOk::OTHER); + + // server ack + let packet_established_server_responce = new_raw(&server, &client, 1, 10, true, false, false, false, &[]); + let ret = connection.update(&packet_established_server_responce).unwrap(); + assert!(ret == TcpSessionOk::ACK_SEGMENT); + let seg: Vec<_> = connection.iter(true).collect(); + assert!(seg.len() == 3); + assert!(seg[0].0 == 0); + assert!(seg[1].0 == 0); + assert!(seg[2].0 == 0); + assert!(raw_packet_convert_to_my_packet(&seg[0].1).unwrap().payload == [1, 2, 3]); + assert!(raw_packet_convert_to_my_packet(&seg[1].1).unwrap().payload == [4, 5, 6]); + assert!(raw_packet_convert_to_my_packet(&seg[2].1).unwrap().payload == [7, 8, 9]); + } + + #[test] + fn several_unordered_segments_in_one_ack() { + let client = PeerInTest { + addr: Ipv4Addr::new(192, 168, 1, 1), + port: 1234, + role: PeerRole::Client, + }; + let server = PeerInTest { + addr: Ipv4Addr::new(192, 168, 1, 2), + port: 80, + role: PeerRole::Server, + }; + + // standard handshake + let packet_handshake1 = new_raw(&client, &server, 0, 0, false, true, false, false, &[]); + let mut connection = TcpConnection::try_new(&packet_handshake1).unwrap(); + let packet_handshake2 = new_raw(&server, &client, 0, 1, true, true, false, false, &[]); + connection.update(&packet_handshake2).unwrap(); + let packet_handshake3 = new_raw(&client, &server, 1, 1, true, false, false, false, &[]); + connection.update(&packet_handshake3).unwrap(); + + // send 3 segments from client + let packet_established_from_client1 = new_raw(&client, &server, 1, 1, true, false, false, false, &[1, 2, 3]); + let packet_established_from_client2 = new_raw(&client, &server, 4, 1, true, false, false, false, &[4, 5, 6]); + let packet_established_from_client3 = new_raw(&client, &server, 7, 1, true, false, false, false, &[7, 8, 9]); + connection.update(&packet_established_from_client3).unwrap(); // unwrap: check not error + connection.update(&packet_established_from_client1).unwrap(); + connection.update(&packet_established_from_client2).unwrap(); + + // server ack + let packet_established_server_responce = new_raw(&server, &client, 1, 10, true, false, false, false, &[]); + let ret = connection.update(&packet_established_server_responce).unwrap(); + assert!(ret == TcpSessionOk::ACK_SEGMENT); + let seg: Vec<_> = connection.iter(true).collect(); + assert!(seg.len() == 3); + // assert!(ret.as_ref().unwrap()[0].payload.as_slice() == &[1, 2, 3]); + assert!(seg[0].0 == 0); + assert!(seg[1].0 == 0); + assert!(seg[2].0 == 0); + assert!(raw_packet_convert_to_my_packet(&seg[0].1).unwrap().payload == [1, 2, 3]); + assert!(raw_packet_convert_to_my_packet(&seg[1].1).unwrap().payload == [4, 5, 6]); + assert!(raw_packet_convert_to_my_packet(&seg[2].1).unwrap().payload == [7, 8, 9]); + } + + #[test] + fn wrong_ack_num() { + let client = PeerInTest { + addr: Ipv4Addr::new(192, 168, 1, 1), + port: 1234, + role: PeerRole::Client, + }; + let server = PeerInTest { + addr: Ipv4Addr::new(192, 168, 1, 2), + port: 80, + role: PeerRole::Server, + }; + // standard handshake + let packet_handshake1 = new_raw(&client, &server, 0, 0, false, true, false, false, &[]); + let mut connection = TcpConnection::try_new(&packet_handshake1).unwrap(); + let packet_handshake2 = new_raw(&server, &client, 0, 1, true, true, false, false, &[]); + connection.update(&packet_handshake2).unwrap(); + let packet_handshake3 = new_raw(&client, &server, 1, 1, true, false, false, false, &[]); + connection.update(&packet_handshake3).unwrap(); + // send 3 segments from client + let packet_established_from_client1 = new_raw(&client, &server, 1, 1, true, false, false, false, &[1, 2, 3]); + connection.update(&packet_established_from_client1).unwrap(); + let packet_established_from_client2 = new_raw(&client, &server, 4, 1, true, false, false, false, &[4, 5, 6]); + connection.update(&packet_established_from_client2).unwrap(); + let packet_established_from_client3 = new_raw(&client, &server, 7, 1, true, false, false, false, &[7, 8, 9]); + connection.update(&packet_established_from_client3).unwrap(); + + // server ack twice + let packet_established_server_responce = new_raw(&server, &client, 1, 10, true, false, false, false, &[]); + let ret = connection.update(&packet_established_server_responce).unwrap(); + assert!(ret == TcpSessionOk::ACK_SEGMENT); + let ret = connection.update(&packet_established_server_responce).unwrap(); + assert!(ret == TcpSessionOk::OTHER); + + // server ack with wrong ack number(smaller) + let packet_established_from_client4 = new_raw(&client, &server, 10, 1, true, false, false, false, &[10, 11, 12]); + connection.update(&packet_established_from_client4).unwrap(); + let packet_established_server_responce_wrong_ack = new_raw(&server, &client, 1, 7, true, false, false, false, &[]); + let ret = connection.update(&packet_established_server_responce_wrong_ack); + assert!(ret == Err(TcpSessionErr::UnexpectedAckNumber)); + let seg: Vec<_> = connection.iter(true).collect(); + assert!(seg.len() == 3); + + // server ack with ack number(bigger). Bigger ack is Ok. + let packet_established_server_responce_wrong_ack = new_raw(&server, &client, 1, 20, true, false, false, false, &[]); + let ret = connection.update(&packet_established_server_responce_wrong_ack); + assert!(ret == Ok(TcpSessionOk::ACK_SEGMENT)); + let seg: Vec<_> = connection.iter(true).collect(); + assert!(seg.len() == 4); + assert!(seg[0].0 == 0); + assert!(seg[1].0 == 0); + assert!(seg[2].0 == 0); + assert!(seg[3].0 == 1); + } // #[test] - // fn several_unordered_segments_in_one_ack() { - // let client = PeerInTest { - // addr: Ipv4Addr::new(192, 168, 1, 1), - // port: 1234, - // role: PeerRole::Client, - // }; - // let server = PeerInTest { - // addr: Ipv4Addr::new(192, 168, 1, 2), - // port: 80, - // role: PeerRole::Server, - // }; - - // // standard handshake - // let packet_handshake1 = new_raw(&client, &server, 0, 0, false, true, false, false, &[]); - // let mut connection = TcpConnection::_try_new(packet_handshake1).unwrap(); - // let packet_handshake2 = new_raw(&server, &client, 0, 1, true, true, false, false, &[]); - // connection.update(&packet_handshake2).unwrap(); - // let packet_handshake3 = new_raw(&client, &server, 1, 1, true, false, false, false, &[]); - // connection.update(&packet_handshake3).unwrap(); - - // // send 3 segments from client - // let packet_established_from_client1 = new_raw(&client, &server, 1, 1, true, false, false, false, &[1, 2, 3]); - // let packet_established_from_client2 = new_raw(&client, &server, 4, 1, true, false, false, false, &[4, 5, 6]); - // let packet_established_from_client3 = new_raw(&client, &server, 7, 1, true, false, false, false, &[7, 8, 9]); - // connection.update(&packet_established_from_client3).unwrap(); - // connection.update(&packet_established_from_client1).unwrap(); - // connection.update(&packet_established_from_client2).unwrap(); - - // // server ack - // let packet_established_server_responce = new_raw(&server, &client, 1, 10, true, false, false, false, &[]); - // let ret = connection.update(&packet_established_server_responce).unwrap(); - // assert!(ret.as_ref().unwrap().len() == 3); - // assert!(ret.as_ref().unwrap()[0].payload.as_slice() == &[1, 2, 3]); - // assert!(ret.as_ref().unwrap()[1].payload.as_slice() == &[4, 5, 6]); - // assert!(ret.as_ref().unwrap()[2].payload.as_slice() == &[7, 8, 9]); - // } - + + + }
\ No newline at end of file |
