1 use std::fmt;
2 
3 use bytes::{BufMut, Bytes};
4 
5 use crate::frame::{self, Error, Head, Kind, Reason, StreamId};
6 
7 #[derive(Clone, Eq, PartialEq)]
8 pub struct GoAway {
9     last_stream_id: StreamId,
10     error_code: Reason,
11     debug_data: Bytes,
12 }
13 
14 impl GoAway {
new(last_stream_id: StreamId, reason: Reason) -> Self15     pub fn new(last_stream_id: StreamId, reason: Reason) -> Self {
16         GoAway {
17             last_stream_id,
18             error_code: reason,
19             debug_data: Bytes::new(),
20         }
21     }
22 
with_debug_data(last_stream_id: StreamId, reason: Reason, debug_data: Bytes) -> Self23     pub fn with_debug_data(last_stream_id: StreamId, reason: Reason, debug_data: Bytes) -> Self {
24         Self {
25             last_stream_id,
26             error_code: reason,
27             debug_data,
28         }
29     }
30 
last_stream_id(&self) -> StreamId31     pub fn last_stream_id(&self) -> StreamId {
32         self.last_stream_id
33     }
34 
reason(&self) -> Reason35     pub fn reason(&self) -> Reason {
36         self.error_code
37     }
38 
debug_data(&self) -> &Bytes39     pub fn debug_data(&self) -> &Bytes {
40         &self.debug_data
41     }
42 
load(payload: &[u8]) -> Result<GoAway, Error>43     pub fn load(payload: &[u8]) -> Result<GoAway, Error> {
44         if payload.len() < 8 {
45             return Err(Error::BadFrameSize);
46         }
47 
48         let (last_stream_id, _) = StreamId::parse(&payload[..4]);
49         let error_code = unpack_octets_4!(payload, 4, u32);
50         let debug_data = Bytes::copy_from_slice(&payload[8..]);
51 
52         Ok(GoAway {
53             last_stream_id,
54             error_code: error_code.into(),
55             debug_data,
56         })
57     }
58 
encode<B: BufMut>(&self, dst: &mut B)59     pub fn encode<B: BufMut>(&self, dst: &mut B) {
60         tracing::trace!("encoding GO_AWAY; code={:?}", self.error_code);
61         let head = Head::new(Kind::GoAway, 0, StreamId::zero());
62         head.encode(8 + self.debug_data.len(), dst);
63         dst.put_u32(self.last_stream_id.into());
64         dst.put_u32(self.error_code.into());
65         dst.put(self.debug_data.slice(..));
66     }
67 }
68 
69 impl<B> From<GoAway> for frame::Frame<B> {
from(src: GoAway) -> Self70     fn from(src: GoAway) -> Self {
71         frame::Frame::GoAway(src)
72     }
73 }
74 
75 impl fmt::Debug for GoAway {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result76     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77         let mut builder = f.debug_struct("GoAway");
78         builder.field("error_code", &self.error_code);
79         builder.field("last_stream_id", &self.last_stream_id);
80 
81         if !self.debug_data.is_empty() {
82             builder.field("debug_data", &self.debug_data);
83         }
84 
85         builder.finish()
86     }
87 }
88