quico 0.2.0 → 0.4.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.
@@ -14,11 +14,10 @@
14
14
 
15
15
  import { Duplex, Readable, Writable } from 'node:stream';
16
16
  import { EventEmitter } from 'node:events';
17
- import dgram from 'node:dgram';
18
17
  import dns from 'node:dns';
19
- import { QUICConnection } from './quic_connection.js';
20
18
  import { H3Connection } from './h3.js';
21
- import { writeVarInt, readVarInt } from './utils.js';
19
+ import { createQuicClientSocket } from './quic_socket.js';
20
+ import { readVarInt, concatUint8Arrays, wt_stream_header, wt_datagram_payload } from './utils.js';
22
21
 
23
22
 
24
23
  // ============================================================
@@ -101,13 +100,7 @@ class WebTransportBidiStream extends Duplex {
101
100
  // First write on this stream: prepend VarInt(0x41) + VarInt(session_id)
102
101
  if (!this._prefixSent) {
103
102
  this._prefixSent = true;
104
- var typePrefix = writeVarInt(0x41); // WEBTRANSPORT_STREAM bidi type
105
- var sessionPrefix = writeVarInt(this._sessionId);
106
- var combined = new Uint8Array(typePrefix.length + sessionPrefix.length + chunk.byteLength);
107
- combined.set(typePrefix, 0);
108
- combined.set(sessionPrefix, typePrefix.length);
109
- combined.set(chunk, typePrefix.length + sessionPrefix.length);
110
- this._quic.sendStream(this._streamId, combined, false);
103
+ this._quic.sendStream(this._streamId, wt_stream_header(true, this._sessionId, chunk), false);
111
104
  } else {
112
105
  this._quic.sendStream(this._streamId, chunk, false);
113
106
  }
@@ -118,12 +111,7 @@ class WebTransportBidiStream extends Duplex {
118
111
  // Send FIN (with type + session_id prefix if nothing was written yet)
119
112
  if (!this._prefixSent) {
120
113
  this._prefixSent = true;
121
- var typePrefix = writeVarInt(0x41);
122
- var sessionPrefix = writeVarInt(this._sessionId);
123
- var header = new Uint8Array(typePrefix.length + sessionPrefix.length);
124
- header.set(typePrefix, 0);
125
- header.set(sessionPrefix, typePrefix.length);
126
- this._quic.sendStream(this._streamId, header, true);
114
+ this._quic.sendStream(this._streamId, wt_stream_header(true, this._sessionId), true);
127
115
  } else {
128
116
  this._quic.sendStream(this._streamId, new Uint8Array(0), true);
129
117
  }
@@ -168,13 +156,7 @@ class WebTransportUniWriteStream extends Writable {
168
156
  if (!this._headerSent) {
169
157
  this._headerSent = true;
170
158
  // Uni stream: VarInt(0x54) (WEBTRANSPORT_STREAM) + VarInt(session_id) + data
171
- var typePrefix = writeVarInt(0x54);
172
- var sessionPrefix = writeVarInt(this._sessionId);
173
- var header = new Uint8Array(typePrefix.length + sessionPrefix.length + chunk.byteLength);
174
- header.set(typePrefix, 0);
175
- header.set(sessionPrefix, typePrefix.length);
176
- header.set(chunk, typePrefix.length + sessionPrefix.length);
177
- this._quic.sendStream(this._streamId, header, false);
159
+ this._quic.sendStream(this._streamId, wt_stream_header(false, this._sessionId, chunk), false);
178
160
  } else {
179
161
  this._quic.sendStream(this._streamId, chunk, false);
180
162
  }
@@ -184,12 +166,7 @@ class WebTransportUniWriteStream extends Writable {
184
166
  _final(callback) {
185
167
  if (!this._headerSent) {
186
168
  this._headerSent = true;
187
- var typePrefix = writeVarInt(0x54);
188
- var sessionPrefix = writeVarInt(this._sessionId);
189
- var header = new Uint8Array(typePrefix.length + sessionPrefix.length);
190
- header.set(typePrefix, 0);
191
- header.set(sessionPrefix, typePrefix.length);
192
- this._quic.sendStream(this._streamId, header, true);
169
+ this._quic.sendStream(this._streamId, wt_stream_header(false, this._sessionId), true);
193
170
  } else {
194
171
  this._quic.sendStream(this._streamId, new Uint8Array(0), true);
195
172
  }
@@ -350,43 +327,31 @@ class WebTransport extends EventEmitter {
350
327
  _startQuic(remoteIp) {
351
328
  var self = this;
352
329
  var remotePort = this._port;
353
- var isIPv6 = remoteIp.indexOf(':') >= 0;
354
330
 
355
- this._udpSocket = dgram.createSocket(isIPv6 ? 'udp6' : 'udp4');
331
+ this._udpSocket = createQuicClientSocket({
332
+ remoteIp: remoteIp,
333
+ remotePort: remotePort,
334
+ hostname: this._hostname,
356
335
 
357
- this._udpSocket.on('message', function (msg, rinfo) {
358
- if (self._quic) self._quic.feedDatagram(rinfo.address, rinfo.port, new Uint8Array(msg));
359
- });
360
-
361
- this._udpSocket.on('error', function (err) {
362
- if (self._state === 'connecting') self._readyReject(err);
363
- self.emit('error', err);
364
- });
365
-
366
- this._udpSocket.bind(0, function () {
367
- self._quic = new QUICConnection({
368
- isServer: false,
369
- hostname: self._hostname
370
- });
371
-
372
- self._quic.on('packet', function (data) {
373
- self._udpSocket.send(data, remotePort, remoteIp);
374
- });
336
+ onError: function (err) {
337
+ if (self._state === 'connecting') self._readyReject(err);
338
+ self.emit('error', err);
339
+ },
375
340
 
376
- self._quic.on('connect', function () {
341
+ onConnect: function (q, s) {
342
+ self._quic = q;
343
+ self._udpSocket = s;
377
344
  self._h3 = new H3Connection({ quicConnection: self._quic, isServer: false, enableWebTransport: true });
378
345
  self._setupH3Handlers();
379
346
  self._sendConnect();
380
- });
347
+ },
381
348
 
382
- self._quic.on('close', function () {
349
+ onClose: function () {
383
350
  self._state = 'closed';
384
351
  self._closedResolve();
385
352
  self.emit('close');
386
- if (self._udpSocket) { try { self._udpSocket.close(); } catch (e) {} }
387
- });
388
-
389
- self._quic.connect();
353
+ // The helper closes the UDP socket.
354
+ }
390
355
  });
391
356
  }
392
357
 
@@ -424,7 +389,7 @@ class WebTransport extends EventEmitter {
424
389
  });
425
390
 
426
391
  // Datagrams — QUIC DATAGRAM payload = VarInt(quarter_stream_id) + app data (RFC 9297)
427
- this._quic.on('datagram', function (_contextId, rawData) {
392
+ this._quic.on('datagram', function (rawData) {
428
393
  if (!rawData || rawData.byteLength === 0) return;
429
394
 
430
395
  // Always parse VarInt quarter_stream_id from payload
@@ -484,7 +449,7 @@ class WebTransport extends EventEmitter {
484
449
  buf.totalLen += data.byteLength;
485
450
 
486
451
  // Try to parse prefix
487
- var combined = buf.totalLen === data.byteLength ? data : this._combineChunks(buf.chunks, buf.totalLen);
452
+ var combined = buf.totalLen === data.byteLength ? data : concatUint8Arrays(buf.chunks);
488
453
  var isBidi = (streamId & 0x2) === 0;
489
454
  var offset = 0;
490
455
 
@@ -552,18 +517,6 @@ class WebTransport extends EventEmitter {
552
517
  }
553
518
  }
554
519
 
555
- _combineChunks(chunks, totalLen) {
556
- if (chunks.length === 1) return chunks[0];
557
- var out = new Uint8Array(totalLen);
558
- var off = 0;
559
- for (var i = 0; i < chunks.length; i++) {
560
- out.set(chunks[i], off);
561
- off += chunks[i].byteLength;
562
- }
563
- return out;
564
- }
565
-
566
-
567
520
  // ---- Send CONNECT ----
568
521
 
569
522
  _sendConnect() {
@@ -660,14 +613,8 @@ class WebTransport extends EventEmitter {
660
613
  if (typeof data === 'string') data = Buffer.from(data);
661
614
  if (Buffer.isBuffer(data)) data = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
662
615
 
663
- // Quarter stream ID as context ID (RFC 9297)
664
- var contextId = Math.floor(this._sessionId / 4);
665
-
666
- // Build datagram: VarInt(contextId) + payload
667
- var contextPrefix = writeVarInt(contextId);
668
- var frame = new Uint8Array(contextPrefix.length + data.byteLength);
669
- frame.set(contextPrefix, 0);
670
- frame.set(data, contextPrefix.length);
616
+ // Build datagram: VarInt(quarter_stream_id) + payload (RFC 9297)
617
+ var frame = wt_datagram_payload(this._sessionId, data);
671
618
 
672
619
  // Send via QUIC DATAGRAM frame
673
620
  if (this._quic && this._quic.sendDatagram) {