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