werift 0.24.4 → 0.25.0-alpha.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.
Files changed (166) hide show
  1. package/README.md +116 -113
  2. package/lib/common/src/transport.d.ts +22 -2
  3. package/lib/common/src/transport.js +84 -26
  4. package/lib/common/src/transport.js.map +1 -1
  5. package/lib/ice/src/exceptions.d.ts +9 -0
  6. package/lib/ice/src/exceptions.js +23 -1
  7. package/lib/ice/src/exceptions.js.map +1 -1
  8. package/lib/ice/src/ice.d.ts +40 -0
  9. package/lib/ice/src/ice.js +194 -28
  10. package/lib/ice/src/ice.js.map +1 -1
  11. package/lib/ice/src/iceBase.d.ts +26 -0
  12. package/lib/ice/src/iceBase.js.map +1 -1
  13. package/lib/ice/src/stun/const.d.ts +7 -0
  14. package/lib/ice/src/stun/const.js +8 -0
  15. package/lib/ice/src/stun/const.js.map +1 -1
  16. package/lib/ice/src/stun/protocol.js +1 -4
  17. package/lib/ice/src/stun/protocol.js.map +1 -1
  18. package/lib/ice/src/stun/tcpProtocol.d.ts +7 -1
  19. package/lib/ice/src/stun/tcpProtocol.js +65 -14
  20. package/lib/ice/src/stun/tcpProtocol.js.map +1 -1
  21. package/lib/ice/src/stun/transaction.d.ts +12 -1
  22. package/lib/ice/src/stun/transaction.js +37 -4
  23. package/lib/ice/src/stun/transaction.js.map +1 -1
  24. package/lib/ice/src/turn/protocol.d.ts +40 -15
  25. package/lib/ice/src/turn/protocol.js +141 -32
  26. package/lib/ice/src/turn/protocol.js.map +1 -1
  27. package/lib/ice/src/types/model.d.ts +8 -0
  28. package/lib/ice/src/types/model.js.map +1 -1
  29. package/lib/index.mjs +6175 -4073
  30. package/lib/nonstandard/index.mjs +286 -1003
  31. package/lib/polyfill/dom.mjs +23794 -0
  32. package/lib/polyfill/index.mjs +23794 -0
  33. package/lib/rtp/src/extra/container/mp4/container.js +12 -4
  34. package/lib/rtp/src/extra/container/mp4/container.js.map +1 -1
  35. package/lib/rtp/src/extra/processor/mp4.js +8 -3
  36. package/lib/rtp/src/extra/processor/mp4.js.map +1 -1
  37. package/lib/rtp/src/extra/processor/mp4Callback.js +3 -1
  38. package/lib/rtp/src/extra/processor/mp4Callback.js.map +1 -1
  39. package/lib/sctp/src/chunk.d.ts +5 -0
  40. package/lib/sctp/src/chunk.js +16 -11
  41. package/lib/sctp/src/chunk.js.map +1 -1
  42. package/lib/sctp/src/index.d.ts +3 -1
  43. package/lib/sctp/src/index.js +10 -1
  44. package/lib/sctp/src/index.js.map +1 -1
  45. package/lib/sctp/src/sctp.d.ts +12 -3
  46. package/lib/sctp/src/sctp.js +51 -18
  47. package/lib/sctp/src/sctp.js.map +1 -1
  48. package/lib/webrtc/src/const.js +2 -0
  49. package/lib/webrtc/src/const.js.map +1 -1
  50. package/lib/webrtc/src/errors.d.ts +9 -1
  51. package/lib/webrtc/src/errors.js +19 -0
  52. package/lib/webrtc/src/errors.js.map +1 -1
  53. package/lib/webrtc/src/media/codec.d.ts +5 -0
  54. package/lib/webrtc/src/media/codec.js +21 -0
  55. package/lib/webrtc/src/media/codec.js.map +1 -1
  56. package/lib/webrtc/src/media/codecCompatibility.d.ts +23 -0
  57. package/lib/webrtc/src/media/codecCompatibility.js +138 -0
  58. package/lib/webrtc/src/media/codecCompatibility.js.map +1 -0
  59. package/lib/webrtc/src/media/index.d.ts +1 -0
  60. package/lib/webrtc/src/media/index.js +1 -0
  61. package/lib/webrtc/src/media/index.js.map +1 -1
  62. package/lib/webrtc/src/media/router.d.ts +2 -0
  63. package/lib/webrtc/src/media/router.js +23 -3
  64. package/lib/webrtc/src/media/router.js.map +1 -1
  65. package/lib/webrtc/src/media/rtpReceiver.d.ts +12 -0
  66. package/lib/webrtc/src/media/rtpReceiver.js +35 -0
  67. package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
  68. package/lib/webrtc/src/media/rtpSender.d.ts +65 -4
  69. package/lib/webrtc/src/media/rtpSender.js +264 -35
  70. package/lib/webrtc/src/media/rtpSender.js.map +1 -1
  71. package/lib/webrtc/src/media/rtpTransceiver.d.ts +42 -0
  72. package/lib/webrtc/src/media/rtpTransceiver.js +157 -4
  73. package/lib/webrtc/src/media/rtpTransceiver.js.map +1 -1
  74. package/lib/webrtc/src/media/track.d.ts +29 -1
  75. package/lib/webrtc/src/media/track.js +164 -5
  76. package/lib/webrtc/src/media/track.js.map +1 -1
  77. package/lib/webrtc/src/nonstandard/index.d.ts +0 -1
  78. package/lib/webrtc/src/nonstandard/index.js +0 -1
  79. package/lib/webrtc/src/nonstandard/index.js.map +1 -1
  80. package/lib/webrtc/src/nonstandard/recorder/writer/webm.js +2 -1
  81. package/lib/webrtc/src/nonstandard/recorder/writer/webm.js.map +1 -1
  82. package/lib/webrtc/src/nonstandard/userMedia.d.ts +1 -2
  83. package/lib/webrtc/src/nonstandard/userMedia.js +30 -14
  84. package/lib/webrtc/src/nonstandard/userMedia.js.map +1 -1
  85. package/lib/webrtc/src/peerConnection.d.ts +126 -5
  86. package/lib/webrtc/src/peerConnection.js +609 -136
  87. package/lib/webrtc/src/peerConnection.js.map +1 -1
  88. package/lib/webrtc/src/polyfill/api.d.ts +14 -0
  89. package/lib/webrtc/src/polyfill/api.js +23 -0
  90. package/lib/webrtc/src/polyfill/api.js.map +1 -0
  91. package/lib/webrtc/src/polyfill/browserIdentity.d.ts +11 -0
  92. package/lib/webrtc/src/polyfill/browserIdentity.js +59 -0
  93. package/lib/webrtc/src/polyfill/browserIdentity.js.map +1 -0
  94. package/lib/webrtc/src/polyfill/dom.d.ts +11 -0
  95. package/lib/webrtc/src/polyfill/dom.js +18 -0
  96. package/lib/webrtc/src/polyfill/dom.js.map +1 -0
  97. package/lib/webrtc/src/polyfill/existingMediaDevices.d.ts +2 -0
  98. package/lib/webrtc/src/polyfill/existingMediaDevices.js +22 -0
  99. package/lib/webrtc/src/polyfill/existingMediaDevices.js.map +1 -0
  100. package/lib/webrtc/src/polyfill/globals.d.ts +28 -0
  101. package/lib/webrtc/src/polyfill/globals.js +3 -0
  102. package/lib/webrtc/src/polyfill/globals.js.map +1 -0
  103. package/lib/webrtc/src/polyfill/index.d.ts +2 -0
  104. package/lib/webrtc/src/polyfill/index.js +19 -0
  105. package/lib/webrtc/src/polyfill/index.js.map +1 -0
  106. package/lib/webrtc/src/polyfill/install.d.ts +13 -0
  107. package/lib/webrtc/src/polyfill/install.js +266 -0
  108. package/lib/webrtc/src/polyfill/install.js.map +1 -0
  109. package/lib/webrtc/src/polyfill/mediaDevices.d.ts +38 -0
  110. package/lib/webrtc/src/polyfill/mediaDevices.js +228 -0
  111. package/lib/webrtc/src/polyfill/mediaDevices.js.map +1 -0
  112. package/lib/webrtc/src/polyfill/mediaRegister.d.ts +51 -0
  113. package/lib/webrtc/src/polyfill/mediaRegister.js +14 -0
  114. package/lib/webrtc/src/polyfill/mediaRegister.js.map +1 -0
  115. package/lib/webrtc/src/polyfill/peerConnectionConfig.d.ts +3 -0
  116. package/lib/webrtc/src/polyfill/peerConnectionConfig.js +52 -0
  117. package/lib/webrtc/src/polyfill/peerConnectionConfig.js.map +1 -0
  118. package/lib/webrtc/src/polyfill/registers/callback.d.ts +16 -0
  119. package/lib/webrtc/src/polyfill/registers/callback.js +57 -0
  120. package/lib/webrtc/src/polyfill/registers/callback.js.map +1 -0
  121. package/lib/webrtc/src/polyfill/registers/empty.d.ts +2 -0
  122. package/lib/webrtc/src/polyfill/registers/empty.js +28 -0
  123. package/lib/webrtc/src/polyfill/registers/empty.js.map +1 -0
  124. package/lib/webrtc/src/polyfill/registers/mp4Webm.d.ts +36 -0
  125. package/lib/webrtc/src/polyfill/registers/mp4Webm.js +242 -0
  126. package/lib/webrtc/src/polyfill/registers/mp4Webm.js.map +1 -0
  127. package/lib/webrtc/src/polyfill/registers/rtpRtcp.d.ts +17 -0
  128. package/lib/webrtc/src/polyfill/registers/rtpRtcp.js +143 -0
  129. package/lib/webrtc/src/polyfill/registers/rtpRtcp.js.map +1 -0
  130. package/lib/webrtc/src/polyfill/rtcSessionDescription.d.ts +18 -0
  131. package/lib/webrtc/src/polyfill/rtcSessionDescription.js +36 -0
  132. package/lib/webrtc/src/polyfill/rtcSessionDescription.js.map +1 -0
  133. package/lib/webrtc/src/polyfill/rtpCodec.d.ts +17 -0
  134. package/lib/webrtc/src/polyfill/rtpCodec.js +93 -0
  135. package/lib/webrtc/src/polyfill/rtpCodec.js.map +1 -0
  136. package/lib/webrtc/src/polyfill/selectSettings.d.ts +31 -0
  137. package/lib/webrtc/src/polyfill/selectSettings.js +156 -0
  138. package/lib/webrtc/src/polyfill/selectSettings.js.map +1 -0
  139. package/lib/webrtc/src/polyfill/sourceIo.d.ts +21 -0
  140. package/lib/webrtc/src/polyfill/sourceIo.js +298 -0
  141. package/lib/webrtc/src/polyfill/sourceIo.js.map +1 -0
  142. package/lib/webrtc/src/polyfill/trackStop.d.ts +4 -0
  143. package/lib/webrtc/src/polyfill/trackStop.js +16 -0
  144. package/lib/webrtc/src/polyfill/trackStop.js.map +1 -0
  145. package/lib/webrtc/src/sctpManager.d.ts +2 -1
  146. package/lib/webrtc/src/sctpManager.js +5 -2
  147. package/lib/webrtc/src/sctpManager.js.map +1 -1
  148. package/lib/webrtc/src/sdp.d.ts +1 -1
  149. package/lib/webrtc/src/sdp.js +5 -6
  150. package/lib/webrtc/src/sdp.js.map +1 -1
  151. package/lib/webrtc/src/sdpManager.d.ts +38 -1
  152. package/lib/webrtc/src/sdpManager.js +236 -30
  153. package/lib/webrtc/src/sdpManager.js.map +1 -1
  154. package/lib/webrtc/src/secureTransportManager.d.ts +43 -12
  155. package/lib/webrtc/src/secureTransportManager.js +123 -47
  156. package/lib/webrtc/src/secureTransportManager.js.map +1 -1
  157. package/lib/webrtc/src/transceiverManager.d.ts +91 -6
  158. package/lib/webrtc/src/transceiverManager.js +477 -62
  159. package/lib/webrtc/src/transceiverManager.js.map +1 -1
  160. package/lib/webrtc/src/transport/ice.d.ts +8 -0
  161. package/lib/webrtc/src/transport/ice.js +17 -1
  162. package/lib/webrtc/src/transport/ice.js.map +1 -1
  163. package/lib/webrtc/src/transport/sctp.d.ts +3 -2
  164. package/lib/webrtc/src/transport/sctp.js +8 -2
  165. package/lib/webrtc/src/transport/sctp.js.map +1 -1
  166. package/package.json +13 -3
