diff options
| author | chenzizhan <[email protected]> | 2023-09-19 17:45:09 +0800 |
|---|---|---|
| committer | chenzizhan <[email protected]> | 2023-09-19 17:45:09 +0800 |
| commit | 021ca429b29d09ffb34b1b3699f165513511cb17 (patch) | |
| tree | 9803353facddc1ce5b8c6c8a2b4f36b32553a8b4 /src/session | |
| parent | 37a5886c9ba2afb2b554074f252086e59b3ae2d6 (diff) | |
reassembly dev4.0 AND fs bindingczz
Diffstat (limited to 'src/session')
| -rw-r--r-- | src/session/tcp_reassembly.rs | 1190 | ||||
| -rw-r--r-- | src/session/tcp_reassembly_with_deque.rs | 1069 |
2 files changed, 1334 insertions, 925 deletions
diff --git a/src/session/tcp_reassembly.rs b/src/session/tcp_reassembly.rs index f812739..5a2db08 100644 --- a/src/session/tcp_reassembly.rs +++ b/src/session/tcp_reassembly.rs @@ -1,1056 +1,396 @@ -use std::collections::VecDeque; -use std::f32::consts::E; -use std::net::{Ipv4Addr}; +use std::collections::BTreeMap; use std::num::Wrapping; -use crate::protocol::ipv4::IPv4Header; -use crate::protocol::ipv6::IPv6Header; -use crate::protocol::udp::UdpHeader; -use crate::protocol::ethernet::EthernetFrame; -use crate::protocol::tcp::{TcpHeader}; -use crate::protocol::dns::DNS_MESSAGE; -use crate::protocol::http::HTTP_MESSAGE; -use crate::packet::packet::Encapsulation; -use crate::packet::packet::Packet as RawPacket; - -const DEFAULT_MAX_PACKETS: usize = 128; - #[derive(Debug, Clone, PartialEq, Eq)] -pub(crate) enum TcpSegmentDescription { +pub enum Description { // has packet - Normal, + Ok, TooManyPacket, - FinTrigger, - - // no packet - Unordered, - DuplicateSeq, - OldPacket, - NoSegment, - NotIp4Tcp, - - HandshakeFail(String), - SynAckOk, - Reopen, // todo -} - -// since the pub encapsulation has many reference of the original packet buffer, we have to copy them first -#[allow(non_camel_case_types)] -#[derive(Debug, Clone)] -enum CopiedEncapsulation { - L2_ETH(EthernetFrame, Vec<u8>), - L3_IP4(IPv4Header, Vec<u8>), - L3_IP6(IPv6Header, Vec<u8>), - L4_TCP(TcpHeader, Vec<u8>), - L4_UDP(UdpHeader, Vec<u8>), - L7_DNS(DNS_MESSAGE, Vec<u8>), - L7_HTTP(HTTP_MESSAGE, Vec<u8>), - Unsupported(Vec<u8>), -} - -#[derive(Debug, Clone)] -pub(crate) struct CopiedRawPacket { - encapsulation: Vec<CopiedEncapsulation>, - - orig_data: Vec<u8>, - orig_len: u32, -} - -impl CopiedRawPacket { - fn header(&self) -> TcpHeader { - for encapsulation in &self.encapsulation { - match encapsulation { - CopiedEncapsulation::L4_TCP(header, _) => return header.clone(), - _ => {} - } - } - panic!("not a tcp packet"); - } - fn payload(&self) -> &[u8] { - for encapsulation in &self.encapsulation { - match encapsulation { - CopiedEncapsulation::L4_TCP(_, payload) => return payload.as_slice(), - _ => {} - } - } - panic!("not a tcp packet"); - } - fn replace_payload(&mut self, payload: Vec<u8>) { - for encapsulation in &mut self.encapsulation { - match encapsulation { - CopiedEncapsulation::L4_TCP(_, p) => { - *p = payload; - return; - } - _ => {} - } - } - panic!("not a tcp packet"); - } -} - -impl From<Encapsulation<'_>> for CopiedEncapsulation { - fn from(encap: Encapsulation<'_>) -> Self { - match encap { - Encapsulation::L2_ETH(l2, bytes) => CopiedEncapsulation::L2_ETH(l2, bytes.to_vec()), - Encapsulation::L3_IP4(ipv4, bytes) => CopiedEncapsulation::L3_IP4(ipv4, bytes.to_vec()), - Encapsulation::L3_IP6(ipv6, bytes) => CopiedEncapsulation::L3_IP6(ipv6, bytes.to_vec()), - Encapsulation::L4_TCP(tcp, bytes) => CopiedEncapsulation::L4_TCP(tcp, bytes.to_vec()), - Encapsulation::L4_UDP(udp, bytes) => CopiedEncapsulation::L4_UDP(udp, bytes.to_vec()), - Encapsulation::L7_DNS(dns, bytes) => CopiedEncapsulation::L7_DNS(dns, bytes.to_vec()), - Encapsulation::L7_HTTP(http, bytes) => CopiedEncapsulation::L7_HTTP(http, bytes.to_vec()), - Encapsulation::Unsupported(bytes) => CopiedEncapsulation::Unsupported(bytes.to_vec()), - } - } -} - -impl From<&RawPacket<'_>> for CopiedRawPacket { - fn from(packet: &RawPacket) -> Self { - CopiedRawPacket { - encapsulation: packet.encapsulation.clone().into_iter().map(CopiedEncapsulation::from).collect(), - orig_data: packet.orig_data.to_vec(), - orig_len: packet.orig_len, - } - } -} - -fn raw_packet_convert_to_my_packet(raw_packet: &RawPacket<'_>) -> Result<TcpPacket, TcpSegmentDescription> { - let mut payload = Vec::new(); - let mut ipv4_header = Option::None; - let mut tcp_header = Option::None; - for encapsulation in &raw_packet.encapsulation { - match encapsulation { - Encapsulation::L3_IP4(ipv4, _) => { - ipv4_header = Some(ipv4); - } - Encapsulation::L4_TCP(tcp, data) => { - tcp_header = Some(tcp); - payload = data.to_vec(); - } - _ => {} - } - } - if ipv4_header.is_none() || tcp_header.is_none() { - return Err(TcpSegmentDescription::NotIp4Tcp); - } - - Ok(TcpPacket { - payload, - src_ip: ipv4_header.unwrap().source_address, - dst_ip: ipv4_header.unwrap().dest_address, - src_port: tcp_header.unwrap().source_port, - dst_port: tcp_header.unwrap().dest_port, - seq_num: tcp_header.unwrap().seq_num, - ack_num: tcp_header.unwrap().ack_num, - raw_packet: CopiedRawPacket::from(raw_packet), - }) + Timeout, + WindowFull, } -/* -------------------------------------------------------------------------- */ -/* stream */ -/* -------------------------------------------------------------------------- */ - #[derive(Debug, Clone)] -struct TcpPacket { - payload : Vec<u8>, - src_ip: Ipv4Addr, - dst_ip: Ipv4Addr, - src_port: u16, - dst_port: u16, - seq_num: u32, - ack_num: u32, - - raw_packet: CopiedRawPacket, -} - -enum TcpFlags { - FIN = 0x01, - SYN = 0x02, - RST = 0x04, - PSH = 0x08, - ACK = 0x10, - URG = 0x20, -} - -impl TcpPacket { - fn get_sequence(&self) -> u32 { - self.seq_num - } - fn get_acknowledgement(&self) -> u32 { - self.ack_num - } - fn payload(&self) -> &[u8] { - self.payload.as_slice() - } - fn has_flag(&self, flag: TcpFlags) -> bool { - let header = self.raw_packet.header(); - match flag { - TcpFlags::URG => header.flag_urg, - TcpFlags::ACK => header.flag_ack, - TcpFlags::PSH => header.flag_psh, - TcpFlags::RST => header.flag_rst, - TcpFlags::SYN => header.flag_syn, - TcpFlags::FIN => header.flag_fin, - } - } -} - -#[derive(Debug)] -struct TcpSegment { - rel_seq: Wrapping<u32>, // todo: wrapping 主要是解决回绕问题https://blog.csdn.net/LU_ZHAO/article/details/105010778.当前没有实现,不过最好测一下 - -// todo: 带回绕的实际值查询、加减、设置和判断,难点是判断,来了一个新的seq number,我可能就要试一下是不是在回绕的范围内,如果把它当成回绕量,判断发现比上一个seq number 大,且大得很有限,就处理为回绕。 -// 看看其他代码怎么处理的. -// 注意输出到raw packet的时候还要再转一下。 +struct Segment { + rel_seq: Wrapping<u32>, // todo: wrapping 主要是解决回绕问题https://blog.csdn.net/LU_ZHAO/article/details/105010778.这个实现感觉不完全,看看别人怎么搞的 payload: Vec<u8>, - - tcp_header: TcpHeader, - - raw_packet: CopiedRawPacket, - rel_ack: Wrapping<u32>, // todo: 干掉它 } -impl TcpSegment { - /// Return the offset of the overlapping area if `self` (as left) overlaps on `right` - fn overlap_offset(&self, right: &TcpSegment) -> Option<usize> { - let next_seq = self.rel_seq + Wrapping(self.payload.len() as u32); - if next_seq > right.rel_seq { - let overlap_offset = (right.rel_seq - self.rel_seq).0 as usize; - Some(overlap_offset) +impl Segment { + fn offset_part(&self, offset: Wrapping<u32>) -> &[u8] { + let this_right = self.rel_seq + Wrapping(self.payload.len() as u32); + if this_right <= offset { + return &[]; } else { - None - } - } - - /// Splits the segment into two at the given offset. - /// - /// # Panics - /// - /// Panics if `offset > self.payload.len()` - fn split_off(&mut self, offset: usize) -> TcpSegment { - assert!(offset < self.payload.len()); - let remaining = self.payload.split_off(offset); - let rel_seq = self.rel_seq + Wrapping(offset as u32); - TcpSegment { - payload: remaining, - rel_seq, - rel_ack: self.rel_ack, - raw_packet: self.raw_packet.clone(), - tcp_header: self.tcp_header.clone(), + let overlap_size = (offset - self.rel_seq).0 as usize; + return &self.payload[overlap_size..]; } } } #[derive(Debug)] -struct TcpPeer { +pub struct Stream { // Initial Seq number (absolute) isn: Wrapping<u32>, - // Initial Ack number (absolute) - ian: Wrapping<u32>, + // Next Seq number, isn + (sum of all sent segments lengths) next_rel_seq: Wrapping<u32>, + min_rel_seq: Wrapping<u32>, // modified when clear() // The current list of segments that this peer is about to sent (ordered by rel_seq) - segments: VecDeque<TcpSegment>, - addr: Ipv4Addr, - port: u16, -} - -impl TcpPeer { - fn insert_sorted(&mut self, s: TcpSegment) { - for (n, item) in self.segments.iter().enumerate() { - if item.rel_seq > s.rel_seq { - self.segments.insert(n, s); - return; - } - } - self.segments.push_back(s); - } -} - -#[derive(Debug)] -struct TcpStream { - pub client: TcpPeer, - pub server: TcpPeer, - in_connection: bool, -} - - -#[derive(Debug)] -pub struct TcpConnection { - stream: TcpStream, + segments: BTreeMap<u32, Segment>, max_packets: usize, + window_size: usize, + timeout: u64, + + used_window_size: usize, + last_ts: Option<u64>, } -impl TcpPeer { - fn new(addr: &Ipv4Addr, port: u16) -> Self { - TcpPeer { - isn: Wrapping(0), - ian: Wrapping(0), - next_rel_seq: Wrapping(0), - segments: VecDeque::new(), - addr: *addr, - port, - } - } -} - -impl TcpStream { - pub fn new(packet: &TcpPacket) -> Self { - TcpStream { - client: TcpPeer::new(&packet.src_ip, packet.src_port), - server: TcpPeer::new(&packet.dst_ip, packet.dst_port), - in_connection: true, +impl Stream { + pub fn new(isn: u32, window_size: usize, max_packets: usize, timeout: u64) -> Self { + // fn new(isn: u32, max_n_packet, window_size, timeout) -> Self { + Stream { + isn: Wrapping(isn), + next_rel_seq: Wrapping(1), + segments: BTreeMap::new(), + min_rel_seq: Wrapping(isn), + max_packets, + window_size, + timeout, + used_window_size: 0, + last_ts: None, } } - - fn handle_synsent(&mut self, tcp: TcpPacket) { - let seq = Wrapping(tcp.get_sequence()); - - self.client.isn = seq; - self.client.next_rel_seq = Wrapping(1); - self.server.ian = seq; - - if !tcp.payload().is_empty() { - println!("Data in handshake SYN"); - // https://stackoverflow.com/questions/37994131/send-tcp-syn-packet-with-payload - // it is possible to have data in SYN, just queue it(the src window size is 0 currently) - let segment = TcpSegment { - rel_seq: Wrapping(1), // just assume client has sent a ACK, and turn to ESTABLISHED. - payload: tcp.payload().to_vec(), - tcp_header: tcp.raw_packet.header(), - raw_packet: tcp.raw_packet, - rel_ack: Wrapping(1), - }; - queue_segment(&mut self.client, segment); + pub fn update(&mut self, offset: u32, payload: &[u8], time_stamp: u64) -> Description { + if self.segments.len() >= self.max_packets { + return Description::TooManyPacket; } - } - - fn handle_synrcv(&mut self, tcp: TcpPacket) -> Result<(), TcpSegmentDescription> { - // Server -- SYN+ACK --> Client - let (src, dst) = (&mut self.server, &mut self.client); - let seq = Wrapping(tcp.get_sequence()); - let ack = Wrapping(tcp.get_acknowledgement()); - if !tcp.has_flag(TcpFlags::SYN) || !tcp.has_flag(TcpFlags::ACK) { - return Err(TcpSegmentDescription::HandshakeFail("Not a SYN + ACK".to_string())); + if self.used_window_size + payload.len()> self.window_size { + return Description::WindowFull; } - // if we had data in SYN, add its length - let next_rel_seq = if dst.segments.is_empty() { - Wrapping(1) - } else { // - Wrapping(1) + Wrapping(dst.segments[0].payload.len() as u32) - }; - if ack != dst.isn + next_rel_seq { - return Err(TcpSegmentDescription::HandshakeFail("ack number is wrong".to_string())); - } - - src.isn = seq; - src.next_rel_seq = Wrapping(1); - dst.ian = seq; - - Ok(()) - } - - fn update_after_handshake(&mut self, - tcp: TcpPacket, - to_server: bool) -> (Option<Vec<TcpSegment>>, TcpSegmentDescription) { - let (origin, destination) = if to_server { - (&mut self.client, &mut self.server) + if self.last_ts.is_none() { + self.last_ts = Some(time_stamp); } else { - (&mut self.server, &mut self.client) - }; - - let rel_seq = Wrapping(tcp.get_sequence()) - origin.isn; - let rel_ack = Wrapping(tcp.get_acknowledgement()) - destination.isn; - let is_fin = tcp.has_flag(TcpFlags::FIN) || tcp.has_flag(TcpFlags::RST); // before borrowing tcp - - println!("update_after_handshake: payload len={}", tcp.payload().len()); - println!( - " Tcp rel seq {} ack {} next seq {}", - rel_seq, - rel_ack, - origin.next_rel_seq - ); - - let segment = TcpSegment { - rel_seq, - rel_ack, - payload: tcp.payload().to_vec(), // XXX data cloned here - tcp_header: tcp.raw_packet.header(), - raw_packet: tcp.raw_packet, - }; - queue_segment(origin, segment); - if is_fin { - // fin packet can also have payload, so we queued it first. Refer to: - // https://stackoverflow.com/questions/8702646/can-a-tcp-packet-with-the-fin-flag-also-have-data - let sent_pkt = flush_peer_segments(origin); - return (Some(sent_pkt), TcpSegmentDescription::FinTrigger); + let last_ts = self.last_ts.unwrap(); + if (time_stamp > last_ts) && (time_stamp - last_ts > self.timeout) { + return Description::Timeout; + } } - // todo: closed connection restart - let sent_pkt = send_peer_segments(origin); - if origin.segments.len() > DEFAULT_MAX_PACKETS { - let sent_pkt = flush_peer_segments(origin); - return (Some(sent_pkt), TcpSegmentDescription::TooManyPacket); - } + self.last_ts = Some(std::cmp::max(self.last_ts.unwrap(), time_stamp)); - if sent_pkt.is_err() { - return (None, sent_pkt.unwrap_err()); - } else { - return (Some(sent_pkt.unwrap()), TcpSegmentDescription::Normal); + if payload.is_empty() { + return Description::Ok; } - } -} - -fn queue_segment(peer: &mut TcpPeer, segment: TcpSegment) { - if segment.payload.is_empty() { - return; - } - //todo: 老代码有一个 EARLY_DETECT_OVERLAP 不知道干嘛的 - - if peer.segments.is_empty() { - println!("Pushing segment (front)"); - peer.segments.push_front(segment); - return; - } - - println!("Adding segment"); - peer.insert_sorted(segment); -} + let segment = Segment { + rel_seq: Wrapping(offset) - self.isn, + payload: payload.to_vec(), + }; + self.insert_sorted(segment); -// let the peer send segments in its queue, update ack numbers, and pop segments that were sent -fn send_peer_segments(peer: &mut TcpPeer) -> Result<Vec<TcpSegment>, TcpSegmentDescription> { - if peer.segments.is_empty() { - println!("No segment to send"); - return Err(TcpSegmentDescription::NoSegment); + Description::Ok } - let mut ret = Vec::new(); - let mut description = TcpSegmentDescription::Normal; - while !peer.segments.is_empty() { - let segment = &peer.segments[0]; - println!("send segment, payload: {:?}", segment.payload); - if segment.rel_seq > peer.next_rel_seq { // there is a gap - println!("Gap detected"); - description = TcpSegmentDescription::Unordered; - break; + // let the peer send segments in its queue, update ack numbers, and pop segments that were sent + pub fn pop(&mut self) -> Option<Vec<u8>> { + if self.segments.is_empty() { + println!("No segment to send"); + return None; } + let mut ret = Vec::new(); - if segment.rel_seq < peer.next_rel_seq { // caused by flush_peer_segments, or duplicate pkt, omit old segments - // todo: 感觉这里最好区别一下是不是因为flush_peer_segments导致的,虽然只影响错误码 - // 甚至会是over lap 导致的 - println!("Dropping segment"); - if (segment.rel_seq + Wrapping(segment.payload.len() as u32)) > peer.next_rel_seq { - println!("Segment overlaps next, payload before: {:?}", segment.payload); - let mut segment = peer.segments.pop_front().unwrap(); - let overlap_offset = (peer.next_rel_seq - segment.rel_seq).0; - segment.payload = segment.payload.split_off(overlap_offset as usize); - println!("Segment overlaps next, payload after: {:?}", segment.payload); - segment.rel_seq = peer.next_rel_seq; - peer.segments.push_front(segment); - assert!(!peer.segments.is_empty()); - } else if (segment.rel_seq + Wrapping(segment.payload.len() as u32)) == peer.next_rel_seq { - println!("Segment ends at next"); - peer.segments.pop_front(); - description = TcpSegmentDescription::DuplicateSeq; - } else { - peer.segments.pop_front(); - description = TcpSegmentDescription::OldPacket; - println!("Segment ends before next"); + while !self.segments.is_empty() { + if self.segments.first_entry().unwrap().get().rel_seq > self.next_rel_seq { + // there is a gap + println!("Gap detected"); + break; } - continue; - } - - // safety: segments is just tested above - let mut segment = peer.segments.pop_front().unwrap(); - - remove_overlapped(peer, &mut segment); - adjust_seq_numbers(peer, &segment); - println!("Sending segment, payload: {:?}", segment.payload); - segment.raw_packet.replace_payload(segment.payload.clone()); - ret.push(segment); - } - println!("ret len: {}", ret.len()); - if ret.len() == 0 { - return Err(description); - } - Ok(ret) -} - -fn flush_peer_segments(peer: &mut TcpPeer) -> Vec<TcpSegment> { - // 最终预期: - // 1. 队列全清空 - // 2. next seq 正常调整 - - // // 之后呢? - // 标记该Session为满释放异常,并声明一个新的变量,为“上次flush的时候,最大的rel seq” - // 之后,如果有新的segment进来,那么就判断,如果rel seq < 上次flush的最大rel seq,那么直接丢弃 - // 否则,就正常处理,放入队列中。 - - let mut ret = Vec::new(); - while !peer.segments.is_empty() { - // safety: segments is just tested above - let mut segment = peer.segments.pop_front().unwrap(); + let segment = self.segments.pop_first().unwrap().1; + let extention = segment.offset_part(self.next_rel_seq); + ret.extend_from_slice(extention); + self.next_rel_seq += Wrapping(extention.len() as u32); - remove_overlapped(peer, &mut segment); - if peer.segments.len() == 0 { // the last one has the biggest rel seq - peer.next_rel_seq = segment.rel_seq + Wrapping(segment.payload.len() as u32); + self.used_window_size -= segment.payload.len(); } + println!("ret len: {}", ret.len()); - ret.push(segment); - } - - ret -} - - // 情况1: [1,2,3] [4,5,6] - // [3, 4,5] - // 2: [1,2,3] - // [1,2,3] - // 3: [4,5,6] - // [4,5,6] - // 以上三种均为duplicate,直接丢弃 - // 4: [1,2,3] - // [1,2,3,4] - // 保留[1,2,3] [4] - // 5: [2,3] [6,7] - // [1,2,3,4,5,6] - // 保留[1,2,3,4,5,6] [7] -fn remove_overlapped(peer: &mut TcpPeer, segment: &mut TcpSegment) { - // loop while segment has overlap - while let Some(next) = peer.segments.front() { - if let Some(overlap_offset) = segment.overlap_offset(next) { - println!( - "overlaps next candidate (at offset={})", - overlap_offset - ); - // we will modify the subsequent segment (next) - // safety: element presence was tested in outer loop - let next = peer.segments.pop_front().unwrap(); - - // split next - let overlap_size = segment.payload.len() - overlap_offset; - let min_overlap_size = std::cmp::min(overlap_size, next.payload.len()); - // compare overlap area - if next.payload[..min_overlap_size] - != segment.payload[overlap_offset..overlap_offset + min_overlap_size] - { - println!("Overlap area differs!"); - } - if overlap_size >= next.payload.len() { - // subsequent segment starts after and is smaller, so drop it - drop(next); - continue; - } - // otherwise, split next into left and right, drop left and accept right - let mut left = next; - let right = left.split_off(overlap_size); - // to accept right, merge it into segment - segment.payload.extend_from_slice(&right.payload); + if ret.is_empty() { + return None; } else { - // println!("no overlap, break"); - break; + return Some(ret); } } -} - -fn adjust_seq_numbers(origin: &mut TcpPeer, segment: &TcpSegment) { - if !segment.payload.is_empty() { - // adding length is wrong in case of overlap - // origin.next_rel_seq += Wrapping(segment.payload.len() as u32); - origin.next_rel_seq = segment.rel_seq + Wrapping(segment.payload.len() as u32); - } - if segment.tcp_header.flag_fin { - // println!("Segment has FIN"); - origin.next_rel_seq += Wrapping(1); - } -} + pub fn clear(&mut self) -> Vec<Vec<u8>> { + let mut ret = Vec::new(); + + while !self.segments.is_empty() { + let segment = self.segments.pop_first().unwrap().1; -impl TcpConnection { - pub(crate) fn try_new(packet: &RawPacket) -> Result<Self, TcpSegmentDescription> { - let simple_packet = raw_packet_convert_to_my_packet(packet)?; - Self::_try_new(simple_packet) - } + if segment.rel_seq + Wrapping(segment.payload.len() as u32) <= self.next_rel_seq { + continue; + } - pub(crate) fn update(&mut self, packet: &RawPacket) -> (Option<Vec<CopiedRawPacket>>, TcpSegmentDescription) { - let simple_packet = raw_packet_convert_to_my_packet(packet); - if let Err(e) = simple_packet { - return (None, e); + let rel = segment.payload.len() as u32; + if segment.rel_seq > self.next_rel_seq || ret.is_empty() { + ret.push(segment.payload); + self.next_rel_seq = segment.rel_seq + Wrapping(rel); + } else { + if let Some(last) = ret.last_mut() { + let extention = segment.offset_part(self.next_rel_seq); + last.extend_from_slice(extention); + self.next_rel_seq += Wrapping(extention.len() as u32); + } + } } - self._update(simple_packet.unwrap()) - } - fn _try_new(packet: TcpPacket) -> Result<Self, TcpSegmentDescription> { - let mut connection = TcpConnection { - stream: TcpStream::new(&packet), - max_packets: DEFAULT_MAX_PACKETS, - }; + self.min_rel_seq = self.next_rel_seq; + self.used_window_size = 0; + + ret + } - if !packet.has_flag(TcpFlags::SYN) { - return Err(TcpSegmentDescription::HandshakeFail("Not a SYN".to_string())); - } - if packet.has_flag(TcpFlags::ACK) { - println!("First packet is SYN+ACK"); - return Err(TcpSegmentDescription::HandshakeFail("First packet is SYN+ACK".to_string())); - } - if packet.has_flag(TcpFlags::RST) { - return Err(TcpSegmentDescription::HandshakeFail("First packet is RST".to_string())); - } - if packet.has_flag(TcpFlags::FIN) { - return Err(TcpSegmentDescription::HandshakeFail("First packet is FIN".to_string())); + pub fn pullup(&mut self) -> &[u8] { + let ret = self.pop(); + if ret.is_none() { + return &[]; } + let ret = ret.unwrap(); + self.insert_sorted(Segment { + rel_seq: self.next_rel_seq, + payload: ret, + }); - connection.stream.handle_synsent(packet); - Ok(connection) + self.segments.iter().next().unwrap().1.payload.as_slice() } - fn _update(&mut self, tcp: TcpPacket) -> (Option<Vec<CopiedRawPacket>>, TcpSegmentDescription) { - let stream = &mut self.stream; - - - // get origin and destination - let to_server = tcp.dst_ip == stream.server.addr && - tcp.dst_port == stream.server.port; - println!("to_server: {}", to_server); - - if self.stream.in_connection { - let ret = self.stream.handle_synrcv(tcp); - if let Err(e) = ret { - return (None, e); - } - - self.stream.in_connection = false; - return (None, TcpSegmentDescription::SynAckOk); + fn insert_sorted(&mut self, s: Segment) { + if s.rel_seq < self.min_rel_seq { + return; } - let (segments, ret) = self.stream.update_after_handshake(tcp, to_server); - - if segments.is_none() { - return (None, ret); - } - - let ret_packet = segments.unwrap().into_iter(). - map(|segment| {segment.raw_packet}).collect(); - - return (Some(ret_packet), ret); + self.used_window_size += s.payload.len(); + self.segments.insert(s.rel_seq.0, s); // todo: 换成wrap 以后这里的key 要有新的比较逻辑 } } - #[cfg(test)] mod tests { - use std::vec; - use crate::protocol::ip::IPProtocol; - use super::*; - static SLICE_DUMMY:&[u8] = &[42,42,42]; - - #[derive(Debug, Clone)] - enum PeerRole { - Client, - Server, - } - #[derive(Debug, Clone)] - struct PeerInTest { - addr: Ipv4Addr, - /// println: port - port: u16, - 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> { - let src_ip = from.addr; - let dst_ip = to.addr; - let header = TcpHeader { - source_port: from.port, - dest_port: to.port, - seq_num, - ack_num, - data_offset: 0, - reserved: 0, - flag_urg: false, - flag_ack: has_ack, - flag_psh: false, - flag_rst: has_rst, - flag_syn: has_syn, - flag_fin: has_fin, - window: 65535, - checksum: 0, - urgent_ptr: 0, - options: None, - }; - - let ip_header = IPv4Header { - version: 4, - ihl: 5, - tos: 0, - length: 0, - id: 0, - flags: 0, - frag_offset: 0, - ttl: 0, - protocol: IPProtocol::TCP, - checksum: 0, - source_address: src_ip, - dest_address: dst_ip, - }; - - let encap1 : Encapsulation = Encapsulation::L3_IP4(ip_header, SLICE_DUMMY); - let encap2 : Encapsulation = Encapsulation::L4_TCP(header, segment); - let encap_vec = vec![encap1, encap2]; - - RawPacket { - orig_data: SLICE_DUMMY, - orig_len: SLICE_DUMMY.len() as u32, - encapsulation: encap_vec, - } - } - - const CLIENT: PeerInTest = PeerInTest { - addr: Ipv4Addr::new(192, 168, 1, 1), - port: 1234, - role: PeerRole::Client, - }; - const SERVER: PeerInTest = PeerInTest { - addr: Ipv4Addr::new(192, 168, 1, 2), - port: 80, - role: PeerRole::Server, - }; - #[test] - fn single_segment_ping_pong() { - const INIT_SEQ:u32 = 12345; - let packet_handshake1 = new_raw(&CLIENT, &SERVER, INIT_SEQ + 0, 0, false, true, false, false, &[]); - let mut connection = TcpConnection::try_new(&packet_handshake1).unwrap(); - - let packet_handshake2 = new_raw(&SERVER, &CLIENT, 0, INIT_SEQ+1, true, true, false, false, &[]); - let ret = connection.update(&packet_handshake2); - assert!(ret.1 == TcpSegmentDescription::SynAckOk); - - let packet_established_from_client = new_raw(&CLIENT, &SERVER, INIT_SEQ+1, 1, true, false, false, false, &[1, 2, 3]); - let ret = connection.update(&packet_established_from_client); - println!("ret: {:?}", ret); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.unwrap()[0].payload() == &[1, 2, 3]); - - let packet_established_from_server = new_raw(&SERVER, &CLIENT, 1, INIT_SEQ+4, true, false, false, false, &[4, 5, 6]); - let ret = connection.update(&packet_established_from_server); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.unwrap()[0].payload() == &[4, 5, 6]); - - let packet_established_from_client2 = new_raw(&CLIENT, &SERVER, INIT_SEQ+4, 4, true, false, false, false, &[7, 8, 9]); - let ret = connection.update(&packet_established_from_client2); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.unwrap()[0].payload() == &[7, 8, 9]); - } - - #[test] - fn several_ordered_consecutive_segments() { - 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); + fn several_ordered_segments() { + let mut s = Stream::new(0, 10000, 100, 10000); + assert_eq!(s.update(1, &[1, 2, 3], 0), Description::Ok); + assert_eq!(s.update(4, &[4, 5], 0), Description::Ok); + assert_eq!(s.update(6, &[6], 0), Description::Ok); - 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); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.unwrap()[0].payload() == &[1, 2, 3]); - 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); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.unwrap()[0].payload() == &[4, 5, 6]); - 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); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.unwrap()[0].payload() == &[7, 8, 9]); + assert_eq!(s.pullup(), &[1, 2, 3, 4, 5, 6]); + let expected_clear = vec![vec![1, 2, 3, 4, 5, 6]]; + assert_eq!(s.clear(), expected_clear); } #[test] - fn several_unordered_consecutive_segments() { - 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); + fn several_unordered_segments() { + let mut s = Stream::new(0, 10000, 100, 10000); + assert_eq!(s.update(6, &[6], 0), Description::Ok); + assert_eq!(s.update(1, &[1, 2, 3], 0), Description::Ok); + assert_eq!(s.update(4, &[4, 5], 0), Description::Ok); - 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); - assert!(ret.1 == TcpSegmentDescription::Unordered); - 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); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.as_ref().unwrap()[0].payload() == &[1, 2, 3]); - assert!(ret.0.unwrap()[1].payload() == &[4, 5, 6]); - 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); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.unwrap()[0].payload() == &[7, 8, 9]); + assert_eq!(s.pullup(), &[1, 2, 3, 4, 5, 6]); + let expected_clear = vec![vec![1, 2, 3, 4, 5, 6]]; + assert_eq!(s.clear(), expected_clear); } #[test] - fn several_unordered_inconsecutive_segments() { - 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); - - 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); - println!("ret: {:?}", ret); - assert!(ret.1 == TcpSegmentDescription::Unordered); - let packet_from_server = new_raw(&SERVER, &CLIENT, 1, 1, true, false, false, false, &[11, 12, 13]); - let ret = connection.update(&packet_from_server); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.as_ref().unwrap()[0].payload() == &[11, 12, 13]); + fn with_hole() { + let mut s = Stream::new(0, 10000, 100, 10000); + assert_eq!(s.update(1, &[1, 2], 0), Description::Ok); // miss 3 + assert_eq!(s.update(4, &[4, 5], 0), Description::Ok); + assert_eq!(s.update(6, &[6], 0), Description::Ok); // miss 7 + assert_eq!(s.update(8, &[8, 9], 0), Description::Ok); - 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); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.as_ref().unwrap()[0].payload() == &[1, 2, 3]); - assert!(ret.0.unwrap()[1].payload() == &[4, 5, 6]); - 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); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.unwrap()[0].payload() == &[7, 8, 9]); + let expected_clear = vec![vec![1, 2], vec![4, 5, 6], vec![8, 9]]; + assert_eq!(s.clear(), expected_clear); } #[test] fn duplicate_packet() { - 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); + let mut s = Stream::new(0, 10000, 100, 10000); + assert_eq!(s.update(1, &[1, 2, 3], 0), Description::Ok); + assert_eq!(s.update(1, &[1, 2, 3], 0), Description::Ok); + assert_eq!(s.update(4, &[4, 5], 0), Description::Ok); - 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); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.as_ref().unwrap()[0].payload() == &[1, 2, 3]); - let ret = connection.update(&packet_established_from_client); - assert!(ret.1 == TcpSegmentDescription::DuplicateSeq); - assert!(ret.0.is_none()); + assert_eq!(s.pullup(), &[1, 2, 3, 4, 5]); + let expected_clear = vec![vec![1, 2, 3, 4, 5]]; + assert_eq!(s.clear(), expected_clear); } #[test] - fn too_many_packet() { - 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); - - // let first packet drop , so that the queue will be filled until full - for i in 1..DEFAULT_MAX_PACKETS + 1{ - let packet_established_from_client = new_raw(&CLIENT, &SERVER, 1 + i as u32, 1, true, false, false, false, &[1]); - let ret = connection.update(&packet_established_from_client); - assert!(ret.1 == TcpSegmentDescription::Unordered); - } - let packet_established_from_client = new_raw(&CLIENT, &SERVER, 1 + DEFAULT_MAX_PACKETS as u32, 1, true, false, false, false, &[1]); - let ret = connection.update(&packet_established_from_client); - assert!(ret.1 == TcpSegmentDescription::TooManyPacket); - assert!(ret.0.unwrap().len() == DEFAULT_MAX_PACKETS); - - // the first packet come unexpectedly, just throw it away - let packet_established_from_client = new_raw(&CLIENT, &SERVER, 1, 1, true, false, false, false, &[1]); - let ret = connection.update(&packet_established_from_client); - assert!(ret.1 == TcpSegmentDescription::OldPacket); - assert!(ret.0.is_none()); - - // continue to send - let packet_established_from_client = new_raw(&CLIENT, &SERVER, 2 + DEFAULT_MAX_PACKETS as u32, 1, true, false, false, false, &[2,3,4]); - let ret = connection.update(&packet_established_from_client); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.unwrap()[0].payload() == &[2,3,4]); + fn pop_empty() { + let mut s = Stream::new(0, 10000, 100, 10000); + assert_eq!(s.pop(), None); } #[test] - fn segment_in_syn() { - let packet_handshake1 = new_raw(&CLIENT, &SERVER, 0, 0, false, true, false, false, &[1,2,3]); - let mut connection = TcpConnection::try_new(&packet_handshake1).unwrap(); - let packet_handshake2 = new_raw(&SERVER, &CLIENT, 0, 4, true, true, false, false, &[]); - connection.update(&packet_handshake2); + fn pop_blocked_by_hole() { + let mut s = Stream::new(0, 10000, 100, 10000); + assert_eq!(s.update(1, &[1, 2], 0), Description::Ok); // miss 3 + assert_eq!(s.update(4, &[4, 5], 0), Description::Ok); - let packet_established_from_client = new_raw(&CLIENT, &SERVER, 4, 1, true, false, false, false, &[4,5,6]); - let ret = connection.update(&packet_established_from_client); - println!("ret: {:?}", ret); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.as_ref().unwrap()[0].payload() == &[1,2,3]); - assert!(ret.0.as_ref().unwrap()[1].payload() == &[4,5,6]); + assert_eq!(s.pop().unwrap(), &[1, 2]); + assert_eq!(s.pop(), None); + assert_eq!(s.pop(), None); + + assert_eq!(s.update(3, &[3], 0), Description::Ok); + assert_eq!(s.pop().unwrap(), &[3, 4, 5]); } #[test] - fn wrong_flag_during_handshake_syn() { - let packet_handshake1 = new_raw(&CLIENT, &SERVER, 0, 0, false, false, false, false, &[]); - let mut connection = TcpConnection::try_new(&packet_handshake1); - assert!(connection.is_err()); - assert!(connection.unwrap_err() == TcpSegmentDescription::HandshakeFail("Not a SYN".to_string())); - - - let packet_handshake1 = new_raw(&CLIENT, &SERVER, 0, 0, false, true, true, false, &[]); - let mut connection = TcpConnection::try_new(&packet_handshake1); - assert!(connection.is_err()); - assert!(connection.unwrap_err() == TcpSegmentDescription::HandshakeFail("First packet is RST".to_string())); + fn overlap_when_popped() { + // [1,2,3] -> popped + // [3,4,5,6] -> [4,5,6] + let mut s = Stream::new(0, 10000, 100, 10000); + assert_eq!(s.update(1, &[1, 2, 3], 0), Description::Ok); + assert_eq!(s.pop().unwrap(), &[1, 2, 3]); + assert_eq!(s.update(3, &[3, 4, 5, 6], 0), Description::Ok); + assert_eq!(s.pop().unwrap(), &[4, 5, 6]); } #[test] - fn wrong_flag_during_handshake_acksyn() { - let packet_handshake1 = new_raw(&CLIENT, &SERVER, 0, 0, false, true, false, false, &[1,2,3]); - let mut connection = TcpConnection::try_new(&packet_handshake1).unwrap(); - - let packet_handshake2 = new_raw(&SERVER, &CLIENT, 0, 3, true, true, false, false, &[]); // expected ack num is 4 - let ret = connection.update(&packet_handshake2); - assert!(ret.1 == TcpSegmentDescription::HandshakeFail("ack number is wrong".to_string())); - - let packet_handshake2 = new_raw(&SERVER, &CLIENT, 0, 4, false, true, false, false, &[]); // no ack - let ret = connection.update(&packet_handshake2); - assert!(ret.1 == TcpSegmentDescription::HandshakeFail("Not a SYN + ACK".to_string())); + fn overlap_as_old_packet() { + // [1,2,3,4,5,6] -> popped + // [2,3,4] -> drop(description: old packet) + let mut s = Stream::new(0, 10000, 100, 10000); + assert_eq!(s.update(1, &[1, 2, 3, 4, 5, 6], 0), Description::Ok); + assert_eq!(s.pop().unwrap(), &[1, 2, 3, 4, 5, 6]); + assert_eq!(s.update(2, &[2, 3, 4], 0), Description::Ok); + assert_eq!(s.pop(), None); } #[test] - fn not_tcp_ip_packet() { - let mut packet = new_raw(&CLIENT, &SERVER, 0, 0, false, true, false, false, &[]); - packet.encapsulation.pop(); - let mut connection = TcpConnection::try_new(&packet); - assert!(connection.is_err()); - assert!(connection.unwrap_err() == TcpSegmentDescription::NotIp4Tcp); + fn overlap_change_next_one() { + // [2,3,4] -> wait + // [3,4,5] -> wait(join the first as [2,3,4,5]) + // [1] -> send [1 2,3,4,5] + let mut s = Stream::new(0, 10000, 100, 10000); + assert_eq!(s.update(2, &[2, 3, 4], 0), Description::Ok); + assert_eq!(s.update(3, &[3, 4, 5], 0), Description::Ok); + assert!(s.pop().is_none()); + + assert_eq!(s.update(1, &[1], 0), Description::Ok); + assert_eq!(s.pop().unwrap(), &[1, 2, 3, 4, 5]); } #[test] - fn fin_with_data() { - 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); - - let packet_established_from_client = new_raw(&CLIENT, &SERVER, 2, 1, true, false, false, false, &[2,3]); - let ret = connection.update(&packet_established_from_client); - assert!(ret.1 == TcpSegmentDescription::Unordered); + fn overlap_del_next_one() { + // [2,3,4,5] -> wait + // [3,4,5] -> del(overlapped) + // [1,2,3] -> send [1,2,3,4,5] + let mut s = Stream::new(0, 10000, 100, 10000); + assert_eq!(s.update(2, &[2, 3, 4, 5], 0), Description::Ok); + assert_eq!(s.update(3, &[3, 4, 5], 0), Description::Ok); + assert!(s.pop().is_none()); - let packet_established_from_client = new_raw(&CLIENT, &SERVER, 4, 1, true, false, false, true, &[4,5,6]); - let ret = connection.update(&packet_established_from_client); - assert!(ret.1 == TcpSegmentDescription::FinTrigger); - assert!(ret.0.as_ref().unwrap()[0].payload() == &[2,3]); - assert!(ret.0.as_ref().unwrap()[1].payload() == &[4,5,6]); + assert_eq!(s.update(1, &[1, 2, 3], 0), Description::Ok); + assert_eq!(s.pop().unwrap(), &[1, 2, 3, 4, 5]); } #[test] - fn overlap_partially_sent_before() { - // [1,2,3] -> sent - // [3,4,5,6] -> [4,5,6] - 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); - - 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); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.as_ref().unwrap()[0].payload() == &[1,2,3]); + fn overlap_surpass_all() { + // [2] -> wait + // [3] -> wait + // [1,2,3,4] -> send [1,2,3,4] + let mut s = Stream::new(0, 10000, 100, 10000); + assert_eq!(s.update(2, &[2], 0), Description::Ok); + assert_eq!(s.update(3, &[3], 0), Description::Ok); + assert!(s.pop().is_none()); - let packet_established_from_client = new_raw(&CLIENT, &SERVER, 3, 1, true, false, false, false, &[3,4,5,6]); - let ret = connection.update(&packet_established_from_client); - println!("ret: {:?}", ret.0.as_ref().unwrap()[0].payload()); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.as_ref().unwrap()[0].payload() == &[4,5,6]); // [3] overlap, only send [4,5,6] + assert_eq!(s.update(1, &[1, 2, 3, 4], 0), Description::Ok); + assert_eq!(s.pop().unwrap(), &[1, 2, 3, 4]); } #[test] - fn overlap_as_old_packet() { - // [1,2,3,4,5,6] -> sent - // [2,3,4] -> drop(description: old packet) - 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); - - let packet_established_from_client = new_raw(&CLIENT, &SERVER, 1, 1, true, false, false, false, &[1,2,3,4,5,6]); - let ret = connection.update(&packet_established_from_client); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.as_ref().unwrap()[0].payload() == &[1,2,3,4,5,6]); + fn clear_and_omit_old_packet() { + // [2,3,4] -> wait + // [3,4,5] -> clear ( return [2,3,4,5] ) + // [1] -> omit + let mut s = Stream::new(0, 10000, 100, 10000); + assert_eq!(s.update(2, &[2, 3, 4], 0), Description::Ok); + assert_eq!(s.update(3, &[3, 4, 5], 0), Description::Ok); + assert_eq!(s.clear(), vec![vec![2, 3, 4, 5]]); - let packet_established_from_client = new_raw(&CLIENT, &SERVER, 2, 1, true, false, false, false, &[2,3,4]); - let ret = connection.update(&packet_established_from_client); - assert!(ret.1 == TcpSegmentDescription::OldPacket); - assert!(ret.0.is_none()); + assert_eq!(s.update(1, &[1], 0), Description::Ok); + assert_eq!(s.clear(), Vec::<Vec<u8>>::new()); // 返回空还是返回[1]? } #[test] - fn overlap_change_next_one() { - // [2,3,4] -> wait - // [3,4,5] -> wait(join the first as [2,3,4,5]) - // [1] -> send [1] [2,3,4,5] - 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); + fn clear_and_omit_old_packet_even_though_something_new() { // it's not a normal case. + // [2] -> wait + // [3] -> clear ( return [2,3] ) + // [1,2,3,4] -> omit + let mut s = Stream::new(0, 10000, 100, 10000); + assert_eq!(s.update(2, &[2], 0), Description::Ok); + assert_eq!(s.update(3, &[3], 0), Description::Ok); + assert_eq!(s.clear(), vec![vec![2, 3]]); - let packet_established_from_client2 = new_raw(&CLIENT, &SERVER, 2, 1, true, false, false, false, &[2,3,4]); - let packet_established_from_client1 = new_raw(&CLIENT, &SERVER, 1, 1, true, false, false, false, &[1]); - let packet_established_from_client3 = new_raw(&CLIENT, &SERVER, 3, 1, true, false, false, false, &[3,4,5]); - let ret = connection.update(&packet_established_from_client2); - assert!(ret.1 == TcpSegmentDescription::Unordered); - let ret = connection.update(&packet_established_from_client3); - assert!(ret.1 == TcpSegmentDescription::Unordered); - let ret = connection.update(&packet_established_from_client1); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.as_ref().unwrap().len() == 2); - assert!(ret.0.as_ref().unwrap()[0].payload() == &[1]); - assert!(ret.0.as_ref().unwrap()[1].payload() == &[2,3,4,5]); + assert_eq!(s.update(1, &[1, 2, 3, 4], 0), Description::Ok); + assert_eq!(s.clear(), Vec::<Vec<u8>>::new()); } #[test] - fn overlap_del_next_one() { + fn overlap_completely_during_clear() { // [2,3,4,5] -> wait // [3,4,5] -> del(overlapped) - // [1,2,3] -> send [1,2,3,4,5] - 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); + // [1,2,3] -> omit + let mut s = Stream::new(0, 10000, 100, 10000); + assert_eq!(s.update(2, &[2, 3, 4, 5], 0), Description::Ok); + assert_eq!(s.update(3, &[3, 4, 5], 0), Description::Ok); + assert_eq!(s.clear(), vec![vec![2, 3, 4, 5]]); - let packet_established_from_client2 = new_raw(&CLIENT, &SERVER, 2, 1, true, false, false, false, &[2,3,4,5]); - let packet_established_from_client1 = new_raw(&CLIENT, &SERVER, 1, 1, true, false, false, false, &[1,2,3]); - let packet_established_from_client3 = new_raw(&CLIENT, &SERVER, 3, 1, true, false, false, false, &[3,4,5]); - let ret = connection.update(&packet_established_from_client2); - assert!(ret.1 == TcpSegmentDescription::Unordered); - let ret = connection.update(&packet_established_from_client3); - assert!(ret.1 == TcpSegmentDescription::Unordered); - let ret = connection.update(&packet_established_from_client1); - assert!(ret.1 == TcpSegmentDescription::Normal); - println!("ret: {:?}", ret.0.as_ref().unwrap()); + assert_eq!(s.update(1, &[1, 2, 3], 0), Description::Ok); + assert_eq!(s.clear(), Vec::<Vec<u8>>::new()); + } + + #[test] + fn timeout() { + let mut s = Stream::new(0, 10000, 100, 10000); + assert_eq!(s.update(1, &[1, 2, 3, 4], 10001), Description::Ok); + assert_eq!(s.update(5, &[2, 3, 4, 5], 20002), Description::Timeout); - assert!(ret.0.as_ref().unwrap().len() == 1); - assert!(ret.0.as_ref().unwrap()[0].payload() == &[1,2,3,4,5]); + assert_eq!(s.clear(), vec![vec![1, 2, 3, 4]]); } #[test] - fn overlap_surpass_all() { - // [2] -> wait - // [3] -> wait - // [1,2,3,4] -> send [1,2,3,4] - 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); + fn full_window() { + let mut s = Stream::new(0, 10, 100, 10000); - let packet_established_from_client2 = new_raw(&CLIENT, &SERVER, 2, 1, true, false, false, false, &[2]); - let packet_established_from_client3 = new_raw(&CLIENT, &SERVER, 3, 1, true, false, false, false, &[3]); - let packet_established_from_client1 = new_raw(&CLIENT, &SERVER, 1, 1, true, false, false, false, &[1,2,3,4]); - let ret = connection.update(&packet_established_from_client3); - assert!(ret.1 == TcpSegmentDescription::Unordered); - let ret = connection.update(&packet_established_from_client2); - assert!(ret.1 == TcpSegmentDescription::Unordered); - let ret = connection.update(&packet_established_from_client1); - assert!(ret.1 == TcpSegmentDescription::Normal); - assert!(ret.0.as_ref().unwrap().len() == 1); - assert!(ret.0.as_ref().unwrap()[0].payload() == &[1,2,3,4]); + assert_eq!(s.update(1, &[1, 2, 3, 4], 0), Description::Ok); + assert_eq!(s.update(5, &[5, 6, 7, 8], 0), Description::Ok); + assert_eq!(s.update(9, &[2, 3, 4, 5], 0), Description::WindowFull); + + assert_eq!(s.pop().unwrap(), &[1, 2, 3, 4, 5, 6, 7, 8]); // pop will clear window size + + let v:Vec<_> = (1..=10).collect(); + assert_eq!(s.update(9, v.as_slice(), 0), Description::Ok); + assert_eq!(s.update(19, &[1], 0), Description::WindowFull); } + #[test] + fn too_many_packet() { + let mut s = Stream::new(0, 10000, 2, 10000); + assert_eq!(s.update(1, &[1, 2, 3, 4], 0), Description::Ok); + assert_eq!(s.update(6, &[6, 7, 8], 0), Description::Ok); // hole + assert_eq!(s.update(9, &[2, 3, 4, 5], 0), Description::TooManyPacket); + assert_eq!(s.pop().unwrap(), &[1, 2, 3, 4]); // pop 1 - // todo: 回绕 -}
\ No newline at end of file + assert_eq!(s.update(9, &[11], 0), Description::Ok); + assert_eq!(s.update(10, &[12], 0), Description::TooManyPacket); + assert_eq!(s.clear(), vec![vec![6, 7, 8, 11]]); + } +} diff --git a/src/session/tcp_reassembly_with_deque.rs b/src/session/tcp_reassembly_with_deque.rs new file mode 100644 index 0000000..0cb14ca --- /dev/null +++ b/src/session/tcp_reassembly_with_deque.rs @@ -0,0 +1,1069 @@ +use std::collections::VecDeque; +use std::f32::consts::E; +use std::net::{Ipv4Addr}; +use std::num::Wrapping; + +use crate::protocol::ipv4::IPv4Header; +use crate::protocol::ipv6::IPv6Header; +use crate::protocol::udp::UdpHeader; +use crate::protocol::ethernet::EthernetFrame; +use crate::protocol::tcp::{TcpHeader}; +use crate::protocol::dns::DNS_MESSAGE; +use crate::protocol::http::HTTP_MESSAGE; +use crate::packet::packet::Encapsulation; +use crate::packet::packet::Packet as RawPacket; + +const DEFAULT_MAX_PACKETS: usize = 128; + + + + +//todo: evbuffer + +// todo: 超时 rdt +// 内存(所有segment 一共加起来有几个byte) +// window size +// 提供各种接口,来设置我的行为 +// todo: interval tree 重新处理overlap 问题 + + + +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) enum TcpSegmentDescription { + // has packet + Normal, + TooManyPacket, + FinTrigger, + + // no packet + Unordered, + DuplicateSeq, + OldPacket, + NoSegment, + NotIp4Tcp, + + HandshakeFail(String), + SynAckOk, + Reopen, // todo +} + +// since the pub encapsulation has many reference of the original packet buffer, we have to copy them first +#[allow(non_camel_case_types)] +#[derive(Debug, Clone)] +enum CopiedEncapsulation { + L2_ETH(EthernetFrame, Vec<u8>), + L3_IP4(IPv4Header, Vec<u8>), + L3_IP6(IPv6Header, Vec<u8>), + L4_TCP(TcpHeader, Vec<u8>), + L4_UDP(UdpHeader, Vec<u8>), + L7_DNS(DNS_MESSAGE, Vec<u8>), + L7_HTTP(HTTP_MESSAGE, Vec<u8>), + Unsupported(Vec<u8>), +} + +#[derive(Debug, Clone)] +pub(crate) struct CopiedRawPacket { + encapsulation: Vec<CopiedEncapsulation>, + + orig_data: Vec<u8>, + orig_len: u32, +} + +impl CopiedRawPacket { + fn header(&self) -> TcpHeader { + for encapsulation in &self.encapsulation { + match encapsulation { + CopiedEncapsulation::L4_TCP(header, _) => return header.clone(), + _ => {} + } + } + panic!("not a tcp packet"); + } + fn payload(&self) -> &[u8] { + for encapsulation in &self.encapsulation { + match encapsulation { + CopiedEncapsulation::L4_TCP(_, payload) => return payload.as_slice(), + _ => {} + } + } + panic!("not a tcp packet"); + } + fn replace_payload(&mut self, payload: Vec<u8>) { + for encapsulation in &mut self.encapsulation { + match encapsulation { + CopiedEncapsulation::L4_TCP(_, p) => { + *p = payload; + return; + } + _ => {} + } + } + panic!("not a tcp packet"); + } +} + +impl From<Encapsulation<'_>> for CopiedEncapsulation { + fn from(encap: Encapsulation<'_>) -> Self { + match encap { + Encapsulation::L2_ETH(l2, bytes) => CopiedEncapsulation::L2_ETH(l2, bytes.to_vec()), + Encapsulation::L3_IP4(ipv4, bytes) => CopiedEncapsulation::L3_IP4(ipv4, bytes.to_vec()), + Encapsulation::L3_IP6(ipv6, bytes) => CopiedEncapsulation::L3_IP6(ipv6, bytes.to_vec()), + Encapsulation::L4_TCP(tcp, bytes) => CopiedEncapsulation::L4_TCP(tcp, bytes.to_vec()), + Encapsulation::L4_UDP(udp, bytes) => CopiedEncapsulation::L4_UDP(udp, bytes.to_vec()), + Encapsulation::L7_DNS(dns, bytes) => CopiedEncapsulation::L7_DNS(dns, bytes.to_vec()), + Encapsulation::L7_HTTP(http, bytes) => CopiedEncapsulation::L7_HTTP(http, bytes.to_vec()), + Encapsulation::Unsupported(bytes) => CopiedEncapsulation::Unsupported(bytes.to_vec()), + } + } +} + +impl From<&RawPacket<'_>> for CopiedRawPacket { + fn from(packet: &RawPacket) -> Self { + CopiedRawPacket { + encapsulation: packet.encapsulation.clone().into_iter().map(CopiedEncapsulation::from).collect(), + orig_data: packet.orig_data.to_vec(), + orig_len: packet.orig_len, + } + } +} + +fn raw_packet_convert_to_my_packet(raw_packet: &RawPacket<'_>) -> Result<TcpPacket, TcpSegmentDescription> { + let mut payload = Vec::new(); + let mut ipv4_header = Option::None; + let mut tcp_header = Option::None; + for encapsulation in &raw_packet.encapsulation { + match encapsulation { + Encapsulation::L3_IP4(ipv4, _) => { + ipv4_header = Some(ipv4); + } + Encapsulation::L4_TCP(tcp, data) => { + tcp_header = Some(tcp); + payload = data.to_vec(); + } + _ => {} + } + } + if ipv4_header.is_none() || tcp_header.is_none() { + return Err(TcpSegmentDescription::NotIp4Tcp); + } + + Ok(TcpPacket { + payload, + src_ip: ipv4_header.unwrap().source_address, + dst_ip: ipv4_header.unwrap().dest_address, + src_port: tcp_header.unwrap().source_port, + dst_port: tcp_header.unwrap().dest_port, + seq_num: tcp_header.unwrap().seq_num, + ack_num: tcp_header.unwrap().ack_num, + raw_packet: CopiedRawPacket::from(raw_packet), + }) +} + +/* -------------------------------------------------------------------------- */ +/* stream */ +/* -------------------------------------------------------------------------- */ + +#[derive(Debug, Clone)] +struct TcpPacket { + payload : Vec<u8>, + src_ip: Ipv4Addr, + dst_ip: Ipv4Addr, + src_port: u16, + dst_port: u16, + seq_num: u32, + ack_num: u32, + + raw_packet: CopiedRawPacket, +} + +enum TcpFlags { + FIN = 0x01, + SYN = 0x02, + RST = 0x04, + PSH = 0x08, + ACK = 0x10, + URG = 0x20, +} + +impl TcpPacket { + fn get_sequence(&self) -> u32 { + self.seq_num + } + fn get_acknowledgement(&self) -> u32 { + self.ack_num + } + fn payload(&self) -> &[u8] { + self.payload.as_slice() + } + fn has_flag(&self, flag: TcpFlags) -> bool { + let header = self.raw_packet.header(); + match flag { + TcpFlags::URG => header.flag_urg, + TcpFlags::ACK => header.flag_ack, + TcpFlags::PSH => header.flag_psh, + TcpFlags::RST => header.flag_rst, + TcpFlags::SYN => header.flag_syn, + TcpFlags::FIN => header.flag_fin, + } + } +} + +#[derive(Debug)] +struct TcpSegment { + rel_seq: Wrapping<u32>, // todo: wrapping 主要是解决回绕问题https://blog.csdn.net/LU_ZHAO/article/details/105010778.当前没有实现,不过最好测一下 + +// todo: 带回绕的实际值查询、加减、设置和判断,难点是判断,来了一个新的seq number,我可能就要试一下是不是在回绕的范围内,如果把它当成回绕量,判断发现比上一个seq number 大,且大得很有限,就处理为回绕。 +// 看看其他代码怎么处理的. +// 注意输出到raw packet的时候还要再转一下。 + payload: Vec<u8>, + + tcp_header: TcpHeader, + + raw_packet: CopiedRawPacket, + rel_ack: Wrapping<u32>, // todo: 干掉它 +} + +impl TcpSegment { + /// Return the offset of the overlapping area if `self` (as left) overlaps on `right` + fn overlap_offset(&self, right: &TcpSegment) -> Option<usize> { + let next_seq = self.rel_seq + Wrapping(self.payload.len() as u32); + if next_seq > right.rel_seq { + let overlap_offset = (right.rel_seq - self.rel_seq).0 as usize; + Some(overlap_offset) + } else { + None + } + } + + /// Splits the segment into two at the given offset. + /// + /// # Panics + /// + /// Panics if `offset > self.payload.len()` + fn split_off(&mut self, offset: usize) -> TcpSegment { + assert!(offset < self.payload.len()); + let remaining = self.payload.split_off(offset); + let rel_seq = self.rel_seq + Wrapping(offset as u32); + TcpSegment { + payload: remaining, + rel_seq, + rel_ack: self.rel_ack, + raw_packet: self.raw_packet.clone(), + tcp_header: self.tcp_header.clone(), + } + } +} + +#[derive(Debug)] +struct TcpPeer { + // Initial Seq number (absolute) + isn: Wrapping<u32>, + // Initial Ack number (absolute) + ian: Wrapping<u32>, + // Next Seq number, isn + (sum of all sent segments lengths) + next_rel_seq: Wrapping<u32>, + // The current list of segments that this peer is about to sent (ordered by rel_seq) + segments: VecDeque<TcpSegment>, + addr: Ipv4Addr, + port: u16, +} + +impl TcpPeer { + fn insert_sorted(&mut self, s: TcpSegment) { + for (n, item) in self.segments.iter().enumerate() { + if item.rel_seq > s.rel_seq { + self.segments.insert(n, s); + return; + } + } + self.segments.push_back(s); + } +} + +#[derive(Debug)] +struct TcpStream { + pub client: TcpPeer, + pub server: TcpPeer, + in_connection: bool, +} + + +#[derive(Debug)] +pub struct TcpConnection { + stream: TcpStream, + + max_packets: usize, +} + +impl TcpPeer { + fn new(addr: &Ipv4Addr, port: u16) -> Self { + TcpPeer { + isn: Wrapping(0), + ian: Wrapping(0), + next_rel_seq: Wrapping(0), + segments: VecDeque::new(), + addr: *addr, + port, + } + } +} + +impl TcpStream { + pub fn new(packet: &TcpPacket) -> Self { + TcpStream { + client: TcpPeer::new(&packet.src_ip, packet.src_port), + server: TcpPeer::new(&packet.dst_ip, packet.dst_port), + in_connection: true, + } + } + + fn handle_synsent(&mut self, tcp: TcpPacket) { + let seq = Wrapping(tcp.get_sequence()); + + self.client.isn = seq; + self.client.next_rel_seq = Wrapping(1); + self.server.ian = seq; + + if !tcp.payload().is_empty() { + println!("Data in handshake SYN"); + // https://stackoverflow.com/questions/37994131/send-tcp-syn-packet-with-payload + // it is possible to have data in SYN, just queue it(the src window size is 0 currently) + let segment = TcpSegment { + rel_seq: Wrapping(1), // just assume client has sent a ACK, and turn to ESTABLISHED. + payload: tcp.payload().to_vec(), + tcp_header: tcp.raw_packet.header(), + raw_packet: tcp.raw_packet, + rel_ack: Wrapping(1), + }; + queue_segment(&mut self.client, segment); + } + } + + fn handle_synrcv(&mut self, tcp: TcpPacket) -> Result<(), TcpSegmentDescription> { + // Server -- SYN+ACK --> Client + let (src, dst) = (&mut self.server, &mut self.client); + let seq = Wrapping(tcp.get_sequence()); + let ack = Wrapping(tcp.get_acknowledgement()); + + if !tcp.has_flag(TcpFlags::SYN) || !tcp.has_flag(TcpFlags::ACK) { + return Err(TcpSegmentDescription::HandshakeFail("Not a SYN + ACK".to_string())); + } + + // if we had data in SYN, add its length + let next_rel_seq = if dst.segments.is_empty() { + Wrapping(1) + } else { // + Wrapping(1) + Wrapping(dst.segments[0].payload.len() as u32) + }; + if ack != dst.isn + next_rel_seq { + return Err(TcpSegmentDescription::HandshakeFail("ack number is wrong".to_string())); + } + + src.isn = seq; + src.next_rel_seq = Wrapping(1); + dst.ian = seq; + + Ok(()) + } + + fn update_after_handshake(&mut self, + tcp: TcpPacket, + to_server: bool) -> (Option<Vec<TcpSegment>>, TcpSegmentDescription) { + let (origin, destination) = if to_server { + (&mut self.client, &mut self.server) + } else { + (&mut self.server, &mut self.client) + }; + + let rel_seq = Wrapping(tcp.get_sequence()) - origin.isn; + let rel_ack = Wrapping(tcp.get_acknowledgement()) - destination.isn; + let is_fin = tcp.has_flag(TcpFlags::FIN) || tcp.has_flag(TcpFlags::RST); // before borrowing tcp + + println!("update_after_handshake: payload len={}", tcp.payload().len()); + println!( + " Tcp rel seq {} ack {} next seq {}", + rel_seq, + rel_ack, + origin.next_rel_seq + ); + + let segment = TcpSegment { + rel_seq, + rel_ack, + payload: tcp.payload().to_vec(), // XXX data cloned here + tcp_header: tcp.raw_packet.header(), + raw_packet: tcp.raw_packet, + }; + queue_segment(origin, segment); + if is_fin { + // fin packet can also have payload, so we queued it first. Refer to: + // https://stackoverflow.com/questions/8702646/can-a-tcp-packet-with-the-fin-flag-also-have-data + let sent_pkt = flush_peer_segments(origin); + return (Some(sent_pkt), TcpSegmentDescription::FinTrigger); + } + // todo: closed connection restart + + let sent_pkt = send_peer_segments(origin); + if origin.segments.len() > DEFAULT_MAX_PACKETS { + let sent_pkt = flush_peer_segments(origin); + return (Some(sent_pkt), TcpSegmentDescription::TooManyPacket); + } + + if sent_pkt.is_err() { + return (None, sent_pkt.unwrap_err()); + } else { + return (Some(sent_pkt.unwrap()), TcpSegmentDescription::Normal); + } + } +} + +fn queue_segment(peer: &mut TcpPeer, segment: TcpSegment) { + if segment.payload.is_empty() { + return; + } + //todo: 老代码有一个 EARLY_DETECT_OVERLAP 不知道干嘛的 + + if peer.segments.is_empty() { + println!("Pushing segment (front)"); + peer.segments.push_front(segment); + return; + } + + println!("Adding segment"); + peer.insert_sorted(segment); +} + +// let the peer send segments in its queue, update ack numbers, and pop segments that were sent +fn send_peer_segments(peer: &mut TcpPeer) -> Result<Vec<TcpSegment>, TcpSegmentDescription> { + if peer.segments.is_empty() { + println!("No segment to send"); + return Err(TcpSegmentDescription::NoSegment); + } + let mut ret = Vec::new(); + let mut description = TcpSegmentDescription::Normal; + while !peer.segments.is_empty() { + let segment = &peer.segments[0]; + println!("send segment, payload: {:?}", segment.payload); + + if segment.rel_seq > peer.next_rel_seq { // there is a gap + println!("Gap detected"); + description = TcpSegmentDescription::Unordered; + break; + } + + if segment.rel_seq < peer.next_rel_seq { // caused by flush_peer_segments, or duplicate pkt, omit old segments + // todo: 感觉这里最好区别一下是不是因为flush_peer_segments导致的,虽然只影响错误码 + // 甚至会是over lap 导致的 + println!("Dropping segment"); + if (segment.rel_seq + Wrapping(segment.payload.len() as u32)) > peer.next_rel_seq { + println!("Segment overlaps next, payload before: {:?}", segment.payload); + let mut segment = peer.segments.pop_front().unwrap(); + let overlap_offset = (peer.next_rel_seq - segment.rel_seq).0; + segment.payload = segment.payload.split_off(overlap_offset as usize); + println!("Segment overlaps next, payload after: {:?}", segment.payload); + segment.rel_seq = peer.next_rel_seq; + peer.segments.push_front(segment); + assert!(!peer.segments.is_empty()); + } else if (segment.rel_seq + Wrapping(segment.payload.len() as u32)) == peer.next_rel_seq { + println!("Segment ends at next"); + peer.segments.pop_front(); + description = TcpSegmentDescription::DuplicateSeq; + } else { + peer.segments.pop_front(); + description = TcpSegmentDescription::OldPacket; + println!("Segment ends before next"); + } + continue; + } + + // safety: segments is just tested above + let mut segment = peer.segments.pop_front().unwrap(); + + remove_overlapped(peer, &mut segment); + adjust_seq_numbers(peer, &segment); + println!("Sending segment, payload: {:?}", segment.payload); + segment.raw_packet.replace_payload(segment.payload.clone()); + ret.push(segment); + } + println!("ret len: {}", ret.len()); + if ret.len() == 0 { + return Err(description); + } + + Ok(ret) +} + +fn flush_peer_segments(peer: &mut TcpPeer) -> Vec<TcpSegment> { + // 最终预期: + // 1. 队列全清空 + // 2. next seq 正常调整 + + // // 之后呢? + // 标记该Session为满释放异常,并声明一个新的变量,为“上次flush的时候,最大的rel seq” + // 之后,如果有新的segment进来,那么就判断,如果rel seq < 上次flush的最大rel seq,那么直接丢弃 + // 否则,就正常处理,放入队列中。 + + let mut ret = Vec::new(); + while !peer.segments.is_empty() { + // safety: segments is just tested above + let mut segment = peer.segments.pop_front().unwrap(); + + remove_overlapped(peer, &mut segment); + if peer.segments.len() == 0 { // the last one has the biggest rel seq + peer.next_rel_seq = segment.rel_seq + Wrapping(segment.payload.len() as u32); + } + + ret.push(segment); + } + + ret +} + + // 情况1: [1,2,3] [4,5,6] + // [3, 4,5] + // 2: [1,2,3] + // [1,2,3] + // 3: [4,5,6] + // [4,5,6] + // 以上三种均为duplicate,直接丢弃 + // 4: [1,2,3] + // [1,2,3,4] + // 保留[1,2,3] [4] + // 5: [2,3] [6,7] + // [1,2,3,4,5,6] + // 保留[1,2,3,4,5,6] [7] +fn remove_overlapped(peer: &mut TcpPeer, segment: &mut TcpSegment) { + // loop while segment has overlap + while let Some(next) = peer.segments.front() { + if let Some(overlap_offset) = segment.overlap_offset(next) { + println!( + "overlaps next candidate (at offset={})", + overlap_offset + ); + // we will modify the subsequent segment (next) + // safety: element presence was tested in outer loop + let next = peer.segments.pop_front().unwrap(); + + // split next + let overlap_size = segment.payload.len() - overlap_offset; + let min_overlap_size = std::cmp::min(overlap_size, next.payload.len()); + // compare overlap area + if next.payload[..min_overlap_size] + != segment.payload[overlap_offset..overlap_offset + min_overlap_size] + { + println!("Overlap area differs!"); + } + if overlap_size >= next.payload.len() { + // subsequent segment starts after and is smaller, so drop it + drop(next); + continue; + } + // otherwise, split next into left and right, drop left and accept right + let mut left = next; + let right = left.split_off(overlap_size); + // to accept right, merge it into segment + segment.payload.extend_from_slice(&right.payload); + } else { + // println!("no overlap, break"); + break; + } + } +} + +fn adjust_seq_numbers(origin: &mut TcpPeer, segment: &TcpSegment) { + if !segment.payload.is_empty() { + // adding length is wrong in case of overlap + // origin.next_rel_seq += Wrapping(segment.payload.len() as u32); + origin.next_rel_seq = segment.rel_seq + Wrapping(segment.payload.len() as u32); + } + + if segment.tcp_header.flag_fin { + // println!("Segment has FIN"); + origin.next_rel_seq += Wrapping(1); + } +} + +impl TcpConnection { + pub(crate) fn try_new(packet: &RawPacket) -> Result<Self, TcpSegmentDescription> { + let simple_packet = raw_packet_convert_to_my_packet(packet)?; + Self::_try_new(simple_packet) + } + + pub(crate) fn update(&mut self, packet: &RawPacket) -> (Option<Vec<CopiedRawPacket>>, TcpSegmentDescription) { + let simple_packet = raw_packet_convert_to_my_packet(packet); + if let Err(e) = simple_packet { + return (None, e); + } + self._update(simple_packet.unwrap()) + } + + fn _try_new(packet: TcpPacket) -> Result<Self, TcpSegmentDescription> { + let mut connection = TcpConnection { + stream: TcpStream::new(&packet), + max_packets: DEFAULT_MAX_PACKETS, + }; + + if !packet.has_flag(TcpFlags::SYN) { + return Err(TcpSegmentDescription::HandshakeFail("Not a SYN".to_string())); + } + if packet.has_flag(TcpFlags::ACK) { + println!("First packet is SYN+ACK"); + return Err(TcpSegmentDescription::HandshakeFail("First packet is SYN+ACK".to_string())); + } + if packet.has_flag(TcpFlags::RST) { + return Err(TcpSegmentDescription::HandshakeFail("First packet is RST".to_string())); + } + if packet.has_flag(TcpFlags::FIN) { + return Err(TcpSegmentDescription::HandshakeFail("First packet is FIN".to_string())); + } + + connection.stream.handle_synsent(packet); + Ok(connection) + } + + fn _update(&mut self, tcp: TcpPacket) -> (Option<Vec<CopiedRawPacket>>, TcpSegmentDescription) { + let stream = &mut self.stream; + + + // get origin and destination + let to_server = tcp.dst_ip == stream.server.addr && + tcp.dst_port == stream.server.port; + println!("to_server: {}", to_server); + + if self.stream.in_connection { + let ret = self.stream.handle_synrcv(tcp); + if let Err(e) = ret { + return (None, e); + } + + self.stream.in_connection = false; + return (None, TcpSegmentDescription::SynAckOk); + } + let (segments, ret) = self.stream.update_after_handshake(tcp, to_server); + + if segments.is_none() { + return (None, ret); + } + + let ret_packet = segments.unwrap().into_iter(). + map(|segment| {segment.raw_packet}).collect(); + + return (Some(ret_packet), ret); + } +} + + +#[cfg(test)] +mod tests { + use std::vec; + use crate::protocol::ip::IPProtocol; + + use super::*; + + static SLICE_DUMMY:&[u8] = &[42,42,42]; + + #[derive(Debug, Clone)] + enum PeerRole { + Client, + Server, + } + #[derive(Debug, Clone)] + struct PeerInTest { + addr: Ipv4Addr, + /// println: port + port: u16, + 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> { + let src_ip = from.addr; + let dst_ip = to.addr; + let header = TcpHeader { + source_port: from.port, + dest_port: to.port, + seq_num, + ack_num, + data_offset: 0, + reserved: 0, + flag_urg: false, + flag_ack: has_ack, + flag_psh: false, + flag_rst: has_rst, + flag_syn: has_syn, + flag_fin: has_fin, + window: 65535, + checksum: 0, + urgent_ptr: 0, + options: None, + }; + + let ip_header = IPv4Header { + version: 4, + ihl: 5, + tos: 0, + length: 0, + id: 0, + flags: 0, + frag_offset: 0, + ttl: 0, + protocol: IPProtocol::TCP, + checksum: 0, + source_address: src_ip, + dest_address: dst_ip, + }; + + let encap1 : Encapsulation = Encapsulation::L3_IP4(ip_header, SLICE_DUMMY); + let encap2 : Encapsulation = Encapsulation::L4_TCP(header, segment); + let encap_vec = vec![encap1, encap2]; + + RawPacket { + orig_data: SLICE_DUMMY, + orig_len: SLICE_DUMMY.len() as u32, + encapsulation: encap_vec, + } + } + + const CLIENT: PeerInTest = PeerInTest { + addr: Ipv4Addr::new(192, 168, 1, 1), + port: 1234, + role: PeerRole::Client, + }; + const SERVER: PeerInTest = PeerInTest { + addr: Ipv4Addr::new(192, 168, 1, 2), + port: 80, + role: PeerRole::Server, + }; + + #[test] + fn single_segment_ping_pong() { + const INIT_SEQ:u32 = 12345; + let packet_handshake1 = new_raw(&CLIENT, &SERVER, INIT_SEQ + 0, 0, false, true, false, false, &[]); + let mut connection = TcpConnection::try_new(&packet_handshake1).unwrap(); + + let packet_handshake2 = new_raw(&SERVER, &CLIENT, 0, INIT_SEQ+1, true, true, false, false, &[]); + let ret = connection.update(&packet_handshake2); + assert!(ret.1 == TcpSegmentDescription::SynAckOk); + + let packet_established_from_client = new_raw(&CLIENT, &SERVER, INIT_SEQ+1, 1, true, false, false, false, &[1, 2, 3]); + let ret = connection.update(&packet_established_from_client); + println!("ret: {:?}", ret); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.unwrap()[0].payload() == &[1, 2, 3]); + + let packet_established_from_server = new_raw(&SERVER, &CLIENT, 1, INIT_SEQ+4, true, false, false, false, &[4, 5, 6]); + let ret = connection.update(&packet_established_from_server); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.unwrap()[0].payload() == &[4, 5, 6]); + + let packet_established_from_client2 = new_raw(&CLIENT, &SERVER, INIT_SEQ+4, 4, true, false, false, false, &[7, 8, 9]); + let ret = connection.update(&packet_established_from_client2); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.unwrap()[0].payload() == &[7, 8, 9]); + } + + #[test] + fn several_ordered_consecutive_segments() { + 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); + + 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); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.unwrap()[0].payload() == &[1, 2, 3]); + 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); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.unwrap()[0].payload() == &[4, 5, 6]); + 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); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.unwrap()[0].payload() == &[7, 8, 9]); + } + + #[test] + fn several_unordered_consecutive_segments() { + 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); + + 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); + assert!(ret.1 == TcpSegmentDescription::Unordered); + 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); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.as_ref().unwrap()[0].payload() == &[1, 2, 3]); + assert!(ret.0.unwrap()[1].payload() == &[4, 5, 6]); + 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); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.unwrap()[0].payload() == &[7, 8, 9]); + } + + #[test] + fn several_unordered_inconsecutive_segments() { + 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); + + 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); + println!("ret: {:?}", ret); + assert!(ret.1 == TcpSegmentDescription::Unordered); + let packet_from_server = new_raw(&SERVER, &CLIENT, 1, 1, true, false, false, false, &[11, 12, 13]); + let ret = connection.update(&packet_from_server); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.as_ref().unwrap()[0].payload() == &[11, 12, 13]); + + 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); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.as_ref().unwrap()[0].payload() == &[1, 2, 3]); + assert!(ret.0.unwrap()[1].payload() == &[4, 5, 6]); + 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); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.unwrap()[0].payload() == &[7, 8, 9]); + } + + #[test] + fn duplicate_packet() { + 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); + + 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); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.as_ref().unwrap()[0].payload() == &[1, 2, 3]); + let ret = connection.update(&packet_established_from_client); + assert!(ret.1 == TcpSegmentDescription::DuplicateSeq); + assert!(ret.0.is_none()); + } + + #[test] + fn too_many_packet() { + 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); + + // let first packet drop , so that the queue will be filled until full + for i in 1..DEFAULT_MAX_PACKETS + 1{ + let packet_established_from_client = new_raw(&CLIENT, &SERVER, 1 + i as u32, 1, true, false, false, false, &[1]); + let ret = connection.update(&packet_established_from_client); + assert!(ret.1 == TcpSegmentDescription::Unordered); + } + let packet_established_from_client = new_raw(&CLIENT, &SERVER, 1 + DEFAULT_MAX_PACKETS as u32, 1, true, false, false, false, &[1]); + let ret = connection.update(&packet_established_from_client); + assert!(ret.1 == TcpSegmentDescription::TooManyPacket); + assert!(ret.0.unwrap().len() == DEFAULT_MAX_PACKETS); + + // the first packet come unexpectedly, just throw it away + let packet_established_from_client = new_raw(&CLIENT, &SERVER, 1, 1, true, false, false, false, &[1]); + let ret = connection.update(&packet_established_from_client); + assert!(ret.1 == TcpSegmentDescription::OldPacket); + assert!(ret.0.is_none()); + + // continue to send + let packet_established_from_client = new_raw(&CLIENT, &SERVER, 2 + DEFAULT_MAX_PACKETS as u32, 1, true, false, false, false, &[2,3,4]); + let ret = connection.update(&packet_established_from_client); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.unwrap()[0].payload() == &[2,3,4]); + } + + #[test] + fn segment_in_syn() { + let packet_handshake1 = new_raw(&CLIENT, &SERVER, 0, 0, false, true, false, false, &[1,2,3]); + let mut connection = TcpConnection::try_new(&packet_handshake1).unwrap(); + let packet_handshake2 = new_raw(&SERVER, &CLIENT, 0, 4, true, true, false, false, &[]); + connection.update(&packet_handshake2); + + let packet_established_from_client = new_raw(&CLIENT, &SERVER, 4, 1, true, false, false, false, &[4,5,6]); + let ret = connection.update(&packet_established_from_client); + println!("ret: {:?}", ret); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.as_ref().unwrap()[0].payload() == &[1,2,3]); + assert!(ret.0.as_ref().unwrap()[1].payload() == &[4,5,6]); + } + + #[test] + fn wrong_flag_during_handshake_syn() { + let packet_handshake1 = new_raw(&CLIENT, &SERVER, 0, 0, false, false, false, false, &[]); + let mut connection = TcpConnection::try_new(&packet_handshake1); + assert!(connection.is_err()); + assert!(connection.unwrap_err() == TcpSegmentDescription::HandshakeFail("Not a SYN".to_string())); + + + let packet_handshake1 = new_raw(&CLIENT, &SERVER, 0, 0, false, true, true, false, &[]); + let mut connection = TcpConnection::try_new(&packet_handshake1); + assert!(connection.is_err()); + assert!(connection.unwrap_err() == TcpSegmentDescription::HandshakeFail("First packet is RST".to_string())); + } + + #[test] + fn wrong_flag_during_handshake_acksyn() { + let packet_handshake1 = new_raw(&CLIENT, &SERVER, 0, 0, false, true, false, false, &[1,2,3]); + let mut connection = TcpConnection::try_new(&packet_handshake1).unwrap(); + + let packet_handshake2 = new_raw(&SERVER, &CLIENT, 0, 3, true, true, false, false, &[]); // expected ack num is 4 + let ret = connection.update(&packet_handshake2); + assert!(ret.1 == TcpSegmentDescription::HandshakeFail("ack number is wrong".to_string())); + + let packet_handshake2 = new_raw(&SERVER, &CLIENT, 0, 4, false, true, false, false, &[]); // no ack + let ret = connection.update(&packet_handshake2); + assert!(ret.1 == TcpSegmentDescription::HandshakeFail("Not a SYN + ACK".to_string())); + } + + #[test] + fn not_tcp_ip_packet() { + let mut packet = new_raw(&CLIENT, &SERVER, 0, 0, false, true, false, false, &[]); + packet.encapsulation.pop(); + let mut connection = TcpConnection::try_new(&packet); + assert!(connection.is_err()); + assert!(connection.unwrap_err() == TcpSegmentDescription::NotIp4Tcp); + } + + #[test] + fn fin_with_data() { + 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); + + let packet_established_from_client = new_raw(&CLIENT, &SERVER, 2, 1, true, false, false, false, &[2,3]); + let ret = connection.update(&packet_established_from_client); + assert!(ret.1 == TcpSegmentDescription::Unordered); + + let packet_established_from_client = new_raw(&CLIENT, &SERVER, 4, 1, true, false, false, true, &[4,5,6]); + let ret = connection.update(&packet_established_from_client); + assert!(ret.1 == TcpSegmentDescription::FinTrigger); + assert!(ret.0.as_ref().unwrap()[0].payload() == &[2,3]); + assert!(ret.0.as_ref().unwrap()[1].payload() == &[4,5,6]); + } + + #[test] + fn overlap_partially_sent_before() { + // [1,2,3] -> sent + // [3,4,5,6] -> [4,5,6] + 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); + + 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); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.as_ref().unwrap()[0].payload() == &[1,2,3]); + + let packet_established_from_client = new_raw(&CLIENT, &SERVER, 3, 1, true, false, false, false, &[3,4,5,6]); + let ret = connection.update(&packet_established_from_client); + println!("ret: {:?}", ret.0.as_ref().unwrap()[0].payload()); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.as_ref().unwrap()[0].payload() == &[4,5,6]); // [3] overlap, only send [4,5,6] + } + + #[test] + fn overlap_as_old_packet() { + // [1,2,3,4,5,6] -> sent + // [2,3,4] -> drop(description: old packet) + 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); + + let packet_established_from_client = new_raw(&CLIENT, &SERVER, 1, 1, true, false, false, false, &[1,2,3,4,5,6]); + let ret = connection.update(&packet_established_from_client); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.as_ref().unwrap()[0].payload() == &[1,2,3,4,5,6]); + + let packet_established_from_client = new_raw(&CLIENT, &SERVER, 2, 1, true, false, false, false, &[2,3,4]); + let ret = connection.update(&packet_established_from_client); + assert!(ret.1 == TcpSegmentDescription::OldPacket); + assert!(ret.0.is_none()); + } + + #[test] + fn overlap_change_next_one() { + // [2,3,4] -> wait + // [3,4,5] -> wait(join the first as [2,3,4,5]) + // [1] -> send [1] [2,3,4,5] + 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); + + let packet_established_from_client2 = new_raw(&CLIENT, &SERVER, 2, 1, true, false, false, false, &[2,3,4]); + let packet_established_from_client1 = new_raw(&CLIENT, &SERVER, 1, 1, true, false, false, false, &[1]); + let packet_established_from_client3 = new_raw(&CLIENT, &SERVER, 3, 1, true, false, false, false, &[3,4,5]); + let ret = connection.update(&packet_established_from_client2); + assert!(ret.1 == TcpSegmentDescription::Unordered); + let ret = connection.update(&packet_established_from_client3); + assert!(ret.1 == TcpSegmentDescription::Unordered); + let ret = connection.update(&packet_established_from_client1); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.as_ref().unwrap().len() == 2); + assert!(ret.0.as_ref().unwrap()[0].payload() == &[1]); + assert!(ret.0.as_ref().unwrap()[1].payload() == &[2,3,4,5]); + } + + #[test] + fn overlap_del_next_one() { + // [2,3,4,5] -> wait + // [3,4,5] -> del(overlapped) + // [1,2,3] -> send [1,2,3,4,5] + 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); + + let packet_established_from_client2 = new_raw(&CLIENT, &SERVER, 2, 1, true, false, false, false, &[2,3,4,5]); + let packet_established_from_client1 = new_raw(&CLIENT, &SERVER, 1, 1, true, false, false, false, &[1,2,3]); + let packet_established_from_client3 = new_raw(&CLIENT, &SERVER, 3, 1, true, false, false, false, &[3,4,5]); + let ret = connection.update(&packet_established_from_client2); + assert!(ret.1 == TcpSegmentDescription::Unordered); + let ret = connection.update(&packet_established_from_client3); + assert!(ret.1 == TcpSegmentDescription::Unordered); + let ret = connection.update(&packet_established_from_client1); + assert!(ret.1 == TcpSegmentDescription::Normal); + println!("ret: {:?}", ret.0.as_ref().unwrap()); + + assert!(ret.0.as_ref().unwrap().len() == 1); + assert!(ret.0.as_ref().unwrap()[0].payload() == &[1,2,3,4,5]); + } + + #[test] + fn overlap_surpass_all() { + // [2] -> wait + // [3] -> wait + // [1,2,3,4] -> send [1,2,3,4] + 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); + + let packet_established_from_client2 = new_raw(&CLIENT, &SERVER, 2, 1, true, false, false, false, &[2]); + let packet_established_from_client3 = new_raw(&CLIENT, &SERVER, 3, 1, true, false, false, false, &[3]); + let packet_established_from_client1 = new_raw(&CLIENT, &SERVER, 1, 1, true, false, false, false, &[1,2,3,4]); + let ret = connection.update(&packet_established_from_client3); + assert!(ret.1 == TcpSegmentDescription::Unordered); + let ret = connection.update(&packet_established_from_client2); + assert!(ret.1 == TcpSegmentDescription::Unordered); + let ret = connection.update(&packet_established_from_client1); + assert!(ret.1 == TcpSegmentDescription::Normal); + assert!(ret.0.as_ref().unwrap().len() == 1); + assert!(ret.0.as_ref().unwrap()[0].payload() == &[1,2,3,4]); + } + + + + + // todo: 回绕 +}
\ No newline at end of file |
