Skip to content

Create QUIC library that can be exposed to JS and uses the Node dgram module #1

Closed
@CMCDragonkai

Description

@CMCDragonkai

Specification

We need QUIC in order to simplify our networking stack in PK.

QUIC is a superior UDP layer that can make use of any UDP socket, and create multiplexed reliable streams. It is also capable of hole punching either just by attempting to send ping frames on the stream, or through the unreliable datagrams.

Our goals is to make use of a QUIC library, something that is compilable to desktop and mobile operating systems, expose its functionality to JS, but have the JS runtime manage the actual sockets.

On NodeJS, it can already manage the underlying UDP sockets, and by relying on NodeJS, it will also ensure that these sockets will mix well with the concurrency/parallelism used by the rest of the NodeJS system due to libuv and thus avoid creating a second IO system running in parallel.

On Mobile runtimes, they may not have a dgram module readily available. In such cases, having an IO runtime to supply the UDP sockets may be required. But it is likely there are already existing libraries that provide this like https://github.com/tradle/react-native-udp.

The underlying QUIC library there is expected to be agnostic to the socket runtime. It will give you data that you need to the UDP socket, and it will take data that comes of the UDP socket.

However it does need 2 major duties:

  1. The multiplexing and managing of streams.
  2. The encryption/decryption TLS side

Again if we want to stay cross platform, we would not want to bind into Node.js's openssl crypto. It would require instead that the library can take a callback of crypto routines to use. However I've found that this is generally not the case with most existing QUIC libraries. But let's see how we go with this.

Additional context

QUIC and NAPI-RS

Sub issues

Tasks

  1. Experiment with Neon or Napi-rs
  2. Experiment with quiche by cloudflare
  3. Create bridge code plumbing UDP sockets and QUIC functions
  4. Create self signed TLS certificate during development - Create QUIC library that can be exposed to JS and uses the Node dgram module #1 (comment)
  5. Extract out the TLS configuration so that it can be set via in-memory PEM variable and key variable. - 2 day - see Enable TLS Configuration with in-memory PEM strings #2
  6. Decide whether application protocols are necessary here, or abstract the quiche Config so the user can decide this (especially since this is not a HTTP3 library). - 0.5 day - see Check if application protocols are required #13
  7. Fix the timeout events and ensure that when a timeout occurs, that the connection gets cleaned up, and we are not inadvertently clearing the timeout due to null. Right now when a quiche client connects to the server, even after closing, the server side is keeping the connection alive. - 1 day
  8. We need lifecycle events for QUICConnection and QUICStream and QUICServer and QUICSocket. This will allow users to hook into the destruction of the object, and perhaps remove their event listeners. These events must be post-facto events. - 0.5 day
  9. [ ] Test the QUICStream and change to BYOB style, so that way there can be a byte buffer for it. Testing code should be able generator functions similar to our RPC handlers. - 1 day - see Fixed size buffer for QUICStream instead of object stream #5.
  10. Complete the QUICClient with the shared socket QUICSocket. - 3 day
  11. Test the multiplexing/demultipexing of the UDP socket with multiple QUICClient and a single QUICServer. - 1 day - See Test connection multiplexing across multiple servers and clients #14
  12. [ ] Test the error handling of the QUIC stream, and life cycle and destruction routines. - 1 day - Create tests for QUICStreams #10
  13. Benchmark this system, by sending lots of data through. - 1 day - See Create benchmarks for sending data #15
  14. Propagate the rinfo from the UDP datagram into the conn.recv() so that the streams (either during construction or otherwise) can have its rinfo updated. Perhaps we can just "set" the rinfo properties of the connection every time we do a conn.recv(). Or... we just mutate the conn parameters every time we receive a UDP packet. - See Propagate connection info along side stream creation #16
  15. Ensure that when a user asks stream.connection they can acquire the remote information and also all the remote peer's certificate chain. - See Propagate connection info along side stream creation #16
  16. [ ] Integrate dgram sending and recving for hole punching logic. - see Allow Bidirectional Hole Punching from QUICClient and QUICServer #4
  17. [ ] Integrate the napi program into the scripts/prebuild.js so we can actually build the package in a similar to other native packages we are using like js-db - see Packaging up js-quic for Linux, Windows, MacOS #7

Metadata

Metadata

Labels

developmentStandard developmentepicBig issue with multiple subissuesr&d:polykey:core activity 4End to End Networking behind Consumer NAT Devices

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions