add support for configuring max frame size
- Adds `max_frame_size` to client and server builders - Pushes max_frame_size into Codec - Detects when the Codec triggers an error from a frame too big - Sends a GOAWAY when FRAME_SIZE_ERROR is encountered reading a frame
This commit is contained in:
		| @@ -1,6 +1,6 @@ | ||||
| use codec::RecvError; | ||||
| use frame::{self, Frame, Kind}; | ||||
| use frame::DEFAULT_SETTINGS_HEADER_TABLE_SIZE; | ||||
| use frame::{self, Frame, Kind, Reason}; | ||||
| use frame::{DEFAULT_MAX_FRAME_SIZE, DEFAULT_SETTINGS_HEADER_TABLE_SIZE, MAX_MAX_FRAME_SIZE}; | ||||
| use frame::Reason::*; | ||||
|  | ||||
| use hpack; | ||||
| @@ -9,6 +9,8 @@ use futures::*; | ||||
|  | ||||
| use bytes::BytesMut; | ||||
|  | ||||
| use std::io; | ||||
|  | ||||
| use tokio_io::AsyncRead; | ||||
| use tokio_io::codec::length_delimited; | ||||
|  | ||||
| @@ -228,9 +230,12 @@ impl<T> FramedRead<T> { | ||||
|     } | ||||
|  | ||||
|     /// Updates the max frame size setting. | ||||
|     /// | ||||
|     /// Must be within 16,384 and 16,777,215. | ||||
|     #[cfg(feature = "unstable")] | ||||
|     #[inline] | ||||
|     pub fn set_max_frame_size(&mut self, val: usize) { | ||||
|         assert!(DEFAULT_MAX_FRAME_SIZE as usize <= val && val <= MAX_MAX_FRAME_SIZE as usize); | ||||
|         self.inner.set_max_frame_length(val) | ||||
|     } | ||||
| } | ||||
| @@ -245,7 +250,7 @@ where | ||||
|     fn poll(&mut self) -> Poll<Option<Frame>, Self::Error> { | ||||
|         loop { | ||||
|             trace!("poll"); | ||||
|             let bytes = match try_ready!(self.inner.poll()) { | ||||
|             let bytes = match try_ready!(self.inner.poll().map_err(map_err)) { | ||||
|                 Some(bytes) => bytes, | ||||
|                 None => return Ok(Async::Ready(None)), | ||||
|             }; | ||||
| @@ -258,3 +263,17 @@ where | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn map_err(err: io::Error) -> RecvError { | ||||
|     use std::error::Error; | ||||
|  | ||||
|     if let io::ErrorKind::InvalidData = err.kind() { | ||||
|         // woah, brittle... | ||||
|         // TODO: with tokio-io v0.1.4, we can check | ||||
|         // err.get_ref().is::<tokio_io::length_delimited::FrameTooBig>() | ||||
|         if err.description() == "frame size too big" { | ||||
|             return RecvError::Connection(Reason::FrameSizeError); | ||||
|         } | ||||
|     } | ||||
|     err.into() | ||||
| } | ||||
|   | ||||
| @@ -227,7 +227,7 @@ impl<T, B> FramedWrite<T, B> { | ||||
|  | ||||
|     /// Set the peer's max frame size. | ||||
|     pub fn set_max_frame_size(&mut self, val: usize) { | ||||
|         assert!(val <= frame::MAX_MAX_FRAME_SIZE); | ||||
|         assert!(val <= frame::MAX_MAX_FRAME_SIZE as usize); | ||||
|         self.max_frame_size = val as FrameSize; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -45,10 +45,12 @@ where | ||||
|             .length_field_length(3) | ||||
|             .length_adjustment(9) | ||||
|             .num_skip(0) // Don't skip the header | ||||
|             .max_frame_length(max_frame_size) | ||||
|             .new_read(framed_write); | ||||
|  | ||||
|         let inner = FramedRead::new(delimited); | ||||
|         let mut inner = FramedRead::new(delimited); | ||||
|  | ||||
|         // Use FramedRead's method since it checks the value is within range. | ||||
|         inner.set_max_frame_size(max_frame_size); | ||||
|  | ||||
|         Codec { | ||||
|             inner, | ||||
| @@ -66,7 +68,6 @@ impl<T, B> Codec<T, B> { | ||||
|     #[cfg(feature = "unstable")] | ||||
|     #[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) | ||||
|     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user