1 /*
2 * Copyright 2024 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 package io.netty.handler.codec.quic;
17
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.Objects;
21
22 /**
23 * <a href="https://www.rfc-editor.org/rfc/rfc9000.html#name-transport-error-codes">
24 * RFC9000 20.1. Transport Error Codes</a>
25 */
26 public final class QuicTransportError {
27
28 /**
29 * An endpoint uses this with CONNECTION_CLOSE to signal that the connection is being closed abruptly in the
30 * absence of any error.
31 */
32 public static final QuicTransportError NO_ERROR =
33 new QuicTransportError(0x0, "NO_ERROR");
34
35 /**
36 * The endpoint encountered an internal error and cannot continue with the connection.
37 */
38 public static final QuicTransportError INTERNAL_ERROR =
39 new QuicTransportError(0x1, "INTERNAL_ERROR");
40
41 /**
42 * The server refused to accept a new connection.
43 */
44 public static final QuicTransportError CONNECTION_REFUSED =
45 new QuicTransportError(0x2, "CONNECTION_REFUSED");
46
47 /**
48 * An endpoint received more data than it permitted in its advertised data limits.
49 */
50 public static final QuicTransportError FLOW_CONTROL_ERROR =
51 new QuicTransportError(0x3, "FLOW_CONTROL_ERROR");
52
53 /**
54 * An endpoint received a frame for a stream identifier that exceeded its advertised stream limit for the
55 * corresponding stream type.
56 */
57 public static final QuicTransportError STREAM_LIMIT_ERROR =
58 new QuicTransportError(0x4, "STREAM_LIMIT_ERROR");
59
60 /**
61 * An endpoint received a frame for a stream that was not in a state that permitted that frame.
62 */
63 public static final QuicTransportError STREAM_STATE_ERROR =
64 new QuicTransportError(0x5, "STREAM_STATE_ERROR");
65
66 /**
67 * (1) An endpoint received a STREAM frame containing data that exceeded the previously established final size,
68 * (2) an endpoint received a STREAM frame or a RESET_STREAM frame containing a final size that was lower than
69 * the size of stream data that was already received, or (3) an endpoint received a STREAM frame or a RESET_STREAM
70 * frame containing a different final size to the one already established.
71 */
72 public static final QuicTransportError FINAL_SIZE_ERROR =
73 new QuicTransportError(0x6, "FINAL_SIZE_ERROR");
74
75 /**
76 * An endpoint received a frame that was badly formatted -- for instance, a frame of an unknown type or an ACK
77 * frame that has more acknowledgment ranges than the remainder of the packet could carry.
78 */
79 public static final QuicTransportError FRAME_ENCODING_ERROR =
80 new QuicTransportError(0x7, "FRAME_ENCODING_ERROR");
81
82 /**
83 * An endpoint received transport parameters that were badly formatted, included an invalid value, omitted a
84 * mandatory transport parameter, included a forbidden transport parameter, or were otherwise in error.
85 */
86 public static final QuicTransportError TRANSPORT_PARAMETER_ERROR =
87 new QuicTransportError(0x8, "TRANSPORT_PARAMETER_ERROR");
88
89 /**
90 * The number of connection IDs provided by the peer exceeds the advertised active_connection_id_limit.
91 */
92 public static final QuicTransportError CONNECTION_ID_LIMIT_ERROR =
93 new QuicTransportError(0x9, "CONNECTION_ID_LIMIT_ERROR");
94
95 /**
96 * An endpoint detected an error with protocol compliance that was not covered by more specific error codes.
97 */
98 public static final QuicTransportError PROTOCOL_VIOLATION =
99 new QuicTransportError(0xa, "PROTOCOL_VIOLATION");
100
101 /**
102 * A server received a client Initial that contained an invalid Token field.
103 */
104 public static final QuicTransportError INVALID_TOKEN =
105 new QuicTransportError(0xb, "INVALID_TOKEN");
106
107 /**
108 * The application or application protocol caused the connection to be closed.
109 */
110 public static final QuicTransportError APPLICATION_ERROR =
111 new QuicTransportError(0xc, "APPLICATION_ERROR");
112
113 /**
114 * An endpoint has received more data in CRYPTO frames than it can buffer.
115 */
116 public static final QuicTransportError CRYPTO_BUFFER_EXCEEDED =
117 new QuicTransportError(0xd, "CRYPTO_BUFFER_EXCEEDED");
118
119 /**
120 * An endpoint detected errors in performing key updates.
121 */
122 public static final QuicTransportError KEY_UPDATE_ERROR =
123 new QuicTransportError(0xe, "KEY_UPDATE_ERROR");
124
125 /**
126 * An endpoint has reached the confidentiality or integrity limit for the AEAD algorithm used by the given
127 * connection.
128 */
129 public static final QuicTransportError AEAD_LIMIT_REACHED =
130 new QuicTransportError(0xf, "AEAD_LIMIT_REACHED");
131
132 /**
133 * n endpoint has determined that the network path is incapable of supporting QUIC. An endpoint is unlikely to
134 * receive a CONNECTION_CLOSE frame carrying this code except when the path does not support a large enough MTU.
135 */
136 public static final QuicTransportError NO_VIABLE_PATH =
137 new QuicTransportError(0x10, "NO_VIABLE_PATH");
138
139 private static final QuicTransportError[] INT_TO_ENUM_MAP;
140 static {
141 List<QuicTransportError> errorList = new ArrayList<>();
142 errorList.add(NO_ERROR);
143 errorList.add(INTERNAL_ERROR);
144 errorList.add(CONNECTION_REFUSED);
145 errorList.add(FLOW_CONTROL_ERROR);
146 errorList.add(STREAM_LIMIT_ERROR);
147 errorList.add(STREAM_STATE_ERROR);
148 errorList.add(FINAL_SIZE_ERROR);
149 errorList.add(FRAME_ENCODING_ERROR);
150 errorList.add(TRANSPORT_PARAMETER_ERROR);
151 errorList.add(CONNECTION_ID_LIMIT_ERROR);
152 errorList.add(PROTOCOL_VIOLATION);
153 errorList.add(INVALID_TOKEN);
154 errorList.add(APPLICATION_ERROR);
155 errorList.add(CRYPTO_BUFFER_EXCEEDED);
156 errorList.add(KEY_UPDATE_ERROR);
157 errorList.add(AEAD_LIMIT_REACHED);
158 errorList.add(NO_VIABLE_PATH);
159
160 // Crypto errors can have various codes.
161 //
162 // See https://www.rfc-editor.org/rfc/rfc9000.html#name-transport-error-codes:
163 // The cryptographic handshake failed. A range of 256 values is reserved for carrying error codes specific to
164 // the cryptographic handshake that is used. Codes for errors occurring when TLS is used for the cryptographic
165 // handshake are described in Section 4.8 of [QUIC-TLS].
166 for (int i = 0x0100; i <= 0x01ff; i++) {
167 errorList.add(new QuicTransportError(i, "CRYPTO_ERROR"));
168 }
169 INT_TO_ENUM_MAP = errorList.toArray(new QuicTransportError[0]);
170 }
171 private final long code;
172 private final String name;
173
174 private QuicTransportError(long code, String name) {
175 this.code = code;
176 this.name = name;
177 }
178
179 /**
180 * Returns true if this is a {@code CRYPTO_ERROR}.
181 */
182 public boolean isCryptoError() {
183 return code >= 0x0100 && code <= 0x01ff;
184 }
185
186 /**
187 * Returns the name of the error as defined by RFC9000.
188 *
189 * @return name
190 */
191 public String name() {
192 return name;
193 }
194
195 /**
196 * Returns the code for this error used on the wire as defined by RFC9000.
197 */
198 public long code() {
199 return code;
200 }
201
202 public static QuicTransportError valueOf(long value) {
203 if (value > 17) {
204 value -= 0x0100;
205 }
206
207 if (value < 0 || value >= INT_TO_ENUM_MAP.length) {
208 throw new IllegalArgumentException("Unknown error code value: " + value);
209 }
210 return INT_TO_ENUM_MAP[(int) value];
211 }
212
213 @Override
214 public boolean equals(Object o) {
215 if (this == o) {
216 return true;
217 }
218 if (o == null || getClass() != o.getClass()) {
219 return false;
220 }
221 QuicTransportError quicError = (QuicTransportError) o;
222 return code == quicError.code;
223 }
224
225 @Override
226 public int hashCode() {
227 return Objects.hash(code);
228 }
229
230 @Override
231 public String toString() {
232 return "QuicTransportError{" +
233 "code=" + code +
234 ", name='" + name + '\'' +
235 '}';
236 }
237 }