quico 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1,13 +1,63 @@
1
1
  /*
2
2
  * quico — TypeScript declarations
3
- * Pure JavaScript QUIC, HTTP/3, QPACK & WebTransport for Node.js
3
+ * A full HTTP stack in JavaScript: QUIC, HTTP/3, HTTP/2, HTTP/1.1, QPACK,
4
+ * WebTransport, WebSocket and CONNECT-UDP, for Node.js.
5
+ *
6
+ * The API mirrors node:https (server, request, Agent) and the browser's
7
+ * WebTransport and WebSocket. See README.md for every option and event.
4
8
  */
5
9
 
6
10
  /// <reference types="node" />
7
11
 
8
- import { IncomingMessage, ServerResponse } from 'node:http';
12
+ import { IncomingMessage as NodeIncomingMessage, ServerResponse as NodeServerResponse, ClientRequest as NodeClientRequest } from 'node:http';
9
13
  import { Duplex, Readable, Writable } from 'node:stream';
10
14
  import { EventEmitter } from 'node:events';
15
+ import { Socket as DgramSocket, RemoteInfo } from 'node:dgram';
16
+ import { Socket as NetSocket } from 'node:net';
17
+
18
+ // ============================================================
19
+ // Shared
20
+ // ============================================================
21
+
22
+ type PemInput = string | Buffer | Array<string | Buffer | { pem: string | Buffer; passphrase?: string }>;
23
+
24
+ /** RFC 9218 priority: urgency 0 (first) – 7, default 3. */
25
+ interface Priority {
26
+ urgency?: number;
27
+ incremental?: boolean;
28
+ }
29
+
30
+ /** QUIC's windows and stream limits, by RFC 9000's names in camelCase. */
31
+ interface TransportParams {
32
+ initialMaxData?: number;
33
+ initialMaxStreamDataBidiLocal?: number;
34
+ initialMaxStreamDataBidiRemote?: number;
35
+ initialMaxStreamDataUni?: number;
36
+ initialMaxStreamsBidi?: number;
37
+ initialMaxStreamsUni?: number;
38
+ maxIdleTimeout?: number;
39
+ disableActiveMigration?: boolean;
40
+ }
41
+
42
+ type StartupCap = 'stall' | 'always' | 'off';
43
+ type QuicVersion = 'v1' | 'v2' | number;
44
+
45
+ /** QUIC connection options, as the server, a request, WebTransport and connectUdp take them. */
46
+ interface QuicConnectionOptions {
47
+ initialCongestionWindow?: number;
48
+ startupCap?: StartupCap;
49
+ pmtuDiscovery?: boolean;
50
+ maxUdpPayloadSize?: number;
51
+ initialRtt?: number;
52
+ reorderWindow?: number;
53
+ }
54
+
55
+ /** A fingerprint: its hash, the raw string it was taken from, and its parts. */
56
+ interface Fingerprint {
57
+ hash: string;
58
+ raw: string;
59
+ [part: string]: any;
60
+ }
11
61
 
12
62
  // ============================================================
13
63
  // Server
@@ -15,144 +65,1051 @@ import { EventEmitter } from 'node:events';
15
65
 
16
66
  type RequestHandler = (req: QuicoIncomingMessage, res: QuicoServerResponse) => void;
17
67
 
