| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 5ca7ef3 commit 2f749dd
10 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -914,6 +914,8 @@ added: REPLACEME | |||
| 914 | 914 | The current application-level options for this session. These include settings | |
| 915 | 915 | that are specific to the negotiated application protocol (e.g. HTTP/3) and may | |
| 916 | 916 | be negotiated separately from the transport parameters. Read only. | |
| 917 | + You can use the callback [`session.onapplication`][] to be informed, when settings | ||
| 918 | + from the remote arrive. | ||
| 917 | 919 | ||
| 918 | 920 | ### `session.close([options])` | |
| 919 | 921 | ||
@@ -1046,6 +1048,16 @@ added: v23.8.0 | |||
| 1046 | 1048 | The endpoint that created this session. Returns `null` if the session | |
| 1047 | 1049 | has been destroyed. Read only. | |
| 1048 | 1050 | ||
| 1051 | + ### `session.onapplication` | ||
| 1052 | + | ||
| 1053 | + <!-- YAML | ||
| 1054 | + added: REPLACEME | ||
| 1055 | + --> | ||
| 1056 | + | ||
| 1057 | + * Type: {quic.OnApplicationCallback} | ||
| 1058 | + | ||
| 1059 | + The callback to invoke when new application options, e.g. HTTP/3 settings arrived. | ||
| 1060 | + | ||
| 1049 | 1061 | ### `session.onerror` | |
| 1050 | 1062 | ||
| 1051 | 1063 | <!-- YAML | |
@@ -3499,11 +3511,11 @@ with that error: | |||
| 3499 | 3511 | ||
| 3500 | 3512 | * Stream callbacks (`onblocked`, `onreset`, `onheaders`, `ontrailers`, | |
| 3501 | 3513 | `oninfo`, `onwanttrailers`): the stream is destroyed. | |
| 3502 | - * Session callbacks (`onstream`, `ondatagram`, `ondatagramstatus`, | ||
| 3503 | - `onpathvalidation`, `onsessionticket`, `onnewtoken`, | ||
| 3504 | - `onversionnegotiation`, `onorigin`, `ongoaway`, `onhandshake`, | ||
| 3505 | - `onkeylog`, `onqlog`): the session is destroyed along with all of its | ||
| 3506 | - streams. | ||
| 3514 | + * Session callbacks (`onapplication`, `onstream`, `ondatagram`, | ||
| 3515 | + `ondatagramstatus`, `onpathvalidation`, `onsessionticket`, | ||
| 3516 | + `onnewtoken`, `onversionnegotiation`, `onorigin`, `ongoaway`, | ||
| 3517 | + `onhandshake`, `onkeylog`, `onqlog`): the session is destroyed along | ||
| 3518 | + with all of its streams. | ||
| 3507 | 3519 | ||
| 3508 | 3520 | Before destruction, the optional [`session.onerror`][] or | |
| 3509 | 3521 | [`stream.onerror`][] callback is invoked (if set), giving the application a | |
@@ -3557,6 +3569,19 @@ added: v23.8.0 | |||
| 3557 | 3569 | datagram was never sent on the wire (dropped due to queue overflow, | |
| 3558 | 3570 | send attempt limit exceeded, or frame size rejection). | |
| 3559 | 3571 | ||
| 3572 | + ### Callback: `OnApplicationCallback` | ||
| 3573 | + | ||
| 3574 | + <!-- YAML | ||
| 3575 | + added: v23.8.0 | ||
| 3576 | + --> | ||
| 3577 | + | ||
| 3578 | + * `this` {quic.QuicSession} | ||
| 3579 | + * `applicationoption` {quic.QuicSession} | ||
| 3580 | + | ||
| 3581 | + The callback function that is invoked when application options change. | ||
| 3582 | + E.g. for http/3 settings are included in applications options and | ||
| 3583 | + may arrive after the connection is established. | ||
| 3584 | + | ||
| 3560 | 3585 | ### Callback: `OnPathValidationCallback` | |
| 3561 | 3586 | ||
| 3562 | 3587 | <!-- YAML | |
@@ -4031,6 +4056,17 @@ added: v23.8.0 | |||
| 4031 | 4056 | ||
| 4032 | 4057 | Published when an endpoint's busy state changes. | |
| 4033 | 4058 | ||
| 4059 | + ### Channel: `quic.session.application` | ||
| 4060 | + | ||
| 4061 | + <!-- YAML | ||
| 4062 | + added: v23.8.0 | ||
| 4063 | + --> | ||
| 4064 | + | ||
| 4065 | + * `applicationoptions` {quic.ApplicationOptions} Current application options. | ||
| 4066 | + * `session` {quic.QuicSession} | ||
| 4067 | + | ||
| 4068 | + Published when a locally-initiated stream is opened. | ||
| 4069 | + | ||
| 4034 | 4070 | ### Channel: `quic.session.created.client` | |
| 4035 | 4071 | ||
| 4036 | 4072 | <!-- YAML | |
@@ -4412,6 +4448,7 @@ throughput issues caused by flow control. | |||
| 4412 | 4448 | [`session.createUnidirectionalStream()`]: #sessioncreateunidirectionalstreamoptions | |
| 4413 | 4449 | [`session.destroy()`]: #sessiondestroyerror-options | |
| 4414 | 4450 | [`session.maxPendingDatagrams`]: #sessionmaxpendingdatagrams | |
| 4451 | + [`session.onapplication`]: #sessiononapplication | ||
| 4415 | 4452 | [`session.ondatagram`]: #sessionondatagram | |
| 4416 | 4453 | [`session.ondatagramstatus`]: #sessionondatagramstatus | |
| 4417 | 4454 | [`session.onearlyrejected`]: #sessiononearlyrejected | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -14,6 +14,7 @@ const onEndpointErrorChannel = dc.channel('quic.endpoint.error'); | |||
| 14 | 14 | const onEndpointBusyChangeChannel = dc.channel('quic.endpoint.busy.change'); | |
| 15 | 15 | const onEndpointClientSessionChannel = dc.channel('quic.session.created.client'); | |
| 16 | 16 | const onEndpointServerSessionChannel = dc.channel('quic.session.created.server'); | |
| 17 | + const onSessionApplicationChannel = dc.channel('quic.session.application'); | ||
| 17 | 18 | const onSessionOpenStreamChannel = dc.channel('quic.session.open.stream'); | |
| 18 | 19 | const onSessionReceivedStreamChannel = dc.channel('quic.session.received.stream'); | |
| 19 | 20 | const onSessionSendDatagramChannel = dc.channel('quic.session.send.datagram'); | |
@@ -48,6 +49,7 @@ module.exports = { | |||
| 48 | 49 | onEndpointBusyChangeChannel, | |
| 49 | 50 | onEndpointClientSessionChannel, | |
| 50 | 51 | onEndpointServerSessionChannel, | |
| 52 | + onSessionApplicationChannel, | ||
| 51 | 53 | onSessionOpenStreamChannel, | |
| 52 | 54 | onSessionReceivedStreamChannel, | |
| 53 | 55 | onSessionSendDatagramChannel, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -204,6 +204,7 @@ const { | |||
| 204 | 204 | kPrivateConstructor, | |
| 205 | 205 | kReset, | |
| 206 | 206 | kSendHeaders, | |
| 207 | + kSessionApplication, | ||
| 207 | 208 | kSessionTicket, | |
| 208 | 209 | kTrailers, | |
| 209 | 210 | kVersionNegotiation, | |
@@ -252,6 +253,7 @@ const { | |||
| 252 | 253 | onSessionReceiveDatagramStatusChannel, | |
| 253 | 254 | onSessionPathValidationChannel, | |
| 254 | 255 | onSessionNewTokenChannel, | |
| 256 | + onSessionApplicationChannel, | ||
| 255 | 257 | onSessionTicketChannel, | |
| 256 | 258 | onSessionVersionNegotiationChannel, | |
| 257 | 259 | onSessionOriginChannel, | |
@@ -453,6 +455,7 @@ const endpointRegistry = new SafeSet(); | |||
| 453 | 455 | * @property {OnGoawayCallback} [ongoaway] GOAWAY frame callback. | |
| 454 | 456 | * @property {OnKeylogCallback} [onkeylog] TLS key-log callback. | |
| 455 | 457 | * @property {OnQlogCallback} [onqlog] qlog data callback. | |
| 458 | + * @property {OnApplicationCallback} [onapplication] application options callback. | ||
| 456 | 459 | * @property {OnHeadersCallback} [onheaders] Default per-stream initial-headers callback. | |
| 457 | 460 | * @property {OnTrailersCallback} [ontrailers] Default per-stream trailing-headers callback. | |
| 458 | 461 | * @property {OnInfoCallback} [oninfo] Default per-stream informational-headers callback. | |
@@ -583,6 +586,13 @@ const endpointRegistry = new SafeSet(); | |||
| 583 | 586 | * @returns {void} | |
| 584 | 587 | */ | |
| 585 | 588 | ||
| 589 | + /** | ||
| 590 | + * @callback OnApplicationCallback | ||
| 591 | + * @this {QuicSession} | ||
| 592 | + * @param {ApplicationOptions} applicationoptions | ||
| 593 | + * @returns {void} | ||
| 594 | + */ | ||
| 595 | + | ||
| 586 | 596 | /** | |
| 587 | 597 | * @callback OnSessionTicketCallback | |
| 588 | 598 | * @this {QuicSession} | |
@@ -660,6 +670,14 @@ const endpointRegistry = new SafeSet(); | |||
| 660 | 670 | * @returns {void} | |
| 661 | 671 | */ | |
| 662 | 672 | ||
| 673 | + /** | ||
| 674 | + * Called when `ApplicationOptions` are changed, e.g. HTTP/3 settings. | ||
| 675 | + * @callback OnApplicationCallback | ||
| 676 | + * @this {QuicSession} | ||
| 677 | + * @param {ApplicationOptions} applicationoptions ApplicationOptions object | ||
| 678 | + * @returns {void} | ||
| 679 | + */ | ||
| 680 | + | ||
| 663 | 681 | /** | |
| 664 | 682 | * @callback OnBlockedCallback | |
| 665 | 683 | * @this {QuicStream} | |
@@ -817,6 +835,16 @@ setCallbacks({ | |||
| 817 | 835 | preferredAddress); | |
| 818 | 836 | }, | |
| 819 | 837 | ||
| 838 | + /** | ||
| 839 | + * Called when the session's application object is updated | ||
| 840 | + * E.g. http/3 session arrived. | ||
| 841 | + * @param {ApplicationOptions} applicationoptions An application object | ||
| 842 | + */ | ||
| 843 | + onSessionApplication(applicationoptions) { | ||
| 844 | + debug('session application callback', this[kOwner]); | ||
| 845 | + this[kOwner][kSessionApplication](applicationoptions); | ||
| 846 | + }, | ||
| 847 | + | ||
| 820 | 848 | /** | |
| 821 | 849 | * Called when the session generates a new TLS session ticket | |
| 822 | 850 | * @param {object} ticket An opaque session ticket | |
@@ -1271,6 +1299,7 @@ function applyCallbacks(session, cbs) { | |||
| 1271 | 1299 | if (cbs.ongoaway) session.ongoaway = cbs.ongoaway; | |
| 1272 | 1300 | if (cbs.onkeylog) session.onkeylog = cbs.onkeylog; | |
| 1273 | 1301 | if (cbs.onqlog) session.onqlog = cbs.onqlog; | |
| 1302 | + if (cbs.onapplication) session.onapplication = cbs.onapplication; | ||
| 1274 | 1303 | if (cbs.onheaders || cbs.ontrailers || cbs.oninfo || cbs.onwanttrailers) { | |
| 1275 | 1304 | session[kStreamCallbacks] = { | |
| 1276 | 1305 | __proto__: null, | |
@@ -2964,6 +2993,25 @@ class QuicSession { | |||
| 2964 | 2993 | } | |
| 2965 | 2994 | } | |
| 2966 | 2995 | ||
| 2996 | + /** @type {Function|undefined} */ | ||
| 2997 | + get onapplication() { | ||
| 2998 | + assertIsQuicSession(this); | ||
| 2999 | + return this.#inner.onapplication; | ||
| 3000 | + } | ||
| 3001 | + | ||
| 3002 | + set onapplication(fn) { | ||
| 3003 | + assertIsQuicSession(this); | ||
| 3004 | + const inner = this.#inner; | ||
| 3005 | + if (fn === undefined) { | ||
| 3006 | + inner.onapplication = undefined; | ||
| 3007 | + inner.state.hasApplicationListener = false; | ||
| 3008 | + } else { | ||
| 3009 | + validateFunction(fn, 'onapplication'); | ||
| 3010 | + inner.onapplication = FunctionPrototypeBind(fn, this); | ||
| 3011 | + inner.state.hasApplicationListener = true; | ||
| 3012 | + } | ||
| 3013 | + } | ||
| 3014 | + | ||
| 2967 | 3015 | /** @type {Function|undefined} */ | |
| 2968 | 3016 | get onversionnegotiation() { | |
| 2969 | 3017 | assertIsQuicSession(this); | |
@@ -3551,6 +3599,7 @@ class QuicSession { | |||
| 3551 | 3599 | inner.ondatagramstatus = undefined; | |
| 3552 | 3600 | inner.onpathvalidation = undefined; | |
| 3553 | 3601 | inner.onsessionticket = undefined; | |
| 3602 | + inner.onapplication = undefined; | ||
| 3554 | 3603 | inner.onkeylog = undefined; | |
| 3555 | 3604 | inner.onversionnegotiation = undefined; | |
| 3556 | 3605 | inner.onhandshake = undefined; | |
@@ -3779,6 +3828,23 @@ class QuicSession { | |||
| 3779 | 3828 | safeCallbackInvoke(inner.onsessionticket, this, ticket); | |
| 3780 | 3829 | } | |
| 3781 | 3830 | ||
| 3831 | + /** | ||
| 3832 | + * @param {ApplicationOptions} applicationoptions | ||
| 3833 | + */ | ||
| 3834 | + [kSessionApplication](applicationoptions) { | ||
| 3835 | + if (this.destroyed) return; | ||
| 3836 | + if (onSessionApplicationChannel.hasSubscribers) { | ||
| 3837 | + onSessionApplicationChannel.publish({ | ||
| 3838 | + __proto__: null, | ||
| 3839 | + applicationoptions, | ||
| 3840 | + session: this, | ||
| 3841 | + }); | ||
| 3842 | + } | ||
| 3843 | + const inner = this.#inner; | ||
| 3844 | + if (typeof inner.onapplication === 'function') | ||
| 3845 | + safeCallbackInvoke(inner.onapplication, this, applicationoptions); | ||
| 3846 | + } | ||
| 3847 | + | ||
| 3782 | 3848 | /** | |
| 3783 | 3849 | * @param {Buffer} token | |
| 3784 | 3850 | * @param {SocketAddress} address | |
@@ -4356,6 +4422,7 @@ class QuicEndpoint { | |||
| 4356 | 4422 | ongoaway, | |
| 4357 | 4423 | onkeylog, | |
| 4358 | 4424 | onqlog, | |
| 4425 | + onapplication, | ||
| 4359 | 4426 | // Stream-level callbacks applied to each incoming stream. | |
| 4360 | 4427 | onheaders, | |
| 4361 | 4428 | ontrailers, | |
@@ -4381,6 +4448,7 @@ class QuicEndpoint { | |||
| 4381 | 4448 | ongoaway, | |
| 4382 | 4449 | onkeylog, | |
| 4383 | 4450 | onqlog, | |
| 4451 | + onapplication, | ||
| 4384 | 4452 | onheaders, | |
| 4385 | 4453 | ontrailers, | |
| 4386 | 4454 | oninfo, | |
@@ -5113,6 +5181,8 @@ function processSessionOptions(options, config = kEmptyObject) { | |||
| 5113 | 5181 | ongoaway, | |
| 5114 | 5182 | onkeylog, | |
| 5115 | 5183 | onqlog, | |
| 5184 | + onapplication, | ||
| 5185 | + // Application level options changed, e.g. HTTP/3 settings related | ||
| 5116 | 5186 | // Stream-level callbacks. | |
| 5117 | 5187 | onheaders, | |
| 5118 | 5188 | ontrailers, | |
@@ -5234,6 +5304,7 @@ function processSessionOptions(options, config = kEmptyObject) { | |||
| 5234 | 5304 | ongoaway, | |
| 5235 | 5305 | onkeylog, | |
| 5236 | 5306 | onqlog, | |
| 5307 | + onapplication, | ||
| 5237 | 5308 | onheaders, | |
| 5238 | 5309 | ontrailers, | |
| 5239 | 5310 | oninfo, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -349,6 +349,7 @@ class QuicSessionState { | |||
| 349 | 349 | static #LISTENER_SESSION_TICKET = 1 << 3; | |
| 350 | 350 | static #LISTENER_NEW_TOKEN = 1 << 4; | |
| 351 | 351 | static #LISTENER_ORIGIN = 1 << 5; | |
| 352 | + static #LISTENER_APPLICATION = 1 << 6; | ||
| 352 | 353 | ||
| 353 | 354 | #getListenerFlag(flag) { | |
| 354 | 355 | const handle = this.#handle; | |
@@ -367,6 +368,14 @@ class QuicSessionState { | |||
| 367 | 368 | val ? (current | flag) : (current & ~flag), kIsLittleEndian); | |
| 368 | 369 | } | |
| 369 | 370 | ||
| 371 | + /** @type {boolean} */ | ||
| 372 | + get hasApplicationListener() { | ||
| 373 | + return this.#getListenerFlag(QuicSessionState.#LISTENER_APPLICATION); | ||
| 374 | + } | ||
| 375 | + set hasApplicationListener(val) { | ||
| 376 | + this.#setListenerFlag(QuicSessionState.#LISTENER_APPLICATION, val); | ||
| 377 | + } | ||
| 378 | + | ||
| 370 | 379 | /** @type {boolean} */ | |
| 371 | 380 | get hasPathValidationListener() { | |
| 372 | 381 | return this.#getListenerFlag(QuicSessionState.#LISTENER_PATH_VALIDATION); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -55,6 +55,7 @@ const kRemoveSession = Symbol('kRemoveSession'); | |||
| 55 | 55 | const kRemoveStream = Symbol('kRemoveStream'); | |
| 56 | 56 | const kReset = Symbol('kReset'); | |
| 57 | 57 | const kSendHeaders = Symbol('kSendHeaders'); | |
| 58 | + const kSessionApplication = Symbol('kSessionApplication'); | ||
| 58 | 59 | const kSessionTicket = Symbol('kSessionTicket'); | |
| 59 | 60 | const kTrailers = Symbol('kTrailers'); | |
| 60 | 61 | const kVersionNegotiation = Symbol('kVersionNegotiation'); | |
@@ -90,6 +91,7 @@ module.exports = { | |||
| 90 | 91 | kRemoveStream, | |
| 91 | 92 | kReset, | |
| 92 | 93 | kSendHeaders, | |
| 94 | + kSessionApplication, | ||
| 93 | 95 | kSessionTicket, | |
| 94 | 96 | kTrailers, | |
| 95 | 97 | kVersionNegotiation, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -41,6 +41,7 @@ class SessionManager; | |||
| 41 | 41 | #define QUIC_JS_CALLBACKS(V) \ | |
| 42 | 42 | V(endpoint_close, EndpointClose) \ | |
| 43 | 43 | V(session_close, SessionClose) \ | |
| 44 | + V(session_application, SessionApplication) \ | ||
| 44 | 45 | V(session_early_data_rejected, SessionEarlyDataRejected) \ | |
| 45 | 46 | V(session_goaway, SessionGoaway) \ | |
| 46 | 47 | V(session_datagram, SessionDatagram) \ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1014,6 +1014,8 @@ class Http3ApplicationImpl final : public Session::Application { | |||
| 1014 | 1014 | Debug(&session(), | |
| 1015 | 1015 | "HTTP/3 application received updated settings: %s", | |
| 1016 | 1016 | options_); | |
| 1017 | + // The settings are part of the application | ||
| 1018 | + session().EmitApplication(); | ||
| 1017 | 1019 | } | |
| 1018 | 1020 | ||
| 1019 | 1021 | bool started_ = false; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -72,6 +72,7 @@ enum class SessionListenerFlags : uint32_t { | |||
| 72 | 72 | SESSION_TICKET = 1 << 3, | |
| 73 | 73 | NEW_TOKEN = 1 << 4, | |
| 74 | 74 | ORIGIN = 1 << 5, | |
| 75 | + APPLICATION = 1 << 6 | ||
| 75 | 76 | }; | |
| 76 | 77 | ||
| 77 | 78 | inline SessionListenerFlags operator|(SessionListenerFlags a, | |
@@ -3677,6 +3678,33 @@ void Session::EmitSessionTicket(Store&& ticket) { | |||
| 3677 | 3678 | } | |
| 3678 | 3679 | } | |
| 3679 | 3680 | ||
| 3681 | + void Session::EmitApplication() { | ||
| 3682 | + if (is_destroyed()) return; | ||
| 3683 | + if (!env()->can_call_into_js()) return; | ||
| 3684 | + | ||
| 3685 | + if (!has_application()) { | ||
| 3686 | + // The application has not yet been selected (ALPN negotiation is not | ||
| 3687 | + // yet complete on the server) or the session has been destroyed. In | ||
| 3688 | + // either case, the application options are not available. | ||
| 3689 | + // Should not happen, but we bail out | ||
| 3690 | + return; | ||
| 3691 | + } | ||
| 3692 | + | ||
| 3693 | + if (!HasListenerFlag(impl_->state()->listener_flags, | ||
| 3694 | + SessionListenerFlags::APPLICATION)) [[likely]] { | ||
| 3695 | + return; | ||
| 3696 | + } | ||
| 3697 | + | ||
| 3698 | + CallbackScope<Session> cb_scope(this); | ||
| 3699 | + | ||
| 3700 | + Local<Value> argv; | ||
| 3701 | + auto& options = application().options(); | ||
| 3702 | + if (options.ToObject(env()).ToLocal(&argv)) { | ||
| 3703 | + MakeCallback( | ||
| 3704 | + BindingData::Get(env()).session_application_callback(), 1, &argv); | ||
| 3705 | + } | ||
| 3706 | + } | ||
| 3707 | + | ||
| 3680 | 3708 | void Session::DestroyAllStreams(const QuicError& error) { | |
| 3681 | 3709 | DCHECK(!is_destroyed()); | |
| 3682 | 3710 | // Copy the streams map since streams remove themselves during | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -615,6 +615,7 @@ class Session final : public AsyncWrap, private SessionTicket::AppData::Source { | |||
| 615 | 615 | void EmitVersionNegotiation(const ngtcp2_pkt_hd& hd, | |
| 616 | 616 | const uint32_t* sv, | |
| 617 | 617 | size_t nsv); | |
| 618 | + void EmitApplication(); | ||
| 618 | 619 | void DatagramStatus(datagram_id datagramId, DatagramStatus status); | |
| 619 | 620 | void DatagramReceived(const uint8_t* data, | |
| 620 | 621 | size_t datalen, | |
| Back | FazBrowse Home | New Git URL |
0 commit comments