diff options
Diffstat (limited to 'src/session/tcp_reassembly.rs')
| -rw-r--r-- | src/session/tcp_reassembly.rs | 1190 |
1 files changed, 265 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]]); + } +} |
