werift 0.22.8 → 0.23.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 (69) hide show
  1. package/lib/common/src/crc.d.ts +4 -0
  2. package/lib/common/src/crc.js +124 -0
  3. package/lib/common/src/crc.js.map +1 -0
  4. package/lib/common/src/index.d.ts +1 -0
  5. package/lib/common/src/index.js +1 -0
  6. package/lib/common/src/index.js.map +1 -1
  7. package/lib/dtls/src/flight/server/flight6.js +12 -2
  8. package/lib/dtls/src/flight/server/flight6.js.map +1 -1
  9. package/lib/dtls/src/server.js +6 -1
  10. package/lib/dtls/src/server.js.map +1 -1
  11. package/lib/dtls/src/socket.d.ts +1 -0
  12. package/lib/dtls/src/socket.js +3 -0
  13. package/lib/dtls/src/socket.js.map +1 -1
  14. package/lib/ice/src/stun/message.js +2 -10
  15. package/lib/ice/src/stun/message.js.map +1 -1
  16. package/lib/index.mjs +705 -113
  17. package/lib/nonstandard/index.mjs +308 -44
  18. package/lib/rtp/src/index.d.ts +1 -0
  19. package/lib/rtp/src/index.js +1 -0
  20. package/lib/rtp/src/index.js.map +1 -1
  21. package/lib/rtp/src/srtp/cipher/ctr.d.ts +3 -3
  22. package/lib/rtp/src/srtp/cipher/ctr.js +25 -14
  23. package/lib/rtp/src/srtp/cipher/ctr.js.map +1 -1
  24. package/lib/rtp/src/srtp/cipher/gcm.d.ts +3 -3
  25. package/lib/rtp/src/srtp/cipher/gcm.js +57 -20
  26. package/lib/rtp/src/srtp/cipher/gcm.js.map +1 -1
  27. package/lib/rtp/src/srtp/cipher/index.d.ts +1 -1
  28. package/lib/rtp/src/srtp/cipher/index.js +1 -1
  29. package/lib/rtp/src/srtp/cipher/index.js.map +1 -1
  30. package/lib/rtp/src/srtp/context/srtp.d.ts +2 -1
  31. package/lib/rtp/src/srtp/context/srtp.js +22 -5
  32. package/lib/rtp/src/srtp/context/srtp.js.map +1 -1
  33. package/lib/rtp/src/srtp/error.d.ts +3 -0
  34. package/lib/rtp/src/srtp/error.js +11 -0
  35. package/lib/rtp/src/srtp/error.js.map +1 -0
  36. package/lib/rtp/src/srtp/packet.d.ts +5 -0
  37. package/lib/rtp/src/srtp/packet.js +48 -0
  38. package/lib/rtp/src/srtp/packet.js.map +1 -0
  39. package/lib/sctp/src/chunk.js +3 -6
  40. package/lib/sctp/src/chunk.js.map +1 -1
  41. package/lib/sctp/src/sctp.d.ts +19 -0
  42. package/lib/sctp/src/sctp.js +259 -23
  43. package/lib/sctp/src/sctp.js.map +1 -1
  44. package/lib/webrtc/src/dataChannel.d.ts +1 -0
  45. package/lib/webrtc/src/dataChannel.js +5 -2
  46. package/lib/webrtc/src/dataChannel.js.map +1 -1
  47. package/lib/webrtc/src/peerConnection.d.ts +4 -1
  48. package/lib/webrtc/src/peerConnection.js +26 -5
  49. package/lib/webrtc/src/peerConnection.js.map +1 -1
  50. package/lib/webrtc/src/sctpManager.d.ts +1 -1
  51. package/lib/webrtc/src/sctpManager.js +3 -2
  52. package/lib/webrtc/src/sctpManager.js.map +1 -1
  53. package/lib/webrtc/src/sdpManager.d.ts +1 -1
  54. package/lib/webrtc/src/sdpManager.js +3 -4
  55. package/lib/webrtc/src/sdpManager.js.map +1 -1
  56. package/lib/webrtc/src/secureTransportManager.js +1 -1
  57. package/lib/webrtc/src/secureTransportManager.js.map +1 -1
  58. package/lib/webrtc/src/transceiverManager.js +3 -2
  59. package/lib/webrtc/src/transceiverManager.js.map +1 -1
  60. package/lib/webrtc/src/transport/dtls.d.ts +1 -0
  61. package/lib/webrtc/src/transport/dtls.js +117 -12
  62. package/lib/webrtc/src/transport/dtls.js.map +1 -1
  63. package/lib/webrtc/src/transport/sctp.d.ts +9 -3
  64. package/lib/webrtc/src/transport/sctp.js +35 -9
  65. package/lib/webrtc/src/transport/sctp.js.map +1 -1
  66. package/lib/webrtc/src/utils.d.ts +2 -0
  67. package/lib/webrtc/src/utils.js +20 -0
  68. package/lib/webrtc/src/utils.js.map +1 -1
  69. package/package.json +1 -3
package/lib/index.mjs CHANGED
@@ -229,6 +229,105 @@ var BitStream = class {
229
229
  }
230
230
  };
231
231
 
232
+ // ../common/src/crc.ts
233
+ var POLY_CRC32 = 3988292384;
234
+ var POLY_CRC32C = 2197175160;
235
+ function isBufferLike(input) {
236
+ return typeof input !== "string";
237
+ }
238
+ function generateCRCTable(polynomial) {
239
+ const table = new Array(256);
240
+ let c = 0;
241
+ for (let n = 0; n < 256; ++n) {
242
+ c = n;
243
+ c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
244
+ c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
245
+ c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
246
+ c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
247
+ c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
248
+ c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
249
+ c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
250
+ c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
251
+ table[n] = c;
252
+ }
253
+ return new Int32Array(table);
254
+ }
255
+ function generateSliceBy16Tables(table0) {
256
+ const table = new Int32Array(4096);
257
+ let c = 0;
258
+ let v = 0;
259
+ let n = 0;
260
+ for (n = 0; n < 256; ++n) table[n] = table0[n];
261
+ for (n = 0; n < 256; ++n) {
262
+ v = table0[n];
263
+ for (c = 256 + n; c < 4096; c += 256) {
264
+ v = table[c] = v >>> 8 ^ table0[v & 255];
265
+ }
266
+ }
267
+ const out = [];
268
+ for (n = 1; n < 16; ++n) {
269
+ out[n - 1] = table.subarray(n * 256, n * 256 + 256);
270
+ }
271
+ return out;
272
+ }
273
+ function crcGenericString(value, seed, table0) {
274
+ let crc = seed ^ -1;
275
+ let i = 0;
276
+ const len = value.length;
277
+ let c = 0;
278
+ let d = 0;
279
+ while (i < len) {
280
+ c = value.charCodeAt(i++);
281
+ if (c < 128) {
282
+ crc = crc >>> 8 ^ table0[(crc ^ c) & 255];
283
+ } else if (c < 2048) {
284
+ crc = crc >>> 8 ^ table0[(crc ^ (192 | c >> 6 & 31)) & 255];
285
+ crc = crc >>> 8 ^ table0[(crc ^ (128 | c & 63)) & 255];
286
+ } else if (c >= 55296 && c < 57344) {
287
+ c = (c & 1023) + 64;
288
+ d = value.charCodeAt(i++) & 1023;
289
+ crc = crc >>> 8 ^ table0[(crc ^ (240 | c >> 8 & 7)) & 255];
290
+ crc = crc >>> 8 ^ table0[(crc ^ (128 | c >> 2 & 63)) & 255];
291
+ crc = crc >>> 8 ^ table0[(crc ^ (128 | d >> 6 & 15 | (c & 3) << 4)) & 255];
292
+ crc = crc >>> 8 ^ table0[(crc ^ (128 | d & 63)) & 255];
293
+ } else {
294
+ crc = crc >>> 8 ^ table0[(crc ^ (224 | c >> 12 & 15)) & 255];
295
+ crc = crc >>> 8 ^ table0[(crc ^ (128 | c >> 6 & 63)) & 255];
296
+ crc = crc >>> 8 ^ table0[(crc ^ (128 | c & 63)) & 255];
297
+ }
298
+ }
299
+ return ~crc >>> 0;
300
+ }
301
+ function crcBuffer(value, seed, table0, tables16) {
302
+ const [t1, t2, t3, t4, t5, t6, t7, t8, t9, ta, tb, tc, td, te, tf] = tables16;
303
+ let crc = seed ^ -1;
304
+ let i = 0;
305
+ let len = value.length - 15;
306
+ while (i < len) {
307
+ crc = tf[value[i++] ^ crc & 255] ^ te[value[i++] ^ crc >>> 8 & 255] ^ td[value[i++] ^ crc >>> 16 & 255] ^ tc[value[i++] ^ crc >>> 24] ^ tb[value[i++]] ^ ta[value[i++]] ^ t9[value[i++]] ^ t8[value[i++]] ^ t7[value[i++]] ^ t6[value[i++]] ^ t5[value[i++]] ^ t4[value[i++]] ^ t3[value[i++]] ^ t2[value[i++]] ^ t1[value[i++]] ^ table0[value[i++]];
308
+ }
309
+ for (len += 15; i < len; ) {
310
+ crc = crc >>> 8 ^ table0[(crc ^ value[i++]) & 255];
311
+ }
312
+ return ~crc >>> 0;
313
+ }
314
+ var table32 = generateCRCTable(POLY_CRC32);
315
+ var tables32By16 = generateSliceBy16Tables(table32);
316
+ var table32c = generateCRCTable(POLY_CRC32C);
317
+ var tables32cBy16 = generateSliceBy16Tables(table32c);
318
+ function crc32(input, seed = 0) {
319
+ if (isBufferLike(input)) {
320
+ return crcBuffer(input, seed, table32, tables32By16);
321
+ }
322
+ return crcGenericString(input, seed, table32);
323
+ }
324
+ function crc32c(input, seed = 0) {
325
+ if (isBufferLike(input)) {
326
+ return crcBuffer(input, seed, table32c, tables32cBy16);
327
+ }
328
+ return crcGenericString(input, seed, table32c);
329
+ }
330
+
232
331
  // ../common/src/number.ts