@@ -4,6 +4,7 @@ exports.TurnProtocol = exports.StunOverTurnProtocol = void 0;
4
4
  exports.createTurnClient = createTurnClient;
5
5
  exports.createStunOverTurnClient = createStunOverTurnClient;
6
6
  exports.makeIntegrityKey = makeIntegrityKey;
7
+ const node_net_1 = require("node:net");
7
8
  const promises_1 = require("timers/promises");
8
9
  const auth_1 = require("../../../ice-server/src/turn/auth");
9
10
  const exceptions_1 = require("../exceptions");
@@ -152,7 +153,9 @@ Object.defineProperty(StunOverTurnProtocol, "type", {
152
153
  value: "turn"
153
154
  });
154
155
  class TurnProtocol {
155
- constructor(server, username, password, lifetime, transport, options = {}) {
156
+ constructor(
157
+ /** TURN server as configured; the host may be a hostname. */
158
+ server, username, password, lifetime, transport, options = {}) {
156
159
  Object.defineProperty(this, "server", {
157
160
  enumerable: true,
158
161
  configurable: true,
@@ -334,29 +337,56 @@ class TurnProtocol {
334
337
  writable: true,
335
338
  value: new Map()
336
339
  });
340
+ /** Concrete TURN server address the allocation lives on, once selected. */
341
+ Object.defineProperty(this, "pinnedServerEndpoint", {
342
+ enumerable: true,
343
+ configurable: true,
344
+ writable: true,
345
+ value: void 0
346
+ });
347
+ Object.defineProperty(this, "serverEndpointSelection", {
348
+ enumerable: true,
349
+ configurable: true,
350
+ writable: true,
351
+ value: void 0
352
+ });
337
353
  Object.defineProperty(this, "refresh", {
338
354
  enumerable: true,
339
355
  configurable: true,
340
356
  writable: true,
341
357
  value: (exp) => {
342
358
  this.refreshHandle = (0, helper_1.cancelable)(async (_, __, onCancel) => {
343
- let run = true;
359
+ const abort = new AbortController();
344
360
  onCancel.once(() => {
345
- run = false;
361
+ abort.abort();
346
362
  });
347
- while (run) {
363
+ while (!abort.signal.aborted) {
348
364
  // refresh before expire
349
365
  const delay = (5 / 6) * exp * 1000;
350
366
  log("refresh delay", delay, { exp });
351
- await (0, promises_1.setTimeout)(delay);
367
+ try {
368
+ await (0, promises_1.setTimeout)(delay, undefined, { signal: abort.signal });
369
+ }
370
+ catch (error) {
371
+ if (abort.signal.aborted) {
372
+ return;
373
+ }
374
+ throw error;
375
+ }
376
+ if (abort.signal.aborted) {
377
+ return;
378
+ }
352
379
  const request = new message_1.Message(const_1.methods.REFRESH, const_1.classes.REQUEST);
353
380
  request.setAttribute("LIFETIME", exp);
354
381
  try {
355
- const [message] = await this.requestWithRetry(request, this.server);
382
+ const [message] = await this.requestWithRetry(request, this.server, abort.signal);
356
383
  exp = message.getAttributeValue("LIFETIME");
357
384
  log("refresh", { exp });
358
385
  }
359
386
  catch (error) {
387
+ if (abort.signal.aborted) {
388
+ return;
389
+ }
360
390
  log("refresh error", error);
361
391
  }
362
392
  }
@@ -476,7 +506,7 @@ class TurnProtocol {
476
506
  // TURN server allocation/refresh uses default STUN retry policy unless
477
507
  // callers pass explicit options. Peer consent goes through StunOverTurnProtocol.
478
508
  // Prefer the TURN session integrity key for response verification.
479
- const resolvedAddr = await (0, transaction_1.resolveRequestAddress)(addr);
509
+ const resolvedAddr = await this.resolveRequestTarget(addr);
480
510
  const options = (0, transaction_1.buildTransactionOptions)(this.integrityKey, retransmissionsOrOptions, onRequestSent);
481
511
  const transaction = new transaction_1.Transaction(request, resolvedAddr, this, options);
482
512
  this.transactions[request.transactionIdHex] = transaction;
@@ -490,18 +520,74 @@ class TurnProtocol {
490
520
  delete this.transactions[request.transactionIdHex];
491
521
  }
492
522
  }
493
- async requestWithRetry(request, addr) {
523
+ /**
524
+ * The concrete TURN server address, selected on the first request and
525
+ * pinned for the rest of the allocation, so a later DNS answer can never
526
+ * move REFRESH, CREATE_PERMISSION, CHANNEL_BIND or data to another server.
527
+ */
528
+ get serverEndpoint() {
529
+ return this.pinnedServerEndpoint;
530
+ }
531
+ /**
532
+ * Address a request to `addr` is sent to, and the address its response
533
+ * must come from. A stream carries every request to the peer it is
534
+ * connected to, so it always uses the server endpoint.
535
+ */
536
+ async resolveRequestTarget(addr) {
537
+ if (isStreamTransport(this.transport) || (0, transaction_1.addressEquals)(addr, this.server)) {
538
+ return this.selectServerEndpoint();
539
+ }
540
+ return (0, transaction_1.resolveRequestAddress)(addr, this.transport.addressFamily ?? 0);
541
+ }
542
+ async serverDestination() {
543
+ return this.pinnedServerEndpoint ?? this.selectServerEndpoint();
544
+ }
545
+ selectServerEndpoint() {
546
+ this.serverEndpointSelection ?? (this.serverEndpointSelection = this.resolveServerEndpoint().then((endpoint) => {
547
+ this.pinnedServerEndpoint = endpoint;
548
+ return endpoint;
549
+ }, (error) => {
550
+ // Let a later request try again, e.g. after a transient DNS failure.
551
+ this.serverEndpointSelection = undefined;
552
+ throw error;
553
+ }));
554
+ return this.serverEndpointSelection;
555
+ }
556
+ /**
557
+ * UDP: resolve the configured server in the bound socket's family; a udp4
558
+ * socket cannot send to an IPv6 answer. TCP/TLS: use the peer the socket
559
+ * actually connected to. Looking the hostname up again could return a
560
+ * different A/AAAA record, and responses from the real peer would then be
561
+ * dropped as coming from an unexpected address.
562
+ */
563
+ async resolveServerEndpoint() {
564
+ const transport = this.transport;
565
+ if (!isStreamTransport(transport)) {
566
+ return (0, transaction_1.resolveRequestAddress)(this.server, transport.addressFamily ?? 0);
567
+ }
568
+ if (transport.remoteAddress) {
569
+ return transport.remoteAddress;
570
+ }
571
+ if (transport instanceof common_1.TcpTransport ||
572
+ transport instanceof common_1.TlsTransport) {
573
+ throw new Error(`${transport.type} transport has no remote address`);
574
+ }
575
+ // A custom stream transport that does not report its peer: fall back to
576
+ // a lookup with no family preference.
577
+ return (0, transaction_1.resolveRequestAddress)(this.server);
578
+ }
579
+ async requestWithRetry(request, addr, signal) {
494
580
  let message, address;
495
581
  try {
496
- [message, address] = await this.request(request, addr);
582
+ [message, address] = await this.request(request, addr, undefined, {
583
+ signal,
584
+ });
497
585
  }
498
586
  catch (error) {
499
587
  if (error instanceof exceptions_1.TransactionFailed == false) {
500
588
  log("requestWithRetry error", error);
501
589
  throw error;
502
590
  }
503
- // resolve dns address
504
- this.server = error.addr;
505
591
  const [errorCode] = error.response.getAttributeValue("ERROR-CODE");
506
592
  const nonce = error.response.getAttributeValue("NONCE");
507
593
  const realm = error.response.getAttributeValue("REALM");
@@ -514,7 +600,7 @@ class TurnProtocol {
514
600
  }
515
601
  this.integrityKey = makeIntegrityKey(this.username, this.realm, this.password);
516
602
  request.transactionId = (0, helper_1.randomTransactionId)();
517
- [message, address] = await this.request(request, this.server);
603
+ [message, address] = await this.request(request, this.server, undefined, { signal });
518
604
  }
519
605
  else {
520
606
  throw error;
@@ -536,10 +622,10 @@ class TurnProtocol {
536
622
  const indicate = new message_1.Message(const_1.methods.SEND, const_1.classes.INDICATION)
537
623
  .setAttribute("DATA", data)
538
624
  .setAttribute("XOR-PEER-ADDRESS", addr);
539
- await this.sendStun(indicate, this.server);
625
+ await this.sendStun(indicate, await this.serverDestination());
540
626
  return;
541
627
  }
542
- await this.send((0, frame_1.encodeChannelData)(channel.number, data), this.server);
628
+ await this.send((0, frame_1.encodeChannelData)(channel.number, data), await this.serverDestination());
543
629
  }
544
630
  /**
545
631
  * Ensure a CreatePermission exists for the peer IP.
@@ -677,31 +763,54 @@ Object.defineProperty(TurnProtocol, "type", {
677
763
  writable: true,
678
764
  value: "turn"
679
765
  });
680
- async function createTurnClient({ address, username, password }, { lifetime, portRange, interfaceAddresses, ssl, tlsOptions, transport: transportType, } = {}) {
766
+ /**
767
+ * Select the UDP socket type for a TURN server.
768
+ * Precedence: IP literal family > udpFamily > 4.
769
+ * An IP literal fixes the destination family, so a conflicting udpFamily is
770
+ * ignored (and logged) rather than making the server unreachable.
771
+ */
772
+ function selectTurnUdpSocketType(address, udpFamily) {
773
+ const literalFamily = (0, node_net_1.isIP)(address[0]);
774
+ if (literalFamily === 4 || literalFamily === 6) {
775
+ if (udpFamily && udpFamily !== literalFamily) {
776
+ log("udpFamily ignored for IP literal TURN server", {
777
+ address,
778
+ udpFamily,
779
+ literalFamily,
780
+ });
781
+ }
782
+ return literalFamily === 6 ? "udp6" : "udp4";
783
+ }
784
+ return (udpFamily ?? 4) === 6 ? "udp6" : "udp4";
785
+ }
786
+ async function createTurnClient({ address, username, password }, { lifetime, portRange, interfaceAddresses, ssl, tlsOptions, transport: transportType, connectTimeoutMs, udpFamily, } = {}) {
681
787
  lifetime ?? (lifetime = DEFAULT_ALLOCATION_LIFETIME);
682
788
  transportType ?? (transportType = ssl ? "tls" : "udp");
683
789
  const transport = transportType === "udp"
684
- ? await common_1.UdpTransport.init("udp4", { portRange, interfaceAddresses })
790
+ ? await common_1.UdpTransport.init(selectTurnUdpSocketType(address, udpFamily), {
791
+ portRange,
792
+ interfaceAddresses,
793
+ })
685
794
  : transportType === "tcp"
686
- ? await common_1.TcpTransport.init(address)
687
- : await common_1.TlsTransport.init(address, tlsOptions);
795
+ ? await common_1.TcpTransport.init(address, { connectTimeoutMs })
796
+ : await common_1.TlsTransport.init(address, tlsOptions, { connectTimeoutMs });
688
797
  const turn = new TurnProtocol(address, username, password, lifetime, transport);
689
- await turn.connectionMade();
798
+ try {
799
+ await turn.connectionMade();
800
+ }
801
+ catch (error) {
802
+ try {
803
+ await turn.close();
804
+ }
805
+ catch (closeError) {
806
+ log("failed to close TURN client after allocation failure", closeError);
807
+ }
808
+ throw error;
809
+ }
690
810
  return turn;
691
811
  }
692
- async function createStunOverTurnClient({ address, username, password, }, { lifetime, portRange, interfaceAddresses, ssl, tlsOptions, transport: transportType, } = {}) {
693
- const turn = await createTurnClient({
694
- address,
695
- username,
696
- password,
697
- }, {
698
- lifetime,
699
- portRange,
700
- interfaceAddresses,
701
- ssl,
702
- tlsOptions,
703
- transport: transportType,
704
- });
812
+ async function createStunOverTurnClient(config, options = {}) {
813
+ const turn = await createTurnClient(config, options);
705
814
  const turnTransport = new StunOverTurnProtocol(turn);
706
815
  return turnTransport;
707
816
  }
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../../ice/src/turn/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { setTimeout } from \"timers/promises\";\n\nimport { makeTurnIntegrityKey } from \"../../../ice-server/src/turn/auth\";\nimport type { Candidate } from \"../candidate\";\nimport { TransactionFailed } from \"../exceptions\";\nimport { type Cancelable, cancelable, randomTransactionId } from \"../helper\";\nimport {\n type Address,\n Event,\n EventDisposer,\n type InterfaceAddresses,\n TcpTransport,\n type TlsConnectionOptions,\n TlsTransport,\n type Transport,\n UdpTransport,\n bufferReader,\n debug,\n int,\n} from \"../imports/common\";\nimport { classes, methods } from \"../stun/const\";\nimport { Message, paddingLength, parseMessage } from \"../stun/message\";\nimport {\n Transaction,\n buildTransactionOptions,\n resolveRequestAddress,\n} from \"../stun/transaction\";\nimport type { Protocol, TransactionRequestOptions } from \"../types/model\";\nimport {\n decodeChannelData,\n encodeChannelData,\n isChannelData,\n padTurnFrame,\n splitTurnTcpFrames,\n} from \"./frame\";\n\nconst log = debug(\"werift-ice:packages/ice/src/turn/protocol.ts\");\n\nconst DEFAULT_CHANNEL_REFRESH_TIME = 500;\nconst DEFAULT_ALLOCATION_LIFETIME = 600;\nconst UDP_TRANSPORT = 0x11000000;\n\n/** Channel binding state for a single peer transport address. */\nexport interface TurnChannel {\n number: number;\n address: Address;\n /** Unix seconds when this channel should be refreshed. */\n refreshAt: number;\n}\n\nfunction isStreamTransport(transport: Transport) {\n return transport.type === \"tcp\" || transport.type === \"tls\";\n}\n\n/** Permission is peer-IP scoped (RFC 8656). */\nfunction permissionKey(addr: Address): string {\n return addr[0];\n}\n\n/** ChannelBind is peer transport-address scoped (IP + port). */\nfunction channelKey(addr: Address): string {\n return JSON.stringify(addr);\n}\n\nexport class StunOverTurnProtocol implements Protocol {\n static type = \"turn\";\n readonly type = StunOverTurnProtocol.type;\n localCandidate!: Candidate;\n private disposer = new EventDisposer();\n onRequestReceived: Event<[Message, Address, Buffer]> = new Event();\n onDataReceived: Event<[Buffer]> = new Event();\n\n constructor(public turn: TurnProtocol) {\n turn.onData\n .subscribe((data, addr) => {\n this.handleStunMessage(data, addr);\n })\n .disposer(this.disposer);\n }\n\n private handleStunMessage = (data: Buffer, addr: Address) => {\n try {\n const message = parseMessage(data);\n if (!message) {\n this.onDataReceived.execute(data);\n return;\n }\n\n if (\n message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR\n ) {\n const transaction = this.turn.transactions[message.transactionIdHex];\n if (transaction) {\n const verified = transaction.integrityKey\n ? parseMessage(data, transaction.integrityKey)\n : message;\n if (!verified) {\n log(\"STUN over TURN response failed MESSAGE-INTEGRITY check\");\n return;\n }\n transaction.responseReceived(verified, addr);\n }\n } else if (message.messageClass === classes.REQUEST) {\n this.onRequestReceived.execute(message, addr, data);\n }\n } catch (error) {\n log(\"datagramReceived error\", error);\n }\n };\n\n async request(\n request: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) {\n if (this.turn.transactions[request.transactionIdHex]) {\n throw new Error(\"exist\");\n }\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n request.addFingerprint();\n }\n\n // Peer-facing STUN over TURN must honor retransmissions/responseTimeout\n // (consent uses retransmissions: 0). Do not confuse with TURN server\n // allocation/refresh policy on TurnProtocol.\n // Peer addresses are already IPs from candidates; resolve for safety.\n const resolvedAddr = await resolveRequestAddress(addr);\n const options = buildTransactionOptions(\n integrityKey,\n retransmissionsOrOptions,\n onRequestSent,\n );\n const transaction = new Transaction(request, resolvedAddr, this, options);\n this.turn.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } catch (e) {\n throw e;\n } finally {\n delete this.turn.transactions[request.transactionIdHex];\n }\n }\n async connectionMade() {}\n async sendData(data: Buffer, addr: Address) {\n await this.turn.sendData(data, addr);\n }\n async sendStun(message: Message, addr: Address) {\n await this.turn.sendData(message.bytes, addr);\n }\n async close() {\n this.disposer.dispose();\n return this.turn.close();\n }\n}\n\nexport class TurnProtocol implements Protocol {\n static type = \"turn\";\n readonly type = TurnProtocol.type;\n readonly onData = new Event<[Buffer, Address]>();\n onRequestReceived: Event<[Message, Address, Buffer]> = new Event();\n onDataReceived: Event<[Buffer]> = new Event();\n integrityKey?: Buffer;\n nonce?: Buffer;\n realm?: string;\n relayedAddress!: Address;\n mappedAddress!: Address;\n localCandidate!: Candidate;\n transactions: { [hexId: string]: Transaction } = {};\n private refreshHandle?: Cancelable<void>;\n private channelNumber = 0x4000;\n private channelByAddr: { [key: string]: TurnChannel } = {};\n private addrByChannel: { [channel: number]: Address } = {};\n /**sec */\n private channelRefreshTime: number;\n /**\n * Serializes ChannelBind requests so allocation-wide auth state\n * (nonce/realm/integrityKey) is not updated concurrently. Rejections\n * must not poison this tail — see channelBindQueue assignment sites.\n */\n private channelBindQueue: Promise<void> = Promise.resolve();\n /** In-flight ChannelBind per peer transport address (dedupe concurrent). */\n private channelBindingByAddr = new Map<string, Promise<TurnChannel>>();\n private tcpBuffer: Buffer = Buffer.alloc(0);\n /** Permission cache keyed by peer IP only (RFC 8656). */\n private permissionByAddr: { [peerIp: string]: boolean } = {};\n /**\n * Serializes CreatePermission requests (auth state race avoidance).\n * Rejections must not poison this tail.\n */\n private permissionQueue: Promise<void> = Promise.resolve();\n /** In-flight CreatePermission per peer IP (dedupe concurrent). */\n private creatingPermissionByAddr = new Map<string, Promise<void>>();\n\n constructor(\n public server: Address,\n public username: string,\n public password: string,\n public lifetime: number,\n public transport: Transport,\n public options: {\n /**sec */\n channelRefreshTime?: number;\n } = {},\n ) {\n this.channelRefreshTime =\n this.options.channelRefreshTime ?? DEFAULT_CHANNEL_REFRESH_TIME;\n }\n\n async connectionMade() {\n this.transport.onData = (data, addr) => {\n this.dataReceived(data, addr);\n };\n\n const request = new Message(methods.ALLOCATE, classes.REQUEST);\n request\n .setAttribute(\"LIFETIME\", this.lifetime)\n .setAttribute(\"REQUESTED-TRANSPORT\", UDP_TRANSPORT);\n\n const [response] = await this.requestWithRetry(request, this.server).catch(\n (e) => {\n log(\"connect error\", e);\n throw e;\n },\n );\n this.relayedAddress = response.getAttributeValue(\"XOR-RELAYED-ADDRESS\");\n this.mappedAddress = response.getAttributeValue(\"XOR-MAPPED-ADDRESS\");\n const exp = response.getAttributeValue(\"LIFETIME\");\n log(\"connect\", this.relayedAddress, this.mappedAddress, { exp });\n\n this.refresh(exp);\n }\n\n private handleChannelData(data: Buffer) {\n const decoded = decodeChannelData(data);\n const addr = decoded && this.addrByChannel[decoded.channelNumber];\n\n if (addr && decoded) {\n this.onData.execute(decoded.data, addr);\n }\n }\n\n private handleSTUNMessage(data: Buffer, addr: Address) {\n try {\n const message = parseMessage(data);\n if (!message) {\n throw new Error(\"not stun message\");\n }\n\n if (\n message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR\n ) {\n const transaction = this.transactions[message.transactionIdHex];\n if (transaction) {\n const verified = transaction.integrityKey\n ? parseMessage(data, transaction.integrityKey)\n : message;\n if (!verified) {\n log(\"TURN STUN response failed MESSAGE-INTEGRITY check\");\n return;\n }\n transaction.responseReceived(verified, addr);\n }\n } else if (message.messageClass === classes.REQUEST) {\n this.onData.execute(data, addr);\n }\n\n if (message.getAttributeValue(\"DATA\")) {\n const buf: Buffer = message.getAttributeValue(\"DATA\");\n const peerAddress =\n message.getAttributeValue(\"XOR-PEER-ADDRESS\") ?? addr;\n this.onData.execute(buf, peerAddress);\n }\n } catch (error) {\n log(\"parse error\", data.toString());\n }\n }\n\n private dataReceived(data: Buffer, addr: Address) {\n const datagramReceived = (data: Buffer, addr: Address) => {\n if (data.length >= 4 && isChannelData(data)) {\n this.handleChannelData(data);\n } else {\n this.handleSTUNMessage(data, addr);\n }\n };\n\n if (isStreamTransport(this.transport)) {\n this.tcpBuffer = Buffer.concat([this.tcpBuffer, data]);\n const { frames, rest } = splitTurnTcpFrames(this.tcpBuffer);\n this.tcpBuffer = rest;\n for (const frame of frames) {\n datagramReceived(frame, addr);\n }\n } else {\n datagramReceived(data, addr);\n }\n }\n\n private async send(data: Buffer, addr: Address) {\n if (this.transport.closed) {\n return;\n }\n\n await this.transport.send(\n isStreamTransport(this.transport) ? padTurnFrame(data) : data,\n addr,\n );\n }\n\n private async createPermission(peerAddress: Address) {\n const request = new Message(methods.CREATE_PERMISSION, classes.REQUEST);\n request\n .setAttribute(\"XOR-PEER-ADDRESS\", peerAddress)\n .setAttribute(\"USERNAME\", this.username)\n .setAttribute(\"REALM\", this.realm)\n .setAttribute(\"NONCE\", this.nonce);\n // Use requestWithRetry for stale-nonce (438) consistency with ChannelBind.\n await this.requestWithRetry(request, this.server);\n }\n\n private refresh = (exp: number) => {\n this.refreshHandle = cancelable<void>(async (_, __, onCancel) => {\n let run = true;\n onCancel.once(() => {\n run = false;\n });\n\n while (run) {\n // refresh before expire\n const delay = (5 / 6) * exp * 1000;\n log(\"refresh delay\", delay, { exp });\n await setTimeout(delay);\n\n const request = new Message(methods.REFRESH, classes.REQUEST);\n request.setAttribute(\"LIFETIME\", exp);\n\n try {\n const [message] = await this.requestWithRetry(request, this.server);\n exp = message.getAttributeValue(\"LIFETIME\");\n log(\"refresh\", { exp });\n } catch (error) {\n log(\"refresh error\", error);\n }\n }\n });\n };\n\n async request(\n request: Message,\n addr: Address,\n _integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ): Promise<[Message, Address]> {\n if (this.transactions[request.transactionIdHex]) {\n throw new Error(\"exist\");\n }\n if (this.integrityKey) {\n request\n .setAttribute(\"USERNAME\", this.username)\n .setAttribute(\"REALM\", this.realm)\n .setAttribute(\"NONCE\", this.nonce)\n .addMessageIntegrity(this.integrityKey)\n .addFingerprint();\n }\n\n // TURN server allocation/refresh uses default STUN retry policy unless\n // callers pass explicit options. Peer consent goes through StunOverTurnProtocol.\n // Prefer the TURN session integrity key for response verification.\n const resolvedAddr = await resolveRequestAddress(addr);\n const options = buildTransactionOptions(\n this.integrityKey,\n retransmissionsOrOptions,\n onRequestSent,\n );\n const transaction = new Transaction(request, resolvedAddr, this, options);\n this.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } catch (e) {\n throw e;\n } finally {\n delete this.transactions[request.transactionIdHex];\n }\n }\n\n async requestWithRetry(\n request: Message,\n addr: Address,\n ): Promise<[Message, Address]> {\n let message: Message, address: Address;\n try {\n [message, address] = await this.request(request, addr);\n } catch (error) {\n if (error instanceof TransactionFailed == false) {\n log(\"requestWithRetry error\", error);\n throw error;\n }\n\n // resolve dns address\n this.server = error.addr;\n\n const [errorCode] = error.response.getAttributeValue(\"ERROR-CODE\");\n const nonce = error.response.getAttributeValue(\"NONCE\");\n const realm = error.response.getAttributeValue(\"REALM\");\n\n if (\n ((errorCode === 401 && realm) || (errorCode === 438 && this.realm)) &&\n nonce\n ) {\n log(\"retry with nonce\", errorCode);\n\n this.nonce = nonce;\n if (errorCode === 401) {\n this.realm = realm;\n }\n this.integrityKey = makeIntegrityKey(\n this.username,\n this.realm!,\n this.password,\n );\n\n request.transactionId = randomTransactionId();\n [message, address] = await this.request(request, this.server);\n } else {\n throw error;\n }\n }\n return [message!, address!];\n }\n\n async sendData(data: Buffer, addr: Address) {\n let channel: TurnChannel | undefined;\n try {\n channel = await this.getChannel(addr);\n } catch (e) {\n // Keep original ChannelBind error for diagnostics (403/438/timeout).\n log(\"channelBind error; falling back to Send Indication\", e);\n }\n\n if (!channel) {\n await this.getPermission(addr);\n const indicate = new Message(methods.SEND, classes.INDICATION)\n .setAttribute(\"DATA\", data)\n .setAttribute(\"XOR-PEER-ADDRESS\", addr);\n\n await this.sendStun(indicate, this.server);\n return;\n }\n\n await this.send(encodeChannelData(channel.number, data), this.server);\n }\n\n /**\n * Ensure a CreatePermission exists for the peer IP.\n * Peer failures are isolated: a rejection for peer A does not poison peer B.\n */\n async getPermission(addr: Address) {\n const key = permissionKey(addr);\n\n if (this.permissionByAddr[key]) {\n return;\n }\n\n const existing = this.creatingPermissionByAddr.get(key);\n if (existing) {\n return existing;\n }\n\n const operation = this.permissionQueue.then(async () => {\n // Another caller may have succeeded while we waited on the queue.\n if (this.permissionByAddr[key]) {\n return;\n }\n\n await this.createPermission(addr);\n // Cache only after successful CreatePermission.\n this.permissionByAddr[key] = true;\n });\n\n // Do not let rejection poison subsequent peers on the shared queue.\n this.permissionQueue = operation.then(\n () => undefined,\n () => undefined,\n );\n\n this.creatingPermissionByAddr.set(key, operation);\n\n try {\n await operation;\n } catch (error) {\n log(\"createPermission error\", error);\n throw error;\n } finally {\n if (this.creatingPermissionByAddr.get(key) === operation) {\n this.creatingPermissionByAddr.delete(key);\n }\n }\n }\n\n /**\n * Ensure a ChannelBind exists for the peer transport address.\n * Peer failures are isolated; concurrent same-peer calls share one Promise.\n */\n async getChannel(addr: Address): Promise<TurnChannel> {\n const key = channelKey(addr);\n\n const existing = this.channelBindingByAddr.get(key);\n if (existing) {\n return existing;\n }\n\n // Fast path: bound and not due for refresh.\n const cached = this.channelByAddr[key];\n const now = int(Date.now() / 1000);\n if (cached && cached.refreshAt > now) {\n return cached;\n }\n\n const operation = this.channelBindQueue.then(() =>\n this.ensureChannel(addr),\n );\n\n // Do not let rejection poison subsequent peers on the shared queue.\n this.channelBindQueue = operation.then(\n () => undefined,\n () => undefined,\n );\n\n this.channelBindingByAddr.set(key, operation);\n\n try {\n return await operation;\n } catch (error) {\n log(\"channelBind error\", error);\n throw error;\n } finally {\n if (this.channelBindingByAddr.get(key) === operation) {\n this.channelBindingByAddr.delete(key);\n }\n }\n }\n\n /**\n * Create or refresh a channel for addr. Provisional mapping is installed\n * before the request so early ChannelData can be decoded; only a failed\n * *initial* bind rolls the mapping back. Failed channel numbers are never\n * reused.\n */\n private async ensureChannel(addr: Address): Promise<TurnChannel> {\n const key = channelKey(addr);\n const now = int(Date.now() / 1000);\n\n let channel = this.channelByAddr[key];\n if (channel && channel.refreshAt > now) {\n return channel;\n }\n\n const isNew = !channel;\n\n if (!channel) {\n channel = {\n number: this.channelNumber++,\n address: addr,\n refreshAt: 0,\n };\n // Provisional mapping for ChannelData that may arrive before success.\n this.channelByAddr[key] = channel;\n this.addrByChannel[channel.number] = addr;\n }\n\n try {\n await this.channelBind(channel.number, addr);\n channel.refreshAt = int(Date.now() / 1000) + this.channelRefreshTime;\n log(isNew ? \"channelBind\" : \"channelBind refresh\", channel);\n return channel;\n } catch (error) {\n if (isNew) {\n // Roll back provisional mapping only for a failed initial bind.\n delete this.channelByAddr[key];\n delete this.addrByChannel[channel.number];\n // Do not reuse the channel number (no channelNumber--).\n }\n throw error;\n }\n }\n\n private async channelBind(channelNumber: number, addr: Address) {\n const request = new Message(methods.CHANNEL_BIND, classes.REQUEST);\n request\n .setAttribute(\"CHANNEL-NUMBER\", channelNumber)\n .setAttribute(\"XOR-PEER-ADDRESS\", addr);\n const [response] = await this.requestWithRetry(request, this.server);\n if (response.messageMethod !== methods.CHANNEL_BIND) {\n throw new Error(\"should be CHANNEL_BIND\");\n }\n }\n\n async sendStun(message: Message, addr: Address) {\n await this.send(message.bytes, addr);\n }\n\n async close() {\n this.refreshHandle?.resolve?.();\n await this.transport.close();\n }\n}\n\nexport interface TurnClientConfig {\n address: Address;\n username: string;\n password: string;\n}\nexport interface TurnClientOptions {\n lifetime?: number;\n ssl?: boolean;\n transport?: \"udp\" | \"tcp\" | \"tls\";\n tlsOptions?: TlsConnectionOptions;\n portRange?: [number, number];\n interfaceAddresses?: InterfaceAddresses;\n}\n\nexport async function createTurnClient(\n { address, username, password }: TurnClientConfig,\n {\n lifetime,\n portRange,\n interfaceAddresses,\n ssl,\n tlsOptions,\n transport: transportType,\n }: TurnClientOptions = {},\n) {\n lifetime ??= DEFAULT_ALLOCATION_LIFETIME;\n transportType ??= ssl ? \"tls\" : \"udp\";\n\n const transport =\n transportType === \"udp\"\n ? await UdpTransport.init(\"udp4\", { portRange, interfaceAddresses })\n : transportType === \"tcp\"\n ? await TcpTransport.init(address)\n : await TlsTransport.init(address, tlsOptions);\n\n const turn = new TurnProtocol(\n address,\n username,\n password,\n lifetime,\n transport,\n );\n\n await turn.connectionMade();\n return turn;\n}\n\nexport async function createStunOverTurnClient(\n {\n address,\n username,\n password,\n }: {\n address: Address;\n username: string;\n password: string;\n },\n {\n lifetime,\n portRange,\n interfaceAddresses,\n ssl,\n tlsOptions,\n transport: transportType,\n }: {\n lifetime?: number;\n ssl?: boolean;\n transport?: \"udp\" | \"tcp\" | \"tls\";\n tlsOptions?: TlsConnectionOptions;\n portRange?: [number, number];\n interfaceAddresses?: InterfaceAddresses;\n } = {},\n) {\n const turn = await createTurnClient(\n {\n address,\n username,\n password,\n },\n {\n lifetime,\n portRange,\n interfaceAddresses,\n ssl,\n tlsOptions,\n transport: transportType,\n },\n );\n const turnTransport = new StunOverTurnProtocol(turn);\n return turnTransport;\n}\n\nexport function makeIntegrityKey(\n username: string,\n realm: string,\n password: string,\n) {\n return makeTurnIntegrityKey(username, realm, password);\n}\n"]}
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../../ice/src/turn/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { isIP } from \"node:net\";\nimport { setTimeout } from \"timers/promises\";\n\nimport { makeTurnIntegrityKey } from \"../../../ice-server/src/turn/auth\";\nimport type { Candidate } from \"../candidate\";\nimport { TransactionFailed } from \"../exceptions\";\nimport { type Cancelable, cancelable, randomTransactionId } from \"../helper\";\nimport {\n type Address,\n Event,\n EventDisposer,\n type InterfaceAddresses,\n TcpTransport,\n type TlsConnectionOptions,\n TlsTransport,\n type Transport,\n UdpTransport,\n bufferReader,\n debug,\n int,\n} from \"../imports/common\";\nimport { classes, methods } from \"../stun/const\";\nimport { Message, paddingLength, parseMessage } from \"../stun/message\";\nimport {\n Transaction,\n addressEquals,\n buildTransactionOptions,\n resolveRequestAddress,\n} from \"../stun/transaction\";\nimport type { Protocol, TransactionRequestOptions } from \"../types/model\";\nimport {\n decodeChannelData,\n encodeChannelData,\n isChannelData,\n padTurnFrame,\n splitTurnTcpFrames,\n} from \"./frame\";\n\nconst log = debug(\"werift-ice:packages/ice/src/turn/protocol.ts\");\n\nconst DEFAULT_CHANNEL_REFRESH_TIME = 500;\nconst DEFAULT_ALLOCATION_LIFETIME = 600;\nconst UDP_TRANSPORT = 0x11000000;\n\n/** Channel binding state for a single peer transport address. */\nexport interface TurnChannel {\n number: number;\n address: Address;\n /** Unix seconds when this channel should be refreshed. */\n refreshAt: number;\n}\n\nfunction isStreamTransport(transport: Transport) {\n return transport.type === \"tcp\" || transport.type === \"tls\";\n}\n\n/** Permission is peer-IP scoped (RFC 8656). */\nfunction permissionKey(addr: Address): string {\n return addr[0];\n}\n\n/** ChannelBind is peer transport-address scoped (IP + port). */\nfunction channelKey(addr: Address): string {\n return JSON.stringify(addr);\n}\n\nexport class StunOverTurnProtocol implements Protocol {\n static type = \"turn\";\n readonly type = StunOverTurnProtocol.type;\n localCandidate!: Candidate;\n private disposer = new EventDisposer();\n onRequestReceived: Event<[Message, Address, Buffer]> = new Event();\n onDataReceived: Event<[Buffer]> = new Event();\n\n constructor(public turn: TurnProtocol) {\n turn.onData\n .subscribe((data, addr) => {\n this.handleStunMessage(data, addr);\n })\n .disposer(this.disposer);\n }\n\n private handleStunMessage = (data: Buffer, addr: Address) => {\n try {\n const message = parseMessage(data);\n if (!message) {\n this.onDataReceived.execute(data);\n return;\n }\n\n if (\n message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR\n ) {\n const transaction = this.turn.transactions[message.transactionIdHex];\n if (transaction) {\n const verified = transaction.integrityKey\n ? parseMessage(data, transaction.integrityKey)\n : message;\n if (!verified) {\n log(\"STUN over TURN response failed MESSAGE-INTEGRITY check\");\n return;\n }\n transaction.responseReceived(verified, addr);\n }\n } else if (message.messageClass === classes.REQUEST) {\n this.onRequestReceived.execute(message, addr, data);\n }\n } catch (error) {\n log(\"datagramReceived error\", error);\n }\n };\n\n async request(\n request: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) {\n if (this.turn.transactions[request.transactionIdHex]) {\n throw new Error(\"exist\");\n }\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n request.addFingerprint();\n }\n\n // Peer-facing STUN over TURN must honor retransmissions/responseTimeout\n // (consent uses retransmissions: 0). Do not confuse with TURN server\n // allocation/refresh policy on TurnProtocol.\n // Peer addresses are already IPs from candidates; resolve for safety.\n const resolvedAddr = await resolveRequestAddress(addr);\n const options = buildTransactionOptions(\n integrityKey,\n retransmissionsOrOptions,\n onRequestSent,\n );\n const transaction = new Transaction(request, resolvedAddr, this, options);\n this.turn.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } catch (e) {\n throw e;\n } finally {\n delete this.turn.transactions[request.transactionIdHex];\n }\n }\n async connectionMade() {}\n async sendData(data: Buffer, addr: Address) {\n await this.turn.sendData(data, addr);\n }\n async sendStun(message: Message, addr: Address) {\n await this.turn.sendData(message.bytes, addr);\n }\n async close() {\n this.disposer.dispose();\n return this.turn.close();\n }\n}\n\nexport class TurnProtocol implements Protocol {\n static type = \"turn\";\n readonly type = TurnProtocol.type;\n readonly onData = new Event<[Buffer, Address]>();\n onRequestReceived: Event<[Message, Address, Buffer]> = new Event();\n onDataReceived: Event<[Buffer]> = new Event();\n integrityKey?: Buffer;\n nonce?: Buffer;\n realm?: string;\n relayedAddress!: Address;\n mappedAddress!: Address;\n localCandidate!: Candidate;\n transactions: { [hexId: string]: Transaction } = {};\n private refreshHandle?: Cancelable<void>;\n private channelNumber = 0x4000;\n private channelByAddr: { [key: string]: TurnChannel } = {};\n private addrByChannel: { [channel: number]: Address } = {};\n /**sec */\n private channelRefreshTime: number;\n /**\n * Serializes ChannelBind requests so allocation-wide auth state\n * (nonce/realm/integrityKey) is not updated concurrently. Rejections\n * must not poison this tail — see channelBindQueue assignment sites.\n */\n private channelBindQueue: Promise<void> = Promise.resolve();\n /** In-flight ChannelBind per peer transport address (dedupe concurrent). */\n private channelBindingByAddr = new Map<string, Promise<TurnChannel>>();\n private tcpBuffer: Buffer = Buffer.alloc(0);\n /** Permission cache keyed by peer IP only (RFC 8656). */\n private permissionByAddr: { [peerIp: string]: boolean } = {};\n /**\n * Serializes CreatePermission requests (auth state race avoidance).\n * Rejections must not poison this tail.\n */\n private permissionQueue: Promise<void> = Promise.resolve();\n /** In-flight CreatePermission per peer IP (dedupe concurrent). */\n private creatingPermissionByAddr = new Map<string, Promise<void>>();\n /** Concrete TURN server address the allocation lives on, once selected. */\n private pinnedServerEndpoint?: Address;\n private serverEndpointSelection?: Promise<Address>;\n\n constructor(\n /** TURN server as configured; the host may be a hostname. */\n public server: Address,\n public username: string,\n public password: string,\n public lifetime: number,\n public transport: Transport,\n public options: {\n /**sec */\n channelRefreshTime?: number;\n } = {},\n ) {\n this.channelRefreshTime =\n this.options.channelRefreshTime ?? DEFAULT_CHANNEL_REFRESH_TIME;\n }\n\n async connectionMade() {\n this.transport.onData = (data, addr) => {\n this.dataReceived(data, addr);\n };\n\n const request = new Message(methods.ALLOCATE, classes.REQUEST);\n request\n .setAttribute(\"LIFETIME\", this.lifetime)\n .setAttribute(\"REQUESTED-TRANSPORT\", UDP_TRANSPORT);\n\n const [response] = await this.requestWithRetry(request, this.server).catch(\n (e) => {\n log(\"connect error\", e);\n throw e;\n },\n );\n this.relayedAddress = response.getAttributeValue(\"XOR-RELAYED-ADDRESS\");\n this.mappedAddress = response.getAttributeValue(\"XOR-MAPPED-ADDRESS\");\n const exp = response.getAttributeValue(\"LIFETIME\");\n log(\"connect\", this.relayedAddress, this.mappedAddress, { exp });\n\n this.refresh(exp);\n }\n\n private handleChannelData(data: Buffer) {\n const decoded = decodeChannelData(data);\n const addr = decoded && this.addrByChannel[decoded.channelNumber];\n\n if (addr && decoded) {\n this.onData.execute(decoded.data, addr);\n }\n }\n\n private handleSTUNMessage(data: Buffer, addr: Address) {\n try {\n const message = parseMessage(data);\n if (!message) {\n throw new Error(\"not stun message\");\n }\n\n if (\n message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR\n ) {\n const transaction = this.transactions[message.transactionIdHex];\n if (transaction) {\n const verified = transaction.integrityKey\n ? parseMessage(data, transaction.integrityKey)\n : message;\n if (!verified) {\n log(\"TURN STUN response failed MESSAGE-INTEGRITY check\");\n return;\n }\n transaction.responseReceived(verified, addr);\n }\n } else if (message.messageClass === classes.REQUEST) {\n this.onData.execute(data, addr);\n }\n\n if (message.getAttributeValue(\"DATA\")) {\n const buf: Buffer = message.getAttributeValue(\"DATA\");\n const peerAddress =\n message.getAttributeValue(\"XOR-PEER-ADDRESS\") ?? addr;\n this.onData.execute(buf, peerAddress);\n }\n } catch (error) {\n log(\"parse error\", data.toString());\n }\n }\n\n private dataReceived(data: Buffer, addr: Address) {\n const datagramReceived = (data: Buffer, addr: Address) => {\n if (data.length >= 4 && isChannelData(data)) {\n this.handleChannelData(data);\n } else {\n this.handleSTUNMessage(data, addr);\n }\n };\n\n if (isStreamTransport(this.transport)) {\n this.tcpBuffer = Buffer.concat([this.tcpBuffer, data]);\n const { frames, rest } = splitTurnTcpFrames(this.tcpBuffer);\n this.tcpBuffer = rest;\n for (const frame of frames) {\n datagramReceived(frame, addr);\n }\n } else {\n datagramReceived(data, addr);\n }\n }\n\n private async send(data: Buffer, addr: Address) {\n if (this.transport.closed) {\n return;\n }\n\n await this.transport.send(\n isStreamTransport(this.transport) ? padTurnFrame(data) : data,\n addr,\n );\n }\n\n private async createPermission(peerAddress: Address) {\n const request = new Message(methods.CREATE_PERMISSION, classes.REQUEST);\n request\n .setAttribute(\"XOR-PEER-ADDRESS\", peerAddress)\n .setAttribute(\"USERNAME\", this.username)\n .setAttribute(\"REALM\", this.realm)\n .setAttribute(\"NONCE\", this.nonce);\n // Use requestWithRetry for stale-nonce (438) consistency with ChannelBind.\n await this.requestWithRetry(request, this.server);\n }\n\n private refresh = (exp: number) => {\n this.refreshHandle = cancelable<void>(async (_, __, onCancel) => {\n const abort = new AbortController();\n onCancel.once(() => {\n abort.abort();\n });\n\n while (!abort.signal.aborted) {\n // refresh before expire\n const delay = (5 / 6) * exp * 1000;\n log(\"refresh delay\", delay, { exp });\n try {\n await setTimeout(delay, undefined, { signal: abort.signal });\n } catch (error) {\n if (abort.signal.aborted) {\n return;\n }\n throw error;\n }\n\n if (abort.signal.aborted) {\n return;\n }\n\n const request = new Message(methods.REFRESH, classes.REQUEST);\n request.setAttribute(\"LIFETIME\", exp);\n\n try {\n const [message] = await this.requestWithRetry(\n request,\n this.server,\n abort.signal,\n );\n exp = message.getAttributeValue(\"LIFETIME\");\n log(\"refresh\", { exp });\n } catch (error) {\n if (abort.signal.aborted) {\n return;\n }\n log(\"refresh error\", error);\n }\n }\n });\n };\n\n async request(\n request: Message,\n addr: Address,\n _integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ): Promise<[Message, Address]> {\n if (this.transactions[request.transactionIdHex]) {\n throw new Error(\"exist\");\n }\n if (this.integrityKey) {\n request\n .setAttribute(\"USERNAME\", this.username)\n .setAttribute(\"REALM\", this.realm)\n .setAttribute(\"NONCE\", this.nonce)\n .addMessageIntegrity(this.integrityKey)\n .addFingerprint();\n }\n\n // TURN server allocation/refresh uses default STUN retry policy unless\n // callers pass explicit options. Peer consent goes through StunOverTurnProtocol.\n // Prefer the TURN session integrity key for response verification.\n const resolvedAddr = await this.resolveRequestTarget(addr);\n const options = buildTransactionOptions(\n this.integrityKey,\n retransmissionsOrOptions,\n onRequestSent,\n );\n const transaction = new Transaction(request, resolvedAddr, this, options);\n this.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } catch (e) {\n throw e;\n } finally {\n delete this.transactions[request.transactionIdHex];\n }\n }\n\n /**\n * The concrete TURN server address, selected on the first request and\n * pinned for the rest of the allocation, so a later DNS answer can never\n * move REFRESH, CREATE_PERMISSION, CHANNEL_BIND or data to another server.\n */\n get serverEndpoint(): Address | undefined {\n return this.pinnedServerEndpoint;\n }\n\n /**\n * Address a request to `addr` is sent to, and the address its response\n * must come from. A stream carries every request to the peer it is\n * connected to, so it always uses the server endpoint.\n */\n private async resolveRequestTarget(addr: Address): Promise<Address> {\n if (isStreamTransport(this.transport) || addressEquals(addr, this.server)) {\n return this.selectServerEndpoint();\n }\n return resolveRequestAddress(addr, this.transport.addressFamily ?? 0);\n }\n\n private async serverDestination(): Promise<Address> {\n return this.pinnedServerEndpoint ?? this.selectServerEndpoint();\n }\n\n private selectServerEndpoint(): Promise<Address> {\n this.serverEndpointSelection ??= this.resolveServerEndpoint().then(\n (endpoint) => {\n this.pinnedServerEndpoint = endpoint;\n return endpoint;\n },\n (error) => {\n // Let a later request try again, e.g. after a transient DNS failure.\n this.serverEndpointSelection = undefined;\n throw error;\n },\n );\n return this.serverEndpointSelection;\n }\n\n /**\n * UDP: resolve the configured server in the bound socket's family; a udp4\n * socket cannot send to an IPv6 answer. TCP/TLS: use the peer the socket\n * actually connected to. Looking the hostname up again could return a\n * different A/AAAA record, and responses from the real peer would then be\n * dropped as coming from an unexpected address.\n */\n private async resolveServerEndpoint(): Promise<Address> {\n const transport = this.transport;\n if (!isStreamTransport(transport)) {\n return resolveRequestAddress(this.server, transport.addressFamily ?? 0);\n }\n if (transport.remoteAddress) {\n return transport.remoteAddress;\n }\n if (\n transport instanceof TcpTransport ||\n transport instanceof TlsTransport\n ) {\n throw new Error(`${transport.type} transport has no remote address`);\n }\n // A custom stream transport that does not report its peer: fall back to\n // a lookup with no family preference.\n return resolveRequestAddress(this.server);\n }\n\n async requestWithRetry(\n request: Message,\n addr: Address,\n signal?: AbortSignal,\n ): Promise<[Message, Address]> {\n let message: Message, address: Address;\n try {\n [message, address] = await this.request(request, addr, undefined, {\n signal,\n });\n } catch (error) {\n if (error instanceof TransactionFailed == false) {\n log(\"requestWithRetry error\", error);\n throw error;\n }\n\n const [errorCode] = error.response.getAttributeValue(\"ERROR-CODE\");\n const nonce = error.response.getAttributeValue(\"NONCE\");\n const realm = error.response.getAttributeValue(\"REALM\");\n\n if (\n ((errorCode === 401 && realm) || (errorCode === 438 && this.realm)) &&\n nonce\n ) {\n log(\"retry with nonce\", errorCode);\n\n this.nonce = nonce;\n if (errorCode === 401) {\n this.realm = realm;\n }\n this.integrityKey = makeIntegrityKey(\n this.username,\n this.realm!,\n this.password,\n );\n\n request.transactionId = randomTransactionId();\n [message, address] = await this.request(\n request,\n this.server,\n undefined,\n { signal },\n );\n } else {\n throw error;\n }\n }\n return [message!, address!];\n }\n\n async sendData(data: Buffer, addr: Address) {\n let channel: TurnChannel | undefined;\n try {\n channel = await this.getChannel(addr);\n } catch (e) {\n // Keep original ChannelBind error for diagnostics (403/438/timeout).\n log(\"channelBind error; falling back to Send Indication\", e);\n }\n\n if (!channel) {\n await this.getPermission(addr);\n const indicate = new Message(methods.SEND, classes.INDICATION)\n .setAttribute(\"DATA\", data)\n .setAttribute(\"XOR-PEER-ADDRESS\", addr);\n\n await this.sendStun(indicate, await this.serverDestination());\n return;\n }\n\n await this.send(\n encodeChannelData(channel.number, data),\n await this.serverDestination(),\n );\n }\n\n /**\n * Ensure a CreatePermission exists for the peer IP.\n * Peer failures are isolated: a rejection for peer A does not poison peer B.\n */\n async getPermission(addr: Address) {\n const key = permissionKey(addr);\n\n if (this.permissionByAddr[key]) {\n return;\n }\n\n const existing = this.creatingPermissionByAddr.get(key);\n if (existing) {\n return existing;\n }\n\n const operation = this.permissionQueue.then(async () => {\n // Another caller may have succeeded while we waited on the queue.\n if (this.permissionByAddr[key]) {\n return;\n }\n\n await this.createPermission(addr);\n // Cache only after successful CreatePermission.\n this.permissionByAddr[key] = true;\n });\n\n // Do not let rejection poison subsequent peers on the shared queue.\n this.permissionQueue = operation.then(\n () => undefined,\n () => undefined,\n );\n\n this.creatingPermissionByAddr.set(key, operation);\n\n try {\n await operation;\n } catch (error) {\n log(\"createPermission error\", error);\n throw error;\n } finally {\n if (this.creatingPermissionByAddr.get(key) === operation) {\n this.creatingPermissionByAddr.delete(key);\n }\n }\n }\n\n /**\n * Ensure a ChannelBind exists for the peer transport address.\n * Peer failures are isolated; concurrent same-peer calls share one Promise.\n */\n async getChannel(addr: Address): Promise<TurnChannel> {\n const key = channelKey(addr);\n\n const existing = this.channelBindingByAddr.get(key);\n if (existing) {\n return existing;\n }\n\n // Fast path: bound and not due for refresh.\n const cached = this.channelByAddr[key];\n const now = int(Date.now() / 1000);\n if (cached && cached.refreshAt > now) {\n return cached;\n }\n\n const operation = this.channelBindQueue.then(() =>\n this.ensureChannel(addr),\n );\n\n // Do not let rejection poison subsequent peers on the shared queue.\n this.channelBindQueue = operation.then(\n () => undefined,\n () => undefined,\n );\n\n this.channelBindingByAddr.set(key, operation);\n\n try {\n return await operation;\n } catch (error) {\n log(\"channelBind error\", error);\n throw error;\n } finally {\n if (this.channelBindingByAddr.get(key) === operation) {\n this.channelBindingByAddr.delete(key);\n }\n }\n }\n\n /**\n * Create or refresh a channel for addr. Provisional mapping is installed\n * before the request so early ChannelData can be decoded; only a failed\n * *initial* bind rolls the mapping back. Failed channel numbers are never\n * reused.\n */\n private async ensureChannel(addr: Address): Promise<TurnChannel> {\n const key = channelKey(addr);\n const now = int(Date.now() / 1000);\n\n let channel = this.channelByAddr[key];\n if (channel && channel.refreshAt > now) {\n return channel;\n }\n\n const isNew = !channel;\n\n if (!channel) {\n channel = {\n number: this.channelNumber++,\n address: addr,\n refreshAt: 0,\n };\n // Provisional mapping for ChannelData that may arrive before success.\n this.channelByAddr[key] = channel;\n this.addrByChannel[channel.number] = addr;\n }\n\n try {\n await this.channelBind(channel.number, addr);\n channel.refreshAt = int(Date.now() / 1000) + this.channelRefreshTime;\n log(isNew ? \"channelBind\" : \"channelBind refresh\", channel);\n return channel;\n } catch (error) {\n if (isNew) {\n // Roll back provisional mapping only for a failed initial bind.\n delete this.channelByAddr[key];\n delete this.addrByChannel[channel.number];\n // Do not reuse the channel number (no channelNumber--).\n }\n throw error;\n }\n }\n\n private async channelBind(channelNumber: number, addr: Address) {\n const request = new Message(methods.CHANNEL_BIND, classes.REQUEST);\n request\n .setAttribute(\"CHANNEL-NUMBER\", channelNumber)\n .setAttribute(\"XOR-PEER-ADDRESS\", addr);\n const [response] = await this.requestWithRetry(request, this.server);\n if (response.messageMethod !== methods.CHANNEL_BIND) {\n throw new Error(\"should be CHANNEL_BIND\");\n }\n }\n\n async sendStun(message: Message, addr: Address) {\n await this.send(message.bytes, addr);\n }\n\n async close() {\n this.refreshHandle?.resolve?.();\n await this.transport.close();\n }\n}\n\nexport interface TurnClientConfig {\n address: Address;\n username: string;\n password: string;\n}\nexport interface TurnClientOptions {\n lifetime?: number;\n ssl?: boolean;\n transport?: \"udp\" | \"tcp\" | \"tls\";\n tlsOptions?: TlsConnectionOptions;\n portRange?: [number, number];\n interfaceAddresses?: InterfaceAddresses;\n /** Maximum time to wait for TCP/TLS connection establishment, in milliseconds. */\n connectTimeoutMs?: number;\n /**\n * Preferred IP family of the UDP socket, applied only when the server\n * address is a hostname. Ignored for an IP literal server address, whose\n * own family always selects the socket. Defaults to 4.\n */\n udpFamily?: 4 | 6;\n}\n\n/**\n * Select the UDP socket type for a TURN server.\n * Precedence: IP literal family > udpFamily > 4.\n * An IP literal fixes the destination family, so a conflicting udpFamily is\n * ignored (and logged) rather than making the server unreachable.\n */\nfunction selectTurnUdpSocketType(\n address: Address,\n udpFamily: 4 | 6 | undefined,\n): \"udp4\" | \"udp6\" {\n const literalFamily = isIP(address[0]);\n if (literalFamily === 4 || literalFamily === 6) {\n if (udpFamily && udpFamily !== literalFamily) {\n log(\"udpFamily ignored for IP literal TURN server\", {\n address,\n udpFamily,\n literalFamily,\n });\n }\n return literalFamily === 6 ? \"udp6\" : \"udp4\";\n }\n return (udpFamily ?? 4) === 6 ? \"udp6\" : \"udp4\";\n}\n\nexport async function createTurnClient(\n { address, username, password }: TurnClientConfig,\n {\n lifetime,\n portRange,\n interfaceAddresses,\n ssl,\n tlsOptions,\n transport: transportType,\n connectTimeoutMs,\n udpFamily,\n }: TurnClientOptions = {},\n) {\n lifetime ??= DEFAULT_ALLOCATION_LIFETIME;\n transportType ??= ssl ? \"tls\" : \"udp\";\n const transport =\n transportType === \"udp\"\n ? await UdpTransport.init(selectTurnUdpSocketType(address, udpFamily), {\n portRange,\n interfaceAddresses,\n })\n : transportType === \"tcp\"\n ? await TcpTransport.init(address, { connectTimeoutMs })\n : await TlsTransport.init(address, tlsOptions, { connectTimeoutMs });\n\n const turn = new TurnProtocol(\n address,\n username,\n password,\n lifetime,\n transport,\n );\n\n try {\n await turn.connectionMade();\n } catch (error) {\n try {\n await turn.close();\n } catch (closeError) {\n log(\"failed to close TURN client after allocation failure\", closeError);\n }\n throw error;\n }\n return turn;\n}\n\nexport async function createStunOverTurnClient(\n config: TurnClientConfig,\n options: TurnClientOptions = {},\n) {\n const turn = await createTurnClient(config, options);\n const turnTransport = new StunOverTurnProtocol(turn);\n return turnTransport;\n}\n\nexport function makeIntegrityKey(\n username: string,\n realm: string,\n password: string,\n) {\n return makeTurnIntegrityKey(username, realm, password);\n}\n"]}
@@ -19,6 +19,12 @@ export interface TransactionRequestOptions {
19
19
  onRequestSent?: (attempt: number) => void;
20
20
  /** Abort the outstanding transaction (e.g. consent lifecycle teardown). */
21
21
  signal?: AbortSignal;
22
+ /**
23
+ * Fail the transaction as soon as the request cannot be sent instead of
24
+ * waiting for the response timeout. Used on reliable transports (TCP),
25
+ * where a send error means the connection itself is unusable.
26
+ */
27
+ failOnSendError?: boolean;
22
28
  /**
23
29
  * When set, responses must include MESSAGE-INTEGRITY and pass HMAC
24
30
  * verification (protocol re-parses the wire bytes with this key; the
@@ -31,6 +37,8 @@ export interface Protocol {
31
37
  type: string;
32
38
  onRequestReceived: Event<[Message, Address, Buffer]>;
33
39
  onDataReceived: Event<[Buffer]>;
40
+ /** Connection-oriented protocols: the connection to this remote address is gone. */
41
+ onConnectionClosed?: Event<[Address]>;
34
42
  request: (message: Message, addr: Address, integrityKey?: Buffer, retransmissionsOrOptions?: number | TransactionRequestOptions, onRequestSent?: (attempt: number) => void) => Promise<[Message, Address]>;
35
43
  close: () => Promise<void>;
36
44
  connectionMade: (...args: any) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../../../ice/src/types/model.ts"],"names":[],"mappings":"","sourcesContent":["import type { Candidate } from \"../candidate\";\nimport type { Address, Event } from \"../imports/common\";\nimport type { Message } from \"../stun/message\";\n\n/**\n * Options for a STUN transaction / Protocol.request.\n * Retransmission count and response wait deadline are independent\n * so consent freshness (retransmissions: 0, longer timeout) can be expressed.\n */\nexport interface TransactionRequestOptions {\n /** Number of retransmissions after the initial send. 0 = send once. */\n retransmissions?: number;\n /**\n * Initial response wait deadline in milliseconds.\n * Doubled after each retransmission when retransmissions > 0.\n * Defaults to RETRY_RTO when omitted.\n */\n responseTimeout?: number;\n /** Called for each wire send (attempt 0 is the initial transmission). */\n onRequestSent?: (attempt: number) => void;\n /** Abort the outstanding transaction (e.g. consent lifecycle teardown). */\n signal?: AbortSignal;\n /**\n * When set, responses must include MESSAGE-INTEGRITY and pass HMAC\n * verification (protocol re-parses the wire bytes with this key; the\n * transaction also rejects unsigned Messages as defense-in-depth).\n * Unsigned or forged responses must not complete the transaction.\n */\n integrityKey?: Buffer;\n}\n\nexport interface Protocol {\n type: string;\n onRequestReceived: Event<[Message, Address, Buffer]>;\n onDataReceived: Event<[Buffer]>;\n request: (\n message: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) => Promise<[Message, Address]>;\n close: () => Promise<void>;\n connectionMade: (...args: any) => Promise<void>;\n sendStun: (message: Message, addr: Address) => Promise<void>;\n sendData: (data: Buffer, addr: Address) => Promise<void>;\n localCandidate?: Candidate;\n sentMessage?: Message;\n responseAddr?: Address;\n responseMessage?: string;\n localIp?: string;\n}\n"]}
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../../../ice/src/types/model.ts"],"names":[],"mappings":"","sourcesContent":["import type { Candidate } from \"../candidate\";\nimport type { Address, Event } from \"../imports/common\";\nimport type { Message } from \"../stun/message\";\n\n/**\n * Options for a STUN transaction / Protocol.request.\n * Retransmission count and response wait deadline are independent\n * so consent freshness (retransmissions: 0, longer timeout) can be expressed.\n */\nexport interface TransactionRequestOptions {\n /** Number of retransmissions after the initial send. 0 = send once. */\n retransmissions?: number;\n /**\n * Initial response wait deadline in milliseconds.\n * Doubled after each retransmission when retransmissions > 0.\n * Defaults to RETRY_RTO when omitted.\n */\n responseTimeout?: number;\n /** Called for each wire send (attempt 0 is the initial transmission). */\n onRequestSent?: (attempt: number) => void;\n /** Abort the outstanding transaction (e.g. consent lifecycle teardown). */\n signal?: AbortSignal;\n /**\n * Fail the transaction as soon as the request cannot be sent instead of\n * waiting for the response timeout. Used on reliable transports (TCP),\n * where a send error means the connection itself is unusable.\n */\n failOnSendError?: boolean;\n /**\n * When set, responses must include MESSAGE-INTEGRITY and pass HMAC\n * verification (protocol re-parses the wire bytes with this key; the\n * transaction also rejects unsigned Messages as defense-in-depth).\n * Unsigned or forged responses must not complete the transaction.\n */\n integrityKey?: Buffer;\n}\n\nexport interface Protocol {\n type: string;\n onRequestReceived: Event<[Message, Address, Buffer]>;\n onDataReceived: Event<[Buffer]>;\n /** Connection-oriented protocols: the connection to this remote address is gone. */\n onConnectionClosed?: Event<[Address]>;\n request: (\n message: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) => Promise<[Message, Address]>;\n close: () => Promise<void>;\n connectionMade: (...args: any) => Promise<void>;\n sendStun: (message: Message, addr: Address) => Promise<void>;\n sendData: (data: Buffer, addr: Address) => Promise<void>;\n localCandidate?: Candidate;\n sentMessage?: Message;\n responseAddr?: Address;\n responseMessage?: string;\n localIp?: string;\n}\n"]}