Skip to main content

ntex_h2/frame/
go_away.rs

1use std::fmt;
2
3use ntex_bytes::{BufMut, Bytes, BytesMut};
4
5use crate::frame::{self, FrameError, Head, Kind, Reason, StreamId};
6
7#[derive(Clone, Eq, PartialEq)]
8pub struct GoAway {
9    last_stream_id: StreamId,
10    error_code: Reason,
11    data: Bytes,
12}
13
14impl GoAway {
15    pub fn new(reason: Reason) -> Self {
16        GoAway {
17            last_stream_id: 0.into(),
18            data: Bytes::new(),
19            error_code: reason,
20        }
21    }
22
23    #[must_use]
24    pub fn set_last_stream_id(mut self, id: StreamId) -> Self {
25        self.last_stream_id = id;
26        self
27    }
28
29    #[must_use]
30    pub fn set_data<T>(mut self, data: T) -> Self
31    where
32        Bytes: From<T>,
33    {
34        self.data = data.into();
35        self
36    }
37
38    #[must_use]
39    pub fn set_reason(mut self, error_code: Reason) -> Self {
40        self.error_code = error_code;
41        self
42    }
43
44    pub fn last_stream_id(&self) -> StreamId {
45        self.last_stream_id
46    }
47
48    pub fn reason(&self) -> Reason {
49        self.error_code
50    }
51
52    pub fn data(&self) -> &Bytes {
53        &self.data
54    }
55
56    pub fn load(payload: &[u8]) -> Result<GoAway, FrameError> {
57        if payload.len() < 8 {
58            return Err(FrameError::BadFrameSize);
59        }
60
61        let (last_stream_id, _) = StreamId::parse(&payload[..4]);
62        let error_code = unpack_octets_4!(payload, 4, u32);
63        let data = Bytes::copy_from_slice(&payload[8..]);
64
65        Ok(GoAway {
66            last_stream_id,
67            data,
68            error_code: error_code.into(),
69        })
70    }
71
72    pub fn encode(&self, dst: &mut BytesMut) {
73        log::trace!("encoding GO_AWAY; code={:?}", self.error_code);
74        let head = Head::new(Kind::GoAway, 0, StreamId::zero());
75        head.encode(8 + self.data.len(), dst);
76        dst.put_u32(self.last_stream_id.into());
77        dst.put_u32(self.error_code.into());
78        dst.extend_from_slice(&self.data);
79    }
80}
81
82impl From<GoAway> for frame::Frame {
83    fn from(src: GoAway) -> Self {
84        frame::Frame::GoAway(src)
85    }
86}
87
88impl fmt::Debug for GoAway {
89    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90        let mut builder = f.debug_struct("GoAway");
91        builder.field("error_code", &self.error_code);
92        builder.field("last_stream_id", &self.last_stream_id);
93
94        if !self.data.is_empty() {
95            builder.field("data", &self.data);
96        }
97
98        builder.finish()
99    }
100}