quiche/
error.rs1// Copyright (C) 2018-2019, Cloudflare, Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// * Redistributions in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27/// A specialized [`Result`] type for quiche operations.
28///
29/// This type is used throughout quiche's public API for any operation that
30/// can produce an error.
31///
32/// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html
33pub type Result<T> = std::result::Result<T, Error>;
34
35/// A QUIC error.
36#[derive(Clone, Copy, Debug, PartialEq, Eq)]
37pub enum Error {
38 /// There is no more work to do.
39 Done,
40
41 /// The provided buffer is too short.
42 BufferTooShort,
43
44 /// The provided packet cannot be parsed because its version is unknown.
45 UnknownVersion,
46
47 /// The provided packet cannot be parsed because it contains an invalid
48 /// frame.
49 InvalidFrame,
50
51 /// The provided packet cannot be parsed.
52 InvalidPacket,
53
54 /// The operation cannot be completed because the connection is in an
55 /// invalid state.
56 InvalidState,
57
58 /// The operation cannot be completed because the stream is in an
59 /// invalid state.
60 ///
61 /// The stream ID is provided as associated data.
62 InvalidStreamState(u64),
63
64 /// The peer's transport params cannot be parsed.
65 InvalidTransportParam,
66
67 /// A cryptographic operation failed.
68 CryptoFail,
69
70 /// The TLS handshake failed.
71 TlsFail,
72
73 /// The peer violated the local flow control limits.
74 FlowControl,
75
76 /// The peer violated the local stream limits.
77 StreamLimit,
78
79 /// The specified stream was stopped by the peer.
80 ///
81 /// The error code sent as part of the `STOP_SENDING` frame is provided as
82 /// associated data.
83 StreamStopped(u64),
84
85 /// The specified stream was reset by the peer.
86 ///
87 /// The error code sent as part of the `RESET_STREAM` frame is provided as
88 /// associated data.
89 StreamReset(u64),
90
91 /// The received data exceeds the stream's final size.
92 FinalSize,
93
94 /// Error in congestion control.
95 CongestionControl,
96
97 /// Too many identifiers were provided.
98 IdLimit,
99
100 /// Not enough available identifiers.
101 OutOfIdentifiers,
102
103 /// Error in key update.
104 KeyUpdate,
105
106 /// The peer sent more data in CRYPTO frames than we can buffer.
107 CryptoBufferExceeded,
108
109 /// The peer sent an ACK frame with an invalid range.
110 InvalidAckRange,
111
112 /// The peer send an ACK frame for a skipped packet used for Optimistic ACK
113 /// mitigation.
114 OptimisticAckDetected,
115
116 /// An invalid DCID was used when connecting to a remote peer.
117 InvalidDcidInitialization,
118}
119
120/// QUIC error codes sent on the wire.
121///
122/// As defined in [RFC9000](https://www.rfc-editor.org/rfc/rfc9000.html#name-error-codes).
123#[derive(Copy, Clone, Debug, Eq, PartialEq)]
124pub enum WireErrorCode {
125 /// An endpoint uses this with CONNECTION_CLOSE to signal that the
126 /// connection is being closed abruptly in the absence of any error.
127 NoError = 0x0,
128 /// The endpoint encountered an internal error and cannot continue with the
129 /// connection.
130 InternalError = 0x1,
131 /// The server refused to accept a new connection.
132 ConnectionRefused = 0x2,
133 /// An endpoint received more data than it permitted in its advertised data
134 /// limits; see Section 4.
135 FlowControlError = 0x3,
136 /// An endpoint received a frame for a stream identifier that exceeded its
137 /// advertised stream limit for the corresponding stream type.
138 StreamLimitError = 0x4,
139 /// An endpoint received a frame for a stream that was not in a state that
140 /// permitted that frame.
141 StreamStateError = 0x5,
142 /// (1) An endpoint received a STREAM frame containing data that exceeded
143 /// the previously established final size, (2) an endpoint received a
144 /// STREAM frame or a RESET_STREAM frame containing a final size that
145 /// was lower than the size of stream data that was already received, or
146 /// (3) an endpoint received a STREAM frame or a RESET_STREAM frame
147 /// containing a different final size to the one already established.
148 FinalSizeError = 0x6,
149 /// An endpoint received a frame that was badly formatted -- for instance, a
150 /// frame of an unknown type or an ACK frame that has more
151 /// acknowledgment ranges than the remainder of the packet could carry.
152 FrameEncodingError = 0x7,
153 /// An endpoint received transport parameters that were badly formatted,
154 /// included an invalid value, omitted a mandatory transport parameter,
155 /// included a forbidden transport parameter, or were otherwise in
156 /// error.
157 TransportParameterError = 0x8,
158 /// The number of connection IDs provided by the peer exceeds the advertised
159 /// active_connection_id_limit.
160 ConnectionIdLimitError = 0x9,
161 /// An endpoint detected an error with protocol compliance that was not
162 /// covered by more specific error codes.
163 ProtocolViolation = 0xa,
164 /// A server received a client Initial that contained an invalid Token
165 /// field.
166 InvalidToken = 0xb,
167 /// The application or application protocol caused the connection to be
168 /// closed.
169 ApplicationError = 0xc,
170 /// An endpoint has received more data in CRYPTO frames than it can buffer.
171 CryptoBufferExceeded = 0xd,
172 /// An endpoint detected errors in performing key updates.
173 KeyUpdateError = 0xe,
174 /// An endpoint has reached the confidentiality or integrity limit for the
175 /// AEAD algorithm used by the given connection.
176 AeadLimitReached = 0xf,
177 /// An endpoint has determined that the network path is incapable of
178 /// supporting QUIC. An endpoint is unlikely to receive a
179 /// CONNECTION_CLOSE frame carrying this code except when the path does
180 /// not support a large enough MTU.
181 NoViablePath = 0x10,
182}
183
184impl Error {
185 pub(crate) fn to_wire(self) -> u64 {
186 match self {
187 Error::Done => WireErrorCode::NoError as u64,
188 Error::InvalidFrame => WireErrorCode::FrameEncodingError as u64,
189 Error::InvalidStreamState(..) =>
190 WireErrorCode::StreamStateError as u64,
191 Error::InvalidTransportParam =>
192 WireErrorCode::TransportParameterError as u64,
193 Error::FlowControl => WireErrorCode::FlowControlError as u64,
194 Error::StreamLimit => WireErrorCode::StreamLimitError as u64,
195 Error::IdLimit => WireErrorCode::ConnectionIdLimitError as u64,
196 Error::FinalSize => WireErrorCode::FinalSizeError as u64,
197 Error::CryptoBufferExceeded =>
198 WireErrorCode::CryptoBufferExceeded as u64,
199 Error::KeyUpdate => WireErrorCode::KeyUpdateError as u64,
200 _ => WireErrorCode::ProtocolViolation as u64,
201 }
202 }
203
204 #[cfg(feature = "ffi")]
205 pub(crate) fn to_c(self) -> libc::ssize_t {
206 match self {
207 Error::Done => -1,
208 Error::BufferTooShort => -2,
209 Error::UnknownVersion => -3,
210 Error::InvalidFrame => -4,
211 Error::InvalidPacket => -5,
212 Error::InvalidState => -6,
213 Error::InvalidStreamState(_) => -7,
214 Error::InvalidTransportParam => -8,
215 Error::CryptoFail => -9,
216 Error::TlsFail => -10,
217 Error::FlowControl => -11,
218 Error::StreamLimit => -12,
219 Error::FinalSize => -13,
220 Error::CongestionControl => -14,
221 Error::StreamStopped { .. } => -15,
222 Error::StreamReset { .. } => -16,
223 Error::IdLimit => -17,
224 Error::OutOfIdentifiers => -18,
225 Error::KeyUpdate => -19,
226 Error::CryptoBufferExceeded => -20,
227 Error::InvalidAckRange => -21,
228 Error::OptimisticAckDetected => -22,
229 Error::InvalidDcidInitialization => -23,
230 }
231 }
232}
233
234impl std::fmt::Display for Error {
235 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
236 write!(f, "{self:?}")
237 }
238}
239
240impl std::error::Error for Error {
241 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
242 None
243 }
244}
245
246impl From<octets::BufferTooShortError> for Error {
247 fn from(_err: octets::BufferTooShortError) -> Self {
248 Error::BufferTooShort
249 }
250}
251
252/// Represents information carried by `CONNECTION_CLOSE` frames.
253#[derive(Clone, Debug, PartialEq, Eq)]
254pub struct ConnectionError {
255 /// Whether the error came from the application or the transport layer.
256 pub is_app: bool,
257
258 /// The error code carried by the `CONNECTION_CLOSE` frame.
259 pub error_code: u64,
260
261 /// The reason carried by the `CONNECTION_CLOSE` frame.
262 pub reason: Vec<u8>,
263}