Skip to main content

ringline_h2/
error.rs

1/// HTTP/2 error codes (RFC 7540 Section 7).
2#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3#[repr(u32)]
4pub enum ErrorCode {
5    NoError = 0x0,
6    ProtocolError = 0x1,
7    InternalError = 0x2,
8    FlowControlError = 0x3,
9    SettingsTimeout = 0x4,
10    StreamClosed = 0x5,
11    FrameSizeError = 0x6,
12    RefusedStream = 0x7,
13    Cancel = 0x8,
14    CompressionError = 0x9,
15    ConnectError = 0xa,
16    EnhanceYourCalm = 0xb,
17    InadequateSecurity = 0xc,
18    Http11Required = 0xd,
19}
20
21impl ErrorCode {
22    pub fn from_u32(v: u32) -> Self {
23        match v {
24            0x0 => Self::NoError,
25            0x1 => Self::ProtocolError,
26            0x2 => Self::InternalError,
27            0x3 => Self::FlowControlError,
28            0x4 => Self::SettingsTimeout,
29            0x5 => Self::StreamClosed,
30            0x6 => Self::FrameSizeError,
31            0x7 => Self::RefusedStream,
32            0x8 => Self::Cancel,
33            0x9 => Self::CompressionError,
34            0xa => Self::ConnectError,
35            0xb => Self::EnhanceYourCalm,
36            0xc => Self::InadequateSecurity,
37            0xd => Self::Http11Required,
38            _ => Self::InternalError,
39        }
40    }
41}
42
43/// Errors produced by the HTTP/2 framing layer.
44#[derive(Debug)]
45pub enum H2Error {
46    /// Frame decoding error (truncated, invalid payload, etc.).
47    FrameError,
48    /// Received a frame that violates the protocol.
49    ProtocolError(String),
50    /// HPACK header compression/decompression error.
51    CompressionError,
52    /// Flow control violation.
53    FlowControlError,
54    /// Frame size exceeds the maximum allowed.
55    FrameSizeError,
56    /// Connection-level error with an error code.
57    ConnectionError(ErrorCode),
58    /// Stream-level error with an error code.
59    StreamError(u32, ErrorCode),
60    /// HTTP message semantic error (malformed pseudo-headers, forbidden
61    /// connection-specific headers, uppercase header names, etc. —
62    /// RFC 9113 §8.1, §8.2).
63    MessageError(String),
64    /// A resource cap configured by `Settings` (`max_header_list_size`,
65    /// `max_recv_buf`, etc.) or by the H2 implementation's hard ceilings
66    /// (HPACK literal count, dynamic table size) was exceeded.
67    MaxSizeExceeded(String),
68    /// Internal error with a description.
69    Internal(String),
70}
71
72impl H2Error {
73    /// The connection-level error code that this error should be reported as
74    /// in a GOAWAY frame (RFC 7540 §7).
75    pub fn code(&self) -> ErrorCode {
76        match self {
77            Self::FrameError | Self::ProtocolError(_) | Self::MessageError(_) => {
78                ErrorCode::ProtocolError
79            }
80            Self::CompressionError => ErrorCode::CompressionError,
81            Self::FlowControlError => ErrorCode::FlowControlError,
82            Self::FrameSizeError => ErrorCode::FrameSizeError,
83            Self::ConnectionError(code) => *code,
84            Self::StreamError(_, code) => *code,
85            Self::MaxSizeExceeded(_) => ErrorCode::EnhanceYourCalm,
86            Self::Internal(_) => ErrorCode::InternalError,
87        }
88    }
89}
90
91impl std::fmt::Display for H2Error {
92    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93        match self {
94            Self::FrameError => write!(f, "frame error"),
95            Self::ProtocolError(s) => write!(f, "protocol error: {s}"),
96            Self::CompressionError => write!(f, "HPACK compression error"),
97            Self::FlowControlError => write!(f, "flow control error"),
98            Self::FrameSizeError => write!(f, "frame size error"),
99            Self::ConnectionError(code) => write!(f, "connection error: {code:?}"),
100            Self::StreamError(id, code) => write!(f, "stream {id} error: {code:?}"),
101            Self::MessageError(s) => write!(f, "message error: {s}"),
102            Self::MaxSizeExceeded(s) => write!(f, "max size exceeded: {s}"),
103            Self::Internal(s) => write!(f, "internal: {s}"),
104        }
105    }
106}
107
108impl std::error::Error for H2Error {}