1use crate::error::Error;
4use crate::varint::read_varint;
5
6#[derive(Debug, Clone, PartialEq)]
8pub struct CryptoFrame {
9 pub offset: u64,
11 pub data: Vec<u8>,
13}
14
15pub fn parse_crypto_frames(decrypted: &[u8]) -> Result<Vec<CryptoFrame>, Error> {
27 let mut cursor = 0;
28 let mut frames = Vec::new();
29
30 while cursor < decrypted.len() {
31 let (frame_type, len) = read_varint(&decrypted[cursor..])?;
32 cursor += len;
33
34 match frame_type {
35 0x06 => {
36 let (offset, off_len) =
37 read_varint(decrypted.get(cursor..).ok_or(Error::TruncatedFrame {
38 offset: cursor as u64,
39 })?)?;
40 cursor += off_len;
41
42 let (length, len_len) =
43 read_varint(decrypted.get(cursor..).ok_or(Error::TruncatedFrame {
44 offset: cursor as u64,
45 })?)?;
46 cursor += len_len;
47 let length = usize::try_from(length).map_err(|_| Error::TruncatedFrame {
48 offset: cursor as u64,
49 })?;
50
51 if cursor + length > decrypted.len() {
52 return Err(Error::TruncatedFrame { offset });
53 }
54
55 let data = decrypted[cursor..cursor + length].to_vec();
56 frames.push(CryptoFrame { offset, data });
57 cursor += length;
58 }
59 0x00 | 0x01 => {}
61 0x02 | 0x03 => {
63 cursor = skip_ack_frame(decrypted, cursor, frame_type == 0x03)?;
64 }
65 _ => break,
66 }
67 }
68
69 Ok(frames)
70}
71
72fn skip_ack_frame(buf: &[u8], mut cursor: usize, has_ecn: bool) -> Result<usize, Error> {
79 let trunc = |pos: usize| Error::TruncatedFrame { offset: pos as u64 };
80
81 let (_, len) = read_varint(buf.get(cursor..).ok_or_else(|| trunc(cursor))?)?;
83 cursor += len;
84 let (_, len) = read_varint(buf.get(cursor..).ok_or_else(|| trunc(cursor))?)?;
86 cursor += len;
87 let (range_count, len) = read_varint(buf.get(cursor..).ok_or_else(|| trunc(cursor))?)?;
89 cursor += len;
90 let (_, len) = read_varint(buf.get(cursor..).ok_or_else(|| trunc(cursor))?)?;
92 cursor += len;
93
94 for _ in 0..range_count {
96 let (_, len) = read_varint(buf.get(cursor..).ok_or_else(|| trunc(cursor))?)?;
97 cursor += len;
98 let (_, len) = read_varint(buf.get(cursor..).ok_or_else(|| trunc(cursor))?)?;
99 cursor += len;
100 }
101
102 if has_ecn {
104 for _ in 0..3 {
105 let (_, len) = read_varint(buf.get(cursor..).ok_or_else(|| trunc(cursor))?)?;
106 cursor += len;
107 }
108 }
109
110 Ok(cursor)
111}
112
113#[must_use]
119pub fn reassemble_crypto_stream(frames: &[CryptoFrame]) -> Vec<u8> {
120 let mut sorted: Vec<&CryptoFrame> = frames.iter().collect();
121 sorted.sort_by_key(|f| f.offset);
122
123 let mut stream = Vec::new();
124 let mut next_offset: u64 = 0;
125
126 for frame in sorted {
127 if frame.offset == next_offset {
128 stream.extend_from_slice(&frame.data);
129 next_offset += frame.data.len() as u64;
130 } else if frame.offset < next_offset {
131 let skip = (next_offset - frame.offset) as usize;
132 if skip < frame.data.len() {
133 stream.extend_from_slice(&frame.data[skip..]);
134 next_offset += (frame.data.len() - skip) as u64;
135 }
136 } else {
137 break;
138 }
139 }
140
141 stream
142}