1use core::fmt;
4
5use super::super::codepoints::{Http3ErrorCode, Http3FrameType};
6use super::super::enums::message::Http3HeadersKind;
7use super::super::frame::Http3Frame;
8use super::super::frame::Http3FramePayloadParseError;
9use super::super::frame::{Http3Data, Http3Headers, Http3PushPromise};
10use super::super::headers::Http3DecodedHeaderSection;
11
12#[derive(Clone, Copy, Debug, Eq, PartialEq)]
14pub enum Http3MessageStreamKind {
15 Request,
17 Response,
19 Push,
21}
22
23#[derive(Clone, Copy, Debug, Eq, PartialEq)]
25pub enum Http3MessagePosition {
26 BeforeHeaders,
28 BeforeFinalResponse,
30 Content,
32 Trailers,
34}
35
36#[derive(Clone, Copy, Debug, Eq, PartialEq)]
38pub enum Http3MessageStreamError {
39 UnexpectedFrame {
41 frame_type: Http3FrameType,
43 position: Http3MessagePosition,
45 },
46 FramePayload {
48 frame_type: Http3FrameType,
50 error: Http3FramePayloadParseError,
52 },
53 InvalidHeaderSection {
55 stream_kind: Http3MessageStreamKind,
57 position: Http3MessagePosition,
59 section_kind: Http3HeadersKind,
61 },
62 IncompleteMessage {
64 stream_kind: Http3MessageStreamKind,
66 position: Http3MessagePosition,
68 },
69}
70
71impl Http3MessageStreamError {
72 pub const fn error_code(self) -> Http3ErrorCode {
74 match self {
75 Self::UnexpectedFrame { .. } => Http3ErrorCode::FRAME_UNEXPECTED,
76 Self::FramePayload { .. } => Http3ErrorCode::FRAME_ERROR,
77 Self::InvalidHeaderSection { .. } => Http3ErrorCode::MESSAGE_ERROR,
78 Self::IncompleteMessage {
79 stream_kind: Http3MessageStreamKind::Request,
80 ..
81 } => Http3ErrorCode::REQUEST_INCOMPLETE,
82 Self::IncompleteMessage {
83 stream_kind: Http3MessageStreamKind::Response | Http3MessageStreamKind::Push,
84 ..
85 } => Http3ErrorCode::MESSAGE_ERROR,
86 }
87 }
88}
89
90impl fmt::Display for Http3MessageStreamError {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 match self {
93 Self::UnexpectedFrame {
94 frame_type,
95 position,
96 } => write!(
97 f,
98 "HTTP/3 frame type {} is unexpected at message position {position:?}",
99 frame_type.value()
100 ),
101 Self::FramePayload { frame_type, error } => write!(
102 f,
103 "HTTP/3 message frame type {} payload: {error}",
104 frame_type.value()
105 ),
106 Self::InvalidHeaderSection {
107 stream_kind,
108 position,
109 section_kind,
110 } => write!(
111 f,
112 "HTTP/3 {section_kind:?} header section is invalid for {stream_kind:?} at message position {position:?}"
113 ),
114 Self::IncompleteMessage {
115 stream_kind,
116 position,
117 } => write!(
118 f,
119 "HTTP/3 {stream_kind:?} message is incomplete at message position {position:?}"
120 ),
121 }
122 }
123}
124
125impl core::error::Error for Http3MessageStreamError {
126 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
127 match self {
128 Self::FramePayload { error, .. } => Some(error),
129 Self::UnexpectedFrame { .. }
130 | Self::InvalidHeaderSection { .. }
131 | Self::IncompleteMessage { .. } => None,
132 }
133 }
134}
135
136#[derive(Clone, Copy, Debug, Eq, PartialEq)]
138pub struct Http3MessageStreamState {
139 kind: Http3MessageStreamKind,
140 position: Http3MessagePosition,
141}
142
143impl Http3MessageStreamState {
144 pub const fn new(kind: Http3MessageStreamKind) -> Self {
146 let position = match kind {
147 Http3MessageStreamKind::Request => Http3MessagePosition::BeforeHeaders,
148 Http3MessageStreamKind::Response | Http3MessageStreamKind::Push => {
149 Http3MessagePosition::BeforeFinalResponse
150 }
151 };
152 Self { kind, position }
153 }
154
155 pub const fn kind(self) -> Http3MessageStreamKind {
157 self.kind
158 }
159
160 pub const fn position(self) -> Http3MessagePosition {
162 self.position
163 }
164
165 pub fn receive<'state, 'wire>(
170 &'state mut self,
171 frame: Http3Frame<'wire>,
172 ) -> Result<Http3MessageFrame<'state, 'wire>, Http3MessageStreamError> {
173 let frame_type = frame.frame_type();
174 let position = self.position;
175
176 match frame_type {
177 Http3FrameType::HEADERS => {
178 if position == Http3MessagePosition::Trailers {
179 return Err(unexpected_frame(frame_type, position));
180 }
181 let headers = Http3Headers::from_frame(frame)
182 .map_err(|error| frame_payload_error(frame_type, error))?;
183 Ok(Http3MessageFrame::Headers(Http3PendingHeaders {
184 state: self,
185 headers,
186 }))
187 }
188 Http3FrameType::DATA => {
189 if position != Http3MessagePosition::Content {
190 return Err(unexpected_frame(frame_type, position));
191 }
192 Http3Data::from_frame(frame)
193 .map(Http3MessageFrame::Data)
194 .map_err(|error| frame_payload_error(frame_type, error))
195 }
196 Http3FrameType::PUSH_PROMISE => {
197 if self.kind != Http3MessageStreamKind::Response {
198 return Err(unexpected_frame(frame_type, position));
199 }
200 Http3PushPromise::from_frame(frame)
201 .map(Http3MessageFrame::PushPromise)
202 .map_err(|error| frame_payload_error(frame_type, error))
203 }
204 Http3FrameType::CANCEL_PUSH
205 | Http3FrameType::SETTINGS
206 | Http3FrameType::GOAWAY
207 | Http3FrameType::MAX_PUSH_ID => Err(unexpected_frame(frame_type, position)),
208 frame_type if is_http2_reserved_frame_type(frame_type) => {
209 Err(unexpected_frame(frame_type, position))
210 }
211 _ => Ok(Http3MessageFrame::Unknown(frame)),
212 }
213 }
214
215 pub const fn finish(&self) -> Result<(), Http3MessageStreamError> {
217 match self.position {
218 Http3MessagePosition::Content | Http3MessagePosition::Trailers => Ok(()),
219 Http3MessagePosition::BeforeHeaders | Http3MessagePosition::BeforeFinalResponse => {
220 Err(Http3MessageStreamError::IncompleteMessage {
221 stream_kind: self.kind,
222 position: self.position,
223 })
224 }
225 }
226 }
227}
228
229#[derive(Debug)]
231pub enum Http3MessageFrame<'state, 'wire> {
232 Data(Http3Data<'wire>),
234 Headers(Http3PendingHeaders<'state, 'wire>),
236 PushPromise(Http3PushPromise<'wire>),
238 Unknown(Http3Frame<'wire>),
240}
241
242#[derive(Debug)]
244pub struct Http3PendingHeaders<'state, 'wire> {
245 state: &'state mut Http3MessageStreamState,
246 headers: Http3Headers<'wire>,
247}
248
249impl<'state, 'wire> Http3PendingHeaders<'state, 'wire> {
250 pub const fn headers(&self) -> Http3Headers<'wire> {
252 self.headers
253 }
254
255 pub fn accept(
260 self,
261 section: &Http3DecodedHeaderSection<'_>,
262 ) -> Result<Http3Headers<'wire>, Http3MessageStreamError> {
263 let section_kind = section.kind();
264 let next_position = next_position(self.state.kind, self.state.position, section_kind)?;
265 self.state.position = next_position;
266 Ok(self.headers)
267 }
268}
269
270const fn next_position(
271 stream_kind: Http3MessageStreamKind,
272 position: Http3MessagePosition,
273 section_kind: Http3HeadersKind,
274) -> Result<Http3MessagePosition, Http3MessageStreamError> {
275 match (stream_kind, position, section_kind) {
276 (
277 Http3MessageStreamKind::Request,
278 Http3MessagePosition::BeforeHeaders,
279 Http3HeadersKind::Request,
280 ) => Ok(Http3MessagePosition::Content),
281 (
282 Http3MessageStreamKind::Request,
283 Http3MessagePosition::Content,
284 Http3HeadersKind::Trailers,
285 ) => Ok(Http3MessagePosition::Trailers),
286 (
287 Http3MessageStreamKind::Response | Http3MessageStreamKind::Push,
288 Http3MessagePosition::BeforeFinalResponse,
289 Http3HeadersKind::InformationalResponse,
290 ) => Ok(Http3MessagePosition::BeforeFinalResponse),
291 (
292 Http3MessageStreamKind::Response | Http3MessageStreamKind::Push,
293 Http3MessagePosition::BeforeFinalResponse,
294 Http3HeadersKind::FinalResponse,
295 ) => Ok(Http3MessagePosition::Content),
296 (
297 Http3MessageStreamKind::Response | Http3MessageStreamKind::Push,
298 Http3MessagePosition::Content,
299 Http3HeadersKind::Trailers,
300 ) => Ok(Http3MessagePosition::Trailers),
301 _ => Err(Http3MessageStreamError::InvalidHeaderSection {
302 stream_kind,
303 position,
304 section_kind,
305 }),
306 }
307}
308
309const fn unexpected_frame(
310 frame_type: Http3FrameType,
311 position: Http3MessagePosition,
312) -> Http3MessageStreamError {
313 Http3MessageStreamError::UnexpectedFrame {
314 frame_type,
315 position,
316 }
317}
318
319const fn frame_payload_error(
320 frame_type: Http3FrameType,
321 error: Http3FramePayloadParseError,
322) -> Http3MessageStreamError {
323 Http3MessageStreamError::FramePayload { frame_type, error }
324}
325
326const fn is_http2_reserved_frame_type(frame_type: Http3FrameType) -> bool {
327 matches!(frame_type.value(), 0x02 | 0x06 | 0x08 | 0x09)
328}