diff --git a/src/codec/framed_read.rs b/src/codec/framed_read.rs index 562290f..f65dfb8 100644 --- a/src/codec/framed_read.rs +++ b/src/codec/framed_read.rs @@ -219,6 +219,18 @@ impl FramedRead { pub fn get_mut(&mut self) -> &mut T { self.inner.get_mut() } + + /// Returns the current max frame size setting + #[inline] + pub fn max_frame_size(&self) -> usize { + self.inner.max_frame_length() + } + + /// Updates the max frame size setting. + #[inline] + pub fn set_max_frame_size(&mut self, val: usize) { + self.inner.set_max_frame_length(val) + } } impl Stream for FramedRead diff --git a/src/codec/mod.rs b/src/codec/mod.rs index 62a321b..3b6d499 100644 --- a/src/codec/mod.rs +++ b/src/codec/mod.rs @@ -27,7 +27,17 @@ impl Codec where T: AsyncRead + AsyncWrite, B: Buf, { + /// Returns a new `Codec` with the default max frame size + #[inline] pub fn new(io: T) -> Self { + Self::with_max_recv_frame_size( + io, + frame::DEFAULT_MAX_FRAME_SIZE as usize + ) + } + + /// Returns a new `Codec` with the given maximum frame size + pub fn with_max_recv_frame_size(io: T, max_frame_size: usize) -> Self { // Wrap with writer let framed_write = FramedWrite::new(io); @@ -37,9 +47,7 @@ impl Codec .length_field_length(3) .length_adjustment(9) .num_skip(0) // Don't skip the header - // TODO: make this configurable and allow it to be changed during - // runtime. - .max_frame_length(frame::DEFAULT_MAX_FRAME_SIZE as usize) + .max_frame_length(max_frame_size) .new_read(framed_write); let inner = FramedRead::new(delimited); @@ -49,6 +57,29 @@ impl Codec } impl Codec { + + /// Updates the max received frame size. + /// + /// The change takes effect the next time a frame is decoded. In other + /// words, if a frame is currently in process of being decoded with a frame + /// size greater than `val` but less than the max frame size in effect + /// before calling this function, then the frame will be allowed. + #[inline] + pub fn set_max_recv_frame_size(&mut self, val: usize) { + // TODO: should probably make some assertions about max frame size... + self.inner.set_max_frame_size(val) + + } + + /// Returns the current max received frame size setting. + /// + /// This is the largest size this codec will accept from the wire. Larger + /// frames will be rejected. + #[inline] + pub fn max_recv_frame_size(&self) -> usize { + self.inner.max_frame_size() + } + /// Returns the max frame size that can be sent to the peer. pub fn max_send_frame_size(&self) -> usize { self.inner.get_ref().max_frame_size() diff --git a/tests/codec_read.rs b/tests/codec_read.rs index 040fb61..a21e1ea 100644 --- a/tests/codec_read.rs +++ b/tests/codec_read.rs @@ -2,6 +2,8 @@ extern crate h2_test_support; use h2_test_support::prelude::*; +use std::error::Error; + #[test] fn read_none() { let mut codec = Codec::from( @@ -111,3 +113,22 @@ fn read_headers_with_pseudo() { #[test] fn read_headers_empty_payload() { } + +#[test] +fn update_max_frame_len_at_rest() { + // TODO: add test for updating max frame length in flight as well? + let mut codec = raw_codec! { + read => [ + 0, 0, 5, 0, 0, 0, 0, 0, 1, + "hello", + "world", + ]; + }; + + assert_eq!(poll_data!(codec).payload(), &b"hello"[..]); + + codec.set_max_recv_frame_size(2); + + assert_eq!(codec.max_recv_frame_size(), 2); + assert_eq!(codec.poll().unwrap_err().description(), "frame size too big"); +}