1use std::{cell::RefCell, rc::Rc};
2
3use ntex_bytes::{BytePages, Bytes, BytesMut};
4use ntex_codec::{Decoder, Encoder};
5
6mod error;
7mod length_delimited;
8
9pub use self::error::EncoderError;
10
11use self::length_delimited::LengthDelimitedCodec;
12use crate::{consts, frame, frame::Frame, frame::Kind, hpack};
13
14const PUSH_PROMISE: u8 = 5;
16
17#[derive(Clone, Debug)]
18pub struct Codec(Rc<RefCell<CodecInner>>);
19
20#[derive(Debug)]
22struct Partial {
23 frame: frame::Headers,
25 buf: Bytes,
27 count: usize,
29}
30
31#[derive(Debug)]
32struct CodecInner {
33 encoder_hpack: hpack::Encoder,
35 encoder_max_frame_size: frame::FrameSize, decoder: LengthDelimitedCodec,
39 decoder_hpack: hpack::Decoder,
40 decoder_max_headers: usize,
41 decoder_max_header_list_size: usize,
42 decoder_max_header_continuations: usize,
43 partial: Option<Partial>, }
45
46impl Default for Codec {
47 #[inline]
48 fn default() -> Self {
50 let decoder = self::length_delimited::Builder::new()
52 .length_field_length(3)
53 .length_adjustment(9)
54 .max_frame_length(frame::DEFAULT_MAX_FRAME_SIZE as usize)
55 .num_skip(0) .new_codec();
57
58 Codec(Rc::new(RefCell::new(CodecInner {
59 decoder,
60 decoder_hpack: hpack::Decoder::new(frame::DEFAULT_SETTINGS_HEADER_TABLE_SIZE),
61 decoder_max_headers: consts::DEFAULT_MAX_HEADERS,
62 decoder_max_header_list_size: consts::DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE as usize,
63 decoder_max_header_continuations: consts::DEFAULT_MAX_COUNTINUATIONS,
64 partial: None,
65
66 encoder_hpack: hpack::Encoder::default(),
67 encoder_max_frame_size: frame::DEFAULT_MAX_FRAME_SIZE,
68 })))
69 }
70}
71
72impl Codec {
73 #[inline]
84 pub fn set_recv_frame_size(&self, val: usize) {
85 assert!(
86 frame::DEFAULT_MAX_FRAME_SIZE as usize <= val
87 && val <= frame::MAX_MAX_FRAME_SIZE as usize
88 );
89 self.0.borrow_mut().decoder.set_max_frame_length(val);
90 }
91
92 pub fn recv_frame_size(&self) -> u32 {
94 self.0.borrow_mut().decoder.max_frame_length() as u32
95 }
96
97 pub fn set_recv_header_list_size(&self, val: usize) {
101 self.0.borrow_mut().decoder_max_header_list_size = val;
102 }
103
104 pub fn set_max_headers(&self, val: usize) {
108 self.0.borrow_mut().decoder_max_headers = val;
109 }
110
111 pub fn set_max_header_continuations(&self, val: usize) {
115 self.0.borrow_mut().decoder_max_header_continuations = val;
116 }
117
118 pub fn set_send_frame_size(&self, val: usize) {
124 assert!(val <= frame::MAX_MAX_FRAME_SIZE as usize);
125 self.0.borrow_mut().encoder_max_frame_size = val as frame::FrameSize;
126 }
127
128 pub fn set_send_header_table_size(&self, val: usize) {
130 self.0.borrow_mut().encoder_hpack.update_max_size(val);
131 }
132
133 pub fn send_frame_size(&self) -> u32 {
135 self.0.borrow_mut().encoder_max_frame_size
136 }
137}
138
139impl Decoder for Codec {
140 type Item = Frame;
141 type Error = frame::FrameError;
142
143 #[allow(clippy::too_many_lines)]
144 fn decode(&self, src: &mut BytesMut) -> Result<Option<Frame>, frame::FrameError> {
148 let mut inner = self.0.borrow_mut();
149 loop {
150 let Some(mut bytes) = inner.decoder.decode(src)? else {
151 return Ok(None);
152 };
153
154 if bytes[3] == PUSH_PROMISE {
156 return Err(frame::FrameError::UnexpectedPushPromise);
157 }
158
159 let head = frame::Head::parse(&bytes);
161 let kind = head.kind();
162
163 if inner.partial.is_some() && kind != Kind::Continuation {
164 proto_err!(conn: "expected CONTINUATION, got {:?}", kind);
165 return Err(frame::FrameError::Continuation(
166 frame::FrameContinuationError::Expected,
167 ));
168 }
169
170 log::trace!("decoding {:?} frame, frame buf len {}", kind, bytes.len());
171
172 let frame = match kind {
173 Kind::Settings => frame::Settings::load(head, &bytes[frame::HEADER_LEN..])
174 .inspect_err(|e| {
175 proto_err!(conn: "failed to load SETTINGS frame; err={:?}", e);
176 })?
177 .into(),
178 Kind::Ping => frame::Ping::load(head, &bytes[frame::HEADER_LEN..])
179 .inspect_err(|e| {
180 proto_err!(conn: "failed to load PING frame; err={:?}", e);
181 })?
182 .into(),
183 Kind::WindowUpdate => frame::WindowUpdate::load(head, &bytes[frame::HEADER_LEN..])
184 .inspect_err(|e| {
185 proto_err!(conn: "failed to load WINDOW_UPDATE frame; err={:?}", e);
186 })?
187 .into(),
188 Kind::Data => {
189 bytes.advance_to(frame::HEADER_LEN);
190
191 frame::Data::load(head, bytes)
192 .inspect_err(|e| {
194 proto_err!(conn: "failed to load DATA frame; err={:?}", e);
195 })?
196 .into()
197 }
198 Kind::Headers => {
199 bytes.advance_to(frame::HEADER_LEN);
201
202 let mut frame = match frame::Headers::load(head, &mut bytes) {
204 Ok(res) => Ok(res),
205 Err(frame::FrameError::InvalidDependencyId) => {
206 proto_err!(stream: "invalid HEADERS dependency ID");
207 Err(frame::FrameError::InvalidDependencyId)
210 }
211 Err(e) => {
212 proto_err!(conn: "failed to load frame; err={:?}", e);
213 Err(e)
214 }
215 }?;
216
217 if frame.is_end_headers() {
218 let max_headers = inner.decoder_max_headers;
219
220 match frame.load_hpack(&mut bytes, &mut inner.decoder_hpack, max_headers) {
222 Ok(()) => {}
223 Err(frame::FrameError::MalformedMessage) => {
224 let id = head.stream_id();
225 proto_err!(stream: "malformed header block; stream={:?}", id);
226 return Err(frame::FrameError::MalformedMessage);
227 }
228 Err(e) => {
229 proto_err!(conn: "failed HPACK decoding; err={:?}", e);
230 return Err(e);
231 }
232 }
233 frame.into()
234 } else {
235 log::trace!("loaded partial header block");
236 inner.partial = Some(Partial {
238 frame,
239 buf: bytes,
240 count: 0,
241 });
242
243 continue;
244 }
245 }
246 Kind::Reset => frame::Reset::load(head, &bytes[frame::HEADER_LEN..])
247 .inspect_err(|e| {
248 proto_err!(conn: "failed to load RESET frame; err={:?}", e);
249 })?
250 .into(),
251 Kind::GoAway => frame::GoAway::load(&bytes[frame::HEADER_LEN..])
252 .inspect_err(|e| {
253 proto_err!(conn: "failed to load GO_AWAY frame; err={:?}", e);
254 })?
255 .into(),
256 Kind::Priority => {
257 if head.stream_id() == 0 {
258 proto_err!(conn: "invalid stream ID 0");
260 return Err(frame::FrameError::InvalidStreamId);
261 }
262
263 match frame::Priority::load(head, &bytes[frame::HEADER_LEN..]) {
264 Ok(frame) => frame.into(),
265 Err(frame::FrameError::InvalidDependencyId) => {
266 let id = head.stream_id();
270 proto_err!(stream: "PRIORITY invalid dependency ID; stream={:?}", id);
271 return Err(frame::FrameError::InvalidDependencyId);
272 }
273 Err(e) => {
274 proto_err!(conn: "failed to load PRIORITY frame; err={:?};", e);
275 return Err(e);
276 }
277 }
278 }
279 Kind::Continuation => {
280 let mut partial = inner.partial.take().ok_or_else(|| {
281 proto_err!(conn: "received unexpected CONTINUATION frame");
282 frame::FrameError::Continuation(frame::FrameContinuationError::Unexpected)
283 })?;
284
285 if partial.frame.stream_id() != head.stream_id() {
287 proto_err!(conn: "CONTINUATION frame stream ID does not match previous frame stream ID");
288 return Err(frame::FrameError::Continuation(
289 frame::FrameContinuationError::UnknownStreamId,
290 ));
291 }
292
293 if inner.decoder_max_header_continuations > 0 {
294 partial.count += 1;
296 if partial.count > inner.decoder_max_header_continuations {
297 proto_err!(conn: "received excessive amount of CONTINUATION frames");
298 return Err(frame::FrameError::Continuation(
299 frame::FrameContinuationError::MaxContinuations,
300 ));
301 }
302 }
303
304 if partial.buf.is_empty() {
306 partial.buf = bytes.split_off(frame::HEADER_LEN);
307 } else {
308 if partial.buf.len() + bytes.len() > inner.decoder_max_header_list_size {
321 proto_err!(conn: "CONTINUATION frame header block size over ignorable limit");
322 return Err(frame::FrameError::Continuation(
323 frame::FrameContinuationError::MaxLeftoverSize,
324 ));
325 }
326 let mut buf = BytesMut::with_capacity(
327 partial.buf.len() + bytes.len() - frame::HEADER_LEN,
328 );
329 buf.extend_from_slice(&partial.buf);
330 buf.extend_from_slice(&bytes[frame::HEADER_LEN..]);
331 partial.buf = buf.into();
332 }
333
334 if (head.flag() & 0x4) == 0x4 {
335 let max_headers = inner.decoder_max_headers;
336 match partial.frame.load_hpack(
337 &mut partial.buf,
338 &mut inner.decoder_hpack,
339 max_headers,
340 ) {
341 Ok(()) => {}
342 Err(frame::FrameError::MalformedMessage) => {
343 let id = head.stream_id();
344 proto_err!(stream: "malformed CONTINUATION frame; stream={:?}", id);
345 return Err(frame::FrameContinuationError::Malformed.into());
346 }
347 Err(e) => {
348 proto_err!(conn: "failed HPACK decoding; err={:?}", e);
349 return Err(e);
350 }
351 }
352
353 partial.frame.into()
354 } else {
355 inner.partial = Some(partial);
356 continue;
357 }
358 }
359 Kind::Unknown => {
360 continue;
362 }
363 };
364
365 return Ok(Some(frame));
366 }
367 }
368}
369
370impl Encoder for Codec {
371 type Item = Frame;
372 type Error = error::EncoderError;
373
374 fn encodev(&self, item: Frame, buf: &mut BytePages) -> Result<(), error::EncoderError> {
375 let mut inner = self.0.borrow_mut();
379
380 match item {
381 Frame::Data(v) => {
382 let len = v.payload().len();
384 if len > inner.encoder_max_frame_size as usize {
385 return Err(error::EncoderError::MaxSizeExceeded);
386 }
387 v.encode(buf);
388 }
389 Frame::Headers(v) => {
390 let max_size = inner.encoder_max_frame_size as usize;
391 v.encode(&mut inner.encoder_hpack, buf, max_size);
392 }
393 Frame::Settings(v) => {
394 v.encode(buf);
395 }
396 Frame::GoAway(v) => {
397 v.encode(buf);
398 }
399 Frame::Ping(v) => {
400 v.encode(buf);
401 }
402 Frame::WindowUpdate(v) => {
403 v.encode(buf);
404 }
405
406 Frame::Priority(_) => (),
407 Frame::Reset(v) => {
408 v.encode(buf);
409 }
410 }
411
412 Ok(())
413 }
414}