diff --git a/src/frame/go_away.rs b/src/frame/go_away.rs index 4dfdcd7..260698c 100644 --- a/src/frame/go_away.rs +++ b/src/frame/go_away.rs @@ -1,11 +1,15 @@ +use std::fmt; + +use bytes::{BufMut, Bytes}; + use crate::frame::{self, Error, Head, Kind, Reason, StreamId}; -use bytes::BufMut; - -#[derive(Debug, Clone, Copy, Eq, PartialEq)] +#[derive(Clone, Eq, PartialEq)] pub struct GoAway { last_stream_id: StreamId, error_code: Reason, + #[allow(unused)] + debug_data: Bytes, } impl GoAway { @@ -13,6 +17,7 @@ impl GoAway { GoAway { last_stream_id, error_code: reason, + debug_data: Bytes::new(), } } @@ -24,6 +29,11 @@ impl GoAway { self.error_code } + #[cfg(feature = "unstable")] + pub fn debug_data(&self) -> &[u8] { + &self.debug_data + } + pub fn load(payload: &[u8]) -> Result { if payload.len() < 8 { return Err(Error::BadFrameSize); @@ -31,10 +41,12 @@ impl GoAway { let (last_stream_id, _) = StreamId::parse(&payload[..4]); let error_code = unpack_octets_4!(payload, 4, u32); + let debug_data = Bytes::from(&payload[8..]); Ok(GoAway { last_stream_id, error_code: error_code.into(), + debug_data, }) } @@ -52,3 +64,17 @@ impl From for frame::Frame { frame::Frame::GoAway(src) } } + +impl fmt::Debug for GoAway { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut builder = f.debug_struct("GoAway"); + builder.field("error_code", &self.error_code); + builder.field("last_stream_id", &self.last_stream_id); + + if !self.debug_data.is_empty() { + builder.field("debug_data", &self.debug_data); + } + + builder.finish() + } +} diff --git a/tests/h2-tests/tests/codec_read.rs b/tests/h2-tests/tests/codec_read.rs index 655e810..000ff1d 100644 --- a/tests/h2-tests/tests/codec_read.rs +++ b/tests/h2-tests/tests/codec_read.rs @@ -214,3 +214,26 @@ async fn update_max_frame_len_at_rest() { "frame with invalid size" ); } + +#[tokio::test] +async fn read_goaway_with_debug_data() { + let mut codec = raw_codec! { + read => [ + // head + 0, 0, 22, 7, 0, 0, 0, 0, 0, + // last_stream_id + 0, 0, 0, 1, + // error_code + 0, 0, 0, 11, + // debug_data + "too_many_pings", + ]; + }; + + let data = poll_frame!(GoAway, codec); + assert_eq!(data.reason(), Reason::ENHANCE_YOUR_CALM); + assert_eq!(data.last_stream_id(), 1); + assert_eq!(data.debug_data(), b"too_many_pings"); + + assert_closed!(codec); +}