1use super::{codes::Code, internal_error::InternalConnectionError};
3use crate::quic::{ConnectionErrorIncoming, StreamId};
4
5#[derive(Debug, Clone)]
12#[non_exhaustive]
13pub enum ConnectionError {
14 #[cfg_attr(not(feature = "unstable"), non_exhaustive)]
16 Local {
17 error: LocalError,
19 },
20 #[cfg_attr(not(feature = "unstable"), non_exhaustive)]
23 Remote(ConnectionErrorIncoming),
24 #[cfg_attr(not(feature = "unstable"), non_exhaustive)]
26 Timeout,
27}
28
29impl ConnectionError {
30 pub fn is_h3_no_error(&self) -> bool {
32 match self {
33 ConnectionError::Local {
34 error:
35 LocalError::Application {
36 code: Code::H3_NO_ERROR,
37 ..
38 },
39 } => true,
40 ConnectionError::Remote(ConnectionErrorIncoming::ApplicationClose { error_code })
41 if *error_code == Code::H3_NO_ERROR.value() =>
42 {
43 true
44 }
45 _ => false,
46 }
47 }
48}
49
50#[derive(Debug, Clone, Hash)]
52#[non_exhaustive]
53pub enum LocalError {
54 #[non_exhaustive]
55 Application {
57 code: Code,
59 reason: String,
61 },
62 #[non_exhaustive]
63 Closing,
65}
66
67#[derive(Debug)]
69#[non_exhaustive]
70pub enum StreamError {
71 #[cfg_attr(not(feature = "unstable"), non_exhaustive)]
74 InvalidStreamState {
75 reason: Box<str>,
77 },
78 #[cfg_attr(not(feature = "unstable"), non_exhaustive)]
81 InvalidRequest {
82 reason: Box<str>,
84 },
85 #[cfg_attr(not(feature = "unstable"), non_exhaustive)]
87 GoawayRejected {
88 stream_id: StreamId,
90 boundary: StreamId,
92 },
93 #[cfg_attr(not(feature = "unstable"), non_exhaustive)]
95 StreamError {
96 code: Code,
98 reason: String,
100 },
101 #[cfg_attr(not(feature = "unstable"), non_exhaustive)]
105 RemoteTerminate {
106 code: Code,
108 },
109 #[cfg_attr(not(feature = "unstable"), non_exhaustive)]
111 ConnectionError(ConnectionError),
112 #[cfg_attr(not(feature = "unstable"), non_exhaustive)]
119 HeaderTooBig {
120 actual_size: u64,
122 max_size: u64,
124 },
125 #[cfg_attr(not(feature = "unstable"), non_exhaustive)]
130 ConnectionClosing,
131 #[cfg_attr(not(feature = "unstable"), non_exhaustive)]
133 Undefined(Box<dyn std::error::Error + Send + Sync>),
134}
135
136impl StreamError {
137 pub fn is_h3_no_error(&self) -> bool {
139 match self {
140 StreamError::StreamError {
141 code: Code::H3_NO_ERROR,
142 ..
143 }
144 | StreamError::RemoteTerminate {
145 code: Code::H3_NO_ERROR,
146 } => true,
147 StreamError::ConnectionError(conn_error) => conn_error.is_h3_no_error(),
148 _ => false,
149 }
150 }
151}
152
153impl From<InternalConnectionError> for LocalError {
154 fn from(err: InternalConnectionError) -> Self {
155 LocalError::Application {
156 code: err.code,
157 reason: err.message,
158 }
159 }
160}
161
162impl std::fmt::Display for ConnectionError {
163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164 match self {
165 ConnectionError::Local { error } => write!(f, "Local error: {:?}", error),
166 ConnectionError::Remote(err) => write!(f, "Remote error: {}", err),
167 ConnectionError::Timeout => write!(f, "Timeout"),
168 }
169 }
170}
171
172impl std::error::Error for ConnectionError {}
173
174impl std::fmt::Display for StreamError {
175 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
176 match self {
177 StreamError::InvalidStreamState { reason } => {
178 write!(f, "Invalid stream state: {reason}")
179 }
180 StreamError::InvalidRequest { reason } => write!(f, "Invalid request: {reason}"),
181 StreamError::GoawayRejected {
182 stream_id,
183 boundary,
184 } => {
185 write!(
186 f,
187 "Request {stream_id} rejected by GOAWAY boundary {boundary}"
188 )
189 }
190 StreamError::StreamError { code, reason } => {
191 write!(f, "Stream error: {:?} - {}", code, reason)
192 }
193 StreamError::ConnectionError(err) => write!(f, "Connection error: {}", err),
194 StreamError::RemoteTerminate { code } => write!(f, "Remote reset: {}", code),
195 StreamError::HeaderTooBig {
196 actual_size,
197 max_size,
198 } => write!(
199 f,
200 "Header too big: actual size: {}, max size: {}",
201 actual_size, max_size
202 ),
203 StreamError::Undefined(err) => write!(f, "Undefined error: {}", err),
204 StreamError::ConnectionClosing => write!(f, "Connection is closing"),
205 }
206 }
207}
208
209impl std::error::Error for StreamError {}