233
332
  function uint8Add(a, b) {
234
333
  return a + b & 255;
@@ -4547,7 +4646,12 @@ import { createHmac as createHmac3 } from "crypto";
4547
4646
  import AES from "aes-js";
4548
4647
 
4549
4648
  // ../rtp/src/srtp/cipher/ctr.ts
4550
- import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, createHmac as createHmac2 } from "crypto";
4649
+ import {
4650
+ createCipheriv as createCipheriv2,
4651
+ createDecipheriv as createDecipheriv2,
4652
+ createHmac as createHmac2,
4653
+ timingSafeEqual
4654
+ } from "crypto";
4551
4655
 
4552
4656
  // ../rtp/src/srtp/cipher/index.ts
4553
4657
  var CipherAesBase = class {
@@ -4560,7 +4664,7 @@ var CipherAesBase = class {
4560
4664
  encryptRtp(header, payload, rolloverCounter) {
4561
4665
  return Buffer.from([]);
4562
4666
  }
4563
- decryptRtp(cipherText, rolloverCounter) {
4667
+ decryptRtp(cipherText, rolloverCounter, header) {
4564
4668
  return [];
4565
4669
  }
4566
4670
  encryptRTCP(rawRtcp, srtcpIndex) {
@@ -4571,6 +4675,74 @@ var CipherAesBase = class {
4571
4675
  }
4572
4676
  };
4573
4677
 
4678
+ // ../rtp/src/srtp/error.ts
4679
+ var SrtpAuthenticationError = class extends Error {
4680
+ constructor(message) {
4681
+ super(message);
4682
+ this.name = "SrtpAuthenticationError";
4683
+ }
4684
+ };
4685
+
4686
+ // ../rtp/src/srtp/packet.ts
4687
+ var minRtpHeaderSize = 12;
4688
+ var minRtcpPacketSize = 8;
4689
+ function parseSrtpRtpHeader(packet, authTagLength, message = "Failed to authenticate SRTP packet") {
4690
+ const authTagOffset = packet.length - authTagLength;
4691
+ assertAuthenticatedPacketLength(
4692
+ packet.length >= minRtpHeaderSize + authTagLength,
4693
+ message
4694
+ );
4695
+ const header = wrapAuthenticationError(
4696
+ () => RtpHeader.deSerialize(packet.subarray(0, authTagOffset)),
4697
+ message
4698
+ );
4699
+ header.paddingSize = 0;
4700
+ assertAuthenticatedPacketLength(
4701
+ header.payloadOffset >= minRtpHeaderSize && header.payloadOffset <= authTagOffset,
4702
+ message
4703
+ );
4704
+ return header;
4705
+ }
4706
+ function parseSrtcpHeader(packet, authTagLength, srtcpIndexSize3, message = "Failed to authenticate SRTCP packet") {
4707
+ assertAuthenticatedPacketLength(
4708
+ packet.length >= minRtcpPacketSize + authTagLength + srtcpIndexSize3,
4709
+ message
4710
+ );
4711
+ return wrapAuthenticationError(
4712
+ () => RtcpHeader.deSerialize(packet.subarray(0, RTCP_HEADER_SIZE)),
4713
+ message
4714
+ );
4715
+ }
4716
+ function assertAuthenticatedPacketLength(condition, message) {
4717
+ if (!condition) {
4718
+ throw new SrtpAuthenticationError(message);
4719
+ }
4720
+ }
4721
+ function wrapAuthenticationError(parse, message) {
4722
+ try {
4723
+ return parse();
4724
+ } catch {
4725
+ throw new SrtpAuthenticationError(message);
4726
+ }
4727
+ }
4728
+ function finalizeSrtpRtpHeader(header, packet, message = "Failed to authenticate SRTP packet") {
4729
+ if (!header.padding) {
4730
+ header.paddingSize = 0;
4731
+ return header;
4732
+ }
4733
+ assertAuthenticatedPacketLength(
4734
+ packet.length > header.payloadOffset,
4735
+ message
4736
+ );
4737
+ const paddingSize = packet[packet.length - 1];
4738
+ assertAuthenticatedPacketLength(
4739
+ paddingSize > 0 && paddingSize <= packet.length - header.payloadOffset,
4740
+ message
4741
+ );
4742
+ header.paddingSize = paddingSize;
4743
+ return header;
4744
+ }
4745
+
4574
4746
  // ../rtp/src/srtp/cipher/ctr.ts
4575
4747
  var CipherAesCtr = class extends CipherAesBase {
4576
4748
  constructor(srtpSessionKey, srtpSessionSalt, srtcpSessionKey, srtcpSessionSalt, srtpSessionAuthTag, srtcpSessionAuthTag) {
@@ -4596,10 +4768,20 @@ var CipherAesCtr = class extends CipherAesBase {
4596
4768
  );
4597
4769
  return Buffer.concat([headerBuffer, enc, authTag]);
4598
4770
  }
4599
- decryptRtp(cipherText, rolloverCounter) {
4600
- const header = RtpHeader.deSerialize(cipherText);
4601
- const size = cipherText.length - this.authTagLength;
4602
- cipherText = cipherText.subarray(0, cipherText.length - this.authTagLength);
4771
+ decryptRtp(cipherText, rolloverCounter, header = parseSrtpRtpHeader(cipherText, this.authTagLength)) {
4772
+ const authTagOffset = cipherText.length - this.authTagLength;
4773
+ const encryptedPacket = cipherText.subarray(0, authTagOffset);
4774
+ const actualAuthTag = cipherText.subarray(authTagOffset);
4775
+ const expectedAuthTag = this.generateSrtpAuthTag(
4776
+ rolloverCounter,
4777
+ encryptedPacket.subarray(0, header.payloadOffset),
4778
+ encryptedPacket.subarray(header.payloadOffset)
4779
+ );
4780
+ assertAuthTag(
4781
+ actualAuthTag,
4782
+ expectedAuthTag,
4783
+ "Failed to authenticate SRTP packet"
4784
+ );
4603
4785
  const counter = this.generateCounter(
4604
4786
  header.sequenceNumber,
4605
4787
  rolloverCounter,
@@ -4611,14 +4793,16 @@ var CipherAesCtr = class extends CipherAesBase {
4611
4793
  this.srtpSessionKey,
4612
4794
  counter
4613
4795
  );
4614
- const payload = cipherText.subarray(header.payloadOffset);
4796
+ const payload = encryptedPacket.subarray(header.payloadOffset);
4615
4797
  const buf = cipher.update(payload);
4616
4798
  const dst = Buffer.concat([
4617
- cipherText.subarray(0, header.payloadOffset),
4618
- buf,
4619
- Buffer.alloc(size - header.payloadOffset - buf.length)
4799
+ encryptedPacket.subarray(0, header.payloadOffset),
4800
+ buf
4620
4801
  ]);
4621
- return [dst, header];
4802
+ return [
4803
+ dst,
4804
+ finalizeSrtpRtpHeader(header, dst, "Failed to authenticate SRTP packet")
4805
+ ];
4622
4806
  }
4623
4807
  encryptRTCP(rtcpPacket, srtcpIndex) {
4624
4808
  let out = Buffer.from(rtcpPacket);
@@ -4640,15 +4824,29 @@ var CipherAesCtr = class extends CipherAesBase {
4640
4824
  return out;
4641
4825
  }
4642
4826
  decryptRTCP(encrypted) {
4643
- const header = RtcpHeader.deSerialize(encrypted);
4827
+ const header = parseSrtcpHeader(
4828
+ encrypted,
4829
+ this.authTagLength,
4830
+ srtcpIndexSize
4831
+ );
4644
4832
  const tailOffset = encrypted.length - (this.authTagLength + srtcpIndexSize);
4833
+ const authenticatedPortion = encrypted.subarray(
4834
+ 0,
4835
+ encrypted.length - this.authTagLength
4836
+ );
4837
+ const actualTag = encrypted.subarray(encrypted.length - this.authTagLength);
4838
+ const expectedTag = this.generateSrtcpAuthTag(authenticatedPortion);
4839
+ assertAuthTag(
4840
+ actualTag,
4841
+ expectedTag,
4842
+ "Failed to authenticate SRTCP packet"
4843
+ );
4645
4844
  const out = Buffer.from(encrypted).slice(0, tailOffset);
4646
- const isEncrypted = encrypted[tailOffset] >> 7;
4845
+ const isEncrypted = encrypted[tailOffset] >>> 7;
4647
4846
  if (isEncrypted === 0) return [out, header];
4648
4847
  let srtcpIndex = encrypted.readUInt32BE(tailOffset);
4649
4848
  srtcpIndex &= ~(1 << 31);
4650
4849
  const ssrc = encrypted.readUInt32BE(4);
4651
- const actualTag = encrypted.subarray(encrypted.length - 10);
4652
4850
  const counter = this.generateCounter(
4653
4851
  srtcpIndex & 65535,
4654
4852
  srtcpIndex >> 16,
@@ -4689,6 +4887,11 @@ var CipherAesCtr = class extends CipherAesBase {
4689
4887
  }
4690
4888
  };
4691
4889
  var srtcpIndexSize = 4;
4890
+ function assertAuthTag(actual, expected, message) {
4891
+ if (actual.length !== expected.length || !timingSafeEqual(actual, expected)) {
4892
+ throw new SrtpAuthenticationError(message);
4893
+ }
4894
+ }
4692
4895
 
4693
4896
  // ../rtp/src/srtp/cipher/gcm.ts
4694
4897
  import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3 } from "crypto";
@@ -4711,20 +4914,25 @@ var CipherAesGcm = class extends CipherAesBase {
4711
4914
  const dst = Buffer.concat([hdr, enc, authTag]);
4712
4915
  return dst;
4713
4916
  }
4714
- decryptRtp(cipherText, rolloverCounter) {
4715
- const header = RtpHeader.deSerialize(cipherText);
4917
+ decryptRtp(cipherText, rolloverCounter, header = parseSrtpRtpHeader(cipherText, this.aeadAuthTagLen)) {
4918
+ const headerBuffer = cipherText.subarray(0, header.payloadOffset);
4919
+ const authTagOffset = cipherText.length - this.aeadAuthTagLen;
4920
+ const authTag = cipherText.subarray(authTagOffset);
4716
4921
  let dst = Buffer.from([]);
4717
4922
  dst = growBufferSize(dst, cipherText.length - this.aeadAuthTagLen);
4718
- cipherText.slice(0, header.payloadOffset).copy(dst);
4923
+ headerBuffer.copy(dst);
4719
4924
  const iv = this.rtpInitializationVector(header, rolloverCounter);
4720
- const enc = cipherText.slice(
4721
- header.payloadOffset,
4722
- cipherText.length - this.aeadAuthTagLen
4723
- );
4724
- const cipher = createDecipheriv3("aes-128-gcm", this.srtpSessionKey, iv);
4725
- const dec = cipher.update(enc);
4925
+ const enc = cipherText.slice(header.payloadOffset, authTagOffset);
4926
+ const decipher = createDecipheriv3("aes-128-gcm", this.srtpSessionKey, iv);
4927
+ decipher.setAAD(headerBuffer);
4928
+ decipher.setAuthTag(authTag);
4929
+ const dec = decipher.update(enc);
4930
+ finalizeAuthenticatedDecryption(decipher, "SRTP");
4726
4931
  dec.copy(dst, header.payloadOffset);
4727
- return [dst, header];
4932
+ return [
4933
+ dst,
4934
+ finalizeSrtpRtpHeader(header, dst, "Failed to authenticate SRTP packet")
4935
+ ];
4728
4936
  }
4729
4937
  encryptRTCP(rtcpPacket, srtcpIndex) {
4730
4938
  const ssrc = rtcpPacket.readUInt32BE(4);
@@ -4745,19 +4953,38 @@ var CipherAesGcm = class extends CipherAesBase {
4745
4953
  return dst;
4746
4954
  }
4747
4955
  decryptRTCP(encrypted) {
4748
- const header = RtcpHeader.deSerialize(encrypted);
4749
- const aadPos = encrypted.length - srtcpIndexSize2;
4750
- const dst = Buffer.alloc(aadPos - this.aeadAuthTagLen);
4751
- encrypted.slice(0, 8).copy(dst);
4956
+ const header = parseSrtcpHeader(
4957
+ encrypted,
4958
+ this.aeadAuthTagLen,
4959
+ srtcpIndexSize2
4960
+ );
4961
+ const srtcpIndexOffset = encrypted.length - srtcpIndexSize2;
4962
+ const authTagOffset = srtcpIndexOffset - this.aeadAuthTagLen;
4752
4963
  const ssrc = encrypted.readUInt32BE(4);
4753
- let srtcpIndex = encrypted.readUInt32BE(encrypted.length - 4);
4754
- srtcpIndex &= ~(rtcpEncryptionFlag << 24);
4964
+ const encodedSrtcpIndex = encrypted.readUInt32BE(srtcpIndexOffset);
4965
+ const isEncrypted = encodedSrtcpIndex >>> 31 === 1;
4966
+ const srtcpIndex = encodedSrtcpIndex & ~(rtcpEncryptionFlag << 24);
4755
4967
  const iv = this.rtcpInitializationVector(ssrc, srtcpIndex);
4756
- const aad = this.rtcpAdditionalAuthenticatedData(encrypted, srtcpIndex);
4757
- const cipher = createDecipheriv3("aes-128-gcm", this.srtcpSessionKey, iv);
4758
- cipher.setAAD(aad);
4759
- const dec = cipher.update(encrypted.slice(8, aadPos));
4760
- dec.copy(dst, 8);
4968
+ const aad = isEncrypted ? Buffer.concat([
4969
+ encrypted.subarray(0, 8),
4970
+ encrypted.subarray(srtcpIndexOffset)
4971
+ ]) : Buffer.concat([
4972
+ encrypted.subarray(0, authTagOffset),
4973
+ encrypted.subarray(srtcpIndexOffset)
4974
+ ]);
4975
+ const cipherText = isEncrypted ? encrypted.slice(8, authTagOffset) : Buffer.alloc(0);
4976
+ const dst = isEncrypted ? Buffer.alloc(authTagOffset) : Buffer.from(encrypted.subarray(0, authTagOffset));
4977
+ if (isEncrypted) {
4978
+ encrypted.slice(0, 8).copy(dst);
4979
+ }
4980
+ const decipher = createDecipheriv3("aes-128-gcm", this.srtcpSessionKey, iv);
4981
+ decipher.setAAD(aad);
4982
+ decipher.setAuthTag(encrypted.subarray(authTagOffset, srtcpIndexOffset));
4983
+ const dec = decipher.update(cipherText);
4984
+ finalizeAuthenticatedDecryption(decipher, "SRTCP");
4985
+ if (isEncrypted) {
4986
+ dec.copy(dst, 8);
4987
+ }
4761
4988
  return [dst, header];
4762
4989
  }
4763
4990
  // https://tools.ietf.org/html/rfc7714#section-8.1
@@ -4793,6 +5020,15 @@ var CipherAesGcm = class extends CipherAesBase {
4793
5020
  };
4794
5021
  var srtcpIndexSize2 = 4;
4795
5022
  var rtcpEncryptionFlag = 128;
5023
+ function finalizeAuthenticatedDecryption(decipher, packetType) {
5024
+ try {
5025
+ decipher.final();
5026
+ } catch {
5027
+ throw new SrtpAuthenticationError(
5028
+ `Failed to authenticate ${packetType} packet`
5029
+ );
5030
+ }
5031
+ }
4796
5032
 
4797
5033
  // ../rtp/src/srtp/context/context.ts
4798
5034
  var Context = class {
@@ -5050,12 +5286,29 @@ var SrtpContext2 = class extends Context {
5050
5286
  return enc;
5051
5287
  }
5052
5288
  decryptRtp(cipherText) {
5053
- const header = RtpHeader.deSerialize(cipherText);
5054
- const s = this.getSrtpSsrcState(header.ssrc);
5055
- this.updateRolloverCount(header.sequenceNumber, s);
5056
- const dec = this.cipher.decryptRtp(cipherText, s.rolloverCounter);
5289
+ const header = parseSrtpRtpHeader(cipherText, this.rtpAuthTagLength);
5290
+ const existingState = this.srtpSSRCStates[header.ssrc];
5291
+ const nextState = existingState ? { ...existingState } : {
5292
+ ssrc: header.ssrc,
5293
+ rolloverCounter: 0,
5294
+ lastSequenceNumber: 0
5295
+ };
5296
+ this.updateRolloverCount(header.sequenceNumber, nextState);
5297
+ const dec = this.cipher.decryptRtp(
5298
+ cipherText,
5299
+ nextState.rolloverCounter,
5300
+ header
5301
+ );
5302
+ if (existingState) {
5303
+ Object.assign(existingState, nextState);
5304
+ } else {
5305
+ this.srtpSSRCStates[header.ssrc] = nextState;
5306
+ }
5057
5307
  return dec;
5058
5308
  }
5309
+ get rtpAuthTagLength() {
5310
+ return this.profile === ProtectionProfileAeadAes128Gcm ? 16 : 10;
5311
+ }
5059
5312
  };
5060
5313
 
5061
5314
  // ../rtp/src/srtp/srtp.ts
@@ -5797,6 +6050,9 @@ var DtlsSocket = class {
5797
6050
  this.sessionType === SessionType.CLIENT
5798
6051
  );
5799
6052
  }
6053
+ get remoteCertificate() {
6054
+ return this.cipher.remoteCertificate;
6055
+ }
5800
6056
  };
5801
6057
 
5802
6058
  // ../dtls/src/client.ts
@@ -6185,6 +6441,16 @@ handlers2[16 /* client_key_exchange_16 */] = ({ cipher, dtls }) => (message) =>
6185
6441
  );
6186
6442
  log16(dtls.sessionId, "setup cipher", cipher.cipher.summary);
6187
6443
  };
6444
+ handlers2[11 /* certificate_11 */] = ({ cipher, dtls }) => (message) => {
6445
+ log16(dtls.sessionId, "handshake certificate", message);
6446
+ cipher.remoteCertificate = message.certificateList[0];
6447
+ };
6448
+ handlers2[15 /* certificate_verify_15 */] = ({ cipher, dtls }) => (message) => {
6449
+ if (!cipher.remoteCertificate) {
6450
+ throw new Error("client certificate missing before certificate verify");
6451
+ }
6452
+ log16(dtls.sessionId, "certificate_verify", message.algorithm);
6453
+ };
6188
6454
  handlers2[20 /* finished_20 */] = ({ dtls }) => (message) => {
6189
6455
  log16(dtls.sessionId, "finished", message);
6190
6456
  };
@@ -6251,7 +6517,14 @@ var DtlsServer = class extends DtlsSocket {
6251
6517
  {
6252
6518
  await this.waitForReady(() => !!this.flight6);
6253
6519
  this.flight6?.handleHandshake(handshake);
6254
- await this.waitForReady(() => this.dtls.checkHandshakesExist([16]));
6520
+ const requiredHandshakes = [
6521
+ 16,
6522
+ this.options.certificateRequest && 11,
6523
+ this.options.certificateRequest && 15
6524
+ ].filter((type) => typeof type === "number");
6525
+ await this.waitForReady(
6526
+ () => this.dtls.checkHandshakesExist(requiredHandshakes)
6527
+ );
6255
6528
  await this.flight6?.exec();
6256
6529
  this.connected = true;
6257
6530
  this.onConnect.execute();
@@ -6320,7 +6593,6 @@ var methods = /* @__PURE__ */ ((methods2) => {
6320
6593
 
6321
6594
  // ../ice/src/stun/message.ts
6322
6595
  import { createHmac as createHmac4 } from "crypto";
6323
- import crc32 from "buffer-crc32";
6324
6596
 
6325
6597
  // ../ice/src/helper.ts
6326
6598
  import { randomBytes as randomBytes5 } from "crypto";
@@ -6330,19 +6602,6 @@ function randomString(length) {
6330
6602
  function randomTransactionId() {
6331
6603
  return randomBytes5(12);
6332
6604
  }
6333
- function bufferXor2(a, b) {
6334
- if (a.length !== b.length) {
6335
- throw new TypeError(
6336
- "[webrtc-stun] You can not XOR buffers which length are different"
6337
- );
6338
- }
6339
- const length = a.length;
6340
- const buffer2 = Buffer.allocUnsafe(length);
6341
- for (let i = 0; i < length; i++) {
6342
- buffer2[i] = a[i] ^ b[i];
6343
- }
6344
- return buffer2;
6345
- }
6346
6605
  var PQueue = class {
6347
6606
  queue = [];
6348
6607
  wait = new Event();
@@ -6676,11 +6935,7 @@ function messageFingerprint(data) {
6676
6935
  data,
6677
6936
  data.length - HEADER_LENGTH + FINGERPRINT_LENGTH
6678
6937
  );
6679
- const crc32Buf = crc32(checkData);
6680
- const xorBuf = Buffer.alloc(4);
6681
- xorBuf.writeInt32BE(FINGERPRINT_XOR, 0);
6682
- const fingerprint2 = bufferXor2(crc32Buf, xorBuf);
6683
- return fingerprint2.readUInt32BE(0);
6938
+ return (crc32(checkData) ^ FINGERPRINT_XOR) >>> 0;
6684
6939
  }
6685
6940
  function messageIntegrity(data, key) {
6686
6941
  const checkData = setBodyLength(
@@ -8519,6 +8774,9 @@ var EventTarget = class extends EventEmitter {
8519
8774
 
8520
8775
  // src/dataChannel.ts
8521
8776
  var log23 = debug("werift:packages/webrtc/src/dataChannel.ts");
8777
+ function getDataChannelMessageSize(data) {
8778
+ return Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data);
8779
+ }
8522
8780
  var RTCDataChannel = class extends EventTarget {
8523
8781
  constructor(sctp, parameters, sendOpen = true) {
8524
8782
  super();
@@ -8624,10 +8882,9 @@ var RTCDataChannel = class extends EventTarget {
8624
8882
  }
8625
8883
  }
8626
8884
  send(data) {
8627
- const size = Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data);
8885
+ const size = this.sctp.datachannelSend(this, data);
8628
8886
  this.messagesSent++;
8629
8887
  this.bytesSent += size;
8630
- this.sctp.datachannelSend(this, data);
8631
8888
  }
8632
8889
  close() {
8633
8890
  this.sctp.dataChannelClose(this);
@@ -9082,6 +9339,24 @@ function fingerprint(file, hashName) {
9082
9339
  const hash2 = createHash4(hashName).update(file).digest("hex");
9083
9340
  return colon(upper(hash2));
9084
9341
  }
9342
+ var fingerprintHashAlgorithms = {
9343
+ sha1: "sha1",
9344
+ "sha-1": "sha1",
9345
+ sha224: "sha224",
9346
+ "sha-224": "sha224",
9347
+ sha256: "sha256",
9348
+ "sha-256": "sha256",
9349
+ sha384: "sha384",
9350
+ "sha-384": "sha384",
9351
+ sha512: "sha512",
9352
+ "sha-512": "sha512"
9353
+ };
9354
+ function normalizeFingerprintAlgorithm(algorithm) {
9355
+ return fingerprintHashAlgorithms[algorithm.trim().toLowerCase()];
9356
+ }
9357
+ function normalizeFingerprintValue(value) {
9358
+ return value.replace(/[^0-9a-f]/gi, "").toLowerCase();
9359
+ }
9085
9360
  function isDtls(buf) {
9086
9361
  const firstByte = buf[0];
9087
9362
  return firstByte > 19 && firstByte < 64;
@@ -9538,13 +9813,18 @@ var RTCDtlsTransport = class _RTCDtlsTransport {
9538
9813
  return this.localCertificatePromise;
9539
9814
  }
9540
9815
  setRemoteParams(remoteParameters) {
9541
- this.remoteParameters = remoteParameters;
9816
+ const fingerprints = deduplicateFingerprints([
9817
+ ...this.remoteParameters?.fingerprints ?? [],
9818
+ ...remoteParameters.fingerprints
9819
+ ]);
9820
+ const role = remoteParameters.role === "auto" && this.remoteParameters?.role ? this.remoteParameters.role : remoteParameters.role;
9821
+ this.remoteParameters = new RTCDtlsParameters(fingerprints, role);
9542
9822
  }
9543
9823
  async start() {
9544
9824
  if (this.state !== "new") {
9545
9825
  throw new Error("state must be new");
9546
9826
  }
9547
- if (this.remoteParameters?.fingerprints.length === 0) {
9827
+ if (!this.remoteParameters || this.remoteParameters.fingerprints.length === 0) {
9548
9828
  throw new Error("remote fingerprint not exist");
9549
9829
  }
9550
9830
  if (this.role === "auto") {
@@ -9563,8 +9843,8 @@ var RTCDtlsTransport = class _RTCDtlsTransport {
9563
9843
  signatureHash: this.localCertificate?.signatureHash,
9564
9844
  transport: createIceTransport(this.iceTransport.connection),
9565
9845
  srtpProfiles: this.srtpProfiles,
9566
- extendedMasterSecret: true
9567
- // certificateRequest: true,
9846
+ extendedMasterSecret: true,
9847
+ certificateRequest: true
9568
9848
  });
9569
9849
  } else {
9570
9850
  this.dtls = new DtlsClient({
@@ -9583,7 +9863,9 @@ var RTCDtlsTransport = class _RTCDtlsTransport {
9583
9863
  this.dataReceiver(buf);
9584
9864
  });
9585
9865
  this.dtls.onClose.subscribe(() => {
9586
- this.setState("closed");
9866
+ if (this.state !== "failed") {
9867
+ this.setState("closed");
9868
+ }
9587
9869
  });
9588
9870
  this.dtls.onConnect.once(r);
9589
9871
  this.dtls.onError.once((error) => {
@@ -9600,16 +9882,70 @@ var RTCDtlsTransport = class _RTCDtlsTransport {
9600
9882
  });
9601
9883
  }
9602
9884
  });
9885
+ try {
9886
+ this.verifyRemoteCertificateFingerprint();
9887
+ } catch (error) {
9888
+ this.setState("failed");
9889
+ this.dtls?.close();
9890
+ throw error;
9891
+ }
9603
9892
  if (this.srtpProfiles.length > 0) {
9604
9893
  this.startSrtp();
9605
9894
  }
9606
- this.dtls.onConnect.subscribe(() => {
9607
- this.updateSrtpSession();
9608
- this.setState("connected");
9609
- });
9610
9895
  this.setState("connected");
9611
9896
  log27("dtls connected");
9612
9897
  }
9898
+ verifyRemoteCertificateFingerprint() {
9899
+ if (!this.remoteParameters || this.remoteParameters.fingerprints.length === 0) {
9900
+ throw new Error("remote fingerprint not exist");
9901
+ }
9902
+ const remoteCertificate = this.dtls?.remoteCertificate;
9903
+ if (!remoteCertificate) {
9904
+ throw new Error("remote certificate not available");
9905
+ }
9906
+ const supportedFingerprints = this.remoteParameters.fingerprints.flatMap(
9907
+ ({ algorithm, value }) => {
9908
+ const normalizedAlgorithm = normalizeFingerprintAlgorithm(algorithm);
9909
+ if (!normalizedAlgorithm) {
9910
+ return [];
9911
+ }
9912
+ const normalizedValue = normalizeFingerprintValue(value);
9913
+ if (!normalizedValue) {
9914
+ throw new Error("remote fingerprint value is empty");
9915
+ }
9916
+ return [{ normalizedAlgorithm, normalizedValue }];
9917
+ }
9918
+ );
9919
+ if (supportedFingerprints.length === 0) {
9920
+ throw new Error("no supported remote fingerprint algorithms");
9921
+ }
9922
+ const preferredAlgorithm = selectPreferredFingerprintAlgorithm(
9923
+ supportedFingerprints
9924
+ );
9925
+ const expectedFingerprints = supportedFingerprints.filter(
9926
+ ({ normalizedAlgorithm }) => normalizedAlgorithm === preferredAlgorithm
9927
+ );
9928
+ const actualFingerprints = expectedFingerprints.reduce(
9929
+ (acc, { normalizedAlgorithm }) => {
9930
+ if (!acc.has(normalizedAlgorithm)) {
9931
+ acc.set(
9932
+ normalizedAlgorithm,
9933
+ normalizeFingerprintValue(
9934
+ fingerprint(remoteCertificate, normalizedAlgorithm)
9935
+ )
9936
+ );
9937
+ }
9938
+ return acc;
9939
+ },
9940
+ /* @__PURE__ */ new Map()
9941
+ );
9942
+ const matched = expectedFingerprints.some(
9943
+ ({ normalizedAlgorithm, normalizedValue }) => actualFingerprints.get(normalizedAlgorithm) === normalizedValue
9944
+ );
9945
+ if (!matched) {
9946
+ throw new Error("remote certificate fingerprint mismatch");
9947
+ }
9948
+ }
9613
9949
  updateSrtpSession() {
9614
9950
  if (!this.dtls) throw new Error();
9615
9951
  const profile = this.dtls.srtp.srtpProfile;
@@ -9642,8 +9978,23 @@ var RTCDtlsTransport = class _RTCDtlsTransport {
9642
9978
  this.bytesReceived += data.length;
9643
9979
  this.packetsReceived++;
9644
9980
  if (isRtcp(data)) {
9645
- const dec = this.srtcp.decrypt(data);
9646
- const rtcpPackets = RtcpPacketConverter.deSerialize(dec);
9981
+ let dec;
9982
+ try {
9983
+ dec = this.srtcp.decrypt(data);
9984
+ } catch (error) {
9985
+ if (error instanceof SrtpAuthenticationError) {
9986
+ log27("dropping invalid SRTCP packet", error);
9987
+ return;
9988
+ }
9989
+ throw error;
9990
+ }
9991
+ let rtcpPackets;
9992
+ try {
9993
+ rtcpPackets = RtcpPacketConverter.deSerialize(dec);
9994
+ } catch (error) {
9995
+ log27("dropping malformed SRTCP packet", error);
9996
+ return;
9997
+ }
9647
9998
  for (const rtcp of rtcpPackets) {
9648
9999
  try {
9649
10000
  this.onRtcp.execute(rtcp);
@@ -9652,8 +10003,23 @@ var RTCDtlsTransport = class _RTCDtlsTransport {
9652
10003
  }
9653
10004
  }
9654
10005
  } else {
9655
- const dec = this.srtp.decrypt(data);
9656
- const rtp = RtpPacket.deSerialize(dec);
10006
+ let dec;
10007
+ try {
10008
+ dec = this.srtp.decrypt(data);
10009
+ } catch (error) {
10010
+ if (error instanceof SrtpAuthenticationError) {
10011
+ log27("dropping invalid SRTP packet", error);
10012
+ return;
10013
+ }
10014
+ throw error;
10015
+ }
10016
+ let rtp;
10017
+ try {
10018
+ rtp = RtpPacket.deSerialize(dec);
10019
+ } catch (error) {
10020
+ log27("dropping malformed SRTP packet", error);
10021
+ return;
10022
+ }
9657
10023
  try {
9658
10024
  this.onRtp.execute(rtp);
9659
10025
  } catch (error) {
@@ -9806,6 +10172,31 @@ var RTCDtlsParameters = class {
9806
10172
  this.role = role;
9807
10173
  }
9808
10174
  };
10175
+ var deduplicateFingerprints = (fingerprints) => {
10176
+ const seen = /* @__PURE__ */ new Set();
10177
+ return fingerprints.filter(({ algorithm, value }) => {
10178
+ const key = `${normalizeFingerprintAlgorithm(algorithm) ?? algorithm.trim().toLowerCase()}:${normalizeFingerprintValue(value)}`;
10179
+ if (seen.has(key)) {
10180
+ return false;
10181
+ }
10182
+ seen.add(key);
10183
+ return true;
10184
+ });
10185
+ };
10186
+ var preferredFingerprintAlgorithms = [
10187
+ "sha512",
10188
+ "sha384",
10189
+ "sha256",
10190
+ "sha224",
10191
+ "sha1"
10192
+ ];
10193
+ var selectPreferredFingerprintAlgorithm = (fingerprints) => {
10194
+ return preferredFingerprintAlgorithms.find(
10195
+ (algorithm) => fingerprints.some(
10196
+ ({ normalizedAlgorithm }) => normalizedAlgorithm === algorithm
10197
+ )
10198
+ ) ?? fingerprints[0].normalizedAlgorithm;
10199
+ };
9809
10200
  var IceTransport = class {
9810
10201
  constructor(ice) {
9811
10202
  this.ice = ice;
@@ -10173,7 +10564,6 @@ import { createHmac as createHmac5, randomBytes as randomBytes7 } from "crypto";
10173
10564
  import { jspack as jspack5 } from "@shinyoshiaki/jspack";
10174
10565
 
10175
10566
  // ../sctp/src/chunk.ts
10176
- import crc32c from "turbo-crc32/crc32c.js";
10177
10567
  var Chunk = class _Chunk {
10178
10568
  constructor(flags = 0, _body = Buffer.from("")) {
10179
10569
  this.flags = flags;
@@ -10737,6 +11127,8 @@ var SCTP_RTO_INITIAL = 3;
10737
11127
  var SCTP_RTO_MIN = 1;
10738
11128
  var SCTP_RTO_MAX = 60;
10739
11129
  var SCTP_TSN_MODULO = 2 ** 32;
11130
+ var SCTP_SACK_DELAY_MS = 200;
11131
+ var SCTP_HEARTBEAT_INTERVAL = 30;
10740
11132
  var RECONFIG_MAX_STREAMS = 135;
10741
11133
  var SCTP_STATE_COOKIE = 7;
10742
11134
  var SCTP_SUPPORTED_CHUNK_EXT = 32776;
@@ -10768,6 +11160,8 @@ var SCTP = class _SCTP {
10768
11160
  started = false;
10769
11161
  state = "new";
10770
11162
  isServer = true;
11163
+ isStopping = false;
11164
+ isClosed = false;
10771
11165
  hmacKey = randomBytes7(16);
10772
11166
  localPartialReliability = true;
10773
11167
  localPort;
@@ -10779,6 +11173,10 @@ var SCTP = class _SCTP {
10779
11173
  // inbound
10780
11174
  advertisedRwnd = 1024 * 1024;
10781
11175
  // Receiver Window
11176
+ peerAdvertisedRwnd = this.advertisedRwnd;
11177
+ get peerRwnd() {
11178
+ return Math.max(0, this.peerAdvertisedRwnd - this.flightSize);
11179
+ }
10782
11180
  inboundStreams = {};
10783
11181
  _inboundStreamsCount = 0;
10784
11182
  _inboundStreamsMax = MAX_STREAMS;
@@ -10787,6 +11185,9 @@ var SCTP = class _SCTP {
10787
11185
  sackDuplicates = [];
10788
11186
  sackMisOrdered = /* @__PURE__ */ new Set();
10789
11187
  sackNeeded = false;
11188
+ sackPacketCount = 0;
11189
+ sackHasNewDataInPacket = false;
11190
+ sackImmediate = false;
10790
11191
  sackTimeout;
10791
11192
  // # outbound
10792
11193
  cwnd = 3 * USERDATA_MAX_LENGTH;
@@ -10805,6 +11206,8 @@ var SCTP = class _SCTP {
10805
11206
  // acknowledgement
10806
11207
  partialBytesAcked = 0;
10807
11208
  sentQueue = [];
11209
+ transmitting = false;
11210
+ transmitRequested = false;
10808
11211
  // # reconfiguration
10809
11212
  /**初期TSNと同じ値に初期化される単調に増加する数です. これは、新しいre-configuration requestパラメーターを送信するたびに1ずつ増加します */
10810
11213
  reconfigRequestSeq = this.localTsn;
@@ -10830,8 +11233,13 @@ var SCTP = class _SCTP {
10830
11233
  /**Re-configuration Timer */
10831
11234
  timerReconfigHandle;
10832
11235
  timerReconfigFailures = 0;
11236
+ timerHeartbeatHandle;
11237
+ heartbeatInterval = SCTP_HEARTBEAT_INTERVAL;
10833
11238
  // etc
10834
11239
  ssthresh;
11240
+ get isStopped() {
11241
+ return this.isStopping || this.isClosed;
11242
+ }
10835
11243
  get maxChannels() {
10836
11244
  if (this._inboundStreamsCount > 0) {
10837
11245
  return Math.min(this._inboundStreamsCount, this._outboundStreamsCount);
@@ -10850,6 +11258,7 @@ var SCTP = class _SCTP {
10850
11258
  }
10851
11259
  // call from dtls transport
10852
11260
  async handleData(data) {
11261
+ if (this.isStopped) return;
10853
11262
  let expectedTag;
10854
11263
  const [, , verificationTag, chunks] = parsePacket2(data);
10855
11264
  const initChunk = chunks.filter((v) => v.type === InitChunk.type).length;
@@ -10864,17 +11273,41 @@ var SCTP = class _SCTP {
10864
11273
  if (verificationTag !== expectedTag) {
10865
11274
  return;
10866
11275
  }
11276
+ this.sackHasNewDataInPacket = false;
10867
11277
  for (const chunk of chunks) {
10868
11278
  await this.receiveChunk(chunk);
10869
11279
  }
10870
11280
  if (this.sackNeeded) {
11281
+ if (this.sackHasNewDataInPacket) {
11282
+ this.sackPacketCount++;
11283
+ }
11284
+ if (this.sackPacketCount >= 2) {
11285
+ this.sackImmediate = true;
11286
+ }
11287
+ await this.scheduleSack();
11288
+ }
11289
+ }
11290
+ async scheduleSack() {
11291
+ if (this.isStopped) return;
11292
+ if (!this.sackNeeded) return;
11293
+ if (this.sackImmediate) {
11294
+ if (this.sackTimeout) {
11295
+ clearTimeout(this.sackTimeout);
11296
+ this.sackTimeout = void 0;
11297
+ }
10871
11298
  await this.sendSack();
11299
+ return;
10872
11300
  }
11301
+ if (this.sackTimeout) return;
11302
+ this.sackTimeout = setTimeout(() => {
11303
+ this.sackTimeout = void 0;
11304
+ this.sendSack().catch((err5) => {
11305
+ log29("send delayed sack failed", err5.message);
11306
+ });
11307
+ }, SCTP_SACK_DELAY_MS);
10873
11308
  }
10874
11309
  async sendSack() {
10875
- if (this.sackTimeout) return;
10876
- await new Promise((r) => this.sackTimeout = setImmediate(r));
10877
- this.sackTimeout = void 0;
11310
+ if (this.isStopped) return;
10878
11311
  if (!this.sackNeeded) return;
10879
11312
  const gaps = [];
10880
11313
  let gapNext;
@@ -10897,6 +11330,8 @@ var SCTP = class _SCTP {
10897
11330
  });
10898
11331
  this.sackDuplicates = [];
10899
11332
  this.sackNeeded = false;
11333
+ this.sackPacketCount = 0;
11334
+ this.sackImmediate = false;
10900
11335
  }
10901
11336
  async receiveChunk(chunk) {
10902
11337
  switch (chunk.type) {
@@ -10914,6 +11349,7 @@ var SCTP = class _SCTP {
10914
11349
  this.reconfigResponseSeq = tsnMinusOne(init.initialTsn);
10915
11350
  this.remoteVerificationTag = init.initiateTag;
10916
11351
  this.ssthresh = init.advertisedRwnd;
11352
+ this.peerAdvertisedRwnd = init.advertisedRwnd;
10917
11353
  this.getExtensions(init.params);
10918
11354
  this._inboundStreamsCount = Math.min(
10919
11355
  init.outboundStreams,
@@ -10952,6 +11388,7 @@ var SCTP = class _SCTP {
10952
11388
  this.reconfigResponseSeq = tsnMinusOne(initAck.initialTsn);
10953
11389
  this.remoteVerificationTag = initAck.initiateTag;
10954
11390
  this.ssthresh = initAck.advertisedRwnd;
11391
+ this.peerAdvertisedRwnd = initAck.advertisedRwnd;
10955
11392
  this.getExtensions(initAck.params);
10956
11393
  this._inboundStreamsCount = Math.min(
10957
11394
  initAck.outboundStreams,
@@ -11149,7 +11586,18 @@ var SCTP = class _SCTP {
11149
11586
  }
11150
11587
  receiveDataChunk(chunk) {
11151
11588
  this.sackNeeded = true;
11152
- if (this.markReceived(chunk.tsn)) return;
11589
+ if (this.markReceived(chunk.tsn)) {
11590
+ this.sackImmediate = true;
11591
+ return;
11592
+ }
11593
+ this.sackHasNewDataInPacket = true;
11594
+ this.sackImmediate = true;
11595
+ if ((chunk.flags & SCTP_DATA_LAST_FRAG) === 0) {
11596
+ this.sackImmediate = true;
11597
+ }
11598
+ if (this.sackMisOrdered.size > 0) {
11599
+ this.sackImmediate = true;
11600
+ }
11153
11601
  const inboundStream = this.getInboundStream(chunk.streamId);
11154
11602
  inboundStream.addChunk(chunk);
11155
11603
  this.advertisedRwnd -= chunk.userData.length;
@@ -11248,12 +11696,14 @@ var SCTP = class _SCTP {
11248
11696
  } else if (done > 0) {
11249
11697
  this.timer3Restart();
11250
11698
  }
11699
+ this.peerAdvertisedRwnd = chunk.advertisedRwnd;
11251
11700
  this.updateAdvancedPeerAckPoint();
11252
11701
  await this.onSackReceived();
11253
11702
  await this.transmit();
11254
11703
  }
11255
11704
  receiveForwardTsnChunk(chunk) {
11256
11705
  this.sackNeeded = true;
11706
+ this.sackImmediate = true;
11257
11707
  if (uint32Gte(this.lastReceivedTsn, chunk.cumulativeTsn)) {
11258
11708
  return;
11259
11709
  }
@@ -11360,17 +11810,29 @@ var SCTP = class _SCTP {
11360
11810
  if (ordered) {
11361
11811
  this.outboundStreamSeq[streamId] = uint16Add(streamSeqNum, 1);
11362
11812
  }
11363
- if (!this.timer3Handle) {
11364
- await this.transmit();
11365
- } else {
11366
- if (this.outboundQueue.length) {
11367
- await this.flush.asPromise();
11368
- } else {
11369
- await new Promise((r) => setImmediate(r));
11370
- }
11813
+ await this.transmit();
11814
+ while (this.outboundQueue.length) {
11815
+ await this.flush.asPromise();
11371
11816
  }
11372
11817
  };
11373
11818
  async transmit() {
11819
+ if (this.isStopped) return;
11820
+ if (this.transmitting) {
11821
+ this.transmitRequested = true;
11822
+ return;
11823
+ }
11824
+ this.transmitting = true;
11825
+ try {
11826
+ do {
11827
+ this.transmitRequested = false;
11828
+ await this.transmitOnce();
11829
+ } while (this.transmitRequested);
11830
+ } finally {
11831
+ this.transmitting = false;
11832
+ }
11833
+ }
11834
+ async transmitOnce() {
11835
+ if (this.isStopped) return;
11374
11836
  if (this.forwardTsnChunk) {
11375
11837
  await this.sendChunk(this.forwardTsnChunk).catch((err5) => {
11376
11838
  log29("send forwardTsn failed", err5.message);
@@ -11388,7 +11850,7 @@ var SCTP = class _SCTP {
11388
11850
  if (this.fastRecoveryTransmit) {
11389
11851
  this.fastRecoveryTransmit = false;
11390
11852
  } else if (this.flightSize >= cwnd) {
11391
- return;
11853
+ break;
11392
11854
  }
11393
11855
  this.flightSizeIncrease(dataChunk);
11394
11856
  dataChunk.misses = 0;
@@ -11403,9 +11865,13 @@ var SCTP = class _SCTP {
11403
11865
  }
11404
11866
  retransmitEarliest = false;
11405
11867
  }
11406
- while (this.outboundQueue.length > 0) {
11868
+ while (this.outboundQueue.length > 0 && this.flightSize < cwnd && this.peerRwnd > 0) {
11407
11869
  const chunk = this.outboundQueue.shift();
11408
- if (!chunk) return;
11870
+ if (!chunk) break;
11871
+ if (chunk.bookSize > this.peerRwnd && this.flightSize > 0) {
11872
+ this.outboundQueue.unshift(chunk);
11873
+ break;
11874
+ }
11409
11875
  this.sentQueue.push(chunk);
11410
11876
  this.flightSizeIncrease(chunk);
11411
11877
  chunk.sentCount++;
@@ -11417,7 +11883,9 @@ var SCTP = class _SCTP {
11417
11883
  this.timer3Start();
11418
11884
  }
11419
11885
  }
11420
- this.outboundQueue = [];
11886
+ if (!this.outboundQueue.length) {
11887
+ this.outboundQueue = [];
11888
+ }
11421
11889
  this.flush.execute();
11422
11890
  }
11423
11891
  async transmitReconfigRequest() {
@@ -11470,16 +11938,19 @@ var SCTP = class _SCTP {
11470
11938
  this.timer1Handle = setTimeout(this.timer1Expired, this.rto * 1e3);
11471
11939
  }
11472
11940
  timer1Expired = () => {
11941
+ if (this.isStopped) return;
11473
11942
  this.timer1Failures++;
11474
11943
  this.timer1Handle = void 0;
11475
11944
  if (this.timer1Failures > SCTP_MAX_INIT_RETRANS) {
11476
11945
  this.setState(1 /* CLOSED */);
11477
11946
  } else {
11478
11947
  setImmediate(() => {
11948
+ if (this.isStopped) return;
11479
11949
  this.sendChunk(this.timer1Chunk).catch((err5) => {
11480
11950
  log29("send timer1 chunk failed", err5.message);
11481
11951
  });
11482
11952
  });
11953
+ if (this.isStopped) return;
11483
11954
  this.timer1Handle = setTimeout(this.timer1Expired, this.rto * 1e3);
11484
11955
  }
11485
11956
  };
@@ -11498,16 +11969,19 @@ var SCTP = class _SCTP {
11498
11969
  this.timer2Handle = setTimeout(this.timer2Expired, this.rto * 1e3);
11499
11970
  }
11500
11971
  timer2Expired = () => {
11972
+ if (this.isStopped) return;
11501
11973
  this.timer2Failures++;
11502
11974
  this.timer2Handle = void 0;
11503
11975
  if (this.timer2Failures > SCTP_MAX_ASSOCIATION_RETRANS) {
11504
11976
  this.setState(1 /* CLOSED */);
11505
11977
  } else {
11506
11978
  setImmediate(() => {
11979
+ if (this.isStopped) return;
11507
11980
  this.sendChunk(this.timer2Chunk).catch((err5) => {
11508
11981
  log29("send timer2Chunk failed", err5.message);
11509
11982
  });
11510
11983
  });
11984
+ if (this.isStopped) return;
11511
11985
  this.timer2Handle = setTimeout(this.timer2Expired, this.rto * 1e3);
11512
11986
  }
11513
11987
  };
@@ -11520,14 +11994,17 @@ var SCTP = class _SCTP {
11520
11994
  }
11521
11995
  /**t3 is wait for data sack */
11522
11996
  timer3Start() {
11997
+ if (this.isStopped) return;
11523
11998
  if (this.timer3Handle) throw new Error();
11524
11999
  this.timer3Handle = setTimeout(this.timer3Expired, this.rto * 1e3);
11525
12000
  }
11526
12001
  timer3Restart() {
12002
+ if (this.isStopped) return;
11527
12003
  this.timer3Cancel();
11528
- this.timer3Handle = setTimeout(this.timer3Expired, this.rto);
12004
+ this.timer3Handle = setTimeout(this.timer3Expired, this.rto * 1e3);
11529
12005
  }
11530
12006
  timer3Expired = () => {
12007
+ if (this.isStopped) return;
11531
12008
  this.timer3Handle = void 0;
11532
12009
  this.sentQueue.forEach((chunk) => {
11533
12010
  if (!this.maybeAbandon(chunk)) {
@@ -11553,6 +12030,7 @@ var SCTP = class _SCTP {
11553
12030
  }
11554
12031
  /**Re-configuration Timer */
11555
12032
  timerReconfigHandleStart() {
12033
+ if (this.isStopped) return;
11556
12034
  if (this.timerReconfigHandle) return;
11557
12035
  log29("timerReconfigHandleStart", { rto: this.rto });
11558
12036
  this.timerReconfigFailures = 0;
@@ -11562,6 +12040,7 @@ var SCTP = class _SCTP {
11562
12040
  );
11563
12041
  }
11564
12042
  timerReconfigHandleExpired = async () => {
12043
+ if (this.isStopped) return;
11565
12044
  this.timerReconfigFailures++;
11566
12045
  this.rto = Math.ceil(this.rto * 1.5);
11567
12046
  if (this.timerReconfigFailures > SCTP_MAX_ASSOCIATION_RETRANS) {
@@ -11571,6 +12050,7 @@ var SCTP = class _SCTP {
11571
12050
  } else if (this.reconfigRequest) {
11572
12051
  log29("timerReconfigHandleExpired", this.timerReconfigFailures, this.rto);
11573
12052
  await this.sendReconfigParam(this.reconfigRequest);
12053
+ if (this.isStopped) return;
11574
12054
  this.timerReconfigHandle = setTimeout(
11575
12055
  this.timerReconfigHandleExpired,
11576
12056
  this.rto * 1e3
@@ -11585,6 +12065,47 @@ var SCTP = class _SCTP {
11585
12065
  this.timerReconfigFailures = 0;
11586
12066
  }
11587
12067
  }
12068
+ heartbeatStart() {
12069
+ if (this.timerHeartbeatHandle || this.associationState !== 4 /* ESTABLISHED */) {
12070
+ return;
12071
+ }
12072
+ this.timerHeartbeatHandle = setTimeout(
12073
+ this.timerHeartbeatExpired,
12074
+ (this.rto + this.heartbeatInterval) * 1e3
12075
+ );
12076
+ }
12077
+ heartbeatRestart() {
12078
+ this.heartbeatCancel();
12079
+ this.heartbeatStart();
12080
+ }
12081
+ heartbeatCancel() {
12082
+ if (this.timerHeartbeatHandle) {
12083
+ clearTimeout(this.timerHeartbeatHandle);
12084
+ this.timerHeartbeatHandle = void 0;
12085
+ }
12086
+ }
12087
+ timerHeartbeatExpired = async () => {
12088
+ this.timerHeartbeatHandle = void 0;
12089
+ if (this.associationState !== 4 /* ESTABLISHED */) return;
12090
+ if (this.flightSize === 0 && this.outboundQueue.length === 0) {
12091
+ const heartbeat = new HeartbeatChunk();
12092
+ heartbeat.params.push([
12093
+ 1,
12094
+ Buffer.from(jspack5.Pack("!L", [Math.floor(Date.now() / 1e3)]))
12095
+ ]);
12096
+ await this.sendChunk(heartbeat).catch((err5) => {
12097
+ log29("send heartbeat failed", err5.message);
12098
+ });
12099
+ }
12100
+ this.heartbeatStart();
12101
+ };
12102
+ setHeartbeatInterval(interval) {
12103
+ if (interval <= 0) {
12104
+ throw new Error("heartbeat interval must be > 0");
12105
+ }
12106
+ this.heartbeatInterval = interval;
12107
+ this.heartbeatRestart();
12108
+ }
11588
12109
  updateAdvancedPeerAckPoint() {
11589
12110
  if (uint32Gt(this.lastSackedTsn, this.advancedPeerAckTsn)) {
11590
12111
  this.advancedPeerAckTsn = this.lastSackedTsn;
@@ -11696,12 +12217,21 @@ var SCTP = class _SCTP {
11696
12217
  this.associationState = state;
11697
12218
  }
11698
12219
  if (state === 4 /* ESTABLISHED */) {
12220
+ this.isStopping = false;
12221
+ this.isClosed = false;
11699
12222
  this.setConnectionState("connected");
12223
+ this.heartbeatStart();
11700
12224
  } else if (state === 1 /* CLOSED */) {
12225
+ this.isClosed = true;
11701
12226
  this.timer1Cancel();
11702
12227
  this.timer2Cancel();
11703
12228
  this.timer3Cancel();
11704
12229
  this.timerReconfigCancel();
12230
+ this.heartbeatCancel();
12231
+ if (this.sackTimeout) {
12232
+ clearTimeout(this.sackTimeout);
12233
+ this.sackTimeout = void 0;
12234
+ }
11705
12235
  this.setConnectionState("closed");
11706
12236
  this.removeAllListeners();
11707
12237
  }
@@ -11712,6 +12242,16 @@ var SCTP = class _SCTP {
11712
12242
  this.stateChanged[state].execute();
11713
12243
  }
11714
12244
  async stop() {
12245
+ if (this.isStopped) {
12246
+ this.setState(1 /* CLOSED */);
12247
+ return;
12248
+ }
12249
+ this.isStopping = true;
12250
+ this.transport.onData = void 0;
12251
+ if (this.sackTimeout) {
12252
+ clearTimeout(this.sackTimeout);
12253
+ this.sackTimeout = void 0;
12254
+ }
11715
12255
  if (this.associationState !== 1 /* CLOSED */) {
11716
12256
  await this.abort();
11717
12257
  }
@@ -11720,6 +12260,8 @@ var SCTP = class _SCTP {
11720
12260
  clearTimeout(this.timer2Handle);
11721
12261
  clearTimeout(this.timer3Handle);
11722
12262
  clearTimeout(this.timerReconfigHandle);
12263
+ clearTimeout(this.timerHeartbeatHandle);
12264
+ clearTimeout(this.sackTimeout);
11723
12265
  }
11724
12266
  async abort() {
11725
12267
  const abort = new AbortChunk();
@@ -11832,9 +12374,11 @@ function tsnPlusOne(a) {
11832
12374
 
11833
12375
  // src/transport/sctp.ts
11834
12376
  var log30 = debug("werift:packages/webrtc/src/transport/sctp.ts");
11835
- var RTCSctpTransport = class {
11836
- constructor(port = 5e3) {
12377
+ var DEFAULT_MAX_MESSAGE_SIZE = 65536;
12378
+ var RTCSctpTransport = class _RTCSctpTransport {
12379
+ constructor(port = 5e3, maxMessageSize = DEFAULT_MAX_MESSAGE_SIZE) {
11837
12380
  this.port = port;
12381
+ this.maxMessageSize = maxMessageSize;
11838
12382
  }
11839
12383
  dtlsTransport;
11840
12384
  sctp;
@@ -11844,6 +12388,7 @@ var RTCSctpTransport = class {
11844
12388
  mLineIndex;
11845
12389
  bundled = false;
11846
12390
  dataChannels = {};
12391
+ remoteMaxMessageSize = DEFAULT_MAX_MESSAGE_SIZE;
11847
12392
  dataChannelQueue = [];
11848
12393
  dataChannelId;
11849
12394
  eventDisposer = [];
@@ -12045,7 +12590,6 @@ var RTCSctpTransport = class {
12045
12590
  }
12046
12591
  async dataChannelFlush() {
12047
12592
  if (this.sctp.associationState != 4 /* ESTABLISHED */) return;
12048
- if (this.sctp.outboundQueue.length > 0) return;
12049
12593
  while (this.dataChannelQueue.length > 0) {
12050
12594
  const [channel, protocol, userData] = this.dataChannelQueue.shift();
12051
12595
  let streamId = channel.id;
@@ -12073,18 +12617,35 @@ var RTCSctpTransport = class {
12073
12617
  }
12074
12618
  this.dataChannelQueue = [];
12075
12619
  }
12620
+ assertSendableMessageSize(size) {
12621
+ if (this.remoteMaxMessageSize !== 0 && size > this.remoteMaxMessageSize) {
12622
+ throw new Error(
12623
+ `max-message-size exceeded: ${size} > ${this.remoteMaxMessageSize}`
12624
+ );
12625
+ }
12626
+ }
12076
12627
  datachannelSend = (channel, data) => {
12077
- channel.addBufferedAmount(data.length);
12628
+ const userData = Buffer.isBuffer(data) ? data : Buffer.from(data);
12629
+ const size = getDataChannelMessageSize(data);
12630
+ this.assertSendableMessageSize(size);
12631
+ channel.addBufferedAmount(size);
12078
12632
  this.dataChannelQueue.push(
12079
- typeof data === "string" ? [channel, WEBRTC_STRING, Buffer.from(data)] : [channel, WEBRTC_BINARY, data]
12633
+ typeof data === "string" ? [channel, WEBRTC_STRING, userData] : [channel, WEBRTC_BINARY, userData]
12080
12634
  );
12081
12635
  if (this.sctp.associationState !== 4 /* ESTABLISHED */) {
12082
12636
  log30("sctp not established", this.sctp.associationState);
12083
12637
  }
12084
12638
  this.dataChannelFlush();
12639
+ return size;
12085
12640
  };
12086
- static getCapabilities() {
12087
- return new RTCSctpCapabilities2(65536);
12641
+ getCapabilities() {
12642
+ return _RTCSctpTransport.getCapabilities(this.maxMessageSize);
12643
+ }
12644
+ static getCapabilities(maxMessageSize = DEFAULT_MAX_MESSAGE_SIZE) {
12645
+ return new RTCSctpCapabilities2(maxMessageSize);
12646
+ }
12647
+ setRemoteMaxMessageSize(maxMessageSize) {
12648
+ this.remoteMaxMessageSize = maxMessageSize ?? DEFAULT_MAX_MESSAGE_SIZE;
12088
12649
  }
12089
12650
  setRemotePort(port) {
12090
12651
  this.sctp.setRemotePort(port);
@@ -13775,8 +14336,8 @@ var SctpTransportManager = class {
13775
14336
  onDataChannel = new Event();
13776
14337
  constructor() {
13777
14338
  }
13778
- createSctpTransport() {
13779
- const sctp = new RTCSctpTransport();
14339
+ createSctpTransport(maxMessageSize) {
14340
+ const sctp = new RTCSctpTransport(5e3, maxMessageSize);
13780
14341
  sctp.mid = void 0;
13781
14342
  sctp.onDataChannel.subscribe((channel) => {
13782
14343
  this.dataChannelsOpened++;
@@ -13834,6 +14395,9 @@ var SctpTransportManager = class {
13834
14395
  if (!this.sctpTransport) {
13835
14396
  return;
13836
14397
  }
14398
+ this.sctpTransport.setRemoteMaxMessageSize(
14399
+ remoteMedia.sctpCapabilities?.maxMessageSize
14400
+ );
13837
14401
  this.sctpRemotePort = remoteMedia.sctpPort;
13838
14402
  if (!this.sctpRemotePort) {
13839
14403
  throw new Error("sctpRemotePort not exist");
@@ -13974,7 +14538,7 @@ var SDPManager = class {
13974
14538
  );
13975
14539
  media.sctpPort = sctp.port;
13976
14540
  media.rtp.muxId = sctp.mid;
13977
- media.sctpCapabilities = RTCSctpTransport.getCapabilities();
14541
+ media.sctpCapabilities = sctp.getCapabilities();
13978
14542
  this.addTransportDescription(media, sctp.dtlsTransport);
13979
14543
  return media;
13980
14544
  }
@@ -14112,7 +14676,7 @@ var SDPManager = class {
14112
14676
  description.media.push(this.createMediaDescriptionForSctp(sctpTransport));
14113
14677
  }
14114
14678
  if (this.bundlePolicy !== "disable") {
14115
- const mids = description.media.map((m) => m.direction !== "inactive" ? m.rtp.muxId : void 0).filter((v) => v);
14679
+ const mids = description.media.map((m) => m.rtp.muxId).filter((v) => v);
14116
14680
  if (mids.length) {
14117
14681
  const bundle = new GroupDescription("BUNDLE", mids);
14118
14682
  description.group.push(bundle);
@@ -14182,7 +14746,7 @@ var SDPManager = class {
14182
14746
  if (this.bundlePolicy !== "disable") {
14183
14747
  const bundle = new GroupDescription("BUNDLE", []);
14184
14748
  for (const media of description.media) {
14185
- if (media.direction !== "inactive") {
14749
+ if (media.rtp.muxId) {
14186
14750
  bundle.items.push(media.rtp.muxId);
14187
14751
  }
14188
14752
  }
@@ -14307,7 +14871,9 @@ var SecureTransportManager = class {
14307
14871
  );
14308
14872
  }
14309
14873
  createTransport() {
14310
- const [existing] = this.iceTransports;
14874
+ const existing = this.iceTransports.find(
14875
+ (transport) => transport.state !== "closed"
14876
+ );
14311
14877
  const iceGatherer = new RTCIceGatherer({
14312
14878
  ...parseIceServers(this.config.iceServers),
14313
14879
  forceTurn: this.config.iceTransportPolicy === "relay",
@@ -14562,6 +15128,7 @@ var RTCPeerConnection = class extends EventTarget {
14562
15128
  secureManager;
14563
15129
  isClosed = false;
14564
15130
  shouldNegotiationneeded = false;
15131
+ remoteBundleNegotiated = false;
14565
15132
  iceGatheringStateChange = new Event();
14566
15133
  iceConnectionStateChange = new Event();
14567
15134
  signalingStateChange = new Event();
@@ -14711,6 +15278,12 @@ var RTCPeerConnection = class extends EventTarget {
14711
15278
  if (min === max) throw new Error("should not be same value");
14712
15279
  if (min >= max) throw new Error("The min must be less than max");
14713
15280
  }
15281
+ if (!Number.isInteger(this.config.maxMessageSize) || this.config.maxMessageSize < 0) {
15282
+ throw new Error("maxMessageSize must be a non-negative integer");
15283
+ }
15284
+ if (this.sctpManager?.sctpTransport) {
15285
+ this.sctpManager.sctpTransport.maxMessageSize = this.config.maxMessageSize;
15286
+ }
14714
15287
  for (const [i, codecParams] of enumerate2([
14715
15288
  ...this.config.codecs.audio || [],
14716
15289
  ...this.config.codecs.video || []
@@ -14767,7 +15340,9 @@ var RTCPeerConnection = class extends EventTarget {
14767
15340
  return description.toJSON();
14768
15341
  }
14769
15342
  createSctpTransport() {
14770
- const sctp = this.sctpManager.createSctpTransport();
15343
+ const sctp = this.sctpManager.createSctpTransport(
15344
+ this.config.maxMessageSize
15345
+ );
14771
15346
  const dtlsTransport = this.findOrCreateTransport();
14772
15347
  sctp.setDtlsTransport(dtlsTransport);
14773
15348
  return sctp;
@@ -14804,10 +15379,13 @@ var RTCPeerConnection = class extends EventTarget {
14804
15379
  });
14805
15380
  };
14806
15381
  findOrCreateTransport() {
14807
- const [existing] = this.iceTransports;
14808
- if (this.sdpManager.bundlePolicy === "max-bundle" || this.sdpManager.bundlePolicy !== "disable" && this.remoteIsBundled) {
14809
- if (existing) {
14810
- return this.dtlsTransports[0];
15382
+ const existingDtlsTransport = this.dtlsTransports.find(
15383
+ (transport) => transport.state !== "closed"
15384
+ );
15385
+ const existing = existingDtlsTransport?.iceTransport;
15386
+ if (this.sdpManager.bundlePolicy === "max-bundle" || this.sdpManager.bundlePolicy !== "disable" && (this.remoteIsBundled || this.remoteBundleNegotiated)) {
15387
+ if (existingDtlsTransport) {
15388
+ return existingDtlsTransport;
14811
15389
  }
14812
15390
  }
14813
15391
  const dtlsTransport = this.secureManager.createTransport();
@@ -14979,6 +15557,11 @@ var RTCPeerConnection = class extends EventTarget {
14979
15557
  sessionDescription,
14980
15558
  this.signalingState
14981
15559
  );
15560
+ if (remoteSdp.group.some(
15561
+ (group) => group.semantic === "BUNDLE" && group.items.length > 0
15562
+ )) {
15563
+ this.remoteBundleNegotiated = true;
15564
+ }
14982
15565
  let bundleTransport;
14983
15566
  const matchTransceiverWithMedia = (transceiver, media) => transceiver.kind === media.kind && [void 0, media.rtp.muxId].includes(transceiver.mid);
14984
15567
  let transports = remoteSdp.media.map((remoteMedia, i) => {
@@ -15196,7 +15779,8 @@ function generateDefaultPeerConfig() {
15196
15779
  bundlePolicy: "max-compat",
15197
15780
  debug: {},
15198
15781
  midSuffix: false,
15199
- forceTurnTCP: false
15782
+ forceTurnTCP: false,
15783
+ maxMessageSize: DEFAULT_MAX_MESSAGE_SIZE
15200
15784
  };
15201
15785
  }
15202
15786
  var defaultPeerConfig = generateDefaultPeerConfig();
@@ -15249,14 +15833,15 @@ var TransceiverManager = class {
15249
15833
  newTransceiver.options = options;
15250
15834
  this.router.registerRtpSender(newTransceiver.sender);
15251
15835
  const inactiveTransceiverIndex = this.transceivers.findIndex(
15252
- (t) => t.currentDirection === "inactive"
15836
+ (t) => t.currentDirection === "inactive" && !t.usedForSender
15253
15837
  );
15254
15838
  const inactiveTransceiver = this.transceivers.find(
15255
- (t) => t.currentDirection === "inactive"
15839
+ (t) => t.currentDirection === "inactive" && !t.usedForSender
15256
15840
  );
15257
15841
  if (inactiveTransceiverIndex > -1 && inactiveTransceiver) {
15258
15842
  this.replaceTransceiver(newTransceiver, inactiveTransceiverIndex);
15259
15843
  newTransceiver.mLineIndex = inactiveTransceiver.mLineIndex;
15844
+ newTransceiver.mid = inactiveTransceiver.mid;
15260
15845
  inactiveTransceiver.setCurrentDirection(void 0);
15261
15846
  } else {
15262
15847
  this.pushTransceiver(newTransceiver);
@@ -15543,6 +16128,7 @@ export {
15543
16128
  Connection,
15544
16129
  ConnectionStates,
15545
16130
  CurveType,
16131
+ DEFAULT_MAX_MESSAGE_SIZE,
15546
16132
  DePacketizerBase,
15547
16133
  Directions,
15548
16134
  DtlsClient,
@@ -15646,6 +16232,7 @@ export {
15646
16232
  SourceDescriptionChunk,
15647
16233
  SourceDescriptionItem,
15648
16234
  SrtcpSession,
16235
+ SrtpAuthenticationError,
15649
16236
  SrtpContext,
15650
16237
  SrtpSession,
15651
16238
  SsrcDescription,
@@ -15680,6 +16267,8 @@ export {
15680
16267
  codecParametersFromString,
15681
16268
  codecParametersToString,
15682
16269
  compactNtp,
16270
+ crc32,
16271
+ crc32c,
15683
16272
  createBufferWriter,
15684
16273
  createSelfSignedCertificate,
15685
16274
  createStunOverTurnClient,
@@ -15702,6 +16291,7 @@ export {
15702
16291
  fingerprint,
15703
16292
  generateStatsId,
15704
16293
  getBit,
16294
+ getDataChannelMessageSize,
15705
16295
  getGlobalIp,
15706
16296
  getHostAddresses,
15707
16297
  getStatsTimestamp,
@@ -15720,6 +16310,8 @@ export {
15720
16310
  milliTime,
15721
16311
  nodeIpAddress,
15722
16312
  normalizeFamilyNodeV18,
16313
+ normalizeFingerprintAlgorithm,
16314
+ normalizeFingerprintValue,
15723
16315
  ntpTime,
15724
16316
  ntpTime2Sec,
15725
16317
  paddingBits,