werift 0.24.0 → 0.24.2

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 (68) hide show
  1. package/lib/common/src/binary.js +2 -3
  2. package/lib/common/src/binary.js.map +1 -1
  3. package/lib/dtls/src/context/transport.d.ts +2 -2
  4. package/lib/dtls/src/context/transport.js +2 -2
  5. package/lib/dtls/src/context/transport.js.map +1 -1
  6. package/lib/dtls/src/socket.d.ts +3 -2
  7. package/lib/dtls/src/socket.js +2 -2
  8. package/lib/dtls/src/socket.js.map +1 -1
  9. package/lib/ice/src/ice.d.ts +20 -0
  10. package/lib/ice/src/ice.js +263 -66
  11. package/lib/ice/src/ice.js.map +1 -1
  12. package/lib/ice/src/iceBase.d.ts +22 -1
  13. package/lib/ice/src/iceBase.js +30 -1
  14. package/lib/ice/src/iceBase.js.map +1 -1
  15. package/lib/ice/src/internal/selectAddresses.d.ts +9 -0
  16. package/lib/ice/src/internal/selectAddresses.js +40 -0
  17. package/lib/ice/src/internal/selectAddresses.js.map +1 -0
  18. package/lib/ice/src/stun/protocol.d.ts +2 -2
  19. package/lib/ice/src/stun/protocol.js +17 -3
  20. package/lib/ice/src/stun/protocol.js.map +1 -1
  21. package/lib/ice/src/stun/tcpProtocol.d.ts +2 -2
  22. package/lib/ice/src/stun/tcpProtocol.js +13 -3
  23. package/lib/ice/src/stun/tcpProtocol.js.map +1 -1
  24. package/lib/ice/src/stun/transaction.d.ts +41 -4
  25. package/lib/ice/src/stun/transaction.js +193 -24
  26. package/lib/ice/src/stun/transaction.js.map +1 -1
  27. package/lib/ice/src/turn/protocol.d.ts +3 -3
  28. package/lib/ice/src/turn/protocol.js +31 -6
  29. package/lib/ice/src/turn/protocol.js.map +1 -1
  30. package/lib/ice/src/types/model.d.ts +27 -1
  31. package/lib/ice/src/types/model.js.map +1 -1
  32. package/lib/ice/src/utils.js +2 -31
  33. package/lib/ice/src/utils.js.map +1 -1
  34. package/lib/ice-server/src/stun/attributes.js +9 -47
  35. package/lib/ice-server/src/stun/attributes.js.map +1 -1
  36. package/lib/ice-server/src/stun/ip.d.ts +12 -0
  37. package/lib/ice-server/src/stun/ip.js +88 -0
  38. package/lib/ice-server/src/stun/ip.js.map +1 -0
  39. package/lib/ice-server/src/stun/message.js +8 -0
  40. package/lib/ice-server/src/stun/message.js.map +1 -1
  41. package/lib/index.mjs +652 -234
  42. package/lib/nonstandard/index.mjs +121 -54
  43. package/lib/rtp/src/codec/av1.js +11 -5
  44. package/lib/rtp/src/codec/av1.js.map +1 -1
  45. package/lib/rtp/src/codec/leb128.d.ts +5 -0
  46. package/lib/rtp/src/codec/leb128.js +24 -0
  47. package/lib/rtp/src/codec/leb128.js.map +1 -0
  48. package/lib/rtp/src/rtp/rtx.js +4 -6
  49. package/lib/rtp/src/rtp/rtx.js.map +1 -1
  50. package/lib/rtp/src/srtp/context/context.d.ts +2 -0
  51. package/lib/rtp/src/srtp/context/context.js +12 -12
  52. package/lib/rtp/src/srtp/context/context.js.map +1 -1
  53. package/lib/sctp/src/param.js +31 -15
  54. package/lib/sctp/src/param.js.map +1 -1
  55. package/lib/sctp/src/sctp.js +10 -9
  56. package/lib/sctp/src/sctp.js.map +1 -1
  57. package/lib/webrtc/src/media/rtpSender.js +2 -3
  58. package/lib/webrtc/src/media/rtpSender.js.map +1 -1
  59. package/lib/webrtc/src/peerConnection.d.ts +2 -2
  60. package/lib/webrtc/src/sdp.js +1 -35
  61. package/lib/webrtc/src/sdp.js.map +1 -1
  62. package/lib/webrtc/src/secureTransportManager.d.ts +1 -1
  63. package/lib/webrtc/src/secureTransportManager.js +12 -0
  64. package/lib/webrtc/src/secureTransportManager.js.map +1 -1
  65. package/lib/webrtc/src/transport/dtls.d.ts +1 -1
  66. package/lib/webrtc/src/transport/sctp.js +17 -16
  67. package/lib/webrtc/src/transport/sctp.js.map +1 -1
  68. package/package.json +1 -7
package/lib/index.mjs CHANGED
@@ -1,11 +1,10 @@
1
1
  // ../common/src/binary.ts
2
2
  import { randomBytes } from "crypto";
3
- import { jspack } from "@shinyoshiaki/jspack";
4
3
  function random16() {
5
- return jspack.Unpack("!H", randomBytes(2))[0];
4
+ return randomBytes(2).readUInt16BE(0);
6
5
  }
7
6
  function random32() {
8
- return jspack.Unpack("!L", randomBytes(4))[0];
7
+ return randomBytes(4).readUInt32BE(0);
9
8
  }
