net_wire/http3/frame/
goaway.rs1use crate::http3::codepoints::Http3FrameType;
4use crate::quic::varint::{QuicVarInt, QuicVarIntLen};
5
6use super::envelope::Http3Frame;
7use super::payload::{
8 Http3FramePayloadBuildError, Http3FramePayloadField, Http3FramePayloadParseError,
9 encode_varint, envelope, parse_exact_varint, validate_type,
10};
11
12#[derive(Clone, Copy, Debug, Eq, PartialEq)]
14pub struct Http3Goaway<'a> {
15 frame: Http3Frame<'a>,
16 identifier: QuicVarInt<'a>,
17}
18
19impl<'a> Http3Goaway<'a> {
20 pub(in crate::http3) fn from_validated(
22 frame: Http3Frame<'a>,
23 identifier: u64,
24 identifier_length: QuicVarIntLen,
25 ) -> Self {
26 let identifier = QuicVarInt::from_validated(
27 &frame.payload()[..identifier_length.byte_len()],
28 identifier,
29 identifier_length,
30 );
31 Self { frame, identifier }
32 }
33
34 pub fn parse(
36 bytes: &'a [u8],
37 maximum_payload: usize,
38 ) -> Result<Self, Http3FramePayloadParseError> {
39 Self::from_frame(
40 Http3Frame::parse(bytes, maximum_payload)
41 .map_err(Http3FramePayloadParseError::Frame)?,
42 )
43 }
44
45 pub fn from_frame(frame: Http3Frame<'a>) -> Result<Self, Http3FramePayloadParseError> {
47 validate_type(frame, Http3FrameType::GOAWAY)?;
48 let identifier =
49 parse_exact_varint(frame.payload(), Http3FramePayloadField::GoawayIdentifier)?;
50 Ok(Self { frame, identifier })
51 }
52
53 pub const fn frame(&self) -> Http3Frame<'a> {
55 self.frame
56 }
57
58 pub const fn as_bytes(&self) -> &'a [u8] {
60 self.frame.as_bytes()
61 }
62
63 pub const fn identifier(&self) -> u64 {
65 self.identifier.value()
66 }
67
68 pub const fn identifier_varint(&self) -> QuicVarInt<'a> {
70 self.identifier
71 }
72}
73
74pub struct Http3GoawayBuilder<'output> {
76 destination: &'output mut [u8],
77 identifier: u64,
78}
79
80impl<'output> Http3GoawayBuilder<'output> {
81 pub fn new(destination: &'output mut [u8], identifier: u64) -> Self {
83 Self {
84 destination,
85 identifier,
86 }
87 }
88
89 pub fn build(self) -> Result<Http3Goaway<'output>, Http3FramePayloadBuildError> {
91 let identifier = encode_varint(self.identifier).map_err(|error| {
92 Http3FramePayloadBuildError::PayloadVarInt {
93 field: Http3FramePayloadField::GoawayIdentifier,
94 error,
95 }
96 })?;
97 let plan = envelope(
98 Http3FrameType::GOAWAY,
99 identifier.byte_len(),
100 self.destination,
101 )?;
102 let header_length = plan.header_length();
103 let required = plan.required();
104 let bytes = &mut self.destination[..required];
105 plan.write_header(bytes);
106 bytes[header_length..].copy_from_slice(identifier.bytes());
107 let frame = plan.finish(bytes);
108 Ok(Http3Goaway::from_validated(
109 frame,
110 self.identifier,
111 identifier.len,
112 ))
113 }
114}