-
Notifications
You must be signed in to change notification settings - Fork 49
QUIC as a native addon (secondary option) #371
Comments
To provide additional context, here's a high-level summary of the current implementation: There are three essential dependencies:
From core, we depend on the following:
There's likely more that I'm forgetting and I will update the list as I remember them. As for the implementation itself... the key elements are:
Add to this a number of utility and helper classes such as QuicApplication (encapsulates the application protocol layer on top of a QuicSession), QuicCID (used as the identifier of a QuicSession), QuicPacket (encapsulates the serialized QUIC packet data to be sent), QuicBuffer (linked list of outbound application data waiting to be serialized into a QUIC packet), and so forth. The implementation:
The overwhelming majority of the implementation exists at the C++ level, with the JavaScript level focusing only on user facing public API elements. A key design goal of the internals is to make QUIC completely usable at the native layer so that we have the option of introducing new application protocols efficiently (http/3 is an example, a QUIC-based inspector protocol implementation replacing the websockets-based would be another example that I've been toying around with). By integrating these at the native layer the way that nghttp3 and Http3Application do, we allow ourselves to take advantage of key performance and implementation optimizations that simply aren't available at the JavaScript level. |
Good writeup and work @jasnell! |
I have started a native addon project called |
I'm not that involved with the addons. But if we think it would be reasonable to be able to implement QUIC in terms of an addon. Then doing the extra work required to sufficiently extend addons might be a big plus for other addons as well, e.g. AsyncWrap might be a good idea to expose regardless of this? @jasnell I remember you mentioning that you might want to consider having a look at http2 based on experience from the Quic work. Does this affect that in anyway? Also, once OpenSSL in Node core does catch up sufficiently. Would it be easy to consolidate? |
Doing it as an addon seems a mountain of work, tedious though it is, refactoring the PR3 so that it doesn't touch non-QUIC code (except in obviously correct ways) seems faster. I'd be willing to RSLGTM such a thing, but I don't feel as comfortable doing so for the PR as it is. |
Just opening this for discussion purposes. Because of the challenges presented by OpenSSL deciding not to land the QUIC related APIs until at least OpenSSL 3.1 (which likely won't happen until 2021 or 2022), the Node.js TSC has expressed some reluctance on landing the QUIC support in core because of the need to float patches on the OpenSSL 1.1.1 version that we ship. The key issues are that (a) the patches will need to be maintained for every 1.1.1 version bump, (b) anyone using openssl via shared library will not be able to use QUIC, and (c) the QUIC implementation would be forced to remain experimental until OpenSSL did officially support QUIC and could be forced to change should OpenSSL decide to go with a different API design than what BoringSSL has adopted.
Therefore, one of the possible paths forward here is to re-implement the QUIC support as a native add-on that statically links it's own modified OpenSSLrather than using core's.
I have started a separate project moving in that direction but there are a number of key challenges stemming from the number of core APIs we are using that are not available via N-API. These aren't difficult or impossible challenges to overcome, but combined they are non-trivial.
While we do not use the TLS/SSLWrap implementation from
node_crypto
, we do make use ofSecureContext
, which is, of course, backed by the OpenSSL version used by Core. As a standalone native addon with it's own separate linked version of OpenSSL, we shouldn't rely on core'sSecureContext
and instead should have an equivalent backed by the addons OpenSSL.The implementation builds directly on UDPWrap and StreamBase, neither of which have N-API equivalents and both of which are guarded by
NODE_WANT_INTERNALS)
. This is not a challenge if we just simply useNODE_WANT_INTERNALS=1
but then we bind ourselves to Node.js internals and fall into the traditional brittle native addon trap that N-API was meant to solve. We also make use of many of the utility macros, types, and functions that are scattered throughout core's internals (Debug, string encoding, Buffer, CHECK, AllocatedBuffer, AliasedArray, http_common, etc). All of which is guarded byNODE_WANT_INTERNALS
and not exposed in any way via N-API.This one is obvious... the addon would need it's own linked OpenSSL. This certainly should be possible but presents a number of challenges given how non-trivial the OpenSSL maintenance and build can be. We would end up duplicating much of the build dev that's currently in core to support it.
The native addon approach is certainly possible, and I already have a project scaffolded out in a repo that I can make public if folks want to help move things in that direction. There are certainly advantages to the addon approach in that the implementation would not be forced to be experimental for potentially years and could be made to work on existing LTS versions of Node.js. The plus side of having it as a native addon should not be discounted at all. If we can find good solutions to the above challenges, then I'm happy to move things in that direction.
/cc @mcollina @addaleax @bnoordhuis
The text was updated successfully, but these errors were encountered: