summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchenzizhan <[email protected]>2023-09-11 16:21:29 +0800
committerchenzizhan <[email protected]>2023-09-11 16:21:29 +0800
commit098361978603494f701a299a2afacba50fff536e (patch)
treeede687a233141bbd4ea65f214a3b4a453ba0dae1
parentd65fee6f87e7814381e58ae383b6389cbc5fc896 (diff)
max packet size
-rw-r--r--src/session/tcp_reassembly.rs50
1 files changed, 32 insertions, 18 deletions
diff --git a/src/session/tcp_reassembly.rs b/src/session/tcp_reassembly.rs
index 5dd6ee9..c18b766 100644
--- a/src/session/tcp_reassembly.rs
+++ b/src/session/tcp_reassembly.rs
@@ -18,6 +18,8 @@ use crate::packet::packet::Packet as RawPacket;
const DEFAULT_TIMEOUT: Duration = Duration{secs:7200, micros:0}; // 120 min timeout, currently do not support option 28 parse
// todo: const TCP_OPTION_TIMESTAMPS: u8 = 28; https://datatracker.ietf.org/doc/rfc5482/
+const DEFAULT_MAX_PACKETS: usize = 2048;
+
// todo: 装的packet太多怎么办
@@ -29,10 +31,9 @@ pub enum TcpSessionErr {
ExpiredSession,
/// the seq number is wrong in the 2nd or 3rd handshake.
HandshakeFailed,
- /// ack number is even higher than the next expected seq number
- DiscardedSegment, // todo
/// new a connection failed, because the packet is not a SYN packet, but the packet is valid
NewConnectionFailed,
+ /// ack number is even higher than the next expected seq number
UnexpectedAckNumber,
/// The packet itself is valid, but the window size is not enough to hold the packet. Tcp state machine will change as usual, while the packet payload is discarded.
SidePeerWindowFull,
@@ -44,6 +45,9 @@ pub mod TcpSessionOk { // use as enum
pub const CLOSING: u32 = 0x02;
pub const CLOSED: u32 = 0x04;
pub const ACK_SEGMENT: u32 = 0x08;
+ pub const PACKET_IN_PAST: u32 = 0x10;
+ pub const TOO_MANY_PACKET_WARNING: u32 = 0x20;
+ pub const TOO_MANY_PACKETS: u32 = 0x40;
pub const OTHER: u32 = 0x0;
}
@@ -344,8 +348,10 @@ pub struct TcpConnection {
packets_sent_by_client: Vec<Vec<CopiedRawPacket>>,
packets_sent_by_server: Vec<Vec<CopiedRawPacket>>,
+ max_packets: usize,
+ max_warning_packets: usize,
- pub timeout: Duration, // todo: 这个现在没有接口来设置和读取
+ pub timeout: Duration, // todo: 当前使用默认值
}
impl TcpPeer {
@@ -724,7 +730,6 @@ fn queue_segment(peer: &mut TcpPeer, segment: TcpSegment) {
}
fn send_peer_segments(peer: &mut TcpPeer, rel_ack: Wrapping<u32>) -> Result<Option<Vec<TcpSegment>>, TcpSessionErr> {
- // todo: window
println!(
"Trying to send segments for {}:{} up to {} (last ack: {})",
peer.addr,
@@ -761,11 +766,8 @@ fn send_peer_segments(peer: &mut TcpPeer, rel_ack: Wrapping<u32>) -> Result<Opti
let mut segment = peer.segments.pop_front().unwrap();
if rel_ack < segment.rel_seq + Wrapping(segment.payload.len() as u32) {
- // println!("ACK lower then seq + segment size - SACK?");
println!("ACK for part of buffer");
// split data and insert new dummy segment
- println!("rel_ack {} segment.rel_seq {}", rel_ack, segment.rel_seq);
- println!("segment data len {}", segment.payload.len());
let acked_len = (rel_ack - segment.rel_seq).0 as usize;
let new_segment = segment.split_off(acked_len);
println!(
@@ -790,7 +792,8 @@ fn send_peer_segments(peer: &mut TcpPeer, rel_ack: Wrapping<u32>) -> Result<Opti
"TCP ACKed unseen segment next_seq {} != ack {} (Missed segments?)",
peer.next_rel_seq, rel_ack
);
- // TODO notify upper layer for missing data
+ // TODO 这个正确吗?如果因为这个,把整个老segment 都删了肯定不对,具体怎么处理错误看需求吧
+ // return Err(TcpSessionErr::UnexpectedAckNumber);
}
peer.last_rel_ack = rel_ack;
@@ -892,6 +895,8 @@ impl TcpConnection {
packets_sent_by_client: Vec::new(),
packets_sent_by_server: Vec::new(),
timeout: DEFAULT_TIMEOUT,
+ max_packets: DEFAULT_MAX_PACKETS,
+ max_warning_packets: DEFAULT_MAX_PACKETS >> 1,
};
if !packet.has_flag(TcpFlags::SYN) {
@@ -911,11 +916,13 @@ impl TcpConnection {
let client_status_before = stream.client.status.clone();
let server_status_before = stream.server.status.clone();
+ let mut ok_ret = TcpSessionOk::OTHER;
// check time delay with previous packet before updating
let packet_ts = tcp.get_timestamp();
if stream.last_seen_ts > packet_ts {
println!("packet received in past");
+ ok_ret |= TcpSessionOk::PACKET_IN_PAST;
} else if packet_ts - stream.last_seen_ts > self.timeout {
println!("TCP stream received packet after timeout");
stream.expire();
@@ -946,7 +953,6 @@ impl TcpConnection {
TcpStatus::Established => {
// check for close request
if tcp.has_flag(TcpFlags::FIN) || tcp.has_flag(TcpFlags::RST) {
- println!("Requesting end of connection");
stream.handle_closing_connection(tcp, to_server)
} else {
stream.handle_established_connection(tcp, to_server)
@@ -955,14 +961,21 @@ impl TcpConnection {
_ => stream.handle_closing_connection(tcp, to_server),
}?;
- let mut ok_ret = TcpSessionOk::OTHER;
if let Some(sent_packet) = sent_packet {
- if !to_server { // ack packet, so the previous packet if from the other side. Like a ack packet from server, so the sent packets are from client
- self.packets_sent_by_client.push(sent_packet.into_iter().map(|s| s.raw_packet).collect());
+ ok_ret = ok_ret | TcpSessionOk::ACK_SEGMENT;
+ let send_queue = if to_server { // ack packet, so the previous packet if from the other side.
+ &mut self.packets_sent_by_server
} else {
- self.packets_sent_by_server.push(sent_packet.into_iter().map(|s| s.raw_packet).collect());
+ &mut self.packets_sent_by_client
+ };
+ if send_queue.len() >= self.max_packets {
+ ok_ret |= TcpSessionOk::TOO_MANY_PACKETS;
+ } else {
+ if send_queue.len() >= self.max_warning_packets {
+ ok_ret |= TcpSessionOk::TOO_MANY_PACKET_WARNING;
+ }
+ send_queue.push(sent_packet.into_iter().map(|s| s.raw_packet).collect());
}
- ok_ret = ok_ret | TcpSessionOk::ACK_SEGMENT;
}
if client_status_before != stream.client.status || server_status_before != stream.server.status {
@@ -970,13 +983,10 @@ impl TcpConnection {
client_status_before, stream.client.status, server_status_before, stream.server.status
);
if stream.client.status == TcpStatus::Established {
- println!("handshake completed");
ok_ret = ok_ret | TcpSessionOk::ESTABLISHED;
} else if stream.client.status == TcpStatus::Closed || stream.server.status == TcpStatus::Closed {
- println!("connection closed");
ok_ret |= TcpSessionOk::CLOSED;
} else if client_status_before == TcpStatus::Established {
- println!("connection closed");
ok_ret = TcpSessionOk::CLOSING;
}
}
@@ -1322,7 +1332,11 @@ mod tests {
}
// #[test]
-
+ // todo: expired session
+
+ // todo: many error flag
+ // todo: window full
+ // todo: many packet in queue(warning and discard)
} \ No newline at end of file