View Javadoc
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 }