h3/error/
internal_error.rs

1//! This module contains the internal error type, which is used to represent errors, which have not yet affected the connection state
2
3use std::error::Error;
4
5use crate::{frame::FrameProtocolError, quic::ConnectionErrorIncoming};
6
7use super::codes::Code;
8use std::fmt::Display;
9
10/// This error type represents an internal error type, which is used
11/// to represent errors, which have not yet affected the connection state
12///
13/// This error type is generated from the error types of h3s submodules or by the modules itself.
14///
15/// This error type is used in functions which handle a http3 connection state
16#[derive(Debug, Clone, Hash)]
17pub struct InternalConnectionError {
18    /// The error code
19    pub(crate) code: Code,
20    /// The error message
21    pub(crate) message: String,
22}
23
24impl InternalConnectionError {
25    /// Create a new internal connection error
26    pub fn new(code: Code, message: String) -> Self {
27        Self { code, message }
28    }
29    /// Creates a new internal connection error from a frame error
30    pub fn got_frame_error(value: FrameProtocolError) -> Self {
31        match value {
32            FrameProtocolError::InvalidStreamId(id) => InternalConnectionError {
33                code: Code::H3_ID_ERROR,
34                message: format!("invalid stream id: {}", id),
35            },
36            FrameProtocolError::InvalidPushId(id) => InternalConnectionError {
37                code: Code::H3_ID_ERROR,
38                message: format!("invalid push id: {}", id),
39            },
40            FrameProtocolError::Settings(error) => InternalConnectionError {
41                // TODO: Check spec which error code to return when a bad settings frame arrives on a stream which is not allowed to have settings
42                //       At the moment, because the Frame is parsed before the stream type is checked, the H3_SETTINGS_ERROR is returned.
43                //       Same for the InvalidStreamId and InvalidPushId
44                    code: Code::H3_SETTINGS_ERROR,
45                    message: error.to_string(),
46            },
47            //= https://www.rfc-editor.org/rfc/rfc9114#section-7.2.8
48            //# These frame
49            //# types MUST NOT be sent, and their receipt MUST be treated as a
50            //# connection error of type H3_FRAME_UNEXPECTED.
51            FrameProtocolError::ForbiddenFrame(number) => InternalConnectionError {
52                    code: Code::H3_FRAME_UNEXPECTED,
53                    message: format!("received a forbidden frame with number {}", number),
54            },
55            //= https://www.rfc-editor.org/rfc/rfc9114#section-7.1
56            //# A frame payload that contains additional bytes
57            //# after the identified fields or a frame payload that terminates before
58            //# the end of the identified fields MUST be treated as a connection
59            //# error of type H3_FRAME_ERROR.
60            FrameProtocolError::InvalidFrameValue | FrameProtocolError::Malformed => InternalConnectionError {
61                code: Code::H3_FRAME_ERROR,
62                message: "frame payload that contains additional bytes after the identified fields or a frame payload that terminates before the end of the identified fields".to_string(),
63            },
64            }
65    }
66}
67
68/// Error type which combines different internal errors
69#[derive(Debug, Clone)]
70pub enum ErrorOrigin {
71    /// Internal Error
72    Internal(InternalConnectionError),
73    /// Quick layer error
74    Quic(ConnectionErrorIncoming),
75}
76
77impl Display for ErrorOrigin {
78    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79        match self {
80            ErrorOrigin::Internal(error) => write!(f, "Internal Error: {}", error.message),
81            ErrorOrigin::Quic(error) => write!(f, "Quic Error: {:?}", error),
82        }
83    }
84}
85
86impl Error for ErrorOrigin {}
87
88impl From<InternalConnectionError> for ErrorOrigin {
89    fn from(error: InternalConnectionError) -> Self {
90        ErrorOrigin::Internal(error)
91    }
92}
93
94impl From<ConnectionErrorIncoming> for ErrorOrigin {
95    fn from(error: ConnectionErrorIncoming) -> Self {
96        ErrorOrigin::Quic(error)
97    }
98}