Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 117 in 50 files Dangling module declarations removed: 5 Cargo edits turning enterprise off: 14 Verification: clean Enterprise feature gates left for rebuilt features: 19 in 18 files Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
111 lines
3.6 KiB
Rust
111 lines
3.6 KiB
Rust
/*
|
|
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
|
*/
|
|
|
|
use std::borrow::Cow;
|
|
|
|
enum State {
|
|
Len {
|
|
buf: [u8; std::mem::size_of::<u32>()],
|
|
bytes_read: usize,
|
|
},
|
|
Frame {
|
|
buf: Vec<u8>,
|
|
frame_len: usize,
|
|
},
|
|
}
|
|
|
|
pub struct Receiver {
|
|
packet_pos: usize,
|
|
state: State,
|
|
max_frame_len: usize,
|
|
}
|
|
|
|
pub enum FrameResult<'x> {
|
|
Frame(Cow<'x, [u8]>),
|
|
Incomplete,
|
|
TooLarge(usize),
|
|
}
|
|
|
|
impl Default for State {
|
|
fn default() -> Self {
|
|
State::Len {
|
|
buf: [0; std::mem::size_of::<u32>()],
|
|
bytes_read: 0,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Receiver {
|
|
pub fn with_max_frame_len(max_frame_len: usize) -> Self {
|
|
Receiver {
|
|
packet_pos: 0,
|
|
state: State::default(),
|
|
max_frame_len,
|
|
}
|
|
}
|
|
|
|
pub fn read_frame<'x>(&mut self, packet: &'x [u8]) -> FrameResult<'x> {
|
|
if !packet.is_empty() {
|
|
match &mut self.state {
|
|
State::Len { buf, bytes_read } => {
|
|
while *bytes_read < std::mem::size_of::<u32>() {
|
|
if let Some(byte) = packet.get(self.packet_pos) {
|
|
buf[*bytes_read] = *byte;
|
|
*bytes_read += 1;
|
|
self.packet_pos += 1;
|
|
} else {
|
|
self.packet_pos = 0;
|
|
return FrameResult::Incomplete;
|
|
}
|
|
}
|
|
let length = u32::from_be_bytes(*buf) as usize;
|
|
if length <= self.max_frame_len {
|
|
if let Some(frame) = packet.get(self.packet_pos..self.packet_pos + length) {
|
|
self.packet_pos += length;
|
|
self.state = State::default();
|
|
FrameResult::Frame(frame.into())
|
|
} else {
|
|
let mut buf = Vec::with_capacity(length);
|
|
if let Some(bytes_available) = packet.get(self.packet_pos..) {
|
|
buf.extend(bytes_available);
|
|
}
|
|
self.state = State::Frame {
|
|
buf,
|
|
frame_len: length,
|
|
};
|
|
self.packet_pos = 0;
|
|
FrameResult::Incomplete
|
|
}
|
|
} else {
|
|
FrameResult::TooLarge(length)
|
|
}
|
|
}
|
|
State::Frame { buf, frame_len } => {
|
|
let bytes_pending = *frame_len - buf.len();
|
|
if let Some(bytes) =
|
|
packet.get(self.packet_pos..self.packet_pos + bytes_pending)
|
|
{
|
|
let mut buf = std::mem::take(buf);
|
|
buf.extend(bytes);
|
|
self.packet_pos += bytes_pending;
|
|
self.state = State::default();
|
|
FrameResult::Frame(buf.into())
|
|
} else if let Some(bytes_available) = packet.get(self.packet_pos..) {
|
|
buf.extend(bytes_available);
|
|
self.packet_pos = 0;
|
|
FrameResult::Incomplete
|
|
} else {
|
|
self.packet_pos = 0;
|
|
FrameResult::Incomplete
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
FrameResult::Incomplete
|
|
}
|
|
}
|
|
}
|