18
- interface ServerOptions {
19
- key?: string | Buffer;
20
- cert?: string | Buffer;
21
- ca?: string | Buffer;
22
- SNICallback?: (servername: string, cb: (err: Error | null, ctx: any) => void) => void;
68
+ interface EchKey {
69
+ config: Uint8Array | Buffer;
70
+ privateKey: Uint8Array | Buffer;
71
+ /** false: kept to decrypt, not sent as retry_configs (rotation). */
72
+ retry?: boolean;
73
+ }
74
+
75
+ interface ConnectionOptionsInfo {
76
+ remoteAddress: string;
77
+ remotePort: number;
78
+ servername: string | null;
79
+ resumed: boolean;
80
+ previous: { rtt: number; bandwidth: number; age: number } | null;
81
+ }
82
+
83
+ interface ConnectionOptionsAnswer extends QuicConnectionOptions {
84
+ transportParams?: TransportParams;
85
+ carefulResume?: boolean;
86
+ }
87
+
88
+ interface ConnectUdpServerOptions {
89
+ template?: string;
90
+ allowPrivate?: boolean;
91
+ maxTunnelsPerConnection?: number;
92
+ idleTimeout?: number;
93
+ lookup?: (host: string, options: { all: true }, cb: (err: Error | null, addresses: Array<{ address: string; family: number }>) => void) => void;
94
+ proxyName?: string;
95
+ }
96
+
97
+ interface ServerOptions extends QuicConnectionOptions {
98
+ key?: PemInput;
99
+ cert?: PemInput;
100
+ ca?: PemInput;
101
+ passphrase?: string;
102
+ SNICallback?: (servername: string, cb: (err: Error | null, ctx?: any) => void, info?: { transport: 'tcp' | 'quic' }) => void;
103
+ http3?: boolean;
104
+ http2?: boolean;
105
+ http1?: boolean;
106
+ ALPNProtocols?: string[];
23
107
  maxConnections?: number;
108
+ ticketKeys?: Buffer;
109
+ ech?: { keys: EchKey[] };
110
+ earlyData?: boolean;
111
+ earlyDataMaxAge?: number;
112
+ earlyDataReplay?: (id: string, ttl: number, cb: (err: Error | null, isNew?: boolean) => void) => void;
113
+ earlyDataFilter?: (req: QuicoIncomingMessage, cb: (err: Error | null, allow?: boolean) => void) => void;
114
+ sessionTimeout?: number;
115
+ requestCert?: boolean;
116
+ rejectUnauthorized?: boolean;
117
+ minVersion?: 'TLSv1.2' | 'TLSv1.3';
118
+ maxVersion?: 'TLSv1.2' | 'TLSv1.3';
119
+ certificateCompression?: Array<'brotli' | 'zstd' | 'zlib'> | boolean;
120
+ honorCipherOrder?: boolean;
121
+ ciphers?: string;
122
+ ecdhCurve?: string;
123
+ sigalgs?: string;
124
+ handshakeTimeout?: number;
125
+ validateAddress?: boolean;
126
+ handshakeLoadThreshold?: number;
127
+ maxHandshakesPerAddress?: number;
128
+ resetTokenSecret?: Buffer;
129
+ tokenSecret?: Buffer;
130
+ socket?: DgramSocket;
131
+ socket6?: DgramSocket;
132
+ greaseQuicBit?: boolean;
133
+ port?: number;
134
+ altSvc?: string | false;
135
+ connectUdp?: ConnectUdpServerOptions;
136
+ shouldUpgradeCallback?: (req: QuicoIncomingMessage) => boolean;
137
+ headersTimeout?: number;
138
+ requestTimeout?: number;
139
+ keepAliveTimeout?: number;
140
+ streamResetBurst?: number;
141
+ streamResetRate?: number;
142
+ maxRequestsPerSocket?: number;
143
+ maxHeaderSize?: number;
144
+ maxHeaderCount?: number;
145
+ noDelay?: boolean;
146
+ keepAlive?: boolean;
147
+ keepAliveInitialDelay?: number;
148
+ transportParams?: TransportParams;
149
+ carefulResume?: boolean;
150
+ quicVersions?: QuicVersion[];
151
+ connectionOptions?: (info: ConnectionOptionsInfo, callback: (err: Error | null, options?: ConnectionOptionsAnswer) => void) => void;
152
+ maxWebTransportSessions?: number;
153
+ // HTTP/2 settings
154
+ maxConcurrentStreams?: number;
155
+ headerTableSize?: number;
156
+ initialWindowSize?: number;
157
+ maxFrameSize?: number;
158
+ maxHeaderListSize?: number;
159
+ connectionWindowSize?: number;
160
+ enableConnectProtocol?: boolean;
161
+ maxSessionMemory?: number;
162
+ }
163
+
164
+ /** The handle of an HTTP/2 or HTTP/3 connection ('connection', 'stream_open', 'stream_reset'). */
165
+ interface ConnectionHandle {
166
+ readonly remoteAddress: string;
167
+ readonly remotePort: number;
168
+ readonly destroyed?: boolean;
169
+ /** HTTP/3: 'h3'-side handle; HTTP/2: the session. */
170
+ readonly httpVersion?: string;
171
+ fingerprint(): Fingerprint | null;
172
+ sendRstStream(streamId: number, code: 'refused' | 'cancelled' | number): void;
173
+ goaway(code?: 'overloaded' | number): void;
174
+ destroy(code?: 'overloaded' | number): void;
175
+ /** QUIC only: this connection's options (see README "One connection's"). */
176
+ setOptions?(options: QuicConnectionOptions & { carefulResume?: boolean }): this;
177
+ getOptions?(): QuicConnectionOptions & { carefulResume?: boolean };
178
+ }
179
+
180
+ interface ServerStats {
181
+ connections: { quic: number; tcp: number };
182
+ handshakes: { quic: { completed: number; failed: number }; tcp: { completed: number; failed: number }; resumed: number };
183
+ protocols: { h3: number; h2: number; 'http/1.1': number; other: number };
184
+ earlyData: { accepted: number; rejected: number; tooEarly: number };
185
+ closes: {
186
+ quic: { sent: Record<string, number>; received: Record<string, number>; silent: number };
187
+ h3: { sent: Record<string, number>; received: Record<string, number> };
188
+ h2: { sent: Record<string, number>; received: Record<string, number> };
189
+ http1: { sent: Record<string, number> };
190
+ };
191
+ streamResets: {
192
+ h3: { sent: Record<string, number>; received: Record<string, number> };
193
+ h2: { sent: Record<string, number>; received: Record<string, number> };
194
+ };
195
+ amplificationBlocked: number;
196
+ internalErrors: number;
197
+ since: number;
198
+ uptime: number;
199
+ }
200
+
201
+ interface ConnectUdpTunnelStats {
202
+ target: { host: string; port: number };
203
+ address: string | null;
204
+ port: number | null;
205
+ httpVersion: string;
206
+ state: 'pending' | 'open' | 'closed';
207
+ transport: 'datagram' | 'capsule';
208
+ openedAt: number | null;
209
+ closedAt: number | null;
210
+ durationMs: number | null;
211
+ packetsFromClient: number;
212
+ bytesFromClient: number;
213
+ packetsToClient: number;
214
+ bytesToClient: number;
215
+ droppedFromClient: number;
216
+ droppedToClient: number;
217
+ }
218
+
219
+ /** A CONNECT-UDP request, server side ('connectUdp'). */
220
+ interface ConnectUdpTunnel extends EventEmitter {
221
+ readonly req: QuicoIncomingMessage;
222
+ readonly target: { host: string; port: number };
223
+ readonly state: 'pending' | 'open' | 'closed';
224
+ readonly closeReason: 'client' | 'local' | 'idle' | 'aborted' | 'socket' | 'rejected' | null;
225
+ readonly error: Error | null;
226
+ readonly stats: ConnectUdpTunnelStats;
227
+ accept(options?: {
228
+ target?: { host: string; port: number };
229
+ socket?: DgramSocket;
230
+ relay?: boolean;
231
+ headers?: Record<string, string | string[]>;
232
+ allowPrivate?: boolean;
233
+ }): void;
234
+ reject(status: number, headers?: Record<string, string | string[]>): void;
235
+ send(buf: Buffer | Uint8Array): boolean;
236
+ close(): void;
237
+ on(event: 'open', listener: () => void): this;
238
+ on(event: 'message', listener: (msg: Buffer) => void): this;
239
+ on(event: 'close', listener: (stats: ConnectUdpTunnelStats) => void): this;
240
+ on(event: string, listener: (...args: any[]) => void): this;
24
241
  }
25
242
 
26
243
  interface QuicoServer extends EventEmitter {
27
- listen(port: number, callback?: () => void): this;
244
+ listen(port?: number, callback?: () => void): this;
28
245
  listen(port: number, host: string, callback?: () => void): this;
29
- close(callback?: () => void): void;
246
+ /** As node:http's: requests in flight finish (HTTP/2, HTTP/3: GOAWAY), idle connections close now; then 'close'. */
247
+ close(callback?: (err?: Error) => void): this;
248
+ /** Connections with no request in flight, all versions. */
249
+ closeIdleConnections(): void;
250
+ /** Every connection, in flight or not (not HTTP/1.1 sockets handed to 'upgrade'). */
251
+ closeAllConnections(): void;
252
+ getConnections(callback: (err: Error | null, count: number) => void): this;
253
+ readonly listening: boolean;
254
+ headersTimeout: number;
255
+ requestTimeout: number;
256
+ /** HTTP/1.1. */
257
+ keepAliveTimeout: number;
258
+ /** HTTP/1.1. */
259
+ maxHeadersCount: number;
260
+ maxRequestsPerSocket: number;
261
+ ref(): this;
262
+ unref(): this;
263
+ [Symbol.asyncDispose](): Promise<void>;
264
+ /** node:tls's: the default certificate, from the next handshake on — all three versions. Throws on a bad one (the old stays). */
265
+ setSecureContext(options: { key?: PemInput | PemInput[]; cert?: PemInput | PemInput[]; ca?: PemInput; passphrase?: string } | ReturnType<typeof createSecureContext>): void;
266
+ /** node:tls's: a certificate for a name (SNI; '*.example.com' covers one label). */
267
+ addContext(hostname: string, context: { key?: PemInput | PemInput[]; cert?: PemInput | PemInput[]; ca?: PemInput; passphrase?: string } | ReturnType<typeof createSecureContext>): void;
268
+ address(): { address: string; family: string; port: number } | null;
269
+ handleConnection(socket: NetSocket): void;
270
+ setTimeout(msecs?: number, callback?: (socket: NetSocket) => void): this;
271
+ timeout: number;
272
+ /** External socket mode: feed a UDP datagram. */
273
+ handlePacket(msg: Buffer, rinfo: RemoteInfo): void;
274
+ /** External socket mode: whether a datagram belongs to a connection of this server. */
275
+ hasConnection(rinfo: RemoteInfo, msg?: Buffer): boolean;
276
+ addProtocol(name: string, handler: (socket: Duplex, protocol: string) => void, options?: { sniff?: (firstBytes: Buffer) => boolean | null }): this;
277
+ getTicketKeys(): Buffer;
278
+ setTicketKeys(keys: Buffer): void;
279
+ getEchKeys(): { keys: EchKey[] } | null;
280
+ setEchKeys(ech: { keys: EchKey[] }): void;
281
+ getValidateAddress(): boolean;
282
+ setValidateAddress(on: boolean): void;
283
+ getResetTokenSecret(): Buffer;
284
+ setResetTokenSecret(secret: Buffer): void;
285
+ getTokenSecret(): Buffer;
286
+ setTokenSecret(secret: Buffer): void;
287
+ setOptions(options: Partial<ServerOptions>): this;
288
+ getOptions(): ServerOptions;
289
+ getPendingHandshakes(): number;
290
+ getStats(): ServerStats;
291
+ getConnectUdpStats(): { active: number; accepted: number; rejected: number; closed: number; [counter: string]: number };
292
+
30
293
  on(event: 'request', listener: RequestHandler): this;
294
+ on(event: 'upgrade', listener: (req: QuicoIncomingMessage, socket: Duplex, head: Buffer) => void): this;
295
+ on(event: 'connectUdp', listener: (req: QuicoIncomingMessage, tunnel: ConnectUdpTunnel) => void): this;
296
+ on(event: 'timeout', listener: (socket: NetSocket) => void): this;
297
+ on(event: 'connection', listener: (conn: NetSocket | ConnectionHandle) => void): this;
298
+ on(event: 'secureConnection', listener: (conn: NetSocket | ConnectionHandle) => void): this;
299
+ on(event: 'stream_open', listener: (conn: ConnectionHandle, streamId: number) => void): this;
300
+ on(event: 'stream_reset', listener: (conn: ConnectionHandle, streamId: number, code: number) => void): this;
301
+ on(event: 'handshakeLoad', listener: (info: { pending: number; high: boolean }) => void): this;
302
+ on(event: 'OCSPRequest', listener: (certificate: Buffer, issuer: Buffer | null, callback: (err: Error | null, response: Buffer | null) => void) => void): this;
303
+ on(event: 'tlsClientError', listener: (err: Error, socket: NetSocket | ConnectionHandle) => void): this;
304
+ on(event: 'clientError', listener: (err: Error, socket: NetSocket) => void): this;
305
+ on(event: 'sessionError', listener: (err: Error, session: ConnectionHandle) => void): this;
31
306
  on(event: 'listening', listener: () => void): this;
307
+ on(event: 'close', listener: () => void): this;
32
308
  on(event: 'error', listener: (err: Error) => void): this;
33
309
  on(event: string, listener: (...args: any[]) => void): this;
34
310
  }
35
311
 
36
- interface QuicoIncomingMessage extends IncomingMessage {
37
- /** QUIC stream ID */
38
- streamId?: number;
312
+ // ============================================================
313
+ // Request, response
314
+ // ============================================================
315
+
316
+ /** A request on the server, or a response on the client (node:http's). */
317
+ interface QuicoIncomingMessage extends NodeIncomingMessage {
318
+ /** '3.0', '2.0' or '1.1'. */
319
+ httpVersion: string;
320
+ /** Server: true if it came in 0-RTT. Client: 'accepted', 'rejected' or null. */
321
+ earlyData: boolean | 'accepted' | 'rejected' | null;
322
+ /** HTTP/2 request's fingerprint. */
323
+ h2Fingerprint?(): Fingerprint;
324
+ /** HTTP/3 request's fingerprint. */
325
+ h3Fingerprint?(): Fingerprint;
39
326
 
40
- // WebTransport events (available after res.writeHead(200) on WT sessions)
41
- on(event: 'stream', listener: (stream: Duplex) => void): this;
42
- on(event: 'unidirectionalStream', listener: (stream: Readable) => void): this;
327
+ // ---- WebTransport (server, after res.writeHead(200) on a session) ----
328
+ /** The protocols the client offered (WT-Available-Protocols), in its order. */
329
+ webTransportProtocols?: string[];
330
+ /** The client's CLOSE_WEBTRANSPORT_SESSION, when it sent one. */
331
+ closeInfo?: WebTransportCloseInfo;
332
+ on(event: 'stream', listener: (stream: WebTransportNodeStream & Duplex) => void): this;
333
+ on(event: 'unidirectionalStream', listener: (stream: WebTransportNodeStream & Readable) => void): this;
43
334
  on(event: 'datagram', listener: (data: Buffer) => void): this;
44
- on(event: string, listener: (...args: any[]) => void): this;
45
- }
46
-
47
- interface QuicoServerResponse extends ServerResponse {
48
- // WebTransport methods (available after res.writeHead(200) on WT sessions)
49
- sendDatagram?(data: Buffer | Uint8Array | string): void;
50
- createBidirectionalStream?(): Duplex;
51
- createUnidirectionalStream?(): Writable;
335
+ on(event: 'draining', listener: () => void): this;
336
+ on(event: 'aborted', listener: () => void): this;
337
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
52
338
  }
53
339
 
340
+ interface QuicoServerResponse extends NodeServerResponse {
341
+ writeEarlyHints(hints: Record<string, string | string[]>, callback?: () => void): void;
342
+ /** HTTP/2 and HTTP/3: the response's priority (RFC 9218). */
343
+ setPriority(priority: Priority): void;
54
344
 
55
- // ============================================================
56
- // Client
57
- // ============================================================
345
+ // ---- WebTransport (after res.writeHead(200) on a session) ----
346
+ /** true when queued, false when it cannot be sent at all. */
347
+ sendDatagram?(data: Buffer | Uint8Array | string, options?: WebTransportSendOptions): boolean;
348
+ maxDatagramSize?(): number;
349
+ readonly datagrams?: WebTransportDatagramDuplexStream | null;
350
+ getStats?(): Promise<WebTransportConnectionStats | null>;
351
+ exportKeyingMaterial?(label: BufferSource, context: BufferSource, outputLength: number): Promise<Uint8Array>;
352
+ /** null, without waitUntilAvailable, past the client's MAX_STREAMS. */
353
+ createBidirectionalStream?(options?: WebTransportSendStreamOptions | null, callback?: (err: Error | null, stream?: WebTransportNodeStream & Duplex) => void): (WebTransportNodeStream & Duplex) | null;
354
+ createUnidirectionalStream?(options?: WebTransportSendStreamOptions | null, callback?: (err: Error | null, stream?: WebTransportNodeStream & Writable) => void): (WebTransportNodeStream & Writable) | null;
355
+ canOpenStream?(options?: { bidirectional?: boolean }): boolean;
356
+ createSendGroup?(): WebTransportSendGroup;
357
+ /** Before writeHead(200): the protocol chosen among req.webTransportProtocols. */
358
+ setWebTransportProtocol?(name: string): void;
359
+ closeSession?(code?: number, reason?: string): void;
360
+ drainSession?(): void;
361
+ }
58
362
 
59
- interface RequestOptions {
363
+ interface RequestOptions extends QuicConnectionOptions {
364
+ protocol?: string;
60
365
  hostname?: string;
61
366
  host?: string;
62
367
  port?: number;
63
368
  path?: string;
64
369
  method?: string;
65
- headers?: Record<string, string | string[]>;
66
- agent?: QuicoAgent;
370
+ headers?: Record<string, string | string[] | number>;
371
+ priority?: Priority;
372
+ ech?: Buffer | Uint8Array | string;
373
+ echGrease?: boolean;
374
+ ecdhCurve?: string;
375
+ sigalgs?: string;
67
376
  rejectUnauthorized?: boolean;
377
+ ca?: PemInput;
378
+ key?: PemInput;
379
+ cert?: PemInput;
380
+ passphrase?: string;
381
+ servername?: string;
382
+ earlyData?: boolean;
383
+ session?: Buffer;
384
+ requestOCSP?: boolean;
385
+ quicVersions?: QuicVersion[];
386
+ agent?: Agent | false;
387
+ http2?: boolean;
388
+ http1?: boolean;
389
+ h3Timeout?: number;
68
390
  timeout?: number;
69
391
  }
70
392
 
71
- interface QuicoClientRequest extends Writable {
393
+ interface QuicoClientRequest extends NodeClientRequest {
394
+ /** The transport actually used: 'h3', 'h2' or 'https'. */
395
+ protocol: string;
396
+ setPriority(priority: Priority): void;
72
397
  on(event: 'response', listener: (res: QuicoIncomingMessage) => void): this;
73
- on(event: 'error', listener: (err: Error) => void): this;
74
- on(event: 'timeout', listener: () => void): this;
75
- on(event: string, listener: (...args: any[]) => void): this;
76
- end(data?: string | Buffer): this;
77
- abort(): void;
78
- setTimeout(ms: number, callback?: () => void): this;
398
+ on(event: 'session', listener: (session: Buffer) => void): this;
399
+ on(event: 'OCSPResponse', listener: (response: Buffer) => void): this;
400
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
79
401
  }
80
402
 
81
-
82
403
  // ============================================================
83
404
  // Agent
84
405
  // ============================================================
85
406
 
86
- interface QuicoAgent {
87
- destroy(): void;
407
+ interface AgentOptions {
408
+ http2?: boolean;
409
+ http1?: boolean;
410
+ h3Timeout?: number;
411
+ keepAlive?: boolean;
412
+ keepAliveMsecs?: number;
413
+ maxSockets?: number;
414
+ maxFreeSockets?: number;
415
+ timeout?: number;
416
+ maxCachedSessions?: number;
417
+ ecdhCurve?: string;
88
418
  }
89
419
 
420
+ declare class Agent extends EventEmitter {
421
+ constructor(options?: AgentOptions);
422
+ getName(options?: RequestOptions): string;
423
+ destroy(): void;
424
+ }
90
425
 
91
426
  // ============================================================
92
- // WebTransport
427
+ // WebTransport — the browser's API (W3C), and a Node-style one
93
428
  // ============================================================
94
429
 
95
- interface WebTransportOptions {
96
- /** Skip certificate verification (default: true for self-signed) */
430
+ type WebTransportReliabilityMode = 'pending' | 'reliable-only' | 'supports-unreliable';
431
+ type WebTransportCongestionControl = 'default' | 'throughput' | 'low-latency';
432
+ type WebTransportErrorSource = 'stream' | 'session';
433
+
434
+ interface WebTransportHash {
435
+ algorithm: string;
436
+ value: BufferSource;
437
+ }
438
+
439
+ interface WebTransportCloseInfo {
440
+ closeCode?: number;
441
+ reason?: string;
442
+ }
443
+
444
+ interface WebTransportSendOptions {
445
+ sendGroup?: WebTransportSendGroup | null;
446
+ sendOrder?: number;
447
+ }
448
+
449
+ interface WebTransportSendStreamOptions extends WebTransportSendOptions {
450
+ waitUntilAvailable?: boolean;
451
+ }
452
+
453
+ interface WebTransportDatagramStats {
454
+ droppedIncoming: number;
455
+ expiredIncoming: number;
456
+ expiredOutgoing: number;
457
+ lostOutgoing: number | null;
458
+ }
459
+
460
+ interface WebTransportConnectionStats {
461
+ timestamp: number;
462
+ /** The application's bytes: new stream data and datagram payloads (no framing, no retransmissions). */
463
+ bytesSent: number | null;
464
+ bytesSentOverhead: number | null;
465
+ bytesAcknowledged: number | null;
466
+ packetsSent: number | null;
467
+ bytesLost: number | null;
468
+ packetsLost: number | null;
469
+ bytesReceived: number | null;
470
+ packetsReceived: number | null;
471
+ smoothedRtt: number | null;
472
+ rttVariation: number | null;
473
+ minRtt: number | null;
474
+ /** Bits per second; null until measured. */
475
+ estimatedSendRate: number | null;
476
+ atSendCapacity: boolean | null;
477
+ /** QUICO's: the congestion window, and the bytes in flight. */
478
+ congestionWindow: number | null;
479
+ bytesInFlight: number | null;
480
+ datagrams: WebTransportDatagramStats;
481
+ }
482
+
483
+ interface WebTransportSendStreamStats {
484
+ bytesWritten: number;
485
+ bytesSent: number;
486
+ bytesAcknowledged: number;
487
+ }
488
+
489
+ interface WebTransportReceiveStreamStats {
490
+ bytesReceived: number;
491
+ bytesRead: number;
492
+ }
493
+
494
+ interface WebTransportOptions extends QuicConnectionOptions {
495
+ // ---- The browser's ----
496
+ allowPooling?: boolean;
497
+ requireUnreliable?: boolean;
498
+ /** The browser's HeadersInit: a Headers, [name, value] pairs, or an object. */
499
+ headers?: HeadersInit | Record<string, string | string[]>;
500
+ serverCertificateHashes?: WebTransportHash[];
501
+ congestionControl?: WebTransportCongestionControl;
502
+ anticipatedConcurrentIncomingUnidirectionalStreams?: number | null;
503
+ anticipatedConcurrentIncomingBidirectionalStreams?: number | null;
504
+ protocols?: string[];
505
+ datagramsReadableType?: 'bytes';
506
+ // ---- Node's (as https.request / QUICO's WebSocket) ----
507
+ /** Sent as Origin on the CONNECT (a browser sends its page's). */
508
+ origin?: string;
509
+ /** Verify the server's certificate (default true). */
97
510
  rejectUnauthorized?: boolean;
511
+ ca?: PemInput;
512
+ key?: PemInput;
513
+ cert?: PemInput;
514
+ passphrase?: string;
515
+ /** A TLS session from an earlier 'session' event, to resume with. */
516
+ session?: Buffer;
517
+ transportParams?: TransportParams;
518
+ quicVersions?: QuicVersion[];
519
+ ech?: Buffer | Uint8Array | string;
520
+ echGrease?: boolean;
521
+ ecdhCurve?: string;
522
+ sigalgs?: string;
523
+ }
524
+
525
+ /** The browser's WebTransportError: a DOMException named 'WebTransportError'. */
526
+ declare class WebTransportError extends DOMException {
527
+ constructor(message?: string, options?: { source?: WebTransportErrorSource; streamErrorCode?: number | null });
528
+ constructor(init: { message?: string; source?: WebTransportErrorSource; streamErrorCode?: number | null });
529
+ readonly source: WebTransportErrorSource;
530
+ readonly streamErrorCode: number | null;
531
+ /** QUICO's Node code, where it gives one (e.g. 'ERR_WEBTRANSPORT_SESSION_LOST'), in place of DOMException's number. */
532
+ readonly code: any;
533
+ /** The QUIC close that lost the session, when the peer closed the connection. */
534
+ readonly quicError?: { code: number; application: boolean; reason: string };
535
+ }
536
+
537
+ declare class WebTransportSendGroup {
538
+ private constructor();
539
+ getStats(): Promise<WebTransportSendStreamStats>;
540
+ }
541
+
542
+ declare class WebTransportWriter extends WritableStreamDefaultWriter<BufferSource> {
543
+ private constructor();
544
+ /** Sent only if all of it fits the flow-control window; otherwise rejects with an AbortError. */
545
+ atomicWrite(chunk: BufferSource): Promise<void>;
546
+ /** What was written so far reaches the peer even if the stream is aborted later (RESET_STREAM_AT). */
547
+ commit(): void;
548
+ }
549
+
550
+ declare class WebTransportSendStream extends WritableStream<BufferSource> {
551
+ private constructor();
552
+ sendGroup: WebTransportSendGroup | null;
553
+ sendOrder: number;
554
+ getWriter(): WebTransportWriter;
555
+ getStats(): Promise<WebTransportSendStreamStats>;
556
+ }
557
+
558
+ /** A byte stream: getReader({ mode: 'byob' }) works. */
559
+ declare class WebTransportReceiveStream extends ReadableStream<Uint8Array> {
560
+ private constructor();
561
+ getStats(): Promise<WebTransportReceiveStreamStats>;
562
+ }
563
+
564
+ /** What a stream also is in QUICO: a Node stream with these. */
565
+ interface WebTransportNodeStream {
566
+ readonly id: number;
567
+ readonly sessionId: number;
568
+ readonly sendState: 'open' | 'finished' | 'committed' | 'reset' | 'stopped' | null;
569
+ readonly recvState: 'open' | 'finished' | 'reset' | 'stopped' | null;
570
+ readonly pending: boolean;
571
+ readonly reliableResetSupported: boolean;
572
+ readonly streamErrorCode: number | null;
573
+ sendOrder: number;
574
+ sendGroup: WebTransportSendGroup | null;
575
+ resetStream(code?: number, options?: { reliableSize?: number }): boolean;
576
+ stopSending(code?: number): void;
577
+ getStats(): Promise<Partial<WebTransportSendStreamStats & WebTransportReceiveStreamStats>>;
578
+ on(event: 'peerReset' | 'peerStopSending', listener: (code: number | null) => void): this;
579
+ on(event: 'committed' | 'ready', listener: () => void): this;
580
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
581
+ }
582
+
583
+ /**
584
+ * The browser's WebTransportBidirectionalStream. In QUICO it is a Node
585
+ * Duplex with the browser's .readable and .writable; instanceof recognises it.
586
+ */
587
+ declare class WebTransportBidirectionalStream {
588
+ private constructor();
589
+ readonly readable: WebTransportReceiveStream;
590
+ readonly writable: WebTransportSendStream;
591
+ }
592
+ type WebTransportBidirectionalNodeStream = WebTransportBidirectionalStream & WebTransportNodeStream & Duplex;
593
+
594
+ /** createUnidirectionalStream(): the browser's send stream, and Node's Writable on it. */
595
+ type WebTransportUnidirectionalNodeStream = WebTransportSendStream & {
596
+ write(chunk: any, cb?: (err?: Error | null) => void): boolean;
597
+ write(chunk: any, encoding: BufferEncoding, cb?: (err?: Error | null) => void): boolean;
598
+ end(chunk?: any, cb?: () => void): void;
599
+ destroy(err?: Error): void;
600
+ resetStream(code?: number, options?: { reliableSize?: number }): boolean;
601
+ readonly id: number;
602
+ readonly sessionId: number;
603
+ readonly sendState: 'open' | 'finished' | 'committed' | 'reset' | 'stopped';
604
+ readonly pending: boolean;
605
+ readonly writableLength: number;
606
+ readonly writableNeedDrain: boolean;
607
+ on(event: string | symbol, listener: (...args: any[]) => void): any;
608
+ once(event: string | symbol, listener: (...args: any[]) => void): any;
609
+ };
610
+
611
+ declare class WebTransportDatagramsWritable extends WritableStream<BufferSource> {
612
+ private constructor();
613
+ sendGroup: WebTransportSendGroup | null;
614
+ sendOrder: number;
615
+ }
616
+
617
+ declare class WebTransportDatagramDuplexStream {
618
+ private constructor();
619
+ createWritable(options?: WebTransportSendOptions): WebTransportDatagramsWritable;
620
+ readonly readable: ReadableStream<Uint8Array>;
621
+ readonly maxDatagramSize: number;
622
+ /** ms; null (or 0 set) is none. */
623
+ incomingMaxAge: number | null;
624
+ outgoingMaxAge: number | null;
625
+ incomingMaxBufferedDatagrams: number;
626
+ outgoingMaxBufferedDatagrams: number;
627
+ /** @deprecated The spec's earlier names: use createWritable() and …MaxBufferedDatagrams. */
628
+ readonly writable: WebTransportDatagramsWritable;
629
+ /** @deprecated Use incomingMaxBufferedDatagrams. */
630
+ incomingHighWaterMark: number;
631
+ /** @deprecated Use outgoingMaxBufferedDatagrams. */
632
+ outgoingHighWaterMark: number;
98
633
  }
99
634
 
100
635
  declare class WebTransport extends EventEmitter {
101
- constructor(url: string, options?: WebTransportOptions);
636
+ constructor(url: string | URL, options?: WebTransportOptions);
102
637
 
103
- /** Resolves when the WebTransport session is established */
638
+ // ---- The browser's ----
104
639
  readonly ready: Promise<void>;
105
- /** Current state: 'connecting' | 'connected' | 'closed' */
106
- readonly state: string;
107
- /** The URL of the WebTransport session */
640
+ readonly closed: Promise<WebTransportCloseInfo>;
641
+ readonly draining: Promise<void>;
642
+ readonly reliability: WebTransportReliabilityMode;
643
+ readonly congestionControl: WebTransportCongestionControl;
644
+ readonly protocol: string;
645
+ /** The server's answer to the CONNECT (immutable); null until ready. */
646
+ readonly responseHeaders: Headers | null;
647
+ anticipatedConcurrentIncomingUnidirectionalStreams: number | null;
648
+ anticipatedConcurrentIncomingBidirectionalStreams: number | null;
649
+ readonly datagrams: WebTransportDatagramDuplexStream;
650
+ readonly incomingBidirectionalStreams: ReadableStream<WebTransportBidirectionalNodeStream>;
651
+ readonly incomingUnidirectionalStreams: ReadableStream<WebTransportReceiveStream>;
652
+ /** false: HTTP/3 only. */
653
+ static readonly supportsReliableOnly: boolean;
654
+
655
+ close(closeInfo?: WebTransportCloseInfo): void;
656
+ getStats(): Promise<WebTransportConnectionStats>;
657
+ exportKeyingMaterial(label: BufferSource, context: BufferSource, outputLength: number): Promise<Uint8Array>;
658
+ createBidirectionalStream(options?: WebTransportSendStreamOptions): Promise<WebTransportBidirectionalNodeStream>;
659
+ createUnidirectionalStream(options?: WebTransportSendStreamOptions): Promise<WebTransportUnidirectionalNodeStream>;
660
+ createSendGroup(): WebTransportSendGroup;
661
+
662
+ // ---- QUICO's, for Node code ----
663
+ /** 'connecting', 'connected', 'closed' or 'failed'. */
664
+ readonly state: 'connecting' | 'connected' | 'closed' | 'failed';
108
665
  readonly url: string;
666
+ /** The server's CLOSE_WEBTRANSPORT_SESSION, or ours. */
667
+ readonly closeInfo?: WebTransportCloseInfo;
668
+ canOpenStream(options?: { bidirectional?: boolean }): boolean;
669
+ /** true when queued, false when it cannot be sent at all. */
670
+ sendDatagram(data: Buffer | Uint8Array | string, options?: WebTransportSendOptions): boolean;
671
+ maxDatagramSize(): number;
109
672
 
110
- /** WHATWG-style datagram interface */
111
- readonly datagrams: {
112
- readonly readable: ReadableStream<Uint8Array>;
113
- readonly writable: WritableStream<Uint8Array>;
114
- };
673
+ on(event: 'ready' | 'draining' | 'close', listener: () => void): this;
674
+ on(event: 'stream', listener: (stream: WebTransportBidirectionalNodeStream) => void): this;
675
+ on(event: 'unidirectionalStream', listener: (stream: WebTransportNodeStream & Readable) => void): this;
676
+ on(event: 'datagram', listener: (data: Buffer) => void): this;
677
+ on(event: 'session', listener: (session: Buffer) => void): this;
678
+ on(event: 'error', listener: (err: WebTransportError) => void): this;
679
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
680
+ }
681
+
682
+ // ============================================================
683
+ // WebSocket
684
+ // ============================================================
685
+
686
+ interface WebSocketClientOptions {
687
+ origin?: string;
688
+ headers?: Record<string, string | string[]>;
689
+ ca?: PemInput;
690
+ rejectUnauthorized?: boolean;
691
+ maxPayload?: number;
692
+ agent?: Agent;
693
+ session?: Buffer;
694
+ }
695
+
696
+ /**
697
+ * The ws package's listeners, beside the browser's addEventListener: they get
698
+ * Node-style arguments ('message': (data, isBinary); 'close': (code, reason)).
699
+ */
700
+ interface WebSocketNodeEvents<T> {
701
+ on(event: 'message', listener: (this: T, data: Buffer, isBinary: boolean) => void): T;
702
+ on(event: 'close', listener: (this: T, code: number, reason: Buffer) => void): T;
703
+ on(event: 'ping' | 'pong', listener: (this: T, data: Buffer) => void): T;
704
+ on(event: 'open', listener: (this: T) => void): T;
705
+ on(event: 'error', listener: (this: T, err: Error) => void): T;
706
+ on(event: 'session', listener: (this: T, session: Buffer) => void): T;
707
+ on(event: string, listener: (this: T, ...args: any[]) => void): T;
708
+ once(event: string, listener: (this: T, ...args: any[]) => void): T;
709
+ addListener(event: string, listener: (this: T, ...args: any[]) => void): T;
710
+ off(event: string, listener: (...args: any[]) => void): T;
711
+ removeListener(event: string, listener: (...args: any[]) => void): T;
712
+ removeAllListeners(event?: string): T;
713
+ listenerCount(event: string): number;
714
+ eventNames(): string[];
715
+ }
115
716
 
116
- /** Create a bidirectional stream (Node.js Duplex + WHATWG .readable/.writable) */
117
- createBidirectionalStream(): Promise<Duplex & {
118
- readonly readable: ReadableStream<Uint8Array>;
119
- readonly writable: WritableStream<Uint8Array>;
120
- }>;
717
+ /** What a WebSocket has, client or server side: the browser's interface, ping() and onpong. */
718
+ interface WebSocketBase extends EventTarget {
719
+ readonly CONNECTING: 0;
720
+ readonly OPEN: 1;
721
+ readonly CLOSING: 2;
722
+ readonly CLOSED: 3;
723
+ readonly url: string;
724
+ readonly readyState: 0 | 1 | 2 | 3;
725
+ readonly bufferedAmount: number;
726
+ readonly protocol: string;
727
+ readonly extensions: string;
728
+ /** 'blob' (the browser's default) or 'arraybuffer'; 'nodebuffer' too. */
729
+ binaryType: 'blob' | 'arraybuffer' | 'nodebuffer';
730
+ onopen: ((event: Event) => void) | null;
731
+ onmessage: ((event: MessageEvent) => void) | null;
732
+ onerror: ((event: Event) => void) | null;
733
+ onclose: ((event: CloseEvent) => void) | null;
734
+ /** Not in the browser: the answer to ping(). */
735
+ onpong: ((event: Event) => void) | null;
736
+ /** options (the ws package's): binary forces a frame's type. */
737
+ send(data: string | ArrayBufferLike | ArrayBufferView | Blob, options?: { binary?: boolean }): void;
738
+ /** Not in the browser: a keepalive for a long-lived connection. */
739
+ ping(data?: string | Buffer | Uint8Array): void;
740
+ close(code?: number, reason?: string): void;
741
+ }
121
742
 
122
- /** Create a unidirectional stream for writing */
123
- createUnidirectionalStream(): Promise<Writable>;
743
+ /** The browser's WebSocket (WHATWG), with a third argument for Node's options. */
744
+ declare class WebSocket extends EventTarget implements WebSocketBase {
745
+ /** protocols may also be an options bag, { protocols } (as WPT has it). */
746
+ constructor(url: string | URL, protocols?: string | string[] | { protocols?: string | string[] }, options?: WebSocketClientOptions);
747
+ static readonly CONNECTING: 0;
748
+ static readonly OPEN: 1;
749
+ static readonly CLOSING: 2;
750
+ static readonly CLOSED: 3;
751
+ readonly CONNECTING: 0;
752
+ readonly OPEN: 1;
753
+ readonly CLOSING: 2;
754
+ readonly CLOSED: 3;
755
+ readonly url: string;
756
+ readonly readyState: 0 | 1 | 2 | 3;
757
+ readonly bufferedAmount: number;
758
+ readonly protocol: string;
759
+ readonly extensions: string;
760
+ binaryType: 'blob' | 'arraybuffer' | 'nodebuffer';
761
+ onopen: ((event: Event) => void) | null;
762
+ onmessage: ((event: MessageEvent) => void) | null;
763
+ onerror: ((event: Event) => void) | null;
764
+ onclose: ((event: CloseEvent) => void) | null;
765
+ onpong: ((event: Event) => void) | null;
766
+ send(data: string | ArrayBufferLike | ArrayBufferView | Blob, options?: { binary?: boolean }): void;
767
+ ping(data?: string | Buffer | Uint8Array): void;
768
+ close(code?: number, reason?: string): void;
769
+ }
770
+ interface WebSocket extends WebSocketNodeEvents<WebSocket> {}
124
771
 
125
- /** Send an unreliable datagram */
126
- sendDatagram(data: Buffer | Uint8Array): void;
772
+ interface WebSocketStreamOptions extends WebSocketClientOptions {
773
+ protocols?: string[];
774
+ signal?: AbortSignal;
775
+ }
776
+ interface WebSocketOpenInfo {
777
+ /** One chunk per message: a string for text, a Uint8Array for binary. */
778
+ readable: ReadableStream<string | Uint8Array>;
779
+ /** An ArrayBuffer or a view goes as binary, anything else as text. */
780
+ writable: WritableStream<string | BufferSource>;
781
+ protocol: string;
782
+ extensions: string;
783
+ }
784
+ interface WebSocketCloseInfo {
785
+ closeCode?: number;
786
+ reason?: string;
787
+ }
127
788
 
128
- /** Close the WebTransport session */
129
- close(info?: { closeCode?: number; reason?: string }): void;
789
+ /**
790
+ * EXPERIMENTAL — the browser's streams WebSocket (WICG explainer; Chrome has
791
+ * it, not yet a standard). Backpressure both ways: an unread message pauses
792
+ * the socket; write() resolves once the frame is sent.
793
+ */
794
+ declare class WebSocketStream {
795
+ constructor(url: string | URL, options?: WebSocketStreamOptions);
796
+ readonly url: string;
797
+ readonly opened: Promise<WebSocketOpenInfo>;
798
+ readonly closed: Promise<{ closeCode: number; reason: string }>;
799
+ close(closeInfo?: WebSocketCloseInfo): void;
800
+ }
130
801
 
131
- on(event: 'datagram', listener: (data: Buffer) => void): this;
132
- on(event: 'close', listener: () => void): this;
802
+ /** The error of a WebSocketStream: a DOMException named 'WebSocketError'. */
803
+ declare class WebSocketError extends DOMException {
804
+ constructor(message?: string, init?: WebSocketCloseInfo);
805
+ readonly closeCode: number | null;
806
+ readonly reason: string;
807
+ }
808
+
809
+ /** A connection a WebSocketServer accepted (or upgradeWebSocket made). */
810
+ interface ServerWebSocket extends WebSocketBase, WebSocketNodeEvents<ServerWebSocket> {}
811
+
812
+ interface UpgradeWebSocketOptions {
813
+ origin?: string | string[] | ((origin: string, req: QuicoIncomingMessage) => boolean);
814
+ verifyClient?: (req: QuicoIncomingMessage) => boolean | { code: number; message?: string; headers?: Record<string, string> };
815
+ protocol?: string | ((offered: string[], req: QuicoIncomingMessage) => string | false | null | undefined);
816
+ protocols?: string[];
817
+ headers?: Record<string, string | string[]>;
818
+ maxPayload?: number;
819
+ }
820
+
821
+ interface WebSocketServerOptions extends UpgradeWebSocketOptions {
822
+ server?: QuicoServer;
823
+ noServer?: boolean;
824
+ path?: string;
825
+ pingInterval?: number;
826
+ }
827
+
828
+ declare class WebSocketServer extends EventTarget {
829
+ constructor(options: WebSocketServerOptions);
830
+ readonly clients: Set<ServerWebSocket>;
831
+ onconnection: ((event: Event & { socket?: ServerWebSocket; request?: QuicoIncomingMessage }) => void) | null;
832
+ handleUpgrade(req: QuicoIncomingMessage, socket: Duplex, head: Buffer, cb: (ws: ServerWebSocket, req: QuicoIncomingMessage) => void): void;
833
+ startAutoPing(intervalMs: number): void;
834
+ stopAutoPing(): void;
835
+ close(code?: number, reason?: string): void;
836
+ on(event: 'connection', listener: (ws: ServerWebSocket, req: QuicoIncomingMessage) => void): this;
133
837
  on(event: string, listener: (...args: any[]) => void): this;
838
+ once(event: string, listener: (...args: any[]) => void): this;
839
+ off(event: string, listener: (...args: any[]) => void): this;
840
+ }
841
+
842
+ /** The socket, or null after answering the client itself (403, 401, …). */
843
+ declare function upgradeWebSocket(req: QuicoIncomingMessage, socket: Duplex, head: Buffer, options?: UpgradeWebSocketOptions): ServerWebSocket | null;
844
+
845
+ // ============================================================
846
+ // CONNECT-UDP client
847
+ // ============================================================
848
+
849
+ interface ConnectUdpOptions extends QuicConnectionOptions {
850
+ protocol?: 'auto' | 'h3' | 'h2' | 'http/1.1';
851
+ h3Timeout?: number;
852
+ fallback?: boolean;
853
+ shareConnection?: boolean;
854
+ headers?: Record<string, string | string[]>;
855
+ ech?: Buffer | Uint8Array | string;
856
+ echGrease?: boolean;
857
+ ecdhCurve?: string;
858
+ sigalgs?: string;
859
+ template?: string;
860
+ rejectUnauthorized?: boolean;
861
+ ca?: PemInput;
862
+ key?: PemInput;
863
+ cert?: PemInput;
864
+ passphrase?: string;
865
+ servername?: string;
866
+ quicVersions?: QuicVersion[];
867
+ agent?: Agent | false;
868
+ session?: Buffer;
869
+ }
870
+
871
+ interface UdpProxySocketStats {
872
+ protocol: string | null;
873
+ transport: 'datagram' | 'capsule' | null;
874
+ target: { host: string; port: number };
875
+ openedAt: number | null;
876
+ closedAt: number | null;
877
+ durationMs: number | null;
878
+ packetsSent: number;
879
+ bytesSent: number;
880
+ packetsReceived: number;
881
+ bytesReceived: number;
882
+ dropped: number;
883
+ }
884
+
885
+ /** A UDP socket through a proxy, behaving as a connected dgram.Socket. */
886
+ interface UdpProxySocket extends EventEmitter {
887
+ send(msg: string | Buffer | Uint8Array | ReadonlyArray<string | Buffer | Uint8Array>, callback?: (err: Error | null, bytes?: number) => void): void;
888
+ send(msg: Buffer | Uint8Array, offset: number, length: number, callback?: (err: Error | null, bytes?: number) => void): void;
889
+ close(callback?: () => void): void;
890
+ remoteAddress(): { address: string; family: string; port: number };
891
+ address(): { address: string; family: string; port: number };
892
+ readonly maxPayloadSize: number;
893
+ readonly protocol: 'h3' | 'h2' | 'http/1.1' | null;
894
+ readonly statusCode: number | null;
895
+ readonly responseHeaders: Record<string, string | string[]> | null;
896
+ readonly closeReason: 'local' | 'proxy' | 'error' | null;
897
+ readonly stats: UdpProxySocketStats;
898
+ on(event: 'connect' | 'close', listener: () => void): this;
899
+ on(event: 'message', listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
900
+ on(event: 'error', listener: (err: Error & { code?: string; statusCode?: number; proxyStatus?: string }) => void): this;
901
+ on(event: 'session', listener: (session: Buffer) => void): this;
902
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
903
+ }
904
+
905
+ declare function connectUdp(
906
+ proxy: string | URL | { hostname: string; port?: number; template?: string },
907
+ target: { host: string; port: number },
908
+ options?: ConnectUdpOptions,
909
+ callback?: () => void
910
+ ): UdpProxySocket;
911
+ declare function connectUdp(
912
+ proxy: string | URL | { hostname: string; port?: number; template?: string },
913
+ target: { host: string; port: number },
914
+ callback?: () => void
915
+ ): UdpProxySocket;
916
+
917
+ // ============================================================
918
+ // Fingerprinting
919
+ // ============================================================
920
+
921
+ declare function ja4h(req: NodeIncomingMessage): Fingerprint & { a: string; b: string; c: string; d: string };
922
+ declare function h2Fingerprint(observed: any): Fingerprint;
923
+ declare function h3Fingerprint(observed: any): Fingerprint;
924
+ declare function observeH2(...args: any[]): any;
925
+ declare function profileRequest(req: NodeIncomingMessage): {
926
+ claimed: any;
927
+ protocol: string;
928
+ fingerprints: { ja4: string | null; ja4s: string | null; h2: string | null; h2raw: string | null; h3: string | null; h3raw: string | null };
929
+ signals: any[];
930
+ suspicion: number;
931
+ };
932
+
933
+ // ============================================================
934
+ // TLS
935
+ // ============================================================
936
+
937
+ declare function createSecureContext(options: { key?: PemInput; cert?: PemInput; ca?: PemInput; passphrase?: string; [option: string]: any }): any;
938
+ declare function generateEchKey(options: { publicName: string; [option: string]: any }): {
939
+ config: Uint8Array;
940
+ privateKey: Uint8Array;
941
+ configListBase64: string;
942
+ [field: string]: any;
943
+ };
944
+
945
+ // ============================================================
946
+ // Transport and protocol layers (see README "Protocol layers", "Low-level QUIC API")
947
+ // ============================================================
948
+
949
+ /** A QUIC connection (low-level API). */
950
+ interface QUICConnection extends EventEmitter {
951
+ readonly state: 'idle' | 'handshaking' | 'connected' | 'closing' | 'draining' | 'closed';
952
+ readonly remoteAddress: string;
953
+ readonly remotePort: number;
954
+ readonly earlyDataStatus: null | 'offered' | 'accepted' | 'rejected';
955
+ readonly resetStreamAtSupported: boolean;
956
+ readonly alpnProtocol: string | null;
957
+ readonly servername: string | null;
958
+ sendStream(id: number, data: Uint8Array | Buffer, fin?: boolean): void;
959
+ whenStreamCommitted(id: number, cb: () => void): void;
960
+ resetStream(id: number, code: number, reliableSize?: number): boolean;
961
+ stopSending(id: number, code: number): void;
962
+ sendDatagram(data: Uint8Array | Buffer, prio?: { urgency?: number; group?: object; order?: number } | null): boolean;
963
+ setStreamPriority(id: number, priority: Priority & { group?: object; order?: number }, fromPeer?: boolean): boolean;
964
+ getStreamPriority(id: number): (Priority & { group?: object; order?: number }) | null;
965
+ canOpenStream(bidi: boolean): boolean;
966
+ isReceiving(id: number): boolean;
967
+ isEarlyStream(id: number): boolean;
968
+ maxDatagramSize(): number;
969
+ whenConfirmed(cb: () => void): void;
970
+ close(errorCode?: number, reason?: string, application?: boolean): void;
971
+ getCertificate(): any;
972
+ getTicketInfo(): any;
973
+ isSessionReused(): boolean;
974
+ exportKeyingMaterial(length: number, label: string, context?: Uint8Array | null): Buffer | null;
975
+ getStats(): Record<string, number | boolean | string | null>;
976
+ on(event: 'stream', listener: (id: number, data: Uint8Array, fin: boolean) => void): this;
977
+ on(event: 'stream_reset', listener: (id: number, code: number, finalSize: number) => void): this;
978
+ on(event: 'stop_sending', listener: (id: number, code: number) => void): this;
979
+ on(event: 'datagram', listener: (data: Uint8Array) => void): this;
980
+ on(event: 'path', listener: (address: string, port: number) => void): this;
981
+ /** The moment the connection is over for the application ('close' follows after the draining period). */
982
+ on(event: 'closing', listener: (peerClose: { error: number; application: boolean; reason: string } | null) => void): this;
983
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
134
984
  }
135
985
 
986
+ interface QuicServer extends EventEmitter {
987
+ listen(port?: number, host?: string, callback?: () => void): this;
988
+ close(callback?: () => void): void;
989
+ handlePacket(msg: Buffer, rinfo: RemoteInfo): void;
990
+ hasConnection(rinfo: RemoteInfo, msg?: Buffer): boolean;
991
+ getPendingHandshakes(): number;
992
+ setOptions(options: Record<string, any>): this;
993
+ getOptions(): Record<string, any>;
994
+ on(event: 'connection', listener: (quic: QUICConnection, peer: { address: string; port: number }) => void): this;
995
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
996
+ [method: string]: any;
997
+ }
998
+
999
+ declare function createQuicServer(options: ServerOptions & { alpn?: string[]; [option: string]: any }): QuicServer;
1000
+ declare function createQuicClientSocket(options: {
1001
+ remoteIp: string;
1002
+ remotePort: number;
1003
+ hostname?: string;
1004
+ alpn?: string | string[];
1005
+ ecdhCurve?: string;
1006
+ idleTimeout?: number;
1007
+ keepAlive?: boolean | number;
1008
+ onConnect?: (quic: QUICConnection, socket: DgramSocket) => void;
1009
+ onSocket?: (quic: QUICConnection, socket: DgramSocket) => void;
1010
+ onError?: (err: Error) => void;
1011
+ onClose?: () => void;
1012
+ [option: string]: any;
1013
+ }): DgramSocket;
1014
+ declare function createTcpListener(options: Record<string, any>): {
1015
+ register(alpn: string, handler: (socket: Duplex, protocol: string) => void, options?: { sniff?: (firstBytes: Buffer) => boolean | null }): void;
1016
+ listen(port: number, host?: string, callback?: () => void): void;
1017
+ [method: string]: any;
1018
+ };
1019
+
1020
+ declare function createH1Server(options: ServerOptions, handler?: RequestHandler): any;
1021
+ declare function createH2Server(options: ServerOptions, handler?: RequestHandler): any;
1022
+ declare function createH3Server(options: ServerOptions, handler?: RequestHandler): any;
1023
+ declare function h1Request(options: RequestOptions, callback?: (res: QuicoIncomingMessage) => void): QuicoClientRequest;
1024
+ declare function h2Request(options: RequestOptions, callback?: (res: QuicoIncomingMessage) => void): QuicoClientRequest;
1025
+ declare function h3Request(options: RequestOptions, callback?: (res: QuicoIncomingMessage) => void): QuicoClientRequest;
136
1026
 
137
1027
  // ============================================================
138
1028
  // Main module
139
1029
  // ============================================================
140
1030
 
141
- declare const quico: {
142
- createServer(options: ServerOptions, handler?: RequestHandler): QuicoServer;
1031
+ declare function createServer(handler?: RequestHandler): QuicoServer;
1032
+ declare function createServer(options: ServerOptions, handler?: RequestHandler): QuicoServer;
143
1033
 
144
- request(url: string | URL, callback?: (res: QuicoIncomingMessage) => void): QuicoClientRequest;
145
- request(url: string | URL, options: RequestOptions, callback?: (res: QuicoIncomingMessage) => void): QuicoClientRequest;
146
- request(options: RequestOptions, callback?: (res: QuicoIncomingMessage) => void): QuicoClientRequest;
1034
+ declare function request(url: string | URL, callback?: (res: QuicoIncomingMessage) => void): QuicoClientRequest;
1035
+ declare function request(url: string | URL, options: RequestOptions, callback?: (res: QuicoIncomingMessage) => void): QuicoClientRequest;
1036
+ declare function request(options: RequestOptions, callback?: (res: QuicoIncomingMessage) => void): QuicoClientRequest;
147
1037
 
148
- get(url: string | URL, callback?: (res: QuicoIncomingMessage) => void): QuicoClientRequest;
149
- get(url: string | URL, options: RequestOptions, callback?: (res: QuicoIncomingMessage) => void): QuicoClientRequest;
150
- get(options: RequestOptions, callback?: (res: QuicoIncomingMessage) => void): QuicoClientRequest;
1038
+ declare function get(url: string | URL, callback?: (res: QuicoIncomingMessage) => void): QuicoClientRequest;
1039
+ declare function get(url: string | URL, options: RequestOptions, callback?: (res: QuicoIncomingMessage) => void): QuicoClientRequest;
1040
+ declare function get(options: RequestOptions, callback?: (res: QuicoIncomingMessage) => void): QuicoClientRequest;
151
1041
 
152
- globalAgent: QuicoAgent;
1042
+ declare const globalAgent: Agent;
1043
+
1044
+ /** node:http's classes, as QUICO's request and response are made. */
1045
+ declare const IncomingMessage: typeof NodeIncomingMessage;
1046
+ declare const ServerResponse: typeof NodeServerResponse;
1047
+ declare const ClientRequest: typeof NodeClientRequest;
1048
+
1049
+ declare const quico: {
1050
+ createServer: typeof createServer;
1051
+ request: typeof request;
1052
+ get: typeof get;
1053
+ Agent: typeof Agent;
1054
+ globalAgent: Agent;
1055
+ IncomingMessage: typeof NodeIncomingMessage;
1056
+ ServerResponse: typeof NodeServerResponse;
1057
+ ClientRequest: typeof NodeClientRequest;
1058
+ connectUdp: typeof connectUdp;
1059
+ createSecureContext: typeof createSecureContext;
1060
+ generateEchKey: typeof generateEchKey;
1061
+ WebTransport: typeof WebTransport;
1062
+ WebTransportError: typeof WebTransportError;
1063
+ WebTransportBidirectionalStream: typeof WebTransportBidirectionalStream;
1064
+ WebTransportReceiveStream: typeof WebTransportReceiveStream;
1065
+ WebTransportSendStream: typeof WebTransportSendStream;
1066
+ WebTransportWriter: typeof WebTransportWriter;
1067
+ WebTransportSendGroup: typeof WebTransportSendGroup;
1068
+ WebTransportDatagramsWritable: typeof WebTransportDatagramsWritable;
1069
+ WebTransportDatagramDuplexStream: typeof WebTransportDatagramDuplexStream;
1070
+ WebSocket: typeof WebSocket;
1071
+ WebSocketStream: typeof WebSocketStream;
1072
+ WebSocketError: typeof WebSocketError;
1073
+ WebSocketServer: typeof WebSocketServer;
1074
+ upgradeWebSocket: typeof upgradeWebSocket;
1075
+ ja4h: typeof ja4h;
1076
+ h2Fingerprint: typeof h2Fingerprint;
1077
+ h3Fingerprint: typeof h3Fingerprint;
1078
+ observeH2: typeof observeH2;
1079
+ profileRequest: typeof profileRequest;
1080
+ createQuicServer: typeof createQuicServer;
1081
+ createQuicClientSocket: typeof createQuicClientSocket;
1082
+ createTcpListener: typeof createTcpListener;
1083
+ createH1Server: typeof createH1Server;
1084
+ createH2Server: typeof createH2Server;
1085
+ createH3Server: typeof createH3Server;
1086
+ h1Request: typeof h1Request;
1087
+ h2Request: typeof h2Request;
1088
+ h3Request: typeof h3Request;
153
1089
  };
154
1090
 
155
1091
  export default quico;
156
- export { WebTransport };
157
- export { QuicoServer, QuicoIncomingMessage, QuicoServerResponse, QuicoClientRequest, QuicoAgent };
158
- export { ServerOptions, RequestOptions, RequestHandler, WebTransportOptions };
1092
+ export {
1093
+ createServer, request, get, Agent, globalAgent,
1094
+ IncomingMessage, ServerResponse, ClientRequest,
1095
+ connectUdp, createSecureContext, generateEchKey,
1096
+ WebTransport, WebTransportError, WebTransportBidirectionalStream, WebTransportReceiveStream, WebTransportSendStream,
1097
+ WebTransportWriter, WebTransportSendGroup, WebTransportDatagramsWritable, WebTransportDatagramDuplexStream,
1098
+ WebSocket, WebSocketStream, WebSocketError, WebSocketServer, upgradeWebSocket,
1099
+ ja4h, h2Fingerprint, h3Fingerprint, observeH2, profileRequest,
1100
+ createQuicServer, createQuicClientSocket, createTcpListener,
1101
+ createH1Server, createH2Server, createH3Server,
1102
+ h1Request, h2Request, h3Request
1103
+ };
1104
+ export type {
1105
+ ServerOptions, RequestOptions, RequestHandler, AgentOptions, Priority, TransportParams, StartupCap,
1106
+ QuicConnectionOptions, ConnectionOptionsInfo, ConnectionHandle, ServerStats, EchKey, Fingerprint,
1107
+ QuicoServer, QuicoIncomingMessage, QuicoServerResponse, QuicoClientRequest,
1108
+ ConnectUdpServerOptions, ConnectUdpTunnel, ConnectUdpTunnelStats, ConnectUdpOptions, UdpProxySocket, UdpProxySocketStats,
1109
+ WebTransportOptions, WebTransportHash, WebTransportCloseInfo, WebTransportSendOptions, WebTransportSendStreamOptions,
1110
+ WebTransportConnectionStats, WebTransportDatagramStats, WebTransportSendStreamStats, WebTransportReceiveStreamStats,
1111
+ WebTransportReliabilityMode, WebTransportCongestionControl, WebTransportErrorSource,
1112
+ WebTransportNodeStream, WebTransportBidirectionalNodeStream, WebTransportUnidirectionalNodeStream,
1113
+ WebSocketClientOptions, WebSocketStreamOptions, WebSocketOpenInfo, WebSocketCloseInfo, WebSocketServerOptions, UpgradeWebSocketOptions, ServerWebSocket,
1114
+ QUICConnection, QuicServer
1115
+ };