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