| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent b2e2e64 commit 4ade02a
18 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1141,12 +1141,26 @@ added: v23.8.0 | |||
| 1141 | 1141 | #### `sessionOptions.alpn` | |
| 1142 | 1142 | ||
| 1143 | 1143 | <!-- YAML | |
| 1144 | - added: v23.8.0 | ||
| 1144 | + added: REPLACEME | ||
| 1145 | 1145 | --> | |
| 1146 | 1146 | ||
| 1147 | - * Type: {string} | ||
| 1147 | + * Type: {string} (client) | {string\[]} (server) | ||
| 1148 | + | ||
| 1149 | + The ALPN (Application-Layer Protocol Negotiation) identifier(s). | ||
| 1150 | + | ||
| 1151 | + For **client** sessions, this is a single string specifying the protocol | ||
| 1152 | + the client wants to use (e.g. `'h3'`). | ||
| 1153 | + | ||
| 1154 | + For **server** sessions, this is an array of protocol names in preference | ||
| 1155 | + order that the server supports (e.g. `['h3', 'h3-29']`). During the TLS | ||
| 1156 | + handshake, the server selects the first protocol from its list that the | ||
| 1157 | + client also supports. | ||
| 1158 | + | ||
| 1159 | + The negotiated ALPN determines which Application implementation is used | ||
| 1160 | + for the session. `'h3'` and `'h3-*'` variants select the HTTP/3 | ||
| 1161 | + application; all other values select the default application. | ||
| 1148 | 1162 | ||
| 1149 | - The ALPN protocol identifier. | ||
| 1163 | + Default: `'h3'` | ||
| 1150 | 1164 | ||
| 1151 | 1165 | #### `sessionOptions.ca` (client only) | |
| 1152 | 1166 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -33,7 +33,6 @@ let debug = require('internal/util/debuglog').debuglog('quic', (fn) => { | |||
| 33 | 33 | ||
| 34 | 34 | const { | |
| 35 | 35 | Endpoint: Endpoint_, | |
| 36 | - Http3Application: Http3, | ||
| 37 | 36 | setCallbacks, | |
| 38 | 37 | ||
| 39 | 38 | // The constants to be exposed to end users for various options. | |
@@ -118,7 +117,6 @@ const { | |||
| 118 | 117 | const kEmptyObject = { __proto__: null }; | |
| 119 | 118 | ||
| 120 | 119 | const { | |
| 121 | - kApplicationProvider, | ||
| 122 | 120 | kBlocked, | |
| 123 | 121 | kConnect, | |
| 124 | 122 | kDatagram, | |
@@ -2222,7 +2220,7 @@ function processIdentityOptions(identity, label) { | |||
| 2222 | 2220 | function processTlsOptions(tls, forServer) { | |
| 2223 | 2221 | const { | |
| 2224 | 2222 | servername, | |
| 2225 | - protocol, | ||
| 2223 | + alpn, | ||
| 2226 | 2224 | ciphers = DEFAULT_CIPHERS, | |
| 2227 | 2225 | groups = DEFAULT_GROUPS, | |
| 2228 | 2226 | keylog = false, | |
@@ -2240,9 +2238,6 @@ function processTlsOptions(tls, forServer) { | |||
| 2240 | 2238 | if (servername !== undefined) { | |
| 2241 | 2239 | validateString(servername, 'options.servername'); | |
| 2242 | 2240 | } | |
| 2243 | - if (protocol !== undefined) { | ||
| 2244 | - validateString(protocol, 'options.protocol'); | ||
| 2245 | - } | ||
| 2246 | 2241 | if (ciphers !== undefined) { | |
| 2247 | 2242 | validateString(ciphers, 'options.ciphers'); | |
| 2248 | 2243 | } | |
@@ -2253,11 +2248,42 @@ function processTlsOptions(tls, forServer) { | |||
| 2253 | 2248 | validateBoolean(verifyClient, 'options.verifyClient'); | |
| 2254 | 2249 | validateBoolean(tlsTrace, 'options.tlsTrace'); | |
| 2255 | 2250 | ||
| 2251 | + // Encode the ALPN option to wire format (length-prefixed protocol names). | ||
| 2252 | + // Server: array of protocol names. Client: single protocol name. | ||
| 2253 | + // If not specified, the C++ default (h3) is used. | ||
| 2254 | + let encodedAlpn; | ||
| 2255 | + if (alpn !== undefined) { | ||
| 2256 | + const protocols = forServer ? | ||
| 2257 | + (ArrayIsArray(alpn) ? alpn : [alpn]) : | ||
| 2258 | + [alpn]; | ||
| 2259 | + if (!forServer) { | ||
| 2260 | + validateString(alpn, 'options.alpn'); | ||
| 2261 | + } | ||
| 2262 | + let totalLen = 0; | ||
| 2263 | + for (let i = 0; i < protocols.length; i++) { | ||
| 2264 | + validateString(protocols[i], `options.alpn[${i}]`); | ||
| 2265 | + if (protocols[i].length === 0 || protocols[i].length > 255) { | ||
| 2266 | + throw new ERR_INVALID_ARG_VALUE(`options.alpn[${i}]`, protocols[i], | ||
| 2267 | + 'must be between 1 and 255 characters'); | ||
| 2268 | + } | ||
| 2269 | + totalLen += 1 + protocols[i].length; | ||
| 2270 | + } | ||
| 2271 | + // Build wire format: [len1][name1][len2][name2]... | ||
| 2272 | + const buf = Buffer.allocUnsafe(totalLen); | ||
| 2273 | + let offset = 0; | ||
| 2274 | + for (let i = 0; i < protocols.length; i++) { | ||
| 2275 | + buf[offset++] = protocols[i].length; | ||
| 2276 | + buf.write(protocols[i], offset, 'ascii'); | ||
| 2277 | + offset += protocols[i].length; | ||
| 2278 | + } | ||
| 2279 | + encodedAlpn = buf.toString('latin1'); | ||
| 2280 | + } | ||
| 2281 | + | ||
| 2256 | 2282 | // Shared TLS options (same for all identities on the endpoint). | |
| 2257 | 2283 | const shared = { | |
| 2258 | 2284 | __proto__: null, | |
| 2259 | 2285 | servername, | |
| 2260 | - protocol, | ||
| 2286 | + alpn: encodedAlpn, | ||
| 2261 | 2287 | ciphers, | |
| 2262 | 2288 | groups, | |
| 2263 | 2289 | keylog, | |
@@ -2360,17 +2386,12 @@ function processSessionOptions(options, config = {}) { | |||
| 2360 | 2386 | maxStreamWindow, | |
| 2361 | 2387 | maxWindow, | |
| 2362 | 2388 | cc, | |
| 2363 | - [kApplicationProvider]: provider, | ||
| 2364 | 2389 | } = options; | |
| 2365 | 2390 | ||
| 2366 | 2391 | const { | |
| 2367 | 2392 | forServer = false, | |
| 2368 | 2393 | } = config; | |
| 2369 | 2394 | ||
| 2370 | - if (provider !== undefined) { | ||
| 2371 | - validateObject(provider, 'options[kApplicationProvider]'); | ||
| 2372 | - } | ||
| 2373 | - | ||
| 2374 | 2395 | if (cc !== undefined) { | |
| 2375 | 2396 | validateOneOf(cc, 'options.cc', [CC_ALGO_RENO, CC_ALGO_BBR, CC_ALGO_CUBIC]); | |
| 2376 | 2397 | } | |
@@ -2392,7 +2413,6 @@ function processSessionOptions(options, config = {}) { | |||
| 2392 | 2413 | maxStreamWindow, | |
| 2393 | 2414 | maxWindow, | |
| 2394 | 2415 | sessionTicket, | |
| 2395 | - provider, | ||
| 2396 | 2416 | cc, | |
| 2397 | 2417 | }; | |
| 2398 | 2418 | } | |
@@ -2494,7 +2514,6 @@ module.exports = { | |||
| 2494 | 2514 | QuicEndpoint, | |
| 2495 | 2515 | QuicSession, | |
| 2496 | 2516 | QuicStream, | |
| 2497 | - Http3, | ||
| 2498 | 2517 | CC_ALGO_RENO, | |
| 2499 | 2518 | CC_ALGO_CUBIC, | |
| 2500 | 2519 | CC_ALGO_BBR, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -62,6 +62,7 @@ const { | |||
| 62 | 62 | IDX_STATE_SESSION_STREAM_OPEN_ALLOWED, | |
| 63 | 63 | IDX_STATE_SESSION_PRIORITY_SUPPORTED, | |
| 64 | 64 | IDX_STATE_SESSION_WRAPPED, | |
| 65 | + IDX_STATE_SESSION_APPLICATION_TYPE, | ||
| 65 | 66 | IDX_STATE_SESSION_LAST_DATAGRAM_ID, | |
| 66 | 67 | ||
| 67 | 68 | IDX_STATE_ENDPOINT_BOUND, | |
@@ -99,6 +100,7 @@ assert(IDX_STATE_SESSION_HANDSHAKE_CONFIRMED !== undefined); | |||
| 99 | 100 | assert(IDX_STATE_SESSION_STREAM_OPEN_ALLOWED !== undefined); | |
| 100 | 101 | assert(IDX_STATE_SESSION_PRIORITY_SUPPORTED !== undefined); | |
| 101 | 102 | assert(IDX_STATE_SESSION_WRAPPED !== undefined); | |
| 103 | + assert(IDX_STATE_SESSION_APPLICATION_TYPE !== undefined); | ||
| 102 | 104 | assert(IDX_STATE_SESSION_LAST_DATAGRAM_ID !== undefined); | |
| 103 | 105 | assert(IDX_STATE_ENDPOINT_BOUND !== undefined); | |
| 104 | 106 | assert(IDX_STATE_ENDPOINT_RECEIVING !== undefined); | |
@@ -347,6 +349,12 @@ class QuicSessionState { | |||
| 347 | 349 | return !!DataViewPrototypeGetUint8(this.#handle, IDX_STATE_SESSION_WRAPPED); | |
| 348 | 350 | } | |
| 349 | 351 | ||
| 352 | + /** @type {number} */ | ||
| 353 | + get applicationType() { | ||
| 354 | + if (this.#handle.byteLength === 0) return undefined; | ||
| 355 | + return DataViewPrototypeGetUint8(this.#handle, IDX_STATE_SESSION_APPLICATION_TYPE); | ||
| 356 | + } | ||
| 357 | + | ||
| 350 | 358 | /** @type {bigint} */ | |
| 351 | 359 | get lastDatagramId() { | |
| 352 | 360 | if (this.#handle.byteLength === 0) return undefined; | |
@@ -407,6 +415,7 @@ class QuicSessionState { | |||
| 407 | 415 | isStreamOpenAllowed: this.isStreamOpenAllowed, | |
| 408 | 416 | isPrioritySupported: this.isPrioritySupported, | |
| 409 | 417 | isWrapped: this.isWrapped, | |
| 418 | + applicationType: this.applicationType, | ||
| 410 | 419 | lastDatagramId: this.lastDatagramId, | |
| 411 | 420 | }, opts)}`; | |
| 412 | 421 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -23,7 +23,6 @@ const { | |||
| 23 | 23 | // Symbols used to hide various private properties and methods from the | |
| 24 | 24 | // public API. | |
| 25 | 25 | ||
| 26 | - const kApplicationProvider = Symbol('kApplicationProvider'); | ||
| 27 | 26 | const kBlocked = Symbol('kBlocked'); | |
| 28 | 27 | const kConnect = Symbol('kConnect'); | |
| 29 | 28 | const kDatagram = Symbol('kDatagram'); | |
@@ -50,7 +49,6 @@ const kWantsHeaders = Symbol('kWantsHeaders'); | |||
| 50 | 49 | const kWantsTrailers = Symbol('kWantsTrailers'); | |
| 51 | 50 | ||
| 52 | 51 | module.exports = { | |
| 53 | - kApplicationProvider, | ||
| 54 | 52 | kBlocked, | |
| 55 | 53 | kConnect, | |
| 56 | 54 | kDatagram, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -464,6 +464,10 @@ class DefaultApplication final : public Session::Application { | |||
| 464 | 464 | // of the namespace. | |
| 465 | 465 | using Application::Application; // NOLINT | |
| 466 | 466 | ||
| 467 | + Session::Application::Type type() const override { | ||
| 468 | + return Session::Application::Type::DEFAULT; | ||
| 469 | + } | ||
| 470 | + | ||
| 467 | 471 | error_code GetNoErrorCode() const override { return 0; } | |
| 468 | 472 | ||
| 469 | 473 | bool ReceiveStreamData(int64_t stream_id, | |
@@ -601,14 +605,9 @@ class DefaultApplication final : public Session::Application { | |||
| 601 | 605 | Stream::Queue stream_queue_; | |
| 602 | 606 | }; | |
| 603 | 607 | ||
| 604 | - std::unique_ptr<Session::Application> Session::SelectApplication( | ||
| 605 | - Session* session, const Config& config) { | ||
| 606 | - if (config.options.application_provider) { | ||
| 607 | - return config.options.application_provider->Create(session); | ||
| 608 | - } | ||
| 609 | - | ||
| 610 | - return std::make_unique<DefaultApplication>(session, | ||
| 611 | - Application_Options::kDefault); | ||
| 608 | + std::unique_ptr<Session::Application> CreateDefaultApplication( | ||
| 609 | + Session* session, const Session::Application_Options& options) { | ||
| 610 | + return std::make_unique<DefaultApplication>(session, options); | ||
| 612 | 611 | } | |
| 613 | 612 | ||
| 614 | 613 | } // namespace quic | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17,9 +17,19 @@ class Session::Application : public MemoryRetainer { | |||
| 17 | 17 | public: | |
| 18 | 18 | using Options = Session::Application_Options; | |
| 19 | 19 | ||
| 20 | + // The type of Application, exposed via the session state so JS | ||
| 21 | + // can observe which Application was selected after ALPN negotiation. | ||
| 22 | + enum class Type : uint8_t { | ||
| 23 | + NONE = 0, // Not yet selected (server pre-negotiation) | ||
| 24 | + DEFAULT = 1, // DefaultApplication (non-h3 ALPN) | ||
| 25 | + HTTP3 = 2, // Http3ApplicationImpl (h3 / h3-XX ALPN) | ||
| 26 | + }; | ||
| 27 | + | ||
| 20 | 28 | Application(Session* session, const Options& options); | |
| 21 | 29 | DISALLOW_COPY_AND_MOVE(Application) | |
| 22 | 30 | ||
| 31 | + virtual Type type() const = 0; | ||
| 32 | + | ||
| 23 | 33 | virtual bool Start(); | |
| 24 | 34 | ||
| 25 | 35 | virtual error_code GetNoErrorCode() const = 0; | |
@@ -169,6 +179,10 @@ struct Session::Application::StreamData final { | |||
| 169 | 179 | std::string ToString() const; | |
| 170 | 180 | }; | |
| 171 | 181 | ||
| 182 | + // Create a DefaultApplication for the given session. | ||
| 183 | + std::unique_ptr<Session::Application> CreateDefaultApplication( | ||
| 184 | + Session* session, const Session::Application_Options& options); | ||
| 185 | + | ||
| 172 | 186 | } // namespace node::quic | |
| 173 | 187 | ||
| 174 | 188 | #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -24,7 +24,6 @@ class Packet; | |||
| 24 | 24 | // The FunctionTemplates the BindingData will store for us. | |
| 25 | 25 | #define QUIC_CONSTRUCTORS(V) \ | |
| 26 | 26 | V(endpoint) \ | |
| 27 | - V(http3application) \ | ||
| 28 | 27 | V(logstream) \ | |
| 29 | 28 | V(session) \ | |
| 30 | 29 | V(stream) \ | |
@@ -59,7 +58,7 @@ class Packet; | |||
| 59 | 58 | V(ack_delay_exponent, "ackDelayExponent") \ | |
| 60 | 59 | V(active_connection_id_limit, "activeConnectionIDLimit") \ | |
| 61 | 60 | V(address_lru_size, "addressLRUSize") \ | |
| 62 | - V(application_provider, "provider") \ | ||
| 61 | + V(application, "application") \ | ||
| 63 | 62 | V(bbr, "bbr") \ | |
| 64 | 63 | V(ca, "ca") \ | |
| 65 | 64 | V(cc_algorithm, "cc") \ | |
@@ -78,7 +77,6 @@ class Packet; | |||
| 78 | 77 | V(groups, "groups") \ | |
| 79 | 78 | V(handshake_timeout, "handshakeTimeout") \ | |
| 80 | 79 | V(http3_alpn, &NGHTTP3_ALPN_H3[1]) \ | |
| 81 | - V(http3application, "Http3Application") \ | ||
| 82 | 80 | V(initial_max_data, "initialMaxData") \ | |
| 83 | 81 | V(initial_max_stream_data_bidi_local, "initialMaxStreamDataBidiLocal") \ | |
| 84 | 82 | V(initial_max_stream_data_bidi_remote, "initialMaxStreamDataBidiRemote") \ | |
@@ -105,7 +103,7 @@ class Packet; | |||
| 105 | 103 | V(max_window, "maxWindow") \ | |
| 106 | 104 | V(min_version, "minVersion") \ | |
| 107 | 105 | V(preferred_address_strategy, "preferredAddressPolicy") \ | |
| 108 | - V(protocol, "protocol") \ | ||
| 106 | + V(alpn, "alpn") \ | ||
| 109 | 107 | V(qlog, "qlog") \ | |
| 110 | 108 | V(qpack_blocked_streams, "qpackBlockedStreams") \ | |
| 111 | 109 | V(qpack_encoder_max_dtable_capacity, "qpackEncoderMaxDTableCapacity") \ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -92,7 +92,7 @@ bool is_diagnostic_packet_loss(double probability) { | |||
| 92 | 92 | return (static_cast<double>(c) / 255) < probability; | |
| 93 | 93 | } | |
| 94 | 94 | ||
| 95 | - template <typename Opt, double Opt::*member> | ||
| 95 | + template <typename Opt, double Opt::* member> | ||
| 96 | 96 | bool SetOption(Environment* env, | |
| 97 | 97 | Opt* options, | |
| 98 | 98 | const Local<Object>& object, | |
@@ -113,7 +113,7 @@ bool SetOption(Environment* env, | |||
| 113 | 113 | } | |
| 114 | 114 | #endif // DEBUG | |
| 115 | 115 | ||
| 116 | - template <typename Opt, uint8_t Opt::*member> | ||
| 116 | + template <typename Opt, uint8_t Opt::* member> | ||
| 117 | 117 | bool SetOption(Environment* env, | |
| 118 | 118 | Opt* options, | |
| 119 | 119 | const Local<Object>& object, | |
@@ -140,7 +140,7 @@ bool SetOption(Environment* env, | |||
| 140 | 140 | return true; | |
| 141 | 141 | } | |
| 142 | 142 | ||
| 143 | - template <typename Opt, TokenSecret Opt::*member> | ||
| 143 | + template <typename Opt, TokenSecret Opt::* member> | ||
| 144 | 144 | bool SetOption(Environment* env, | |
| 145 | 145 | Opt* options, | |
| 146 | 146 | const Local<Object>& object, | |
@@ -511,7 +511,6 @@ JS_CONSTRUCTOR_IMPL(Endpoint, endpoint_constructor_template, { | |||
| 511 | 511 | ||
| 512 | 512 | void Endpoint::InitPerIsolate(IsolateData* data, Local<ObjectTemplate> target) { | |
| 513 | 513 | // TODO(@jasnell): Implement the per-isolate state | |
| 514 | - Http3Application::InitPerIsolate(data, target); | ||
| 515 | 514 | } | |
| 516 | 515 | ||
| 517 | 516 | void Endpoint::InitPerContext(Realm* realm, Local<Object> target) { | |
@@ -567,8 +566,6 @@ void Endpoint::InitPerContext(Realm* realm, Local<Object> target) { | |||
| 567 | 566 | NODE_DEFINE_CONSTANT(target, CLOSECONTEXT_SEND_FAILURE); | |
| 568 | 567 | NODE_DEFINE_CONSTANT(target, CLOSECONTEXT_START_FAILURE); | |
| 569 | 568 | ||
| 570 | - Http3Application::InitPerContext(realm, target); | ||
| 571 | - | ||
| 572 | 569 | SetConstructorFunction(realm->context(), | |
| 573 | 570 | target, | |
| 574 | 571 | "Endpoint", | |
| Back | FazBrowse Home | New Git URL |
0 commit comments