summaryrefslogtreecommitdiff
path: root/src/session/tcp_reassembly.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/session/tcp_reassembly.rs')
-rw-r--r--src/session/tcp_reassembly.rs1190
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]]);
+ }
+}