mirror of
https://github.com/denoland/deno.git
synced 2025-10-02 07:01:16 +00:00
feat(unstable): Implement QUIC (#21942)
Implements a QUIC interface, loosely based on the WebTransport API (a future change could add the WebTransport API, built on top of this one). [quinn](https://docs.rs/quinn/latest/quinn/) is used for the underlying QUIC implementation, for a few reasons: - A cloneable "handle" api which fits quite nicely into deno resources. - Good collaboration with the rust ecosystem, especially rustls. - I like it. <!-- Before submitting a PR, please read https://deno.com/manual/contributing 1. Give the PR a descriptive title. Examples of good title: - fix(std/http): Fix race condition in server - docs(console): Update docstrings - feat(doc): Handle nested reexports Examples of bad title: - fix #7123 - update docs - fix bugs 2. Ensure there is a related issue and it is referenced in the PR text. 3. Ensure there are tests that cover the changes. 4. Ensure `cargo test` passes. 5. Ensure `./tools/format.js` passes without changing files. 6. Ensure `./tools/lint.js` passes. 7. Open as a draft PR if your work is still in progress. The CI won't run all steps, but you can add '[ci]' to a commit message to force it to. 8. If you would like to run the benchmarks on the CI, add the 'ci-bench' label. -->
This commit is contained in:
parent
23f7032d56
commit
65b647909d
12 changed files with 1591 additions and 19 deletions
288
ext/net/lib.deno_net.d.ts
vendored
288
ext/net/lib.deno_net.d.ts
vendored
|
@ -450,5 +450,293 @@ declare namespace Deno {
|
|||
options?: StartTlsOptions,
|
||||
): Promise<TlsConn>;
|
||||
|
||||
/**
|
||||
* **UNSTABLE**: New API, yet to be vetted.
|
||||
* @experimental
|
||||
* @category Network
|
||||
*/
|
||||
export interface QuicTransportOptions {
|
||||
/** Period of inactivity before sending a keep-alive packet. Keep-alive
|
||||
* packets prevent an inactive but otherwise healthy connection from timing
|
||||
* out. Only one side of any given connection needs keep-alive enabled for
|
||||
* the connection to be preserved.
|
||||
* @default {undefined}
|
||||
*/
|
||||
keepAliveInterval?: number;
|
||||
/** Maximum duration of inactivity to accept before timing out the
|
||||
* connection. The true idle timeout is the minimum of this and the peer’s
|
||||
* own max idle timeout.
|
||||
* @default {undefined}
|
||||
*/
|
||||
maxIdleTimeout?: number;
|
||||
/** Maximum number of incoming bidirectional streams that may be open
|
||||
* concurrently.
|
||||
* @default {100}
|
||||
*/
|
||||
maxConcurrentBidirectionalStreams?: number;
|
||||
/** Maximum number of incoming unidirectional streams that may be open
|
||||
* concurrently.
|
||||
* @default {100}
|
||||
*/
|
||||
maxConcurrentUnidirectionalStreams?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* **UNSTABLE**: New API, yet to be vetted.
|
||||
* @experimental
|
||||
* @category Network
|
||||
*/
|
||||
export interface ListenQuicOptions extends QuicTransportOptions {
|
||||
/** The port to connect to. */
|
||||
port: number;
|
||||
/**
|
||||
* A literal IP address or host name that can be resolved to an IP address.
|
||||
* @default {"0.0.0.0"}
|
||||
*/
|
||||
hostname?: string;
|
||||
/** Server private key in PEM format */
|
||||
key: string;
|
||||
/** Cert chain in PEM format */
|
||||
cert: string;
|
||||
/** Application-Layer Protocol Negotiation (ALPN) protocols to announce to
|
||||
* the client. QUIC requires the use of ALPN.
|
||||
*/
|
||||
alpnProtocols: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* **UNSTABLE**: New API, yet to be vetted.
|
||||
* Listen announces on the local transport address over QUIC.
|
||||
*
|
||||
* ```ts
|
||||
* const lstnr = await Deno.listenQuic({ port: 443, cert: "...", key: "...", alpnProtocols: ["h3"] });
|
||||
* ```
|
||||
*
|
||||
* Requires `allow-net` permission.
|
||||
*
|
||||
* @experimental
|
||||
* @tags allow-net
|
||||
* @category Network
|
||||
*/
|
||||
export function listenQuic(options: ListenQuicOptions): Promise<QuicListener>;
|
||||
|
||||
/**
|
||||
* **UNSTABLE**: New API, yet to be vetted.
|
||||
* @experimental
|
||||
* @category Network
|
||||
*/
|
||||
export interface ConnectQuicOptions extends QuicTransportOptions {
|
||||
/** The port to connect to. */
|
||||
port: number;
|
||||
/** A literal IP address or host name that can be resolved to an IP address. */
|
||||
hostname: string;
|
||||
/** The name used for validating the certificate provided by the server. If
|
||||
* not provided, defaults to `hostname`. */
|
||||
serverName?: string | undefined;
|
||||
/** Application-Layer Protocol Negotiation (ALPN) protocols supported by
|
||||
* the client. QUIC requires the use of ALPN.
|
||||
*/
|
||||
alpnProtocols: string[];
|
||||
/** A list of root certificates that will be used in addition to the
|
||||
* default root certificates to verify the peer's certificate.
|
||||
*
|
||||
* Must be in PEM format. */
|
||||
caCerts?: string[];
|
||||
/**
|
||||
* The congestion control algorithm used when sending data over this connection.
|
||||
*/
|
||||
congestionControl?: "throughput" | "low-latency";
|
||||
}
|
||||
|
||||
/**
|
||||
* **UNSTABLE**: New API, yet to be vetted.
|
||||
* Establishes a secure connection over QUIC using a hostname and port. The
|
||||
* cert file is optional and if not included Mozilla's root certificates will
|
||||
* be used. See also https://github.com/ctz/webpki-roots for specifics.
|
||||
*
|
||||
* ```ts
|
||||
* const caCert = await Deno.readTextFile("./certs/my_custom_root_CA.pem");
|
||||
* const conn1 = await Deno.connectQuic({ hostname: "example.com", port: 443, alpnProtocols: ["h3"] });
|
||||
* const conn2 = await Deno.connectQuic({ caCerts: [caCert], hostname: "example.com", port: 443, alpnProtocols: ["h3"] });
|
||||
* ```
|
||||
*
|
||||
* Requires `allow-net` permission.
|
||||
*
|
||||
* @experimental
|
||||
* @tags allow-net
|
||||
* @category Network
|
||||
*/
|
||||
export function connectQuic(options: ConnectQuicOptions): Promise<QuicConn>;
|
||||
|
||||
/**
|
||||
* **UNSTABLE**: New API, yet to be vetted.
|
||||
* @experimental
|
||||
* @category Network
|
||||
*/
|
||||
export interface QuicCloseInfo {
|
||||
/** A number representing the error code for the error. */
|
||||
closeCode: number;
|
||||
/** A string representing the reason for closing the connection. */
|
||||
reason: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* **UNSTABLE**: New API, yet to be vetted.
|
||||
* An incoming connection for which the server has not yet begun its part of the handshake.
|
||||
*
|
||||
* @experimental
|
||||
* @category Network
|
||||
*/
|
||||
export interface QuicIncoming {
|
||||
/**
|
||||
* The local IP address which was used when the peer established the connection.
|
||||
*/
|
||||
readonly localIp: string;
|
||||
|
||||
/**
|
||||
* The peer’s UDP address.
|
||||
*/
|
||||
readonly remoteAddr: NetAddr;
|
||||
|
||||
/**
|
||||
* Whether the socket address that is initiating this connection has proven that they can receive traffic.
|
||||
*/
|
||||
readonly remoteAddressValidated: boolean;
|
||||
|
||||
/**
|
||||
* Accept this incoming connection.
|
||||
*/
|
||||
accept(): Promise<QuicConn>;
|
||||
|
||||
/**
|
||||
* Refuse this incoming connection.
|
||||
*/
|
||||
refuse(): void;
|
||||
|
||||
/**
|
||||
* Ignore this incoming connection attempt, not sending any packet in response.
|
||||
*/
|
||||
ignore(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* **UNSTABLE**: New API, yet to be vetted.
|
||||
* Specialized listener that accepts QUIC connections.
|
||||
*
|
||||
* @experimental
|
||||
* @category Network
|
||||
*/
|
||||
export interface QuicListener extends AsyncIterable<QuicConn> {
|
||||
/** Return the address of the `QuicListener`. */
|
||||
readonly addr: NetAddr;
|
||||
|
||||
/** Waits for and resolves to the next connection to the `QuicListener`. */
|
||||
accept(): Promise<QuicConn>;
|
||||
|
||||
/** Waits for and resolves to the next incoming request to the `QuicListener`. */
|
||||
incoming(): Promise<QuicIncoming>;
|
||||
|
||||
/** Close closes the listener. Any pending accept promises will be rejected
|
||||
* with errors. */
|
||||
close(info: QuicCloseInfo): void;
|
||||
|
||||
[Symbol.asyncIterator](): AsyncIterableIterator<QuicConn>;
|
||||
}
|
||||
|
||||
/**
|
||||
* **UNSTABLE**: New API, yet to be vetted.
|
||||
*
|
||||
* @experimental
|
||||
* @category Network
|
||||
*/
|
||||
export interface QuicSendStreamOptions {
|
||||
/** Indicates the send priority of this stream relative to other streams for
|
||||
* which the value has been set.
|
||||
* @default {undefined}
|
||||
*/
|
||||
sendOrder?: number;
|
||||
/** Wait until there is sufficient flow credit to create the stream.
|
||||
* @default {false}
|
||||
*/
|
||||
waitUntilAvailable?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* **UNSTABLE**: New API, yet to be vetted.
|
||||
*
|
||||
* @experimental
|
||||
* @category Network
|
||||
*/
|
||||
export interface QuicConn {
|
||||
/** Close closes the listener. Any pending accept promises will be rejected
|
||||
* with errors. */
|
||||
close(info: QuicCloseInfo): void;
|
||||
/** Opens and returns a bidirectional stream. */
|
||||
createBidirectionalStream(
|
||||
options?: QuicSendStreamOptions,
|
||||
): Promise<QuicBidirectionalStream>;
|
||||
/** Opens and returns a unidirectional stream. */
|
||||
createUnidirectionalStream(
|
||||
options?: QuicSendStreamOptions,
|
||||
): Promise<QuicSendStream>;
|
||||
/** Send a datagram. The provided data cannot be larger than
|
||||
* `maxDatagramSize`. */
|
||||
sendDatagram(data: Uint8Array): Promise<void>;
|
||||
/** Receive a datagram. If no buffer is provider, one will be allocated.
|
||||
* The size of the provided buffer should be at least `maxDatagramSize`. */
|
||||
readDatagram(buffer?: Uint8Array): Promise<Uint8Array>;
|
||||
|
||||
/** Return the remote address for the connection. Clients may change
|
||||
* addresses at will, for example when switching to a cellular internet
|
||||
* connection.
|
||||
*/
|
||||
readonly remoteAddr: NetAddr;
|
||||
/** The negotiated ALPN protocol, if provided. */
|
||||
readonly protocol: string | undefined;
|
||||
/** Returns a promise that resolves when the connection is closed. */
|
||||
readonly closed: Promise<QuicCloseInfo>;
|
||||
/** A stream of bidirectional streams opened by the peer. */
|
||||
readonly incomingBidirectionalStreams: ReadableStream<
|
||||
QuicBidirectionalStream
|
||||
>;
|
||||
/** A stream of unidirectional streams opened by the peer. */
|
||||
readonly incomingUnidirectionalStreams: ReadableStream<QuicReceiveStream>;
|
||||
/** Returns the datagram stream for sending and receiving datagrams. */
|
||||
readonly maxDatagramSize: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* **UNSTABLE**: New API, yet to be vetted.
|
||||
*
|
||||
* @experimental
|
||||
* @category Network
|
||||
*/
|
||||
export interface QuicBidirectionalStream {
|
||||
/** Returns a QuicReceiveStream instance that can be used to read incoming data. */
|
||||
readonly readable: QuicReceiveStream;
|
||||
/** Returns a QuicSendStream instance that can be used to write outgoing data. */
|
||||
readonly writable: QuicSendStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* **UNSTABLE**: New API, yet to be vetted.
|
||||
*
|
||||
* @experimental
|
||||
* @category Network
|
||||
*/
|
||||
export interface QuicSendStream extends WritableStream<Uint8Array> {
|
||||
/** Indicates the send priority of this stream relative to other streams for
|
||||
* which the value has been set. */
|
||||
sendOrder: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* **UNSTABLE**: New API, yet to be vetted.
|
||||
*
|
||||
* @experimental
|
||||
* @category Network
|
||||
*/
|
||||
export interface QuicReceiveStream extends ReadableStream<Uint8Array> {}
|
||||
|
||||
export {}; // only export exports
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue