forked from nodejs/node
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdata.h
More file actions
311 lines (267 loc) Β· 13.3 KB
/
data.h
File metadata and controls
311 lines (267 loc) Β· 13.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
#pragma once
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#include <env.h>
#include <memory_tracker.h>
#include <nghttp3/nghttp3.h>
#include <ngtcp2/ngtcp2.h>
#include <node_internals.h>
#include <node_realm.h>
#include <node_sockaddr.h>
#include <v8.h>
#include <concepts>
#include <string>
#include "defs.h"
namespace node::quic {
template <typename T>
concept OneByteType = sizeof(T) == 1;
struct Path final : public ngtcp2_path {
explicit Path(const SocketAddress& local, const SocketAddress& remote);
Path(Path&& other) noexcept = default;
Path& operator=(Path&& other) noexcept = default;
DISALLOW_COPY(Path)
std::string ToString() const;
};
struct PathStorage final : public ngtcp2_path_storage {
explicit PathStorage();
PathStorage(PathStorage&& other) noexcept = default;
PathStorage& operator=(PathStorage&& other) noexcept = default;
DISALLOW_COPY(PathStorage)
void Reset();
void CopyTo(PathStorage* path) const;
bool operator==(const PathStorage& other) const;
bool operator!=(const PathStorage& other) const;
};
// Store acts as a wrapper around a v8::BackingStore, providing a convenient
// abstraction to map it to various buffer types used in QUIC, HTTP/3, and
// libuv, taking care of the necessary adjustments for length and offset.
class Store final : public MemoryRetainer {
public:
Store() = default;
Store(std::shared_ptr<v8::BackingStore> store,
size_t length,
size_t offset = 0);
Store(std::unique_ptr<v8::BackingStore> store,
size_t length,
size_t offset = 0);
Store(Store&& other) noexcept = default;
Store& operator=(Store&& other) noexcept = default;
DISALLOW_COPY(Store)
// Creates a Store from the contents of an ArrayBuffer, always detaching
// it in the process. An empty Maybe will be returned if the ArrayBuffer
// is not detachable or detaching failed (likely due to a detach key
// mismatch).
static v8::Maybe<Store> From(
v8::Local<v8::ArrayBuffer> buffer,
v8::Local<v8::Value> detach_key = v8::Local<v8::Value>());
// Creates a Store from the contents of an ArrayBufferView, always detaching
// it in the process. An empty Maybe will be returned if the ArrayBuffer
// is not detachable or detaching failed (likely due to a detach key
// mismatch).
static v8::Maybe<Store> From(
v8::Local<v8::ArrayBufferView> view,
v8::Local<v8::Value> detach_key = v8::Local<v8::Value>());
v8::Local<v8::Uint8Array> ToUint8Array(Environment* env) const;
inline v8::Local<v8::Uint8Array> ToUint8Array(Realm* realm) const {
return ToUint8Array(realm->env());
}
operator uv_buf_t() const;
operator ngtcp2_vec() const;
operator nghttp3_vec() const;
operator bool() const;
size_t length() const;
// Returns the total length of the underlying store, not just the
// length of the view. This is useful for memory accounting.
size_t total_length() const;
void MemoryInfo(MemoryTracker* tracker) const override;
SET_MEMORY_INFO_NAME(Store)
SET_SELF_SIZE(Store)
private:
template <typename T, OneByteType N>
T convert() const;
std::shared_ptr<v8::BackingStore> store_;
size_t length_ = 0;
size_t offset_ = 0;
// Because Store holds the v8::BackingStore and not the v8::ArrayBuffer,
// etc, the memory held by the Store is not directly, automatically
// associated with a v8::Isolate, and is therefore not accounted for
// as external memory. It is the responsibility of the owner of the
// Store instance to ensure the memory remains accounted for.
};
// Periodically, these need to be updated to match the latest ngtcp2 defs.
#define QUIC_TRANSPORT_ERRORS(V) \
V(INTERNAL_ERROR) \
V(CONNECTION_REFUSED) \
V(FLOW_CONTROL_ERROR) \
V(STREAM_LIMIT_ERROR) \
V(STREAM_STATE_ERROR) \
V(FINAL_SIZE_ERROR) \
V(FRAME_ENCODING_ERROR) \
V(TRANSPORT_PARAMETER_ERROR) \
V(CONNECTION_ID_LIMIT_ERROR) \
V(PROTOCOL_VIOLATION) \
V(INVALID_TOKEN) \
V(APPLICATION_ERROR) \
V(CRYPTO_BUFFER_EXCEEDED) \
V(KEY_UPDATE_ERROR) \
V(AEAD_LIMIT_REACHED) \
V(NO_VIABLE_PATH) \
V(CRYPTO_ERROR) \
V(VERSION_NEGOTIATION_ERROR)
// Periodically, these need to be updated to match the latest nghttp3 defs.
#define HTTP3_APPLICATION_ERRORS(V) \
V(H3_NO_ERROR) \
V(H3_GENERAL_PROTOCOL_ERROR) \
V(H3_INTERNAL_ERROR) \
V(H3_STREAM_CREATION_ERROR) \
V(H3_CLOSED_CRITICAL_STREAM) \
V(H3_FRAME_UNEXPECTED) \
V(H3_FRAME_ERROR) \
V(H3_EXCESSIVE_LOAD) \
V(H3_ID_ERROR) \
V(H3_SETTINGS_ERROR) \
V(H3_MISSING_SETTINGS) \
V(H3_REQUEST_REJECTED) \
V(H3_REQUEST_CANCELLED) \
V(H3_REQUEST_INCOMPLETE) \
V(H3_MESSAGE_ERROR) \
V(H3_CONNECT_ERROR) \
V(H3_VERSION_FALLBACK) \
V(QPACK_DECOMPRESSION_FAILED) \
V(QPACK_ENCODER_STREAM_ERROR) \
V(QPACK_DECODER_STREAM_ERROR)
class QuicError final : public MemoryRetainer {
public:
// The known error codes for the transport namespace.
enum class TransportError : error_code {
// NO_ERROR has to be treated specially since it is a macro on
// some Windows cases and results in a compile error if we leave
// it as is.
NO_ERROR_ = NGTCP2_NO_ERROR,
#define V(name) name = NGTCP2_##name,
QUIC_TRANSPORT_ERRORS(V)
#undef V
};
// Every QUIC application defines its own error codes in the application
// namespace. These are managed independently of each other and may overlap
// with other applications and even the transport namespace. The only way
// to correctly interpret an application error code is to know which
// application is being used. For convenience, we define constants for the
// known HTTP/3 application error codes here.
enum class Http3Error : error_code {
#define V(name) name = NGHTTP3_##name,
HTTP3_APPLICATION_ERRORS(V)
#undef V
};
static constexpr error_code QUIC_NO_ERROR = NGTCP2_NO_ERROR;
static constexpr error_code HTTP3_NO_ERROR_CODE = NGHTTP3_H3_NO_ERROR;
// In QUIC, Errors are represented as namespaced 64-bit error codes.
// The error code only has meaning within the context of a specific
// namespace. The QuicError::Type enum defines the available namespaces.
// There are essentially two namespaces: transport and application, with
// a few additional special-cases that are variants of the transport
// namespace.
enum class Type {
TRANSPORT = NGTCP2_CCERR_TYPE_TRANSPORT,
APPLICATION = NGTCP2_CCERR_TYPE_APPLICATION,
// These are special cases of transport errors.
VERSION_NEGOTIATION = NGTCP2_CCERR_TYPE_VERSION_NEGOTIATION,
IDLE_CLOSE = NGTCP2_CCERR_TYPE_IDLE_CLOSE,
DROP_CONNECTION = NGTCP2_CCERR_TYPE_DROP_CONN,
RETRY = NGTCP2_CCERR_TYPE_RETRY,
};
// Do not use the constructors directly in regular use. Use the static
// factory methods instead. Those will ensure that the underlying
// ngtcp2_ccerr is initialized correctly based on the type of error
// being created.
explicit QuicError(const std::string& reason = "");
explicit QuicError(const ngtcp2_ccerr* ptr);
explicit QuicError(const ngtcp2_ccerr& error);
QuicError(QuicError&& other) noexcept = default;
QuicError& operator=(QuicError&& other) noexcept = default;
DISALLOW_COPY(QuicError)
Type type() const;
error_code code() const;
const std::string_view reason() const;
uint64_t frame_type() const;
operator const ngtcp2_ccerr&() const;
operator const ngtcp2_ccerr*() const;
// Crypto errors are a subset of transport errors. The error code includes
// the TLS alert code embedded within it.
bool is_crypto_error() const;
std::optional<int> get_crypto_error() const;
// Note that since application errors are application-specific and we
// don't know which application is being used here, it is possible that
// the comparing two different QuicError instances from different applications
// will return true even if they are not semantically equivalent. This should
// not be a problem in practice.
bool operator==(const QuicError& other) const;
bool operator!=(const QuicError& other) const;
void MemoryInfo(MemoryTracker* tracker) const override;
SET_MEMORY_INFO_NAME(QuicError)
SET_SELF_SIZE(QuicError)
std::string ToString() const;
// Returns an array containing [type, code, reason], where type is a string
// representation of the error type, code is a bigint representation of the
// error code, and reason is a string representation of the error reason, or
// undefined if the reason is the empty string. This is expected to be used
// to construct a JS error object from the information in JS.
v8::MaybeLocal<v8::Value> ToV8Value(Environment* env) const;
inline v8::MaybeLocal<v8::Value> ToV8Value(Realm* realm) const {
return ToV8Value(realm->env());
}
// Utility functions for getting the default error reason strings for
// internal error codes returned by the underlying ngtcp2/nghttp3 libraries.
static std::string reason_for_liberr(int liberr);
static std::string reason_for_h3_liberr(int liberr);
// Utility functions for checking if the given internal error codes are
// considered to be fatal by the underlying ngtcp2/nghttp3 libraries.
static bool is_fatal_liberror(int liberr);
static bool is_fatal_h3_liberror(int liberr);
// Utility functions for converting between ngtcp2/nghttp3 internal error
// codes to the corresponding QUIC error codes.
static error_code liberr_to_code(int liberr);
static error_code h3_liberr_to_code(int liberr);
// Utility functions for creating QuicError instances.
// The reason is expected to always be UTF-8 encoded.
static const QuicError ForTransport(TransportError code,
std::string reason = "");
static const QuicError ForTransport(error_code code, std::string reason = "");
static const QuicError ForApplication(Http3Error code,
std::string reason = "");
static const QuicError ForApplication(error_code code,
std::string reason = "");
static const QuicError ForVersionNegotiation(std::string reason = "");
static const QuicError ForIdleClose(std::string reason = "");
static const QuicError ForDropConnection(std::string reason = "");
static const QuicError ForRetry(std::string reason = "");
static const QuicError ForNgtcp2Error(int code, std::string reason = "");
static const QuicError ForTlsAlert(int code, std::string reason = "");
static const QuicError FromConnectionClose(ngtcp2_conn* session);
static const QuicError TRANSPORT_NO_ERROR;
#define V(name) static const QuicError TRANSPORT_##name;
QUIC_TRANSPORT_ERRORS(V)
#undef V
static const QuicError HTTP3_NO_ERROR;
static const QuicError VERSION_NEGOTIATION;
static const QuicError IDLE_CLOSE;
static const QuicError DROP_CONNECTION;
static const QuicError RETRY;
static const QuicError INTERNAL_ERROR;
private:
const uint8_t* reason_c_str() const;
std::string reason_;
ngtcp2_ccerr error_;
const ngtcp2_ccerr* ptr_ = nullptr;
};
// Marked maybe_unused because these are used in the tests but not in the
// production code.
[[maybe_unused]] static bool operator==(const QuicError::TransportError& lhs,
error_code rhs) {
return static_cast<error_code>(lhs) == rhs;
}
[[maybe_unused]] static bool operator==(const QuicError::Http3Error& lhs,
error_code rhs) {
return static_cast<error_code>(lhs) == rhs;
}
} // namespace node::quic
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS