Skip to main content

net_wire/http2/
control.rs

1use super::error::Http2ParseError;
2use super::frame::Http2Frame;
3use super::layout::{validate_exact_payload, validate_frame, validate_type, validate_zero_stream};
4use super::priority::Http2Priority;
5use super::types::{Http2ErrorCode, Http2FrameType, Http2StreamId};
6
7/// A validated borrowed HTTP/2 GOAWAY frame.
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub struct Http2Goaway<'a> {
10    frame: Http2Frame<'a>,
11    last_stream_id: Http2StreamId,
12    error_code: Http2ErrorCode,
13}
14
15impl<'a> Http2Goaway<'a> {
16    pub(super) fn from_validated(
17        frame: Http2Frame<'a>,
18        last_stream_id: Http2StreamId,
19        error_code: Http2ErrorCode,
20    ) -> Self {
21        Self {
22            frame,
23            last_stream_id,
24            error_code,
25        }
26    }
27
28    /// Parses the first complete GOAWAY frame, enforcing the caller-provided payload maximum.
29    pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
30        Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
31    }
32
33    /// Validates a raw GOAWAY frame's intrinsic layout.
34    pub fn from_frame(frame: Http2Frame<'a>) -> Result<Self, Http2ParseError> {
35        validate_type(frame, Http2FrameType::GOAWAY)?;
36        validate_zero_stream(frame)?;
37        let payload = frame.payload();
38        if payload.len() < 8 {
39            return Err(Http2ParseError::MalformedPayload {
40                required: 8,
41                available: payload.len(),
42            });
43        }
44        Ok(Self {
45            last_stream_id: Http2StreamId::new(u32::from_be_bytes([
46                payload[0], payload[1], payload[2], payload[3],
47            ])),
48            error_code: Http2ErrorCode::new(u32::from_be_bytes([
49                payload[4], payload[5], payload[6], payload[7],
50            ])),
51            frame,
52        })
53    }
54
55    /// Returns the validated raw frame.
56    pub const fn frame(&self) -> Http2Frame<'a> {
57        self.frame
58    }
59
60    /// Returns the exact represented frame bytes.
61    pub fn as_bytes(&self) -> &'a [u8] {
62        self.frame.as_bytes()
63    }
64
65    /// Returns the raw last-stream identifier, including its reserved bit.
66    pub const fn last_stream_id(&self) -> Http2StreamId {
67        self.last_stream_id
68    }
69
70    /// Returns the raw-preserving connection error code.
71    pub const fn error_code(&self) -> Http2ErrorCode {
72        self.error_code
73    }
74
75    /// Returns the arbitrary trailing debug data.
76    pub fn additional_debug_data(&self) -> &'a [u8] {
77        &self.frame.payload()[8..]
78    }
79}
80
81/// A WINDOW_UPDATE increment preserving its reserved high bit.
82#[repr(transparent)]
83#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
84pub struct Http2WindowIncrement(u32);
85
86impl Http2WindowIncrement {
87    /// Creates an increment from its raw encoded field, including the reserved bit.
88    pub const fn new(raw: u32) -> Self {
89        Self(raw)
90    }
91
92    fn parse(bytes: &[u8]) -> Self {
93        Self(u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
94    }
95
96    /// Returns the raw encoded increment, including its reserved bit.
97    pub const fn raw(self) -> u32 {
98        self.0
99    }
100
101    /// Returns the 31-bit window increment value.
102    pub const fn value(self) -> u32 {
103        self.0 & 0x7fff_ffff
104    }
105
106    /// Returns whether the raw encoded increment has its reserved bit set.
107    pub const fn has_reserved_bit(self) -> bool {
108        self.0 & 0x8000_0000 != 0
109    }
110}
111
112/// A validated borrowed HTTP/2 PRIORITY frame.
113#[derive(Clone, Copy, Debug, Eq, PartialEq)]
114pub struct Http2PriorityFrame<'a> {
115    frame: Http2Frame<'a>,
116    priority: Http2Priority,
117}
118
119impl<'a> Http2PriorityFrame<'a> {
120    pub(super) fn from_validated(frame: Http2Frame<'a>, priority: Http2Priority) -> Self {
121        Self { frame, priority }
122    }
123
124    /// Parses the first complete PRIORITY frame, enforcing the caller-provided payload maximum.
125    pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
126        Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
127    }
128
129    /// Validates a raw PRIORITY frame's intrinsic layout.
130    pub fn from_frame(frame: Http2Frame<'a>) -> Result<Self, Http2ParseError> {
131        validate_frame(frame, Http2FrameType::PRIORITY)?;
132        validate_exact_payload(frame, 5)?;
133        Ok(Self {
134            priority: Http2Priority::parse(frame.payload()),
135            frame,
136        })
137    }
138
139    /// Returns the validated raw frame.
140    pub const fn frame(&self) -> Http2Frame<'a> {
141        self.frame
142    }
143    /// Returns the exact represented frame bytes.
144    pub fn as_bytes(&self) -> &'a [u8] {
145        self.frame.as_bytes()
146    }
147    /// Returns the frame priority section.
148    pub const fn priority(&self) -> Http2Priority {
149        self.priority
150    }
151}
152
153/// A validated borrowed HTTP/2 RST_STREAM frame.
154#[derive(Clone, Copy, Debug, Eq, PartialEq)]
155pub struct Http2RstStream<'a> {
156    frame: Http2Frame<'a>,
157    error_code: Http2ErrorCode,
158}
159
160impl<'a> Http2RstStream<'a> {
161    pub(super) fn from_validated(frame: Http2Frame<'a>, error_code: Http2ErrorCode) -> Self {
162        Self { frame, error_code }
163    }
164
165    /// Parses the first complete RST_STREAM frame, enforcing the caller-provided payload maximum.
166    pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
167        Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
168    }
169
170    /// Validates a raw RST_STREAM frame's intrinsic layout.
171    pub fn from_frame(frame: Http2Frame<'a>) -> Result<Self, Http2ParseError> {
172        validate_frame(frame, Http2FrameType::RST_STREAM)?;
173        validate_exact_payload(frame, 4)?;
174        let payload = frame.payload();
175        Ok(Self {
176            error_code: Http2ErrorCode::new(u32::from_be_bytes([
177                payload[0], payload[1], payload[2], payload[3],
178            ])),
179            frame,
180        })
181    }
182
183    /// Returns the validated raw frame.
184    pub const fn frame(&self) -> Http2Frame<'a> {
185        self.frame
186    }
187    /// Returns the exact represented frame bytes.
188    pub fn as_bytes(&self) -> &'a [u8] {
189        self.frame.as_bytes()
190    }
191    /// Returns the raw-preserving stream error code.
192    pub const fn error_code(&self) -> Http2ErrorCode {
193        self.error_code
194    }
195}
196
197/// A validated borrowed HTTP/2 PING frame.
198#[derive(Clone, Copy, Debug, Eq, PartialEq)]
199pub struct Http2Ping<'a> {
200    frame: Http2Frame<'a>,
201    opaque_data: &'a [u8; 8],
202}
203
204impl<'a> Http2Ping<'a> {
205    pub(super) fn from_validated(frame: Http2Frame<'a>, opaque_data: &'a [u8; 8]) -> Self {
206        Self { frame, opaque_data }
207    }
208
209    /// Parses the first complete PING frame, enforcing the caller-provided payload maximum.
210    pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
211        Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
212    }
213
214    /// Validates a raw PING frame's intrinsic layout.
215    pub fn from_frame(frame: Http2Frame<'a>) -> Result<Self, Http2ParseError> {
216        validate_type(frame, Http2FrameType::PING)?;
217        validate_zero_stream(frame)?;
218        validate_exact_payload(frame, 8)?;
219        let payload = frame.payload();
220        let opaque_data = payload
221            .try_into()
222            .map_err(|_| Http2ParseError::FrameSizeMismatch {
223                expected: 8,
224                actual: payload.len(),
225            })?;
226        Ok(Self { frame, opaque_data })
227    }
228
229    /// Returns the validated raw frame.
230    pub const fn frame(&self) -> Http2Frame<'a> {
231        self.frame
232    }
233    /// Returns the exact represented frame bytes.
234    pub fn as_bytes(&self) -> &'a [u8] {
235        self.frame.as_bytes()
236    }
237    /// Returns the eight opaque payload bytes.
238    pub const fn opaque_data(&self) -> &'a [u8; 8] {
239        self.opaque_data
240    }
241    /// Returns whether the ACK flag is set.
242    pub fn is_ack(&self) -> bool {
243        self.frame.flags() & 0x1 != 0
244    }
245}
246
247/// A validated borrowed HTTP/2 WINDOW_UPDATE frame.
248#[derive(Clone, Copy, Debug, Eq, PartialEq)]
249pub struct Http2WindowUpdate<'a> {
250    frame: Http2Frame<'a>,
251    increment: Http2WindowIncrement,
252}
253
254impl<'a> Http2WindowUpdate<'a> {
255    pub(super) fn from_validated(frame: Http2Frame<'a>, increment: Http2WindowIncrement) -> Self {
256        Self { frame, increment }
257    }
258
259    /// Parses the first complete WINDOW_UPDATE frame, enforcing the caller-provided payload maximum.
260    pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
261        Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
262    }
263
264    /// Validates a raw WINDOW_UPDATE frame's intrinsic layout.
265    pub fn from_frame(frame: Http2Frame<'a>) -> Result<Self, Http2ParseError> {
266        validate_type(frame, Http2FrameType::WINDOW_UPDATE)?;
267        validate_exact_payload(frame, 4)?;
268        let increment = Http2WindowIncrement::parse(frame.payload());
269        if increment.value() == 0 {
270            return Err(Http2ParseError::ZeroWindowIncrement);
271        }
272        Ok(Self { frame, increment })
273    }
274
275    /// Returns the validated raw frame.
276    pub const fn frame(&self) -> Http2Frame<'a> {
277        self.frame
278    }
279    /// Returns the exact represented frame bytes.
280    pub fn as_bytes(&self) -> &'a [u8] {
281        self.frame.as_bytes()
282    }
283    /// Returns the raw-preserving window increment.
284    pub const fn increment(&self) -> Http2WindowIncrement {
285        self.increment
286    }
287}