atmos/kernel/net/
reassembly.rs1extern crate alloc;
19
20use alloc::vec::Vec;
21
22pub const MAX_SEGMENTS: usize = 16;
25
26pub const MAX_BYTES: usize = 64 * 1024;
28
29#[derive(Debug, PartialEq, Eq, Clone, Copy)]
31pub enum InsertOutcome {
32 Stored,
34 Duplicate,
36 Dropped,
38}
39
40#[derive(Debug, PartialEq, Eq, Clone, Copy)]
42pub enum ReassemblyError {
43 EmptyPayload,
45}
46
47#[derive(Debug, Default)]
49pub struct Reassembler {
50 segs: Vec<(u32, Vec<u8>)>,
52 bytes: usize,
53}
54
55impl Reassembler {
56 pub fn new() -> Self {
57 Self::default()
58 }
59
60 pub const fn new_const() -> Self {
62 Self {
63 segs: Vec::new(),
64 bytes: 0,
65 }
66 }
67
68 pub fn len(&self) -> usize {
70 self.segs.len()
71 }
72
73 pub fn is_empty(&self) -> bool {
74 self.segs.is_empty()
75 }
76
77 pub fn bytes(&self) -> usize {
79 self.bytes
80 }
81
82 pub fn insert(&mut self, seq: u32, data: &[u8]) -> Result<InsertOutcome, ReassemblyError> {
87 if data.is_empty() {
88 crate::error!("[TCP][REASM] 空ペイロードは保持できません seq={}", seq);
89 return Err(ReassemblyError::EmptyPayload);
90 }
91 if self.segs.iter().any(|(s, _)| *s == seq) {
92 return Ok(InsertOutcome::Duplicate);
93 }
94 if self.segs.len() >= MAX_SEGMENTS || self.bytes + data.len() > MAX_BYTES {
95 return Ok(InsertOutcome::Dropped);
96 }
97 let pos = self
99 .segs
100 .iter()
101 .position(|(s, _)| *s > seq)
102 .unwrap_or(self.segs.len());
103 self.segs.insert(pos, (seq, data.to_vec()));
104 self.bytes += data.len();
105 Ok(InsertOutcome::Stored)
106 }
107
108 pub fn pop_contiguous(&mut self, rcv_nxt: u32) -> (u32, Vec<u8>) {
113 let mut next = rcv_nxt;
114 let mut out: Vec<u8> = Vec::new();
115 loop {
116 let Some(idx) = self.segs.iter().position(|(s, _)| *s == next) else {
117 break;
118 };
119 let (_, data) = self.segs.remove(idx);
120 next = next.wrapping_add(data.len() as u32);
121 self.bytes -= data.len();
122 out.extend_from_slice(&data);
123 }
124 (next, out)
125 }
126
127 pub fn drop_before(&mut self, rcv_nxt: u32) -> usize {
130 let before = self.segs.len();
131 let mut freed = 0usize;
132 self.segs.retain(|(s, d)| {
133 let is_past = rcv_nxt.wrapping_sub(*s) < 0x8000_0000
135 && rcv_nxt.wrapping_sub(*s) >= d.len() as u32;
136 if is_past {
137 freed += d.len();
138 }
139 !is_past
140 });
141 self.bytes -= freed;
142 before - self.segs.len()
143 }
144
145 pub fn clear(&mut self) {
147 self.segs.clear();
148 self.bytes = 0;
149 }
150}