Make Codec max frame length configurable (#57)
This commit is contained in:
		
				
					committed by
					
						 Carl Lerche
						Carl Lerche
					
				
			
			
				
	
			
			
			
						parent
						
							460afa41c8
						
					
				
				
					commit
					11de86b34e
				
			| @@ -219,6 +219,18 @@ impl<T> FramedRead<T> { | |||||||
|     pub fn get_mut(&mut self) -> &mut T { |     pub fn get_mut(&mut self) -> &mut T { | ||||||
|         self.inner.get_mut() |         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<T> Stream for FramedRead<T> | impl<T> Stream for FramedRead<T> | ||||||
|   | |||||||
| @@ -27,7 +27,17 @@ impl<T, B> Codec<T, B> | |||||||
|     where T: AsyncRead + AsyncWrite, |     where T: AsyncRead + AsyncWrite, | ||||||
|           B: Buf, |           B: Buf, | ||||||
| { | { | ||||||
|  |     /// Returns a new `Codec` with the default max frame size | ||||||
|  |     #[inline] | ||||||
|     pub fn new(io: T) -> Self { |     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 |         // Wrap with writer | ||||||
|         let framed_write = FramedWrite::new(io); |         let framed_write = FramedWrite::new(io); | ||||||
|  |  | ||||||
| @@ -37,9 +47,7 @@ impl<T, B> Codec<T, B> | |||||||
|             .length_field_length(3) |             .length_field_length(3) | ||||||
|             .length_adjustment(9) |             .length_adjustment(9) | ||||||
|             .num_skip(0) // Don't skip the header |             .num_skip(0) // Don't skip the header | ||||||
|             // TODO: make this configurable and allow it to be changed during |             .max_frame_length(max_frame_size) | ||||||
|             // runtime. |  | ||||||
|             .max_frame_length(frame::DEFAULT_MAX_FRAME_SIZE as usize) |  | ||||||
|             .new_read(framed_write); |             .new_read(framed_write); | ||||||
|  |  | ||||||
|         let inner = FramedRead::new(delimited); |         let inner = FramedRead::new(delimited); | ||||||
| @@ -49,6 +57,29 @@ impl<T, B> Codec<T, B> | |||||||
| } | } | ||||||
|  |  | ||||||
| impl<T, B> Codec<T, B> { | impl<T, B> Codec<T, B> { | ||||||
|  |  | ||||||
|  |     /// 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. |     /// Returns the max frame size that can be sent to the peer. | ||||||
|     pub fn max_send_frame_size(&self) -> usize { |     pub fn max_send_frame_size(&self) -> usize { | ||||||
|         self.inner.get_ref().max_frame_size() |         self.inner.get_ref().max_frame_size() | ||||||
|   | |||||||
| @@ -2,6 +2,8 @@ | |||||||
| extern crate h2_test_support; | extern crate h2_test_support; | ||||||
| use h2_test_support::prelude::*; | use h2_test_support::prelude::*; | ||||||
|  |  | ||||||
|  | use std::error::Error; | ||||||
|  |  | ||||||
| #[test] | #[test] | ||||||
| fn read_none() { | fn read_none() { | ||||||
|     let mut codec = Codec::from( |     let mut codec = Codec::from( | ||||||
| @@ -111,3 +113,22 @@ fn read_headers_with_pseudo() { | |||||||
| #[test] | #[test] | ||||||
| fn read_headers_empty_payload() { | 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"); | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user