10
9
  function bufferXor(a, b) {
11
10
  if (a.length !== b.length) {
@@ -2600,8 +2599,25 @@ var saltLength = (profile) => {
2600
2599
  }
2601
2600
  };
2602
2601
 
2602
+ // ../rtp/src/codec/leb128.ts
2603
+ function leb128encode(value) {
2604
+ if (!Number.isInteger(value) || value < 0 || !Number.isSafeInteger(value)) {
2605
+ throw new Error("LEB128 encode requires a non-negative safe integer");
2606
+ }
2607
+ const bytes = [];
2608
+ let remaining = value;
2609
+ do {
2610
+ let byte = remaining & 127;
2611
+ remaining = Math.floor(remaining / 128);
2612
+ if (remaining !== 0) {
2613
+ byte |= 128;
2614
+ }
2615
+ bytes.push(byte);
2616
+ } while (remaining !== 0);
2617
+ return Buffer.from(bytes);
2618
+ }
2619
+
2603
2620
  // ../rtp/src/codec/av1.ts
2604
- import { LEB128 } from "@minhducsun2002/leb128";
2605
2621
  var log3 = debug("werift-rtp : packages/rtp/src/codec/av1.ts");
2606
2622
  var AV1RtpPayload = class _AV1RtpPayload {
2607
2623
  /**
@@ -2731,7 +2747,7 @@ var AV1Obu = class _AV1Obu {
2731
2747
  const header = new BitWriter2(8).set(this.obu_forbidden_bit).set(OBU_TYPE_IDS[this.obu_type], 4).set(this.obu_extension_flag).set(this.obu_has_size_field).set(this.obu_reserved_1bit).buffer;
2732
2748
  let obuSize = Buffer.alloc(0);
2733
2749
  if (this.obu_has_size_field) {
2734
- obuSize = LEB128.encode(this.payload.length);
2750
+ obuSize = leb128encode(this.payload.length);
2735
2751
  }
2736
2752
  return Buffer.concat([header, obuSize, this.payload]);
2737
2753
  }
@@ -2740,14 +2756,20 @@ function leb128decode(buf) {
2740
2756
  let value = 0;
2741
2757
  let leb128bytes = 0;
2742
2758
  for (let i = 0; i < 8; i++) {
2759
+ if (i >= buf.length) {
2760
+ throw new Error("LEB128 decode incomplete");
2761
+ }
2743
2762
  const leb128byte = buf.readUInt8(i);
2744
- value |= (leb128byte & 127) << i * 7;
2763
+ value += (leb128byte & 127) * 128 ** i;
2745
2764
  leb128bytes++;
2746
2765
  if (!(leb128byte & 128)) {
2747
- break;
2766
+ if (!Number.isSafeInteger(value)) {
2767
+ throw new Error("LEB128 value exceeds safe integer");
2768
+ }
2769
+ return [value, leb128bytes];
2748
2770
  }
2749
2771
  }
2750
- return [value, leb128bytes];
2772
+ throw new Error("LEB128 decode incomplete");
2751
2773
  }
2752
2774
  var OBU_TYPES = {
2753
2775
  0: "Reserved",
@@ -4694,13 +4716,12 @@ var RtpPacket = class _RtpPacket {
4694
4716
  };
4695
4717
 
4696
4718
  // ../rtp/src/rtp/rtx.ts
4697
- import { jspack as jspack2 } from "@shinyoshiaki/jspack";
4698
4719
  function unwrapRtx(rtx, payloadType, ssrc) {
4699
4720
  const packet = new RtpPacket(
4700
4721
  new RtpHeader({
4701
4722
  payloadType,
4702
4723
  marker: rtx.header.marker,
4703
- sequenceNumber: jspack2.Unpack("!H", rtx.payload.subarray(0, 2))[0],
4724
+ sequenceNumber: rtx.payload.readUInt16BE(0),
4704
4725
  timestamp: rtx.header.timestamp,
4705
4726
  ssrc
4706
4727
  }),
@@ -4709,6 +4730,8 @@ function unwrapRtx(rtx, payloadType, ssrc) {
4709
4730
  return packet;
4710
4731
  }
4711
4732
  function wrapRtx(packet, payloadType, sequenceNumber, ssrc) {
4733
+ const originalSequence = Buffer.allocUnsafe(2);
4734
+ originalSequence.writeUInt16BE(packet.header.sequenceNumber, 0);
4712
4735
  const rtx = new RtpPacket(
4713
4736
  new RtpHeader({
4714
4737
  payloadType,
@@ -4719,17 +4742,13 @@ function wrapRtx(packet, payloadType, sequenceNumber, ssrc) {
4719
4742
  csrc: packet.header.csrc,
4720
4743
  extensions: packet.header.extensions
4721
4744
  }),
4722
- Buffer.concat([
4723
- Buffer.from(jspack2.Pack("!H", [packet.header.sequenceNumber])),
4724
- packet.payload
4725
- ])
4745
+ Buffer.concat([originalSequence, packet.payload])
4726
4746
  );
4727
4747
  return rtx;
4728
4748
  }
4729
4749
 
4730
4750
  // ../rtp/src/srtp/context/context.ts
4731
- import { createHmac as createHmac3 } from "crypto";
4732
- import AES from "aes-js";
4751
+ import { createCipheriv as createCipheriv4, createHmac as createHmac3 } from "crypto";
4733
4752
 
4734
4753
  // ../rtp/src/srtp/cipher/ctr.ts
4735
4754
  import {
@@ -5117,6 +5136,11 @@ function finalizeAuthenticatedDecryption(decipher, packetType) {
5117
5136
  }
5118
5137
 
5119
5138
  // ../rtp/src/srtp/context/context.ts
5139
+ function aes128EcbEncrypt(key, plaintext) {
5140
+ const cipher = createCipheriv4("aes-128-ecb", key, null);
5141
+ cipher.setAutoPadding(false);
5142
+ return Buffer.concat([cipher.update(plaintext), cipher.final()]);
5143
+ }
5120
5144
  var Context = class {
5121
5145
  constructor(masterKey, masterSalt, profile) {
5122
5146
  this.masterKey = masterKey;
@@ -5183,8 +5207,7 @@ var Context = class {
5183
5207
  sessionKey[j] = sessionKey[j] ^ labelAndIndexOverKdr[i];
5184
5208
  }
5185
5209
  sessionKey = Buffer.concat([sessionKey, Buffer.from([0, 0])]);
5186
- const block = new AES.AES(this.masterKey);
5187
- return Buffer.from(block.encrypt(sessionKey));
5210
+ return aes128EcbEncrypt(this.masterKey, sessionKey);
5188
5211
  }
5189
5212
  generateSessionSalt(label) {
5190
5213
  let sessionSalt = Buffer.from(this.masterSalt);
@@ -5201,8 +5224,7 @@ var Context = class {
5201
5224
  sessionSalt[j] = sessionSalt[j] ^ labelAndIndexOverKdr[i];
5202
5225
  }
5203
5226
  sessionSalt = Buffer.concat([sessionSalt, Buffer.from([0, 0])]);
5204
- const block = new AES.AES(this.masterKey);
5205
- sessionSalt = Buffer.from(block.encrypt(sessionSalt));
5227
+ sessionSalt = aes128EcbEncrypt(this.masterKey, sessionSalt);
5206
5228
  return sessionSalt.subarray(0, 14);
5207
5229
  }
5208
5230
  generateSessionAuthTag(label) {
@@ -5227,9 +5249,8 @@ var Context = class {
5227
5249
  sessionAuthTag,
5228
5250
  Buffer.from([0, 1])
5229
5251
  ]);
5230
- const block = new AES.AES(this.masterKey);
5231
- firstRun = Buffer.from(block.encrypt(firstRun));
5232
- secondRun = Buffer.from(block.encrypt(secondRun));
5252
+ firstRun = aes128EcbEncrypt(this.masterKey, firstRun);
5253
+ secondRun = aes128EcbEncrypt(this.masterKey, secondRun);
5233
5254
  return Buffer.concat([firstRun, secondRun.subarray(0, 4)]);
5234
5255
  }
5235
5256
  getSrtpSsrcState(ssrc) {
@@ -5746,8 +5767,8 @@ var TransportContext = class {
5746
5767
  constructor(socket) {
5747
5768
  this.socket = socket;
5748
5769
  }
5749
- send = (buf) => {
5750
- return this.socket.send(buf);
5770
+ send = (buf, addr) => {
5771
+ return this.socket.send(buf, addr);
5751
5772
  };
5752
5773
  };
5753
5774
 
@@ -6086,12 +6107,12 @@ var DtlsSocket = class {
6086
6107
  return handshakes;
6087
6108
  }
6088
6109
  /**send application data */
6089
- send = async (buf) => {
6110
+ send = async (buf, addr) => {
6090
6111
  const pkt = createPlaintext(this.dtls)(
6091
6112
  [{ type: 23 /* applicationData */, fragment: buf }],
6092
6113
  ++this.dtls.recordSequenceNumber
6093
6114
  )[0];
6094
- await this.transport.send(this.cipher.encryptPacket(pkt).serialize());
6115
+ await this.transport.send(this.cipher.encryptPacket(pkt).serialize(), addr);
6095
6116
  };
6096
6117
  close() {
6097
6118
  this.transport.socket.close();
@@ -6735,17 +6756,82 @@ import { connect as connect3, createServer } from "node:net";
6735
6756
  // ../ice-server/src/stun/message.ts
6736
6757
  import { createHmac as createHmac4, randomBytes as randomBytes5 } from "crypto";
6737
6758
 
6759
+ // ../ice-server/src/stun/ip.ts
6760
+ import { isIPv4, isIPv6 } from "node:net";
6761
+ function ipAddressToBuffer(address) {
6762
+ if (isIPv4(address)) {
6763
+ const buf = Buffer.allocUnsafe(4);
6764
+ const parts = address.split(".");
6765
+ for (let i = 0; i < 4; i++) {
6766
+ buf[i] = Number(parts[i]) & 255;
6767
+ }
6768
+ return buf;
6769
+ }
6770
+ if (!isIPv6(address)) {
6771
+ throw new Error(`Invalid ip address: ${address}`);
6772
+ }
6773
+ const sections = address.split(":", 8);
6774
+ for (let i = 0; i < sections.length; i++) {
6775
+ let v4Buffer;
6776
+ if (isIPv4(sections[i])) {
6777
+ v4Buffer = ipAddressToBuffer(sections[i]);
6778
+ sections[i] = v4Buffer.subarray(0, 2).toString("hex");
6779
+ }
6780
+ if (v4Buffer && ++i < 8) {
6781
+ sections.splice(i, 0, v4Buffer.subarray(2, 4).toString("hex"));
6782
+ }
6783
+ }
6784
+ if (sections[0] === "") {
6785
+ while (sections.length < 8) sections.unshift("0");
6786
+ } else if (sections[sections.length - 1] === "") {
6787
+ while (sections.length < 8) sections.push("0");
6788
+ } else if (sections.length < 8) {
6789
+ let emptyIndex = 0;
6790
+ for (; emptyIndex < sections.length && sections[emptyIndex] !== ""; emptyIndex++) ;
6791
+ const zeros = [];
6792
+ for (let n = 9 - sections.length; n > 0; n--) {
6793
+ zeros.push("0");
6794
+ }
6795
+ sections.splice(emptyIndex, 1, ...zeros);
6796
+ }
6797
+ const result = Buffer.allocUnsafe(16);
6798
+ let offset = 0;
6799
+ for (const section of sections) {
6800
+ const word = Number.parseInt(section, 16) || 0;
6801
+ result[offset++] = word >> 8 & 255;
6802
+ result[offset++] = word & 255;
6803
+ }
6804
+ return result;
6805
+ }
6806
+ function bufferToIpAddress(buf) {
6807
+ if (buf.length === 4) {
6808
+ return `${buf[0]}.${buf[1]}.${buf[2]}.${buf[3]}`;
6809
+ }
6810
+ if (buf.length !== 16) {
6811
+ throw new Error(`Invalid ip address buffer length: ${buf.length}`);
6812
+ }
6813
+ const hextets = [];
6814
+ for (let i = 0; i < 16; i += 2) {
6815
+ hextets.push(buf.readUInt16BE(i).toString(16));
6816
+ }
6817
+ let result = hextets.join(":");
6818
+ result = result.replace(/(^|:)0(:0)*:0(:|$)/, "$1::$3");
6819
+ result = result.replace(/:{3,4}/, "::");
6820
+ return result;
6821
+ }
6822
+ function isIpV4Address(address) {
6823
+ return isIPv4(address);
6824
+ }
6825
+
6738
6826
  // ../ice-server/src/stun/attributes.ts
6739
- import * as Int64 from "int64-buffer";
6740
- import nodeIp from "ip";
6741
6827
  function packAddress(value) {
6742
6828
  const [address] = value;
6743
- const protocol = nodeIp.isV4Format(address) ? IPV4_PROTOCOL : IPV6_PROTOCOL;
6829
+ const protocol = isIpV4Address(address) ? IPV4_PROTOCOL : IPV6_PROTOCOL;
6744
6830
  const buffer2 = Buffer.alloc(4);
6745
6831
  buffer2.writeUInt8(0, 0);
6746
6832
  buffer2.writeUInt8(protocol, 1);
6747
6833
  buffer2.writeUInt16BE(value[1], 2);
6748
- return Buffer.concat([buffer2, nodeIp.toBuffer(address)]);
6834
+ return Buffer.concat([buffer2, ipAddressToBuffer(address)]);
6749
6835
  }
6750
6836
  function unpackErrorCode(data) {
6751
6837
  if (data.length < 4) {
@@ -6768,12 +6854,12 @@ function unpackAddress(data) {
6768
6854
  if (address.length !== 4) {
6769
6855
  throw new Error("STUN address has invalid length for IPv4");
6770
6856
  }
6771
- return [nodeIp.toString(address), port];
6857
+ return [bufferToIpAddress(address), port];
6772
6858
  case IPV6_PROTOCOL:
6773
6859
  if (address.length !== 16) {
6774
6860
  throw new Error("STUN address has invalid length for IPv6");
6775
6861
  }
6776
- return [nodeIp.toString(address), port];
6862
+ return [bufferToIpAddress(address), port];
6777
6863
  default:
6778
6864
  throw new Error("STUN address has unknown protocol");
6779
6865
  }
@@ -6836,12 +6922,11 @@ var packUnsignedShort = (value) => {
6836
6922
  };
6837
6923
  var unpackUnsignedShort = (data) => data.readUInt16BE(0);
6838
6924
  var packUnsigned64 = (value) => {
6839
- return new Int64.Int64BE(value.toString()).toBuffer();
6840
- };
6841
- var unpackUnsigned64 = (data) => {
6842
- const int2 = new Int64.Int64BE(data);
6843
- return BigInt(int2.toString());
6925
+ const buffer2 = Buffer.allocUnsafe(8);
6926
+ buffer2.writeBigUInt64BE(value, 0);
6927
+ return buffer2;
6844
6928
  };
6929
+ var unpackUnsigned64 = (data) => data.readBigUInt64BE(0);
6845
6930
  var packString = (value) => Buffer.from(value, "utf8");
6846
6931
  var unpackString = (data) => data.toString("utf8");
6847
6932
  var packSoftware = (value) => {
@@ -6948,6 +7033,7 @@ function parseMessage(data, integrityKey) {
6948
7033
  );
6949
7034
  const attributeRepository = new AttributeRepository();
6950
7035
  const rawAttributes = [];
7036
+ let messageIntegrityVerified = false;
6951
7037
  for (let pos = HEADER_LENGTH; pos < data.length; ) {
6952
7038
  if (pos + 4 > data.length) {
6953
7039
  return void 0;
@@ -6985,6 +7071,7 @@ function parseMessage(data, integrityKey) {
6985
7071
  if (!integrity.equals(expected)) {
6986
7072
  return void 0;
6987
7073
  }
7074
+ messageIntegrityVerified = true;
6988
7075
  }
6989
7076
  } else {
6990
7077
  rawAttributes.push({
@@ -6995,6 +7082,9 @@ function parseMessage(data, integrityKey) {
6995
7082
  }
6996
7083
  pos = valueEnd + padLen;
6997
7084
  }
7085
+ if (integrityKey && !messageIntegrityVerified) {
7086
+ return void 0;
7087
+ }
6998
7088
  return new Message(
6999
7089
  messageType & 16111,
7000
7090
  messageType & 272,
@@ -7119,6 +7209,10 @@ function paddingLength(length) {
7119
7209
  return rest === 0 ? 0 : 4 - rest;
7120
7210
  }
7121
7211
 
7212
+ // ../ice/src/stun/transaction.ts
7213
+ import { promises as dns } from "node:dns";
7214
+ import { isIP as isIP2 } from "node:net";
7215
+
7122
7216
  // ../ice/src/exceptions.ts
7123
7217
  var TransactionError = class extends Error {
7124
7218
  response;
@@ -7148,32 +7242,100 @@ var TransactionTimeout = class extends TransactionError {
7148
7242
 
7149
7243
  // ../ice/src/stun/transaction.ts
7150
7244
  var log18 = debug("werift-ice:packages/ice/src/stun/transaction.ts");
7245
+ async function resolveRequestAddress(addr, family = 0) {
7246
+ if (isIP2(addr[0])) {
7247
+ return addr;
7248
+ }
7249
+ const looked = await dns.lookup(addr[0], { family });
7250
+ return [looked.address, addr[1]];
7251
+ }
7252
+ function normalizeTransactionOptions(retransmissionsOrOptions, onRequestSent) {
7253
+ if (retransmissionsOrOptions !== null && typeof retransmissionsOrOptions === "object") {
7254
+ return retransmissionsOrOptions;
7255
+ }
7256
+ const retransmissions = typeof retransmissionsOrOptions === "number" ? retransmissionsOrOptions : void 0;
7257
+ return {
7258
+ retransmissions,
7259
+ onRequestSent
7260
+ };
7261
+ }
7262
+ function addressEquals(a, b) {
7263
+ return a[0] === b[0] && a[1] === b[1];
7264
+ }
7151
7265
  var Transaction = class {
7152
- constructor(request, addr, protocol, retransmissions, onRequestSent) {
7266
+ constructor(request, addr, protocol, retransmissionsOrOptions, onRequestSent) {
7153
7267
  this.request = request;
7154
7268
  this.addr = addr;
7155
7269
  this.protocol = protocol;
7156
- this.retransmissions = retransmissions;
7157
- this.onRequestSent = onRequestSent;
7158
- this.triesMax = 1 + (this.retransmissions ?? RETRY_MAX);
7159
- }
7160
- timeoutDelay = RETRY_RTO;
7270
+ const options = normalizeTransactionOptions(
7271
+ retransmissionsOrOptions,
7272
+ onRequestSent
7273
+ );
7274
+ this.triesMax = 1 + (options.retransmissions ?? RETRY_MAX);
7275
+ this.timeoutDelay = options.responseTimeout ?? RETRY_RTO;
7276
+ this.onRequestSent = options.onRequestSent;
7277
+ this.signal = options.signal;
7278
+ this.expectedAddr = addr;
7279
+ this.integrityKey = options.integrityKey;
7280
+ }
7281
+ timeoutDelay;
7161
7282
  ended = false;
7162
7283
  tries = 0;
7163
7284
  triesMax;
7164
7285
  onResponse = new Event2();
7286
+ onRequestSent;
7287
+ signal;
7288
+ /** Remote address this transaction was sent to; responses must match. */
7289
+ expectedAddr;
7290
+ /**
7291
+ * When set, protocol layers re-parse the wire response with this key so
7292
+ * MESSAGE-INTEGRITY failures are rejected before responseReceived.
7293
+ */
7294
+ integrityKey;
7295
+ waitTimer;
7296
+ waitResolve;
7297
+ onAbort;
7298
+ /**
7299
+ * Accept a matching authenticated non-error response from the expected
7300
+ * remote address. Wrong address, missing MESSAGE-INTEGRITY (when required),
7301
+ * or non-success class is rejected without completing the transaction
7302
+ * (wrong address / unauthenticated responses are ignored so we keep waiting).
7303
+ */
7165
7304
  responseReceived = (message, addr) => {
7166
- if (this.onResponse.length > 0) {
7167
- if (message.messageClass === 256 /* RESPONSE */) {
7168
- this.onResponse.execute(message, addr);
7169
- this.onResponse.complete();
7170
- } else {
7171
- this.onResponse.error(new TransactionFailed(message, addr));
7305
+ if (this.ended || this.onResponse.length === 0) {
7306
+ return;
7307
+ }
7308
+ if (!addressEquals(this.expectedAddr, addr)) {
7309
+ log18(
7310
+ "ignore STUN response from unexpected address",
7311
+ addr,
7312
+ "expected",
7313
+ this.expectedAddr
7314
+ );
7315
+ return;
7316
+ }
7317
+ if (this.integrityKey) {
7318
+ const hasIntegrity = message.attributesKeys.includes("MESSAGE-INTEGRITY") || message.attributesKeys.includes("MESSAGE-INTEGRITY-SHA256");
7319
+ if (!hasIntegrity) {
7320
+ log18(
7321
+ "ignore unauthenticated STUN response (MESSAGE-INTEGRITY required)"
7322
+ );
7323
+ return;
7172
7324
  }
7173
7325
  }
7326
+ if (message.messageClass === 256 /* RESPONSE */) {
7327
+ this.onResponse.execute(message, addr);
7328
+ this.onResponse.complete();
7329
+ } else {
7330
+ this.onResponse.error(new TransactionFailed(message, addr));
7331
+ }
7174
7332
  };
7175
7333
  run = async () => {
7176
7334
  try {
7335
+ if (this.signal?.aborted) {
7336
+ throw new TransactionTimeout();
7337
+ }
7338
+ this.attachAbortListener();
7177
7339
  this.retry().catch((e) => {
7178
7340
  log18("retry failed", e);
7179
7341
  });
@@ -7185,28 +7347,85 @@ var Transaction = class {
7185
7347
  this.cancel();
7186
7348
  }
7187
7349
  };
7350
+ attachAbortListener() {
7351
+ if (!this.signal) {
7352
+ return;
7353
+ }
7354
+ this.onAbort = () => {
7355
+ this.failWithTimeout();
7356
+ };
7357
+ this.signal.addEventListener("abort", this.onAbort, { once: true });
7358
+ }
7359
+ failWithTimeout() {
7360
+ if (this.ended) {
7361
+ return;
7362
+ }
7363
+ this.ended = true;
7364
+ this.clearWait();
7365
+ if (this.onResponse.length > 0) {
7366
+ this.onResponse.error(new TransactionTimeout());
7367
+ }
7368
+ }
7369
+ clearWait() {
7370
+ if (this.waitTimer !== void 0) {
7371
+ clearTimeout(this.waitTimer);
7372
+ this.waitTimer = void 0;
7373
+ }
7374
+ const resolve = this.waitResolve;
7375
+ this.waitResolve = void 0;
7376
+ resolve?.();
7377
+ }
7378
+ wait(ms) {
7379
+ return new Promise((resolve) => {
7380
+ if (this.ended || this.signal?.aborted) {
7381
+ resolve();
7382
+ return;
7383
+ }
7384
+ this.waitResolve = resolve;
7385
+ this.waitTimer = setTimeout(() => {
7386
+ this.waitTimer = void 0;
7387
+ this.waitResolve = void 0;
7388
+ resolve();
7389
+ }, ms);
7390
+ });
7391
+ }
7188
7392
  retry = async () => {
7189
7393
  while (this.tries < this.triesMax && !this.ended) {
7190
7394
  this.onRequestSent?.(this.tries);
7191
7395
  this.protocol.sendStun(this.request, this.addr).catch((e) => {
7192
7396
  log18("send stun failed", e);
7193
7397
  });
7194
- await new Promise((r) => setTimeout(r, this.timeoutDelay));
7398
+ await this.wait(this.timeoutDelay);
7195
7399
  if (this.ended) {
7196
7400
  break;
7197
7401
  }
7198
7402
  this.timeoutDelay *= 2;
7199
7403
  this.tries++;
7200
7404
  }
7201
- if (this.tries >= this.triesMax) {
7405
+ if (this.tries >= this.triesMax && !this.ended) {
7202
7406
  log18(`retry failed times:${this.tries} maxLimit:${this.triesMax}`);
7203
- this.onResponse.error(new TransactionTimeout());
7407
+ this.failWithTimeout();
7204
7408
  }
7205
7409
  };
7206
7410
  cancel() {
7207
7411
  this.ended = true;
7412
+ this.clearWait();
7413
+ if (this.signal && this.onAbort) {
7414
+ this.signal.removeEventListener("abort", this.onAbort);
7415
+ this.onAbort = void 0;
7416
+ }
7208
7417
  }
7209
7418
  };
7419
+ function buildTransactionOptions(integrityKey, retransmissionsOrOptions, onRequestSent) {
7420
+ const options = normalizeTransactionOptions(
7421
+ retransmissionsOrOptions,
7422
+ onRequestSent
7423
+ );
7424
+ if (integrityKey && !options.integrityKey) {
7425
+ options.integrityKey = integrityKey;
7426
+ }
7427
+ return options;
7428
+ }
7210
7429
 
7211
7430
  // ../ice/src/stun/tcpProtocol.ts
7212
7431
  var log19 = debug("werift-ice:packages/ice/src/stun/tcpProtocol.ts");
@@ -7305,10 +7524,13 @@ var BaseTcpProtocol = class _BaseTcpProtocol {
7305
7524
  return;
7306
7525
  }
7307
7526
  if ((message.messageClass === 256 /* RESPONSE */ || message.messageClass === 272 /* ERROR */) && this.transactions[message.transactionIdHex]) {
7308
- this.transactions[message.transactionIdHex].responseReceived(
7309
- message,
7310
- addr
7311
- );
7527
+ const transaction = this.transactions[message.transactionIdHex];
7528
+ const verified = transaction.integrityKey ? parseMessage(data, transaction.integrityKey) : message;
7529
+ if (!verified) {
7530
+ log19("STUN response failed MESSAGE-INTEGRITY check");
7531
+ return;
7532
+ }
7533
+ transaction.responseReceived(verified, addr);
7312
7534
  } else if (message.messageClass === 0 /* REQUEST */) {
7313
7535
  this.onRequestReceived.execute(message, addr, data);
7314
7536
  }
@@ -7334,7 +7556,7 @@ var BaseTcpProtocol = class _BaseTcpProtocol {
7334
7556
  async sendData(data, addr) {
7335
7557
  await this.sendFrame(data, addr);
7336
7558
  }
7337
- async request(request, addr, integrityKey, retransmissions, onRequestSent) {
7559
+ async request(request, addr, integrityKey, retransmissionsOrOptions, onRequestSent) {
7338
7560
  if (this.transactions[request.transactionIdHex]) {
7339
7561
  throw new Error("already requested");
7340
7562
  }
@@ -7342,13 +7564,13 @@ var BaseTcpProtocol = class _BaseTcpProtocol {
7342
7564
  request.addMessageIntegrity(integrityKey);
7343
7565
  request.addFingerprint();
7344
7566
  }
7345
- const transaction = new Transaction(
7346
- request,
7347
- addr,
7348
- this,
7349
- retransmissions,
7567
+ const resolvedAddr = await resolveRequestAddress(addr);
7568
+ const options = buildTransactionOptions(
7569
+ integrityKey,
7570
+ retransmissionsOrOptions,
7350
7571
  onRequestSent
7351
7572
  );
7573
+ const transaction = new Transaction(request, resolvedAddr, this, options);
7352
7574
  this.transactions[request.transactionIdHex] = transaction;
7353
7575
  try {
7354
7576
  return await transaction.run();
@@ -7507,7 +7729,12 @@ var StunProtocol = class _StunProtocol {
7507
7729
  }
7508
7730
  if ((message.messageClass === 256 /* RESPONSE */ || message.messageClass === 272 /* ERROR */) && this.transactionsKeys.includes(message.transactionIdHex)) {
7509
7731
  const transaction = this.transactions[message.transactionIdHex];
7510
- transaction.responseReceived(message, addr);
7732
+ const verified = transaction.integrityKey ? parseMessage(data, transaction.integrityKey) : message;
7733
+ if (!verified) {
7734
+ log20("STUN response failed MESSAGE-INTEGRITY check");
7735
+ return;
7736
+ }
7737
+ transaction.responseReceived(verified, addr);
7511
7738
  } else if (message.messageClass === 0 /* REQUEST */) {
7512
7739
  this.onRequestReceived.execute(message, addr, data);
7513
7740
  }
@@ -7534,19 +7761,26 @@ var StunProtocol = class _StunProtocol {
7534
7761
  }
7535
7762
  await this.transport.send(data, addr);
7536
7763
  }
7537
- async request(request, addr, integrityKey, retransmissions, onRequestSent) {
7764
+ async request(request, addr, integrityKey, retransmissionsOrOptions, onRequestSent) {
7538
7765
  if (this.transactionsKeys.includes(request.transactionIdHex))
7539
7766
  throw new Error("already request ed");
7540
7767
  if (integrityKey) {
7541
7768
  request.addMessageIntegrity(integrityKey);
7542
7769
  request.addFingerprint();
7543
7770
  }
7771
+ const socketType = this.transport.socketType;
7772
+ const family = socketType === "udp6" ? 6 : 4;
7773
+ const resolvedAddr = await resolveRequestAddress(addr, family);
7774
+ const options = buildTransactionOptions(
7775
+ integrityKey,
7776
+ retransmissionsOrOptions,
7777
+ onRequestSent
7778
+ );
7544
7779
  const transaction = new Transaction(
7545
7780
  request,
7546
- addr,
7781
+ resolvedAddr,
7547
7782
  this,
7548
- retransmissions,
7549
- onRequestSent
7783
+ options
7550
7784
  );
7551
7785
  this.transactions[request.transactionIdHex] = transaction;
7552
7786
  try {
@@ -7717,7 +7951,12 @@ var StunOverTurnProtocol = class _StunOverTurnProtocol {
7717
7951
  if (message.messageClass === 256 /* RESPONSE */ || message.messageClass === 272 /* ERROR */) {
7718
7952
  const transaction = this.turn.transactions[message.transactionIdHex];
7719
7953
  if (transaction) {
7720
- transaction.responseReceived(message, addr);
7954
+ const verified = transaction.integrityKey ? parseMessage(data, transaction.integrityKey) : message;
7955
+ if (!verified) {
7956
+ log21("STUN over TURN response failed MESSAGE-INTEGRITY check");
7957
+ return;
7958
+ }
7959
+ transaction.responseReceived(verified, addr);
7721
7960
  }
7722
7961
  } else if (message.messageClass === 0 /* REQUEST */) {
7723
7962
  this.onRequestReceived.execute(message, addr, data);
@@ -7726,7 +7965,7 @@ var StunOverTurnProtocol = class _StunOverTurnProtocol {
7726
7965
  log21("datagramReceived error", error);
7727
7966
  }
7728
7967
  };
7729
- async request(request, addr, integrityKey, _retransmissions, onRequestSent) {
7968
+ async request(request, addr, integrityKey, retransmissionsOrOptions, onRequestSent) {
7730
7969
  if (this.turn.transactions[request.transactionIdHex]) {
7731
7970
  throw new Error("exist");
7732
7971
  }
@@ -7734,13 +7973,13 @@ var StunOverTurnProtocol = class _StunOverTurnProtocol {
7734
7973
  request.addMessageIntegrity(integrityKey);
7735
7974
  request.addFingerprint();
7736
7975
  }
7737
- const transaction = new Transaction(
7738
- request,
7739
- addr,
7740
- this,
7741
- void 0,
7976
+ const resolvedAddr = await resolveRequestAddress(addr);
7977
+ const options = buildTransactionOptions(
7978
+ integrityKey,
7979
+ retransmissionsOrOptions,
7742
7980
  onRequestSent
7743
7981
  );
7982
+ const transaction = new Transaction(request, resolvedAddr, this, options);
7744
7983
  this.turn.transactions[request.transactionIdHex] = transaction;
7745
7984
  try {
7746
7985
  return await transaction.run();
@@ -7830,7 +8069,12 @@ var TurnProtocol = class _TurnProtocol {
7830
8069
  if (message.messageClass === 256 /* RESPONSE */ || message.messageClass === 272 /* ERROR */) {
7831
8070
  const transaction = this.transactions[message.transactionIdHex];
7832
8071
  if (transaction) {
7833
- transaction.responseReceived(message, addr);
8072
+ const verified = transaction.integrityKey ? parseMessage(data, transaction.integrityKey) : message;
8073
+ if (!verified) {
8074
+ log21("TURN STUN response failed MESSAGE-INTEGRITY check");
8075
+ return;
8076
+ }
8077
+ transaction.responseReceived(verified, addr);
7834
8078
  }
7835
8079
  } else if (message.messageClass === 0 /* REQUEST */) {
7836
8080
  this.onData.execute(data, addr);
@@ -7902,20 +8146,20 @@ var TurnProtocol = class _TurnProtocol {
7902
8146
  }
7903
8147
  });
7904
8148
  };
7905
- async request(request, addr, _integrityKey, _retransmissions, onRequestSent) {
8149
+ async request(request, addr, _integrityKey, retransmissionsOrOptions, onRequestSent) {
7906
8150
  if (this.transactions[request.transactionIdHex]) {
7907
8151
  throw new Error("exist");
7908
8152
  }
7909
8153
  if (this.integrityKey) {
7910
8154
  request.setAttribute("USERNAME", this.username).setAttribute("REALM", this.realm).setAttribute("NONCE", this.nonce).addMessageIntegrity(this.integrityKey).addFingerprint();
7911
8155
  }
7912
- const transaction = new Transaction(
7913
- request,
7914
- addr,
7915
- this,
7916
- void 0,
8156
+ const resolvedAddr = await resolveRequestAddress(addr);
8157
+ const options = buildTransactionOptions(
8158
+ this.integrityKey,
8159
+ retransmissionsOrOptions,
7917
8160
  onRequestSent
7918
8161
  );
8162
+ const transaction = new Transaction(request, resolvedAddr, this, options);
7919
8163
  this.transactions[request.transactionIdHex] = transaction;
7920
8164
  try {
7921
8165
  return await transaction.run();
@@ -8086,7 +8330,7 @@ function makeIntegrityKey(username, realm, password) {
8086
8330
 
8087
8331
  // ../ice/src/candidate.ts
8088
8332
  import { createHash as createHash3, randomUUID } from "crypto";
8089
- import { isIPv4 } from "net";
8333
+ import { isIPv4 as isIPv42 } from "net";
8090
8334
  var Candidate = class _Candidate {
8091
8335
  constructor(foundation, component, transport, priority, host, port, type, relatedAddress, relatedPort, tcptype, generation, ufrag) {
8092
8336
  this.foundation = foundation;
@@ -8151,8 +8395,8 @@ var Candidate = class _Candidate {
8151
8395
  );
8152
8396
  }
8153
8397
  canPairWith(other) {
8154
- const a = isIPv4(this.host);
8155
- const b = isIPv4(other.host);
8398
+ const a = isIPv42(this.host);
8399
+ const b = isIPv42(other.host);
8156
8400
  return this.component === other.component && this.transport.toLowerCase() === other.transport.toLowerCase() && canPairTcpCandidates(this, other) && a === b;
8157
8401
  }
8158
8402
  toSdp() {
@@ -8257,10 +8501,8 @@ function remoteTcpTypeForIncoming(localTcpType) {
8257
8501
 
8258
8502
  // ../ice/src/ice.ts
8259
8503
  import { randomBytes as randomBytes7 } from "crypto";
8260
- import { isIPv4 as isIPv42 } from "net";
8261
- import * as Int642 from "int64-buffer";
8504
+ import { isIPv4 as isIPv43 } from "net";
8262
8505
  import * as timers from "node:timers/promises";
8263
- import isEqual from "fast-deep-equal";
8264
8506
 
8265
8507
  // ../ice/src/dns/lookup.ts
8266
8508
  import mdns from "multicast-dns";
@@ -8383,6 +8625,18 @@ var ICE_COMPLETED = 1;
8383
8625
  var ICE_FAILED = 2;
8384
8626
  var CONSENT_INTERVAL = 5;
8385
8627
  var CONSENT_FAILURES = 6;
8628
+ var CONSENT_TIMEOUT = 30;
8629
+ var CONSENT_RESPONSE_TIMEOUT = 1e3;
8630
+ var CONSENT_RESPONSE_TIMEOUT_MIN = 500;
8631
+ function consentResponseTimeoutMs(rttSeconds) {
8632
+ if (rttSeconds === void 0 || !Number.isFinite(rttSeconds) || rttSeconds <= 0) {
8633
+ return CONSENT_RESPONSE_TIMEOUT;
8634
+ }
8635
+ return Math.max(
8636
+ CONSENT_RESPONSE_TIMEOUT_MIN,
8637
+ Math.round(rttSeconds * 1e3 * 2 + 200)
8638
+ );
8639
+ }
8386
8640
  var CandidatePairState = /* @__PURE__ */ ((CandidatePairState2) => {
8387
8641
  CandidatePairState2[CandidatePairState2["FROZEN"] = 0] = "FROZEN";
8388
8642
  CandidatePairState2[CandidatePairState2["WAITING"] = 1] = "WAITING";
@@ -8461,7 +8715,34 @@ function validateAddress(addr) {
8461
8715
 
8462
8716
  // ../ice/src/utils.ts
8463
8717
  import * as os from "node:os";
8464
- import nodeIp2 from "ip";
8718
+
8719
+ // ../ice/src/internal/selectAddresses.ts
8720
+ function selectAddressesFromInterfaces(interfaces, family, options = {}, isLinkLocal) {
8721
+ const costlyNetworks = ["ipsec", "tun", "utun", "tap"];
8722
+ const banNetworks = ["vmnet", "veth"];
8723
+ const { useLinkLocalAddress } = options;
8724
+ const all = Object.keys(interfaces).map((nic) => {
8725
+ for (const word of [...costlyNetworks, ...banNetworks]) {
8726
+ if (nic.startsWith(word)) {
8727
+ return {
8728
+ nic,
8729
+ addresses: []
8730
+ };
8731
+ }
8732
+ }
8733
+ const addresses = (interfaces[nic] ?? []).filter(
8734
+ (details) => normalizeFamilyNodeV18(details.family) === family && !details.internal && (useLinkLocalAddress ? true : !isLinkLocal(details))
8735
+ );
8736
+ return {
8737
+ nic,
8738
+ addresses: addresses.map((address) => address.address)
8739
+ };
8740
+ }).filter((address) => !!address);
8741
+ all.sort((a, b) => a.nic.localeCompare(b.nic));
8742
+ return Object.values(all).flatMap((entry) => entry.addresses);
8743
+ }
8744
+
8745
+ // ../ice/src/utils.ts
8465
8746
  var logger = debug("werift-ice : packages/ice/src/utils.ts");
8466
8747
  async function getGlobalIp(stunServer, interfaceAddresses) {
8467
8748
  const protocol = new StunProtocol();
@@ -8481,29 +8762,14 @@ function isLinkLocalAddress(info) {
8481
8762
  function nodeIpAddress(family, {
8482
8763
  useLinkLocalAddress
8483
8764
  } = {}) {
8484
- const costlyNetworks = ["ipsec", "tun", "utun", "tap"];
8485
- const banNetworks = ["vmnet", "veth"];
8486
8765
  const interfaces = os.networkInterfaces();
8487
8766
  logger(interfaces);
8488
- const all = Object.keys(interfaces).map((nic) => {
8489
- for (const word of [...costlyNetworks, ...banNetworks]) {
8490
- if (nic.startsWith(word)) {
8491
- return {
8492
- nic,
8493
- addresses: []
8494
- };
8495
- }
8496
- }
8497
- const addresses = interfaces[nic].filter(
8498
- (details) => normalizeFamilyNodeV18(details.family) === family && !nodeIp2.isLoopback(details.address) && (useLinkLocalAddress ? true : !isLinkLocalAddress(details))
8499
- );
8500
- return {
8501
- nic,
8502
- addresses: addresses.map((address) => address.address)
8503
- };
8504
- }).filter((address) => !!address);
8505
- all.sort((a, b) => a.nic.localeCompare(b.nic));
8506
- return Object.values(all).flatMap((entry) => entry.addresses);
8767
+ return selectAddressesFromInterfaces(
8768
+ interfaces,
8769
+ family,
8770
+ { useLinkLocalAddress },
8771
+ isLinkLocalAddress
8772
+ );
8507
8773
  }
8508
8774
  function getHostAddresses(useIpv4, useIpv6, options = {}) {
8509
8775
  const address = [];
@@ -8556,9 +8822,7 @@ var Connection = class {
8556
8822
  localCandidatesEnd = false;
8557
8823
  generation = -1;
8558
8824
  userHistory = {};
8559
- tieBreaker = BigInt(
8560
- new Int642.Uint64BE(randomBytes7(64)).toString()
8561
- );
8825
+ tieBreaker = randomBytes7(8).readBigUInt64BE(0);
8562
8826
  state = "new";
8563
8827
  lookup;
8564
8828
  _remoteCandidates = [];
@@ -8572,6 +8836,12 @@ var Connection = class {
8572
8836
  localCandidatesStart = false;
8573
8837
  protocols = [];
8574
8838
  queryConsentHandle;
8839
+ /** RFC 7675 consent-to-send: application data may use the selected pair. */
8840
+ consentFresh = false;
8841
+ /** Invalidates in-flight consent callbacks on restart / close / replace / expire. */
8842
+ consentSessionId = 0;
8843
+ consentExpiryTimer;
8844
+ consentRequestAbort;
8575
8845
  onData = new Event2();
8576
8846
  stateChanged = new Event2();
8577
8847
  onIceCandidate = new Event2();
@@ -8582,13 +8852,10 @@ var Connection = class {
8582
8852
  if (this.iceLite) {
8583
8853
  value = false;
8584
8854
  }
8585
- if (this.generation > 0 || this.nominated) {
8855
+ if (this.nominated) {
8586
8856
  return;
8587
8857
  }
8588
- this._iceControlling = value;
8589
- for (const pair of this.checkList) {
8590
- pair.iceControlling = value;
8591
- }
8858
+ this.applyIceControlling(value);
8592
8859
  }
8593
8860
  get iceLite() {
8594
8861
  return this.options.iceLite;
@@ -8625,13 +8892,13 @@ var Connection = class {
8625
8892
  protocol.localCandidate.ufrag = this.localUsername;
8626
8893
  }
8627
8894
  }
8628
- this.queryConsentHandle?.resolve?.();
8629
- this.queryConsentHandle = void 0;
8895
+ this.stopConsentLifecycle();
8630
8896
  }
8631
8897
  resetNominatedPair() {
8632
8898
  log23("resetNominatedPair");
8633
8899
  this.nominated = void 0;
8634
8900
  this.nominating = false;
8901
+ this.stopConsentLifecycle();
8635
8902
  }
8636
8903
  setRemoteParams({
8637
8904
  iceLite,
@@ -8647,6 +8914,13 @@ var Connection = class {
8647
8914
  async gatherCandidates() {
8648
8915
  if (!this.localCandidatesStart) {
8649
8916
  this.localCandidatesStart = true;
8917
+ for (const protocol of this.protocols) {
8918
+ if (protocol.localCandidate) {
8919
+ protocol.localCandidate.generation = this.generation;
8920
+ protocol.localCandidate.ufrag = this.localUsername;
8921
+ this.appendLocalCandidate(protocol.localCandidate);
8922
+ }
8923
+ }
8650
8924
  let address = getHostAddresses(
8651
8925
  this.options.useIpv4,
8652
8926
  this.options.useIpv6,
@@ -8752,7 +9026,7 @@ var Connection = class {
8752
9026
  this.ensureProtocol(protocol);
8753
9027
  try {
8754
9028
  await protocol.connectionMade(
8755
- isIPv42(address),
9029
+ isIPv43(address),
8756
9030
  this.options.portRange,
8757
9031
  this.options.interfaceAddresses
8758
9032
  );
@@ -8853,7 +9127,7 @@ var Connection = class {
8853
9127
  const stunCandidatePromise = new Promise(
8854
9128
  async (r, f) => {
8855
9129
  const timer2 = setTimeout(f, timeout * 1e3);
8856
- if (protocol.localCandidate?.host && isIPv42(protocol.localCandidate?.host)) {
9130
+ if (protocol.localCandidate?.host && isIPv43(protocol.localCandidate?.host)) {
8857
9131
  const candidate = await serverReflexiveCandidate(
8858
9132
  protocol,
8859
9133
  stunServer
@@ -9039,84 +9313,211 @@ var Connection = class {
9039
9313
  }
9040
9314
  return false;
9041
9315
  }
9042
- // 4.1.1.4 ? 生存確認 life check
9316
+ /**
9317
+ * Stop consent request cadence, expiry timer, and outstanding transactions.
9318
+ * Does not change ICE state by itself.
9319
+ */
9320
+ stopConsentLifecycle() {
9321
+ this.consentSessionId++;
9322
+ this.consentFresh = false;
9323
+ if (this.consentExpiryTimer !== void 0) {
9324
+ clearTimeout(this.consentExpiryTimer);
9325
+ this.consentExpiryTimer = void 0;
9326
+ }
9327
+ this.consentRequestAbort?.abort();
9328
+ this.consentRequestAbort = void 0;
9329
+ const handle = this.queryConsentHandle;
9330
+ this.queryConsentHandle = void 0;
9331
+ handle?.resolve?.();
9332
+ }
9333
+ /**
9334
+ * ICE-lite interop only (not required by RFC 7675): mirror libwebrtc
9335
+ * semi-aggressive nomination — attach USE-CANDIDATE when we are controlling,
9336
+ * the remote is ICE-lite, and the target is the current selected pair.
9337
+ */
9338
+ shouldNominateConsentRequest(pair) {
9339
+ return this.iceControlling && this.remoteIsLite && this.nominated?.id === pair.id;
9340
+ }
9341
+ canSendApplicationData() {
9342
+ if (!this.nominated) {
9343
+ return false;
9344
+ }
9345
+ if (this.state === "closed" || this.state === "failed") {
9346
+ return false;
9347
+ }
9348
+ if (this.iceLite) {
9349
+ return true;
9350
+ }
9351
+ return this.consentFresh;
9352
+ }
9353
+ abortableDelay(ms, signal) {
9354
+ return new Promise((resolve, reject) => {
9355
+ if (signal.aborted) {
9356
+ reject(new DOMException("The operation was aborted", "AbortError"));
9357
+ return;
9358
+ }
9359
+ const timer2 = setTimeout(() => {
9360
+ signal.removeEventListener("abort", onAbort);
9361
+ resolve();
9362
+ }, ms);
9363
+ const onAbort = () => {
9364
+ clearTimeout(timer2);
9365
+ reject(new DOMException("The operation was aborted", "AbortError"));
9366
+ };
9367
+ signal.addEventListener("abort", onAbort, { once: true });
9368
+ });
9369
+ }
9370
+ // RFC 7675 consent freshness
9043
9371
  queryConsent = () => {
9044
9372
  if (this.iceLite) {
9045
9373
  return;
9046
9374
  }
9047
- if (this.queryConsentHandle) {
9048
- this.queryConsentHandle.resolve();
9049
- }
9050
- this.queryConsentHandle = cancelable(async (_, __, onCancel) => {
9051
- let failures = 0;
9375
+ this.stopConsentLifecycle();
9376
+ const sessionId = this.consentSessionId;
9377
+ this.consentFresh = true;
9378
+ const handle = cancelable(async (_, __, onCancel) => {
9052
9379
  let canceled = false;
9053
9380
  const cancelEvent = new AbortController();
9381
+ const clearConsentExpiry = () => {
9382
+ if (this.consentExpiryTimer === void 0) {
9383
+ return;
9384
+ }
9385
+ clearTimeout(this.consentExpiryTimer);
9386
+ this.consentExpiryTimer = void 0;
9387
+ };
9388
+ const refreshConsentExpiry = () => {
9389
+ if (canceled || sessionId !== this.consentSessionId) {
9390
+ return;
9391
+ }
9392
+ clearConsentExpiry();
9393
+ this.consentExpiryTimer = setTimeout(() => {
9394
+ this.consentExpiryTimer = void 0;
9395
+ if (canceled || sessionId !== this.consentSessionId) {
9396
+ return;
9397
+ }
9398
+ if (this.state === "closed" || this.state === "failed") {
9399
+ return;
9400
+ }
9401
+ log23("Consent to send expired");
9402
+ this.consentFresh = false;
9403
+ this.consentSessionId++;
9404
+ this.consentRequestAbort?.abort();
9405
+ this.consentRequestAbort = void 0;
9406
+ if (this.queryConsentHandle === handle) {
9407
+ this.queryConsentHandle = void 0;
9408
+ }
9409
+ canceled = true;
9410
+ cancelEvent.abort();
9411
+ this.setState("failed");
9412
+ }, CONSENT_TIMEOUT * 1e3);
9413
+ };
9054
9414
  onCancel.once(() => {
9055
9415
  canceled = true;
9056
- failures += CONSENT_FAILURES;
9416
+ if (sessionId === this.consentSessionId) {
9417
+ clearConsentExpiry();
9418
+ this.consentRequestAbort?.abort();
9419
+ this.consentRequestAbort = void 0;
9420
+ }
9057
9421
  cancelEvent.abort();
9058
- this.queryConsentHandle = void 0;
9422
+ if (this.queryConsentHandle === handle) {
9423
+ this.queryConsentHandle = void 0;
9424
+ }
9059
9425
  });
9060
- const { localUsername, remoteUsername, iceControlling } = this;
9426
+ refreshConsentExpiry();
9427
+ const randomizedConsentInterval = () => CONSENT_INTERVAL * (0.8 + 0.4 * Math.random()) * 1e3;
9428
+ let nextConsentAt = Date.now() + randomizedConsentInterval();
9429
+ const isTerminalState = () => this.state === "closed" || this.state === "failed";
9061
9430
  try {
9062
- while (this.state !== "closed" && !canceled) {
9063
- await timers.setTimeout(
9064
- CONSENT_INTERVAL * (0.8 + 0.4 * Math.random()) * 1e3,
9065
- void 0,
9066
- { signal: cancelEvent.signal }
9431
+ while (!isTerminalState() && !canceled && sessionId === this.consentSessionId) {
9432
+ await this.abortableDelay(
9433
+ Math.max(0, nextConsentAt - Date.now()),
9434
+ cancelEvent.signal
9067
9435
  );
9436
+ if (canceled || isTerminalState() || sessionId !== this.consentSessionId) {
9437
+ break;
9438
+ }
9439
+ nextConsentAt = Date.now() + randomizedConsentInterval();
9068
9440
  const nominated = this.nominated;
9069
- if (!nominated || canceled) {
9441
+ if (!nominated) {
9070
9442
  break;
9071
9443
  }
9444
+ const pairId = nominated.id;
9445
+ const generation = this.generation;
9446
+ const remotePassword = this.remotePassword;
9447
+ const { localUsername, remoteUsername, iceControlling } = this;
9072
9448
  const request = this.buildRequest({
9073
- nominate: false,
9449
+ nominate: this.shouldNominateConsentRequest(nominated),
9074
9450
  localUsername,
9075
9451
  remoteUsername,
9076
9452
  iceControlling,
9077
9453
  localCandidate: nominated.localCandidate
9078
9454
  });
9079
- try {
9080
- nominated.consentRequestsSent++;
9081
- nominated.requestsSent++;
9082
- await nominated.protocol.request(
9083
- request,
9084
- nominated.remoteAddr,
9085
- Buffer.from(this.remotePassword, "utf8"),
9086
- 0,
9087
- (attempt) => {
9455
+ this.consentRequestAbort?.abort();
9456
+ const requestAbort = new AbortController();
9457
+ this.consentRequestAbort = requestAbort;
9458
+ nominated.consentRequestsSent++;
9459
+ nominated.requestsSent++;
9460
+ const responseTimeout = consentResponseTimeoutMs(nominated.rtt);
9461
+ const requestStartedAt = performance.now();
9462
+ nominated.protocol.request(
9463
+ request,
9464
+ nominated.remoteAddr,
9465
+ Buffer.from(remotePassword, "utf8"),
9466
+ {
9467
+ retransmissions: 0,
9468
+ responseTimeout,
9469
+ signal: requestAbort.signal,
9470
+ onRequestSent: (attempt) => {
9088
9471
  if (attempt > 0) {
9089
9472
  nominated.retransmissionsSent++;
9090
9473
  }
9091
9474
  }
9092
- );
9475
+ }
9476
+ ).then(() => {
9477
+ if (sessionId !== this.consentSessionId || canceled) {
9478
+ return;
9479
+ }
9480
+ const state = this.state;
9481
+ if (state === "closed" || state === "failed") {
9482
+ return;
9483
+ }
9484
+ if (this.nominated?.id !== pairId) {
9485
+ return;
9486
+ }
9487
+ if (this.generation !== generation) {
9488
+ return;
9489
+ }
9490
+ if (this.remotePassword !== remotePassword) {
9491
+ return;
9492
+ }
9493
+ const rtt = (performance.now() - requestStartedAt) / 1e3;
9494
+ nominated.rtt = rtt;
9495
+ nominated.totalRoundTripTime += rtt;
9496
+ nominated.roundTripTimeMeasurements++;
9093
9497
  nominated.responsesReceived++;
9094
- failures = 0;
9095
- if (this.state === "disconnected") {
9498
+ this.consentFresh = true;
9499
+ refreshConsentExpiry();
9500
+ if (state === "disconnected") {
9096
9501
  this.setState("connected");
9097
9502
  }
9098
- } catch (error) {
9099
- if (nominated.id === this.nominated?.id) {
9100
- log23("no stun response");
9101
- failures++;
9102
- this.setState("disconnected");
9103
- break;
9503
+ }).catch((error) => {
9504
+ if (sessionId === this.consentSessionId && this.nominated?.id === pairId) {
9505
+ log23("no stun response", error);
9104
9506
  }
9105
- }
9106
- if (failures >= CONSENT_FAILURES) {
9107
- log23("Consent to send expired");
9108
- this.queryConsentHandle = void 0;
9109
- this.setState("closed");
9110
- break;
9111
- }
9507
+ });
9112
9508
  }
9113
9509
  } catch (error) {
9510
+ } finally {
9511
+ if (sessionId === this.consentSessionId) {
9512
+ clearConsentExpiry();
9513
+ }
9114
9514
  }
9115
9515
  });
9516
+ this.queryConsentHandle = handle;
9116
9517
  };
9117
9518
  async close() {
9118
9519
  this.setState("closed");
9119
- this.queryConsentHandle?.resolve?.();
9520
+ this.stopConsentLifecycle();
9120
9521
  if (this.checkList && !this.checkListDone) {
9121
9522
  this.checkListState.put(
9122
9523
  new Promise((r) => {
@@ -9166,14 +9567,13 @@ var Connection = class {
9166
9567
  this.sortCheckList();
9167
9568
  }
9168
9569
  send = async (data) => {
9169
- const activePair = this.nominated;
9170
- if (activePair) {
9171
- await activePair.protocol.sendData(data, activePair.remoteAddr);
9172
- activePair.packetsSent++;
9173
- activePair.bytesSent += data.length;
9174
- } else {
9570
+ if (!this.canSendApplicationData()) {
9175
9571
  return;
9176
9572
  }
9573
+ const activePair = this.nominated;
9574
+ await activePair.protocol.sendData(data, activePair.remoteAddr);
9575
+ activePair.packetsSent++;
9576
+ activePair.bytesSent += data.length;
9177
9577
  };
9178
9578
  getDefaultCandidate() {
9179
9579
  const candidates = this.localCandidates.sort(
@@ -9208,13 +9608,22 @@ var Connection = class {
9208
9608
  }
9209
9609
  findPair(protocol, remoteCandidate) {
9210
9610
  const pair = this.checkList.find(
9211
- (pair2) => isEqual(pair2.protocol, protocol) && isEqual(pair2.remoteCandidate, remoteCandidate)
9611
+ (pair2) => pair2.protocol === protocol && pair2.remoteCandidate === remoteCandidate
9212
9612
  );
9213
9613
  return pair;
9214
9614
  }
9615
+ applyIceControlling(iceControlling) {
9616
+ this._iceControlling = iceControlling;
9617
+ for (const pair of this.checkList) {
9618
+ pair.iceControlling = iceControlling;
9619
+ }
9620
+ }
9215
9621
  switchRole(iceControlling) {
9216
9622
  log23("switch role", iceControlling);
9217
- this.iceControlling = iceControlling;
9623
+ if (this.iceLite) {
9624
+ iceControlling = false;
9625
+ }
9626
+ this.applyIceControlling(iceControlling);
9218
9627
  this.sortCheckList();
9219
9628
  }
9220
9629
  checkComplete(pair) {
@@ -9226,6 +9635,9 @@ var Connection = class {
9226
9635
  this.nominated = pair;
9227
9636
  this.nominating = false;
9228
9637
  this.pruneTcpConnections(pair);
9638
+ if (!this.iceLite && (this.state === "connected" || this.state === "completed")) {
9639
+ this.queryConsent();
9640
+ }
9229
9641
  for (const p of this.checkList) {
9230
9642
  if (p.component === pair.component && [1 /* WAITING */, 0 /* FROZEN */].includes(
9231
9643
  p.state
@@ -9351,7 +9763,7 @@ var Connection = class {
9351
9763
  return;
9352
9764
  }
9353
9765
  }
9354
- if (!isEqual(result.addr, pair.remoteAddr)) {
9766
+ if (result.addr[0] !== pair.remoteAddr[0] || result.addr[1] !== pair.remoteAddr[1]) {
9355
9767
  pair.updateState(4 /* FAILED */);
9356
9768
  this.checkComplete(pair);
9357
9769
  r();
@@ -10763,8 +11175,7 @@ var StreamStatistics = class {
10763
11175
 
10764
11176
  // src/sdp.ts
10765
11177
  import { randomBytes as randomBytes9 } from "crypto";
10766
- import { isIPv4 as isIPv43 } from "net";
10767
- import * as Int643 from "int64-buffer";
11178
+ import { isIPv4 as isIPv44 } from "net";
10768
11179
 
10769
11180
  // src/transport/dtls.ts
10770
11181
  import { Certificate as Certificate3, PrivateKey as PrivateKey2 } from "@fidm/x509";
@@ -11698,11 +12109,9 @@ var RTCIceParameters = class {
11698
12109
 
11699
12110
  // src/transport/sctp.ts
11700
12111
  import { randomUUID as randomUUID8 } from "crypto";
11701
- import { jspack as jspack5 } from "@shinyoshiaki/jspack";
11702
12112
 
11703
12113
  // ../sctp/src/sctp.ts
11704
12114
  import { createHmac as createHmac5, randomBytes as randomBytes8 } from "crypto";
11705
- import { jspack as jspack4 } from "@shinyoshiaki/jspack";
11706
12115
 
11707
12116
  // ../sctp/src/chunk.ts
11708
12117
  var Chunk = class _Chunk {
@@ -12155,7 +12564,6 @@ function createEventsFromList(list) {
12155
12564
  }
12156
12565
 
12157
12566
  // ../sctp/src/param.ts
12158
- import { jspack as jspack3 } from "@shinyoshiaki/jspack";
12159
12567
  var OutgoingSSNResetRequestParam = class _OutgoingSSNResetRequestParam {
12160
12568
  // Outgoing SSN Reset Request Parameter
12161
12569
  constructor(requestSequence, responseSequence, lastTsn, streams) {
@@ -12169,26 +12577,26 @@ var OutgoingSSNResetRequestParam = class _OutgoingSSNResetRequestParam {
12169
12577
  return _OutgoingSSNResetRequestParam.type;
12170
12578
  }
12171
12579
  get bytes() {
12172
- const data = Buffer.from(
12173
- jspack3.Pack("!LLL", [
12174
- this.requestSequence,
12175
- this.responseSequence,
12176
- this.lastTsn
12177
- ])
12178
- );
12580
+ const data = Buffer.allocUnsafe(12);
12581
+ data.writeUInt32BE(this.requestSequence, 0);
12582
+ data.writeUInt32BE(this.responseSequence, 4);
12583
+ data.writeUInt32BE(this.lastTsn, 8);
12179
12584
  return Buffer.concat([
12180
12585
  data,
12181
- ...this.streams.map((stream) => Buffer.from(jspack3.Pack("!H", [stream])))
12586
+ ...this.streams.map((stream) => {
12587
+ const buf = Buffer.allocUnsafe(2);
12588
+ buf.writeUInt16BE(stream, 0);
12589
+ return buf;
12590
+ })
12182
12591
  ]);
12183
12592
  }
12184
12593
  static parse(data) {
12185
- const [requestSequence, responseSequence, lastTsn] = jspack3.Unpack(
12186
- "!LLL",
12187
- data
12188
- );
12594
+ const requestSequence = data.readUInt32BE(0);
12595
+ const responseSequence = data.readUInt32BE(4);
12596
+ const lastTsn = data.readUInt32BE(8);
12189
12597
  const stream = [];
12190
12598
  for (let pos = 12; pos < data.length; pos += 2) {
12191
- stream.push(jspack3.Unpack("!H", data.slice(pos))[0]);
12599
+ stream.push(data.readUInt16BE(pos));
12192
12600
  }
12193
12601
  return new _OutgoingSSNResetRequestParam(
12194
12602
  requestSequence,
@@ -12209,12 +12617,15 @@ var StreamAddOutgoingParam = class _StreamAddOutgoingParam {
12209
12617
  return _StreamAddOutgoingParam.type;
12210
12618
  }
12211
12619
  get bytes() {
12212
- return Buffer.from(
12213
- jspack3.Pack("!LHH", [this.requestSequence, this.newStreams, 0])
12214
- );
12620
+ const buf = Buffer.allocUnsafe(8);
12621
+ buf.writeUInt32BE(this.requestSequence, 0);
12622
+ buf.writeUInt16BE(this.newStreams, 4);
12623
+ buf.writeUInt16BE(0, 6);
12624
+ return buf;
12215
12625
  }
12216
12626
  static parse(data) {
12217
- const [requestSequence, newStreams] = jspack3.Unpack("!LHH", data);
12627
+ const requestSequence = data.readUInt32BE(0);
12628
+ const newStreams = data.readUInt16BE(4);
12218
12629
  return new _StreamAddOutgoingParam(requestSequence, newStreams);
12219
12630
  }
12220
12631
  };
@@ -12233,12 +12644,14 @@ var ReconfigResponseParam = class _ReconfigResponseParam {
12233
12644
  return _ReconfigResponseParam.type;
12234
12645
  }
12235
12646
  get bytes() {
12236
- return Buffer.from(
12237
- jspack3.Pack("!LL", [this.responseSequence, this.result])
12238
- );
12647
+ const buf = Buffer.allocUnsafe(8);
12648
+ buf.writeUInt32BE(this.responseSequence, 0);
12649
+ buf.writeUInt32BE(this.result, 4);
12650
+ return buf;
12239
12651
  }
12240
12652
  static parse(data) {
12241
- const [requestSequence, result] = jspack3.Unpack("!LL", data);
12653
+ const requestSequence = data.readUInt32BE(0);
12654
+ const result = data.readUInt32BE(4);
12242
12655
  return new _ReconfigResponseParam(requestSequence, result);
12243
12656
  }
12244
12657
  };
@@ -12507,8 +12920,10 @@ var SCTP = class _SCTP {
12507
12920
  ack.inboundStreams = this._inboundStreamsCount;
12508
12921
  ack.initialTsn = this.localTsn;
12509
12922
  this.setExtensions(ack.params);
12510
- const time = Date.now() / 1e3;
12511
- let cookie = Buffer.from(jspack4.Pack("!L", [time]));
12923
+ const time = Math.floor(Date.now() / 1e3);
12924
+ const cookieTime = Buffer.allocUnsafe(4);
12925
+ cookieTime.writeUInt32BE(time, 0);
12926
+ let cookie = cookieTime;
12512
12927
  cookie = Buffer.concat([
12513
12928
  cookie,
12514
12929
  createHmac5("sha1", this.hmacKey).update(cookie).digest()
@@ -12599,8 +13014,8 @@ var SCTP = class _SCTP {
12599
13014
  log30("x State cookie is invalid");
12600
13015
  return;
12601
13016
  }
12602
- const now = Date.now() / 1e3;
12603
- const stamp = jspack4.Unpack("!L", cookie)[0];
13017
+ const now = Math.floor(Date.now() / 1e3);
13018
+ const stamp = cookie.readUInt32BE(0);
12604
13019
  if (stamp < now - COOKIE_LIFETIME || stamp > now) {
12605
13020
  const error = new ErrorChunk(0, void 0);
12606
13021
  error.params.push([
@@ -13230,10 +13645,9 @@ var SCTP = class _SCTP {
13230
13645
  if (this.associationState !== 4 /* ESTABLISHED */) return;
13231
13646
  if (this.flightSize === 0 && this.outboundQueue.length === 0) {
13232
13647
  const heartbeat = new HeartbeatChunk();
13233
- heartbeat.params.push([
13234
- 1,
13235
- Buffer.from(jspack4.Pack("!L", [Math.floor(Date.now() / 1e3)]))
13236
- ]);
13648
+ const heartbeatTime = Buffer.allocUnsafe(4);
13649
+ heartbeatTime.writeUInt32BE(Math.floor(Date.now() / 1e3), 0);
13650
+ heartbeat.params.push([1, heartbeatTime]);
13237
13651
  await this.sendChunk(heartbeat).catch((err5) => {
13238
13652
  log30("send heartbeat failed", err5.message);
13239
13653
  });
@@ -13599,14 +14013,10 @@ var RTCSctpTransport = class _RTCSctpTransport {
13599
14013
  return;
13600
14014
  }
13601
14015
  if (!Object.keys(this.dataChannels).includes(streamId.toString())) {
13602
- const [
13603
- ,
13604
- channelType,
13605
- ,
13606
- reliability,
13607
- labelLength,
13608
- protocolLength
13609
- ] = jspack5.Unpack("!BBHLHH", data);
14016
+ const channelType = data.readUInt8(1);
14017
+ const reliability = data.readUInt32BE(4);
14018
+ const labelLength = data.readUInt16BE(8);
14019
+ const protocolLength = data.readUInt16BE(10);
13610
14020
  let pos = 12;
13611
14021
  const label = data.slice(pos, pos + labelLength).toString("utf8");
13612
14022
  pos += labelLength;
@@ -13637,11 +14047,9 @@ var RTCSctpTransport = class _RTCSctpTransport {
13637
14047
  log31("datachannel already opened", "retransmit ack");
13638
14048
  }
13639
14049
  const channel = this.dataChannels[streamId];
13640
- this.dataChannelQueue.push([
13641
- channel,
13642
- WEBRTC_DCEP,
13643
- Buffer.from(jspack5.Pack("!B", [DATA_CHANNEL_ACK]))
13644
- ]);
14050
+ const ack = Buffer.allocUnsafe(1);
14051
+ ack.writeUInt8(DATA_CHANNEL_ACK, 0);
14052
+ this.dataChannelQueue.push([channel, WEBRTC_DCEP, ack]);
13645
14053
  await this.dataChannelFlush();
13646
14054
  }
13647
14055
  break;
@@ -13716,16 +14124,15 @@ var RTCSctpTransport = class _RTCSctpTransport {
13716
14124
  channelType = 2;
13717
14125
  reliability = channel.maxPacketLifeTime;
13718
14126
  }
13719
- const data = jspack5.Pack("!BBHLHH", [
13720
- DATA_CHANNEL_OPEN,
13721
- channelType,
13722
- priority,
13723
- reliability,
13724
- channel.label.length,
13725
- channel.protocol.length
13726
- ]);
14127
+ const data = Buffer.allocUnsafe(12);
14128
+ data.writeUInt8(DATA_CHANNEL_OPEN, 0);
14129
+ data.writeUInt8(channelType, 1);
14130
+ data.writeUInt16BE(priority, 2);
14131
+ data.writeUInt32BE(reliability, 4);
14132
+ data.writeUInt16BE(channel.label.length, 8);
14133
+ data.writeUInt16BE(channel.protocol.length, 10);
13727
14134
  const send = Buffer.concat([
13728
- Buffer.from(data),
14135
+ data,
13729
14136
  Buffer.from(channel.label, "utf8"),
13730
14137
  Buffer.from(channel.protocol, "utf8")
13731
14138
  ]);
@@ -14332,7 +14739,7 @@ function ipAddressFromSdp(sdp) {
14332
14739
  return m[2];
14333
14740
  }
14334
14741
  function ipAddressToSdp(addr) {
14335
- const version = isIPv43(addr) ? 4 : 6;
14742
+ const version = isIPv44(addr) ? 4 : 6;
14336
14743
  return `IN IP${version} ${addr}`;
14337
14744
  }
14338
14745
  function candidateToSdp(c) {
@@ -14422,7 +14829,7 @@ var RTCSessionDescription = class {
14422
14829
  };
14423
14830
  function addSDPHeader(type, description) {
14424
14831
  const username = "-";
14425
- const sessionId = new Int643.Uint64BE(randomBytes9(64)).toString().slice(0, 8);
14832
+ const sessionId = randomBytes9(8).readBigUInt64BE(0).toString().slice(0, 8);
14426
14833
  const sessionVersion = 0;
14427
14834
  description.origin = `${username} ${sessionId} ${sessionVersion} IN IP4 0.0.0.0`;
14428
14835
  description.msidSemantic.push(new GroupDescription("WMS", ["*"]));
@@ -14977,7 +15384,6 @@ var RtpRouter = class {
14977
15384
 
14978
15385
  // src/media/rtpSender.ts
14979
15386
  import { randomBytes as randomBytes10 } from "crypto";
14980
- import { jspack as jspack6 } from "@shinyoshiaki/jspack";
14981
15387
  import { randomUUID as randomUUID10 } from "crypto";
14982
15388
  import { setTimeout as setTimeout9 } from "timers/promises";
14983
15389
 
@@ -15140,8 +15546,8 @@ var RTCRtpSender = class {
15140
15546
  }
15141
15547
  type = "sender";
15142
15548
  kind;
15143
- ssrc = jspack6.Unpack("!L", randomBytes10(4))[0];
15144
- rtxSsrc = jspack6.Unpack("!L", randomBytes10(4))[0];
15549
+ ssrc = randomBytes10(4).readUInt32BE(0);
15550
+ rtxSsrc = randomBytes10(4).readUInt32BE(0);
15145
15551
  trackId = randomUUID10().toString();
15146
15552
  onReady = new Event2();
15147
15553
  onRtcp = new Event2();
@@ -16561,6 +16967,11 @@ var SecureTransportManager = class {
16561
16967
  log36("iceConnectionStateChange", newState);
16562
16968
  this.iceConnectionState = newState;
16563
16969
  this.iceConnectionStateChange.execute(newState);
16970
+ if (newState === "failed" && this.connectionState !== "closed") {
16971
+ this.setConnectionState("failed");
16972
+ } else if (newState === "disconnected" && this.connectionState === "connected") {
16973
+ this.setConnectionState("disconnected");
16974
+ }
16564
16975
  }
16565
16976
  async gatherCandidates(remoteIsBundled) {
16566
16977
  const connected = this.iceTransports.find(
@@ -16577,6 +16988,9 @@ var SecureTransportManager = class {
16577
16988
  }
16578
16989
  }
16579
16990
  setConnectionState(state) {
16991
+ if (this.connectionState === state) {
16992
+ return;
16993
+ }
16580
16994
  log36("connectionStateChange", state);
16581
16995
  this.connectionState = state;
16582
16996
  this.connectionStateChange.execute(state);
@@ -17936,6 +18350,9 @@ export {
17936
18350
  BufferChain,
17937
18351
  CONSENT_FAILURES,
17938
18352
  CONSENT_INTERVAL,
18353
+ CONSENT_RESPONSE_TIMEOUT,
18354
+ CONSENT_RESPONSE_TIMEOUT_MIN,
18355
+ CONSENT_TIMEOUT,
17939
18356
  COOKIE,
17940
18357
  Candidate,
17941
18358
  CandidatePair,
@@ -18091,6 +18508,7 @@ export {
18091
18508
  codecParametersFromString,
18092
18509
  codecParametersToString,
18093
18510
  compactNtp,
18511
+ consentResponseTimeoutMs,
18094
18512
  crc32,
18095
18513
  crc32c,
18096
18514
  createBufferWriter,