werift 0.22.9 → 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 (56) hide show
  1. package/lib/dtls/src/flight/server/flight6.js +12 -2
  2. package/lib/dtls/src/flight/server/flight6.js.map +1 -1
  3. package/lib/dtls/src/server.js +6 -1
  4. package/lib/dtls/src/server.js.map +1 -1
  5. package/lib/dtls/src/socket.d.ts +1 -0
  6. package/lib/dtls/src/socket.js +3 -0
  7. package/lib/dtls/src/socket.js.map +1 -1
  8. package/lib/index.mjs +434 -75
  9. package/lib/nonstandard/index.mjs +207 -40
  10. package/lib/rtp/src/index.d.ts +1 -0
  11. package/lib/rtp/src/index.js +1 -0
  12. package/lib/rtp/src/index.js.map +1 -1
  13. package/lib/rtp/src/srtp/cipher/ctr.d.ts +3 -3
  14. package/lib/rtp/src/srtp/cipher/ctr.js +25 -14
  15. package/lib/rtp/src/srtp/cipher/ctr.js.map +1 -1
  16. package/lib/rtp/src/srtp/cipher/gcm.d.ts +3 -3
  17. package/lib/rtp/src/srtp/cipher/gcm.js +57 -20
  18. package/lib/rtp/src/srtp/cipher/gcm.js.map +1 -1
  19. package/lib/rtp/src/srtp/cipher/index.d.ts +1 -1
  20. package/lib/rtp/src/srtp/cipher/index.js +1 -1
  21. package/lib/rtp/src/srtp/cipher/index.js.map +1 -1
  22. package/lib/rtp/src/srtp/context/srtp.d.ts +2 -1
  23. package/lib/rtp/src/srtp/context/srtp.js +22 -5
  24. package/lib/rtp/src/srtp/context/srtp.js.map +1 -1
  25. package/lib/rtp/src/srtp/error.d.ts +3 -0
  26. package/lib/rtp/src/srtp/error.js +11 -0
  27. package/lib/rtp/src/srtp/error.js.map +1 -0
  28. package/lib/rtp/src/srtp/packet.d.ts +5 -0
  29. package/lib/rtp/src/srtp/packet.js +48 -0
  30. package/lib/rtp/src/srtp/packet.js.map +1 -0
  31. package/lib/webrtc/src/dataChannel.d.ts +1 -0
  32. package/lib/webrtc/src/dataChannel.js +5 -2
  33. package/lib/webrtc/src/dataChannel.js.map +1 -1
  34. package/lib/webrtc/src/peerConnection.d.ts +4 -1
  35. package/lib/webrtc/src/peerConnection.js +26 -5
  36. package/lib/webrtc/src/peerConnection.js.map +1 -1
  37. package/lib/webrtc/src/sctpManager.d.ts +1 -1
  38. package/lib/webrtc/src/sctpManager.js +3 -2
  39. package/lib/webrtc/src/sctpManager.js.map +1 -1
  40. package/lib/webrtc/src/sdpManager.d.ts +1 -1
  41. package/lib/webrtc/src/sdpManager.js +3 -4
  42. package/lib/webrtc/src/sdpManager.js.map +1 -1
  43. package/lib/webrtc/src/secureTransportManager.js +1 -1
  44. package/lib/webrtc/src/secureTransportManager.js.map +1 -1
  45. package/lib/webrtc/src/transceiverManager.js +3 -2
  46. package/lib/webrtc/src/transceiverManager.js.map +1 -1
  47. package/lib/webrtc/src/transport/dtls.d.ts +1 -0
  48. package/lib/webrtc/src/transport/dtls.js +117 -12
  49. package/lib/webrtc/src/transport/dtls.js.map +1 -1
  50. package/lib/webrtc/src/transport/sctp.d.ts +9 -3
  51. package/lib/webrtc/src/transport/sctp.js +35 -7
  52. package/lib/webrtc/src/transport/sctp.js.map +1 -1
  53. package/lib/webrtc/src/utils.d.ts +2 -0
  54. package/lib/webrtc/src/utils.js +20 -0
  55. package/lib/webrtc/src/utils.js.map +1 -1
  56. package/package.json +1 -1
@@ -5,8 +5,8 @@ const crypto_1 = require("crypto");
5
5
  const _1 = require(".");
6
6
  const src_1 = require("../../../../common/src");
7
7
  const helper_1 = require("../../helper");
8
- const header_1 = require("../../rtcp/header");
9
- const rtp_1 = require("../../rtp/rtp");
8
+ const error_1 = require("../error");
9
+ const packet_1 = require("../packet");
10
10
  class CipherAesGcm extends _1.CipherAesBase {
11
11
  constructor(srtpSessionKey, srtpSessionSalt, srtcpSessionKey, srtcpSessionSalt) {
12
12
  super(srtpSessionKey, srtpSessionSalt, srtcpSessionKey, srtcpSessionSalt);
@@ -46,17 +46,25 @@ class CipherAesGcm extends _1.CipherAesBase {
46
46
  const dst = Buffer.concat([hdr, enc, authTag]);
47
47
  return dst;
48
48
  }
49
- decryptRtp(cipherText, rolloverCounter) {
50
- const header = rtp_1.RtpHeader.deSerialize(cipherText);
49
+ decryptRtp(cipherText, rolloverCounter, header = (0, packet_1.parseSrtpRtpHeader)(cipherText, this.aeadAuthTagLen)) {
50
+ const headerBuffer = cipherText.subarray(0, header.payloadOffset);
51
+ const authTagOffset = cipherText.length - this.aeadAuthTagLen;
52
+ const authTag = cipherText.subarray(authTagOffset);
51
53
  let dst = Buffer.from([]);
52
54
  dst = (0, helper_1.growBufferSize)(dst, cipherText.length - this.aeadAuthTagLen);
53
- cipherText.slice(0, header.payloadOffset).copy(dst);
55
+ headerBuffer.copy(dst);
54
56
  const iv = this.rtpInitializationVector(header, rolloverCounter);
55
- const enc = cipherText.slice(header.payloadOffset, cipherText.length - this.aeadAuthTagLen);
56
- const cipher = (0, crypto_1.createDecipheriv)("aes-128-gcm", this.srtpSessionKey, iv);
57
- const dec = cipher.update(enc);
57
+ const enc = cipherText.slice(header.payloadOffset, authTagOffset);
58
+ const decipher = (0, crypto_1.createDecipheriv)("aes-128-gcm", this.srtpSessionKey, iv);
59
+ decipher.setAAD(headerBuffer);
60
+ decipher.setAuthTag(authTag);
61
+ const dec = decipher.update(enc);
62
+ finalizeAuthenticatedDecryption(decipher, "SRTP");
58
63
  dec.copy(dst, header.payloadOffset);
59
- return [dst, header];
64
+ return [
65
+ dst,
66
+ (0, packet_1.finalizeSrtpRtpHeader)(header, dst, "Failed to authenticate SRTP packet"),
67
+ ];
60
68
  }
61
69
  encryptRTCP(rtcpPacket, srtcpIndex) {
62
70
  const ssrc = rtcpPacket.readUInt32BE(4);
@@ -77,19 +85,40 @@ class CipherAesGcm extends _1.CipherAesBase {
77
85
  return dst;
78
86
  }
79
87
  decryptRTCP(encrypted) {
80
- const header = header_1.RtcpHeader.deSerialize(encrypted);
81
- const aadPos = encrypted.length - srtcpIndexSize;
82
- const dst = Buffer.alloc(aadPos - this.aeadAuthTagLen);
83
- encrypted.slice(0, 8).copy(dst);
88
+ const header = (0, packet_1.parseSrtcpHeader)(encrypted, this.aeadAuthTagLen, srtcpIndexSize);
89
+ const srtcpIndexOffset = encrypted.length - srtcpIndexSize;
90
+ const authTagOffset = srtcpIndexOffset - this.aeadAuthTagLen;
84
91
  const ssrc = encrypted.readUInt32BE(4);
85
- let srtcpIndex = encrypted.readUInt32BE(encrypted.length - 4);
86
- srtcpIndex &= ~(rtcpEncryptionFlag << 24);
92
+ const encodedSrtcpIndex = encrypted.readUInt32BE(srtcpIndexOffset);
93
+ const isEncrypted = encodedSrtcpIndex >>> 31 === 1;
94
+ const srtcpIndex = encodedSrtcpIndex & ~(rtcpEncryptionFlag << 24);
87
95
  const iv = this.rtcpInitializationVector(ssrc, srtcpIndex);
88
- const aad = this.rtcpAdditionalAuthenticatedData(encrypted, srtcpIndex);
89
- const cipher = (0, crypto_1.createDecipheriv)("aes-128-gcm", this.srtcpSessionKey, iv);
90
- cipher.setAAD(aad);
91
- const dec = cipher.update(encrypted.slice(8, aadPos));
92
- dec.copy(dst, 8);
96
+ const aad = isEncrypted
97
+ ? Buffer.concat([
98
+ encrypted.subarray(0, 8),
99
+ encrypted.subarray(srtcpIndexOffset),
100
+ ])
101
+ : Buffer.concat([
102
+ encrypted.subarray(0, authTagOffset),
103
+ encrypted.subarray(srtcpIndexOffset),
104
+ ]);
105
+ const cipherText = isEncrypted
106
+ ? encrypted.slice(8, authTagOffset)
107
+ : Buffer.alloc(0);
108
+ const dst = isEncrypted
109
+ ? Buffer.alloc(authTagOffset)
110
+ : Buffer.from(encrypted.subarray(0, authTagOffset));
111
+ if (isEncrypted) {
112
+ encrypted.slice(0, 8).copy(dst);
113
+ }
114
+ const decipher = (0, crypto_1.createDecipheriv)("aes-128-gcm", this.srtcpSessionKey, iv);
115
+ decipher.setAAD(aad);
116
+ decipher.setAuthTag(encrypted.subarray(authTagOffset, srtcpIndexOffset));
117
+ const dec = decipher.update(cipherText);
118
+ finalizeAuthenticatedDecryption(decipher, "SRTCP");
119
+ if (isEncrypted) {
120
+ dec.copy(dst, 8);
121
+ }
93
122
  return [dst, header];
94
123
  }
95
124
  // https://tools.ietf.org/html/rfc7714#section-8.1
@@ -126,4 +155,12 @@ class CipherAesGcm extends _1.CipherAesBase {
126
155
  exports.CipherAesGcm = CipherAesGcm;
127
156
  const srtcpIndexSize = 4;
128
157
  const rtcpEncryptionFlag = 0x80;
158
+ function finalizeAuthenticatedDecryption(decipher, packetType) {
159
+ try {
160
+ decipher.final();
161
+ }
162
+ catch {
163
+ throw new error_1.SrtpAuthenticationError(`Failed to authenticate ${packetType} packet`);
164
+ }
165
+ }
129
166
  //# sourceMappingURL=gcm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"gcm.js","sourceRoot":"","sources":["../../../../../../rtp/src/srtp/cipher/gcm.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCipheriv, createDecipheriv } from \"crypto\";\n\nimport { CipherAesBase } from \".\";\nimport { createBufferWriter } from \"../../../../common/src\";\nimport { growBufferSize } from \"../../helper\";\nimport { RtcpHeader } from \"../../rtcp/header\";\nimport { RtpHeader } from \"../../rtp/rtp\";\n\nexport class CipherAesGcm extends CipherAesBase {\n readonly aeadAuthTagLen = 16;\n readonly rtpIvWriter = createBufferWriter([2, 4, 4, 2], true);\n readonly rtcpIvWriter = createBufferWriter([2, 4, 2, 4], true);\n readonly aadWriter = createBufferWriter([4], true);\n\n constructor(\n srtpSessionKey: Buffer,\n srtpSessionSalt: Buffer,\n srtcpSessionKey: Buffer,\n srtcpSessionSalt: Buffer,\n ) {\n super(srtpSessionKey, srtpSessionSalt, srtcpSessionKey, srtcpSessionSalt);\n }\n\n encryptRtp(header: RtpHeader, payload: Buffer, rolloverCounter: number) {\n const hdr = header.serialize(header.serializeSize);\n\n const iv = this.rtpInitializationVector(header, rolloverCounter);\n\n const cipher = createCipheriv(\"aes-128-gcm\", this.srtpSessionKey, iv);\n cipher.setAAD(hdr);\n const enc = cipher.update(payload);\n cipher.final();\n\n const authTag = cipher.getAuthTag();\n\n const dst = Buffer.concat([hdr, enc, authTag]);\n return dst;\n }\n\n decryptRtp(cipherText: Buffer, rolloverCounter: number): [Buffer, RtpHeader] {\n const header = RtpHeader.deSerialize(cipherText);\n\n let dst = Buffer.from([]);\n dst = growBufferSize(dst, cipherText.length - this.aeadAuthTagLen);\n cipherText.slice(0, header.payloadOffset).copy(dst);\n\n const iv = this.rtpInitializationVector(header, rolloverCounter);\n\n const enc = cipherText.slice(\n header.payloadOffset,\n cipherText.length - this.aeadAuthTagLen,\n );\n\n const cipher = createDecipheriv(\"aes-128-gcm\", this.srtpSessionKey, iv);\n const dec = cipher.update(enc);\n\n dec.copy(dst, header.payloadOffset);\n\n return [dst, header];\n }\n\n encryptRTCP(rtcpPacket: Buffer, srtcpIndex: number): Buffer {\n const ssrc = rtcpPacket.readUInt32BE(4);\n\n const addPos = rtcpPacket.length + this.aeadAuthTagLen;\n let dst = Buffer.from([]);\n dst = growBufferSize(dst, addPos + srtcpIndexSize);\n rtcpPacket.slice(0, 8).copy(dst);\n\n const iv = this.rtcpInitializationVector(ssrc, srtcpIndex);\n const aad = this.rtcpAdditionalAuthenticatedData(rtcpPacket, srtcpIndex);\n\n const cipher = createCipheriv(\"aes-128-gcm\", this.srtcpSessionKey, iv);\n cipher.setAAD(aad);\n const enc = cipher.update(rtcpPacket.slice(8));\n cipher.final();\n enc.copy(dst, 8);\n\n const authTag = cipher.getAuthTag();\n authTag.copy(dst, 8 + enc.length);\n aad.slice(8, 12).copy(dst, addPos);\n\n return dst;\n }\n\n decryptRTCP(encrypted: Buffer): [Buffer, RtcpHeader] {\n const header = RtcpHeader.deSerialize(encrypted);\n const aadPos = encrypted.length - srtcpIndexSize;\n\n const dst = Buffer.alloc(aadPos - this.aeadAuthTagLen);\n encrypted.slice(0, 8).copy(dst);\n\n const ssrc = encrypted.readUInt32BE(4);\n\n let srtcpIndex = encrypted.readUInt32BE(encrypted.length - 4);\n srtcpIndex &= ~(rtcpEncryptionFlag << 24);\n\n const iv = this.rtcpInitializationVector(ssrc, srtcpIndex);\n const aad = this.rtcpAdditionalAuthenticatedData(encrypted, srtcpIndex);\n\n const cipher = createDecipheriv(\"aes-128-gcm\", this.srtcpSessionKey, iv);\n cipher.setAAD(aad);\n const dec = cipher.update(encrypted.slice(8, aadPos));\n\n dec.copy(dst, 8);\n\n return [dst, header];\n }\n\n // https://tools.ietf.org/html/rfc7714#section-8.1\n private rtpInitializationVector(header: RtpHeader, rolloverCounter: number) {\n const iv = this.rtpIvWriter([\n 0,\n header.ssrc,\n rolloverCounter,\n header.sequenceNumber,\n ]);\n for (let i = 0; i < iv.length; i++) {\n iv[i] ^= this.srtpSessionSalt[i];\n }\n return iv;\n }\n\n // https://tools.ietf.org/html/rfc7714#section-9.1\n private rtcpInitializationVector(ssrc: number, srtcpIndex: number) {\n const iv = this.rtcpIvWriter([0, ssrc, 0, srtcpIndex]);\n for (let i = 0; i < iv.length; i++) {\n iv[i] ^= this.srtcpSessionSalt[i];\n }\n return iv;\n }\n\n // https://datatracker.ietf.org/doc/html/rfc7714#section-17\n private rtcpAdditionalAuthenticatedData(\n rtcpPacket: Buffer,\n srtcpIndex: number,\n ) {\n const aad = Buffer.concat([\n rtcpPacket.subarray(0, 8),\n this.aadWriter([srtcpIndex]),\n ]);\n aad[8] |= rtcpEncryptionFlag;\n return aad;\n }\n}\n\nconst srtcpIndexSize = 4;\nconst rtcpEncryptionFlag = 0x80;\n"]}
1
+ {"version":3,"file":"gcm.js","sourceRoot":"","sources":["../../../../../../rtp/src/srtp/cipher/gcm.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCipheriv, createDecipheriv } from \"crypto\";\n\nimport { CipherAesBase } from \".\";\nimport { createBufferWriter } from \"../../../../common/src\";\nimport { growBufferSize } from \"../../helper\";\nimport type { RtcpHeader } from \"../../rtcp/header\";\nimport type { RtpHeader } from \"../../rtp/rtp\";\nimport { SrtpAuthenticationError } from \"../error\";\nimport {\n finalizeSrtpRtpHeader,\n parseSrtcpHeader,\n parseSrtpRtpHeader,\n} from \"../packet\";\n\nexport class CipherAesGcm extends CipherAesBase {\n readonly aeadAuthTagLen = 16;\n readonly rtpIvWriter = createBufferWriter([2, 4, 4, 2], true);\n readonly rtcpIvWriter = createBufferWriter([2, 4, 2, 4], true);\n readonly aadWriter = createBufferWriter([4], true);\n\n constructor(\n srtpSessionKey: Buffer,\n srtpSessionSalt: Buffer,\n srtcpSessionKey: Buffer,\n srtcpSessionSalt: Buffer,\n ) {\n super(srtpSessionKey, srtpSessionSalt, srtcpSessionKey, srtcpSessionSalt);\n }\n\n encryptRtp(header: RtpHeader, payload: Buffer, rolloverCounter: number) {\n const hdr = header.serialize(header.serializeSize);\n\n const iv = this.rtpInitializationVector(header, rolloverCounter);\n\n const cipher = createCipheriv(\"aes-128-gcm\", this.srtpSessionKey, iv);\n cipher.setAAD(hdr);\n const enc = cipher.update(payload);\n cipher.final();\n\n const authTag = cipher.getAuthTag();\n\n const dst = Buffer.concat([hdr, enc, authTag]);\n return dst;\n }\n\n decryptRtp(\n cipherText: Buffer,\n rolloverCounter: number,\n header = parseSrtpRtpHeader(cipherText, this.aeadAuthTagLen),\n ): [Buffer, RtpHeader] {\n const headerBuffer = cipherText.subarray(0, header.payloadOffset);\n const authTagOffset = cipherText.length - this.aeadAuthTagLen;\n const authTag = cipherText.subarray(authTagOffset);\n\n let dst = Buffer.from([]);\n dst = growBufferSize(dst, cipherText.length - this.aeadAuthTagLen);\n headerBuffer.copy(dst);\n\n const iv = this.rtpInitializationVector(header, rolloverCounter);\n\n const enc = cipherText.slice(header.payloadOffset, authTagOffset);\n\n const decipher = createDecipheriv(\"aes-128-gcm\", this.srtpSessionKey, iv);\n decipher.setAAD(headerBuffer);\n decipher.setAuthTag(authTag);\n const dec = decipher.update(enc);\n finalizeAuthenticatedDecryption(decipher, \"SRTP\");\n\n dec.copy(dst, header.payloadOffset);\n\n return [\n dst,\n finalizeSrtpRtpHeader(header, dst, \"Failed to authenticate SRTP packet\"),\n ];\n }\n\n encryptRTCP(rtcpPacket: Buffer, srtcpIndex: number): Buffer {\n const ssrc = rtcpPacket.readUInt32BE(4);\n\n const addPos = rtcpPacket.length + this.aeadAuthTagLen;\n let dst = Buffer.from([]);\n dst = growBufferSize(dst, addPos + srtcpIndexSize);\n rtcpPacket.slice(0, 8).copy(dst);\n\n const iv = this.rtcpInitializationVector(ssrc, srtcpIndex);\n const aad = this.rtcpAdditionalAuthenticatedData(rtcpPacket, srtcpIndex);\n\n const cipher = createCipheriv(\"aes-128-gcm\", this.srtcpSessionKey, iv);\n cipher.setAAD(aad);\n const enc = cipher.update(rtcpPacket.slice(8));\n cipher.final();\n enc.copy(dst, 8);\n\n const authTag = cipher.getAuthTag();\n authTag.copy(dst, 8 + enc.length);\n aad.slice(8, 12).copy(dst, addPos);\n\n return dst;\n }\n\n decryptRTCP(encrypted: Buffer): [Buffer, RtcpHeader] {\n const header = parseSrtcpHeader(\n encrypted,\n this.aeadAuthTagLen,\n srtcpIndexSize,\n );\n const srtcpIndexOffset = encrypted.length - srtcpIndexSize;\n const authTagOffset = srtcpIndexOffset - this.aeadAuthTagLen;\n\n const ssrc = encrypted.readUInt32BE(4);\n const encodedSrtcpIndex = encrypted.readUInt32BE(srtcpIndexOffset);\n const isEncrypted = encodedSrtcpIndex >>> 31 === 1;\n const srtcpIndex = encodedSrtcpIndex & ~(rtcpEncryptionFlag << 24);\n\n const iv = this.rtcpInitializationVector(ssrc, srtcpIndex);\n const aad = isEncrypted\n ? Buffer.concat([\n encrypted.subarray(0, 8),\n encrypted.subarray(srtcpIndexOffset),\n ])\n : Buffer.concat([\n encrypted.subarray(0, authTagOffset),\n encrypted.subarray(srtcpIndexOffset),\n ]);\n const cipherText = isEncrypted\n ? encrypted.slice(8, authTagOffset)\n : Buffer.alloc(0);\n const dst = isEncrypted\n ? Buffer.alloc(authTagOffset)\n : Buffer.from(encrypted.subarray(0, authTagOffset));\n if (isEncrypted) {\n encrypted.slice(0, 8).copy(dst);\n }\n\n const decipher = createDecipheriv(\"aes-128-gcm\", this.srtcpSessionKey, iv);\n decipher.setAAD(aad);\n decipher.setAuthTag(encrypted.subarray(authTagOffset, srtcpIndexOffset));\n const dec = decipher.update(cipherText);\n finalizeAuthenticatedDecryption(decipher, \"SRTCP\");\n\n if (isEncrypted) {\n dec.copy(dst, 8);\n }\n\n return [dst, header];\n }\n\n // https://tools.ietf.org/html/rfc7714#section-8.1\n private rtpInitializationVector(header: RtpHeader, rolloverCounter: number) {\n const iv = this.rtpIvWriter([\n 0,\n header.ssrc,\n rolloverCounter,\n header.sequenceNumber,\n ]);\n for (let i = 0; i < iv.length; i++) {\n iv[i] ^= this.srtpSessionSalt[i];\n }\n return iv;\n }\n\n // https://tools.ietf.org/html/rfc7714#section-9.1\n private rtcpInitializationVector(ssrc: number, srtcpIndex: number) {\n const iv = this.rtcpIvWriter([0, ssrc, 0, srtcpIndex]);\n for (let i = 0; i < iv.length; i++) {\n iv[i] ^= this.srtcpSessionSalt[i];\n }\n return iv;\n }\n\n // https://datatracker.ietf.org/doc/html/rfc7714#section-17\n private rtcpAdditionalAuthenticatedData(\n rtcpPacket: Buffer,\n srtcpIndex: number,\n ) {\n const aad = Buffer.concat([\n rtcpPacket.subarray(0, 8),\n this.aadWriter([srtcpIndex]),\n ]);\n aad[8] |= rtcpEncryptionFlag;\n return aad;\n }\n}\n\nconst srtcpIndexSize = 4;\nconst rtcpEncryptionFlag = 0x80;\n\nfunction finalizeAuthenticatedDecryption(\n decipher: ReturnType<typeof createDecipheriv>,\n packetType: \"SRTP\" | \"SRTCP\",\n) {\n try {\n decipher.final();\n } catch {\n throw new SrtpAuthenticationError(\n `Failed to authenticate ${packetType} packet`,\n );\n }\n}\n"]}
@@ -7,7 +7,7 @@ export declare abstract class CipherAesBase {
7
7
  srtcpSessionSalt: Buffer;
8
8
  constructor(srtpSessionKey: Buffer, srtpSessionSalt: Buffer, srtcpSessionKey: Buffer, srtcpSessionSalt: Buffer);
9
9
  encryptRtp(header: RtpHeader, payload: Buffer, rolloverCounter: number): Buffer;
10
- decryptRtp(cipherText: Buffer, rolloverCounter: number): [Buffer, RtpHeader];
10
+ decryptRtp(cipherText: Buffer, rolloverCounter: number, header?: RtpHeader): [Buffer, RtpHeader];
11
11
  encryptRTCP(rawRtcp: Buffer, srtcpIndex: number): Buffer;
12
12
  decryptRTCP(encrypted: Buffer): [Buffer, RtcpHeader];
13
13
  }
@@ -31,7 +31,7 @@ class CipherAesBase {
31
31
  encryptRtp(header, payload, rolloverCounter) {
32
32
  return Buffer.from([]);
33
33
  }
34
- decryptRtp(cipherText, rolloverCounter) {
34
+ decryptRtp(cipherText, rolloverCounter, header) {
35
35
  return [];
36
36
  }
37
37
  encryptRTCP(rawRtcp, srtcpIndex) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../rtp/src/srtp/cipher/index.ts"],"names":[],"mappings":";;;AAGA,MAAsB,aAAa;IACjC,YACS,cAAsB,EACtB,eAAuB,EACvB,eAAuB,EACvB,gBAAwB;QAH/B;;;;mBAAO,cAAc;WAAQ;QAC7B;;;;mBAAO,eAAe;WAAQ;QAC9B;;;;mBAAO,eAAe;WAAQ;QAC9B;;;;mBAAO,gBAAgB;WAAQ;IAC9B,CAAC;IAEJ,UAAU,CACR,MAAiB,EACjB,OAAe,EACf,eAAuB;QAEvB,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC;IAED,UAAU,CAAC,UAAkB,EAAE,eAAuB;QACpD,OAAO,EAAS,CAAC;IACnB,CAAC;IAED,WAAW,CAAC,OAAe,EAAE,UAAkB;QAC7C,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC;IAED,WAAW,CAAC,SAAiB;QAC3B,OAAO,EAAS,CAAC;IACnB,CAAC;CACF;AA3BD,sCA2BC","sourcesContent":["import type { RtcpHeader } from \"../../rtcp/header\";\nimport type { RtpHeader } from \"../../rtp/rtp\";\n\nexport abstract class CipherAesBase {\n constructor(\n public srtpSessionKey: Buffer,\n public srtpSessionSalt: Buffer,\n public srtcpSessionKey: Buffer,\n public srtcpSessionSalt: Buffer,\n ) {}\n\n encryptRtp(\n header: RtpHeader,\n payload: Buffer,\n rolloverCounter: number,\n ): Buffer {\n return Buffer.from([]);\n }\n\n decryptRtp(cipherText: Buffer, rolloverCounter: number): [Buffer, RtpHeader] {\n return [] as any;\n }\n\n encryptRTCP(rawRtcp: Buffer, srtcpIndex: number): Buffer {\n return Buffer.from([]);\n }\n\n decryptRTCP(encrypted: Buffer): [Buffer, RtcpHeader] {\n return [] as any;\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../rtp/src/srtp/cipher/index.ts"],"names":[],"mappings":";;;AAGA,MAAsB,aAAa;IACjC,YACS,cAAsB,EACtB,eAAuB,EACvB,eAAuB,EACvB,gBAAwB;QAH/B;;;;mBAAO,cAAc;WAAQ;QAC7B;;;;mBAAO,eAAe;WAAQ;QAC9B;;;;mBAAO,eAAe;WAAQ;QAC9B;;;;mBAAO,gBAAgB;WAAQ;IAC9B,CAAC;IAEJ,UAAU,CACR,MAAiB,EACjB,OAAe,EACf,eAAuB;QAEvB,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC;IAED,UAAU,CACR,UAAkB,EAClB,eAAuB,EACvB,MAAkB;QAElB,OAAO,EAAS,CAAC;IACnB,CAAC;IAED,WAAW,CAAC,OAAe,EAAE,UAAkB;QAC7C,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC;IAED,WAAW,CAAC,SAAiB;QAC3B,OAAO,EAAS,CAAC;IACnB,CAAC;CACF;AA/BD,sCA+BC","sourcesContent":["import type { RtcpHeader } from \"../../rtcp/header\";\nimport type { RtpHeader } from \"../../rtp/rtp\";\n\nexport abstract class CipherAesBase {\n constructor(\n public srtpSessionKey: Buffer,\n public srtpSessionSalt: Buffer,\n public srtcpSessionKey: Buffer,\n public srtcpSessionSalt: Buffer,\n ) {}\n\n encryptRtp(\n header: RtpHeader,\n payload: Buffer,\n rolloverCounter: number,\n ): Buffer {\n return Buffer.from([]);\n }\n\n decryptRtp(\n cipherText: Buffer,\n rolloverCounter: number,\n header?: RtpHeader,\n ): [Buffer, RtpHeader] {\n return [] as any;\n }\n\n encryptRTCP(rawRtcp: Buffer, srtcpIndex: number): Buffer {\n return Buffer.from([]);\n }\n\n decryptRTCP(encrypted: Buffer): [Buffer, RtcpHeader] {\n return [] as any;\n }\n}\n"]}
@@ -1,8 +1,9 @@
1
- import { RtpHeader } from "../../rtp/rtp";
1
+ import type { RtpHeader } from "../../rtp/rtp";
2
2
  import type { SrtpProfile } from "../const";
3
3
  import { Context } from "./context";
4
4
  export declare class SrtpContext extends Context {
5
5
  constructor(masterKey: Buffer, masterSalt: Buffer, profile: SrtpProfile);
6
6
  encryptRtp(payload: Buffer, header: RtpHeader): Buffer<ArrayBufferLike>;
7
7
  decryptRtp(cipherText: Buffer): [Buffer, RtpHeader];
8
+ private get rtpAuthTagLength();
8
9
  }
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SrtpContext = void 0;
4
- const rtp_1 = require("../../rtp/rtp");
4
+ const const_1 = require("../const");
5
+ const packet_1 = require("../packet");
5
6
  const context_1 = require("./context");
6
7
  class SrtpContext extends context_1.Context {
7
8
  constructor(masterKey, masterSalt, profile) {
@@ -14,12 +15,28 @@ class SrtpContext extends context_1.Context {
14
15
  return enc;
15
16
  }
16
17
  decryptRtp(cipherText) {
17
- const header = rtp_1.RtpHeader.deSerialize(cipherText);
18
- const s = this.getSrtpSsrcState(header.ssrc);
19
- this.updateRolloverCount(header.sequenceNumber, s);
20
- const dec = this.cipher.decryptRtp(cipherText, s.rolloverCounter);
18
+ const header = (0, packet_1.parseSrtpRtpHeader)(cipherText, this.rtpAuthTagLength);
19
+ const existingState = this.srtpSSRCStates[header.ssrc];
20
+ const nextState = existingState
21
+ ? { ...existingState }
22
+ : {
23
+ ssrc: header.ssrc,
24
+ rolloverCounter: 0,
25
+ lastSequenceNumber: 0,
26
+ };
27
+ this.updateRolloverCount(header.sequenceNumber, nextState);
28
+ const dec = this.cipher.decryptRtp(cipherText, nextState.rolloverCounter, header);
29
+ if (existingState) {
30
+ Object.assign(existingState, nextState);
31
+ }
32
+ else {
33
+ this.srtpSSRCStates[header.ssrc] = nextState;
34
+ }
21
35
  return dec;
22
36
  }
37
+ get rtpAuthTagLength() {
38
+ return this.profile === const_1.ProtectionProfileAeadAes128Gcm ? 16 : 10;
39
+ }
23
40
  }
24
41
  exports.SrtpContext = SrtpContext;
25
42
  //# sourceMappingURL=srtp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"srtp.js","sourceRoot":"","sources":["../../../../../../rtp/src/srtp/context/srtp.ts"],"names":[],"mappings":";;;AAAA,uCAA0C;AAE1C,uCAAoC;AAEpC,MAAa,WAAY,SAAQ,iBAAO;IACtC,YAAY,SAAiB,EAAE,UAAkB,EAAE,OAAoB;QACrE,KAAK,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,UAAU,CAAC,OAAe,EAAE,MAAiB;QAC3C,MAAM,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QAEnD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC;QACvE,OAAO,GAAG,CAAC;IACb,CAAC;IAED,UAAU,CAAC,UAAkB;QAC3B,MAAM,MAAM,GAAG,eAAS,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAEjD,MAAM,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QAEnD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC;QAClE,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAtBD,kCAsBC","sourcesContent":["import { RtpHeader } from \"../../rtp/rtp\";\nimport type { SrtpProfile } from \"../const\";\nimport { Context } from \"./context\";\n\nexport class SrtpContext extends Context {\n constructor(masterKey: Buffer, masterSalt: Buffer, profile: SrtpProfile) {\n super(masterKey, masterSalt, profile);\n }\n\n encryptRtp(payload: Buffer, header: RtpHeader) {\n const s = this.getSrtpSsrcState(header.ssrc);\n this.updateRolloverCount(header.sequenceNumber, s);\n\n const enc = this.cipher.encryptRtp(header, payload, s.rolloverCounter);\n return enc;\n }\n\n decryptRtp(cipherText: Buffer): [Buffer, RtpHeader] {\n const header = RtpHeader.deSerialize(cipherText);\n\n const s = this.getSrtpSsrcState(header.ssrc);\n this.updateRolloverCount(header.sequenceNumber, s);\n\n const dec = this.cipher.decryptRtp(cipherText, s.rolloverCounter);\n return dec;\n }\n}\n"]}
1
+ {"version":3,"file":"srtp.js","sourceRoot":"","sources":["../../../../../../rtp/src/srtp/context/srtp.ts"],"names":[],"mappings":";;;AACA,oCAA0D;AAE1D,sCAA+C;AAC/C,uCAAoC;AAEpC,MAAa,WAAY,SAAQ,iBAAO;IACtC,YAAY,SAAiB,EAAE,UAAkB,EAAE,OAAoB;QACrE,KAAK,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,UAAU,CAAC,OAAe,EAAE,MAAiB;QAC3C,MAAM,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QAEnD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC;QACvE,OAAO,GAAG,CAAC;IACb,CAAC;IAED,UAAU,CAAC,UAAkB;QAC3B,MAAM,MAAM,GAAG,IAAA,2BAAkB,EAAC,UAAU,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAErE,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACvD,MAAM,SAAS,GAAG,aAAa;YAC7B,CAAC,CAAC,EAAE,GAAG,aAAa,EAAE;YACtB,CAAC,CAAC;gBACE,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,eAAe,EAAE,CAAC;gBAClB,kBAAkB,EAAE,CAAC;aACtB,CAAC;QACN,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;QAE3D,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAChC,UAAU,EACV,SAAS,CAAC,eAAe,EACzB,MAAM,CACP,CAAC;QACF,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;QAC/C,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,IAAY,gBAAgB;QAC1B,OAAO,IAAI,CAAC,OAAO,KAAK,sCAA8B,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,CAAC;CACF;AA1CD,kCA0CC","sourcesContent":["import type { RtpHeader } from \"../../rtp/rtp\";\nimport { ProtectionProfileAeadAes128Gcm } from \"../const\";\nimport type { SrtpProfile } from \"../const\";\nimport { parseSrtpRtpHeader } from \"../packet\";\nimport { Context } from \"./context\";\n\nexport class SrtpContext extends Context {\n constructor(masterKey: Buffer, masterSalt: Buffer, profile: SrtpProfile) {\n super(masterKey, masterSalt, profile);\n }\n\n encryptRtp(payload: Buffer, header: RtpHeader) {\n const s = this.getSrtpSsrcState(header.ssrc);\n this.updateRolloverCount(header.sequenceNumber, s);\n\n const enc = this.cipher.encryptRtp(header, payload, s.rolloverCounter);\n return enc;\n }\n\n decryptRtp(cipherText: Buffer): [Buffer, RtpHeader] {\n const header = parseSrtpRtpHeader(cipherText, this.rtpAuthTagLength);\n\n const existingState = this.srtpSSRCStates[header.ssrc];\n const nextState = existingState\n ? { ...existingState }\n : {\n ssrc: header.ssrc,\n rolloverCounter: 0,\n lastSequenceNumber: 0,\n };\n this.updateRolloverCount(header.sequenceNumber, nextState);\n\n const dec = this.cipher.decryptRtp(\n cipherText,\n nextState.rolloverCounter,\n header,\n );\n if (existingState) {\n Object.assign(existingState, nextState);\n } else {\n this.srtpSSRCStates[header.ssrc] = nextState;\n }\n return dec;\n }\n\n private get rtpAuthTagLength() {\n return this.profile === ProtectionProfileAeadAes128Gcm ? 16 : 10;\n }\n}\n"]}
@@ -0,0 +1,3 @@
1
+ export declare class SrtpAuthenticationError extends Error {
2
+ constructor(message: string);
3
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SrtpAuthenticationError = void 0;
4
+ class SrtpAuthenticationError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "SrtpAuthenticationError";
8
+ }
9
+ }
10
+ exports.SrtpAuthenticationError = SrtpAuthenticationError;
11
+ //# sourceMappingURL=error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.js","sourceRoot":"","sources":["../../../../../rtp/src/srtp/error.ts"],"names":[],"mappings":";;;AAAA,MAAa,uBAAwB,SAAQ,KAAK;IAChD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AALD,0DAKC","sourcesContent":["export class SrtpAuthenticationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SrtpAuthenticationError\";\n }\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import { RtcpHeader } from "../rtcp/header";
2
+ import { RtpHeader } from "../rtp/rtp";
3
+ export declare function parseSrtpRtpHeader(packet: Buffer, authTagLength: number, message?: string): RtpHeader;
4
+ export declare function parseSrtcpHeader(packet: Buffer, authTagLength: number, srtcpIndexSize: number, message?: string): RtcpHeader;
5
+ export declare function finalizeSrtpRtpHeader(header: RtpHeader, packet: Buffer, message?: string): RtpHeader;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseSrtpRtpHeader = parseSrtpRtpHeader;
4
+ exports.parseSrtcpHeader = parseSrtcpHeader;
5
+ exports.finalizeSrtpRtpHeader = finalizeSrtpRtpHeader;
6
+ const header_1 = require("../rtcp/header");
7
+ const rtp_1 = require("../rtp/rtp");
8
+ const error_1 = require("./error");
9
+ const minRtpHeaderSize = 12;
10
+ const minRtcpPacketSize = 8;
11
+ function parseSrtpRtpHeader(packet, authTagLength, message = "Failed to authenticate SRTP packet") {
12
+ const authTagOffset = packet.length - authTagLength;
13
+ assertAuthenticatedPacketLength(packet.length >= minRtpHeaderSize + authTagLength, message);
14
+ const header = wrapAuthenticationError(() => rtp_1.RtpHeader.deSerialize(packet.subarray(0, authTagOffset)), message);
15
+ header.paddingSize = 0;
16
+ assertAuthenticatedPacketLength(header.payloadOffset >= minRtpHeaderSize &&
17
+ header.payloadOffset <= authTagOffset, message);
18
+ return header;
19
+ }
20
+ function parseSrtcpHeader(packet, authTagLength, srtcpIndexSize, message = "Failed to authenticate SRTCP packet") {
21
+ assertAuthenticatedPacketLength(packet.length >= minRtcpPacketSize + authTagLength + srtcpIndexSize, message);
22
+ return wrapAuthenticationError(() => header_1.RtcpHeader.deSerialize(packet.subarray(0, header_1.RTCP_HEADER_SIZE)), message);
23
+ }
24
+ function assertAuthenticatedPacketLength(condition, message) {
25
+ if (!condition) {
26
+ throw new error_1.SrtpAuthenticationError(message);
27
+ }
28
+ }
29
+ function wrapAuthenticationError(parse, message) {
30
+ try {
31
+ return parse();
32
+ }
33
+ catch {
34
+ throw new error_1.SrtpAuthenticationError(message);
35
+ }
36
+ }
37
+ function finalizeSrtpRtpHeader(header, packet, message = "Failed to authenticate SRTP packet") {
38
+ if (!header.padding) {
39
+ header.paddingSize = 0;
40
+ return header;
41
+ }
42
+ assertAuthenticatedPacketLength(packet.length > header.payloadOffset, message);
43
+ const paddingSize = packet[packet.length - 1];
44
+ assertAuthenticatedPacketLength(paddingSize > 0 && paddingSize <= packet.length - header.payloadOffset, message);
45
+ header.paddingSize = paddingSize;
46
+ return header;
47
+ }
48
+ //# sourceMappingURL=packet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packet.js","sourceRoot":"","sources":["../../../../../rtp/src/srtp/packet.ts"],"names":[],"mappings":";;AAOA,gDAwBC;AAED,4CAeC;AAgBD,sDAuBC;AAvFD,2CAA8D;AAC9D,oCAAuC;AACvC,mCAAkD;AAElD,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAE5B,SAAgB,kBAAkB,CAChC,MAAc,EACd,aAAqB,EACrB,OAAO,GAAG,oCAAoC;IAE9C,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,GAAG,aAAa,CAAC;IACpD,+BAA+B,CAC7B,MAAM,CAAC,MAAM,IAAI,gBAAgB,GAAG,aAAa,EACjD,OAAO,CACR,CAAC;IAEF,MAAM,MAAM,GAAG,uBAAuB,CACpC,GAAG,EAAE,CAAC,eAAS,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,EAC9D,OAAO,CACR,CAAC;IACF,MAAM,CAAC,WAAW,GAAG,CAAC,CAAC;IAEvB,+BAA+B,CAC7B,MAAM,CAAC,aAAa,IAAI,gBAAgB;QACtC,MAAM,CAAC,aAAa,IAAI,aAAa,EACvC,OAAO,CACR,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,gBAAgB,CAC9B,MAAc,EACd,aAAqB,EACrB,cAAsB,EACtB,OAAO,GAAG,qCAAqC;IAE/C,+BAA+B,CAC7B,MAAM,CAAC,MAAM,IAAI,iBAAiB,GAAG,aAAa,GAAG,cAAc,EACnE,OAAO,CACR,CAAC;IAEF,OAAO,uBAAuB,CAC5B,GAAG,EAAE,CAAC,mBAAU,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,yBAAgB,CAAC,CAAC,EAClE,OAAO,CACR,CAAC;AACJ,CAAC;AAED,SAAS,+BAA+B,CAAC,SAAkB,EAAE,OAAe;IAC1E,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,+BAAuB,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB,CAAI,KAAc,EAAE,OAAe;IACjE,IAAI,CAAC;QACH,OAAO,KAAK,EAAE,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,+BAAuB,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,SAAgB,qBAAqB,CACnC,MAAiB,EACjB,MAAc,EACd,OAAO,GAAG,oCAAoC;IAE9C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,CAAC,WAAW,GAAG,CAAC,CAAC;QACvB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,+BAA+B,CAC7B,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,aAAa,EACpC,OAAO,CACR,CAAC;IAEF,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC9C,+BAA+B,CAC7B,WAAW,GAAG,CAAC,IAAI,WAAW,IAAI,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,aAAa,EACtE,OAAO,CACR,CAAC;IAEF,MAAM,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { RTCP_HEADER_SIZE, RtcpHeader } from \"../rtcp/header\";\nimport { RtpHeader } from \"../rtp/rtp\";\nimport { SrtpAuthenticationError } from \"./error\";\n\nconst minRtpHeaderSize = 12;\nconst minRtcpPacketSize = 8;\n\nexport function parseSrtpRtpHeader(\n packet: Buffer,\n authTagLength: number,\n message = \"Failed to authenticate SRTP packet\",\n) {\n const authTagOffset = packet.length - authTagLength;\n assertAuthenticatedPacketLength(\n packet.length >= minRtpHeaderSize + authTagLength,\n message,\n );\n\n const header = wrapAuthenticationError(\n () => RtpHeader.deSerialize(packet.subarray(0, authTagOffset)),\n message,\n );\n header.paddingSize = 0;\n\n assertAuthenticatedPacketLength(\n header.payloadOffset >= minRtpHeaderSize &&\n header.payloadOffset <= authTagOffset,\n message,\n );\n\n return header;\n}\n\nexport function parseSrtcpHeader(\n packet: Buffer,\n authTagLength: number,\n srtcpIndexSize: number,\n message = \"Failed to authenticate SRTCP packet\",\n) {\n assertAuthenticatedPacketLength(\n packet.length >= minRtcpPacketSize + authTagLength + srtcpIndexSize,\n message,\n );\n\n return wrapAuthenticationError(\n () => RtcpHeader.deSerialize(packet.subarray(0, RTCP_HEADER_SIZE)),\n message,\n );\n}\n\nfunction assertAuthenticatedPacketLength(condition: boolean, message: string) {\n if (!condition) {\n throw new SrtpAuthenticationError(message);\n }\n}\n\nfunction wrapAuthenticationError<T>(parse: () => T, message: string) {\n try {\n return parse();\n } catch {\n throw new SrtpAuthenticationError(message);\n }\n}\n\nexport function finalizeSrtpRtpHeader(\n header: RtpHeader,\n packet: Buffer,\n message = \"Failed to authenticate SRTP packet\",\n) {\n if (!header.padding) {\n header.paddingSize = 0;\n return header;\n }\n\n assertAuthenticatedPacketLength(\n packet.length > header.payloadOffset,\n message,\n );\n\n const paddingSize = packet[packet.length - 1];\n assertAuthenticatedPacketLength(\n paddingSize > 0 && paddingSize <= packet.length - header.payloadOffset,\n message,\n );\n\n header.paddingSize = paddingSize;\n return header;\n}\n"]}
@@ -8,6 +8,7 @@ export interface DataChannelStats {
8
8
  messagesReceived: number;
9
9
  bytesReceived: number;
10
10
  }
11
+ export declare function getDataChannelMessageSize(data: Buffer | string): number;
11
12
  export declare class RTCDataChannel extends EventTarget implements DataChannelStats {
12
13
  readonly sctp: RTCSctpTransport;
13
14
  private readonly parameters;
@@ -1,9 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RTCDataChannelParameters = exports.RTCDataChannel = void 0;
4
+ exports.getDataChannelMessageSize = getDataChannelMessageSize;
4
5
  const common_1 = require("./imports/common");
5
6
  const helper_1 = require("./helper");
6
7
  const log = (0, common_1.debug)("werift:packages/webrtc/src/dataChannel.ts");
8
+ function getDataChannelMessageSize(data) {
9
+ return Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data);
10
+ }
7
11
  class RTCDataChannel extends helper_1.EventTarget {
8
12
  constructor(sctp, parameters, sendOpen = true) {
9
13
  super();
@@ -220,10 +224,9 @@ class RTCDataChannel extends helper_1.EventTarget {
220
224
  }
221
225
  }
222
226
  send(data) {
223
- const size = Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data);
227
+ const size = this.sctp.datachannelSend(this, data);
224
228
  this.messagesSent++;
225
229
  this.bytesSent += size;
226
- this.sctp.datachannelSend(this, data);
227
230
  }
228
231
  close() {
229
232
  this.sctp.dataChannelClose(this);
@@ -1 +1 @@
1
- {"version":3,"file":"dataChannel.js","sourceRoot":"","sources":["../../../src/dataChannel.ts"],"names":[],"mappings":"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","sourcesContent":["import { Event, debug } from \"./imports/common\";\n\nimport { EventTarget } from \"./helper\";\nimport type { RTCSctpTransport } from \"./transport/sctp\";\nimport type { Callback, CallbackWithValue } from \"./types/util\";\n\nconst log = debug(\"werift:packages/webrtc/src/dataChannel.ts\");\n\nexport interface DataChannelStats {\n messagesSent: number;\n bytesSent: number;\n messagesReceived: number;\n bytesReceived: number;\n}\n\nexport class RTCDataChannel extends EventTarget implements DataChannelStats {\n readonly stateChange = new Event<[DCState]>();\n readonly stateChanged = new Event<[DCState]>();\n readonly onMessage = new Event<[string | Buffer]>();\n // todo impl\n readonly error = new Event<[Error]>();\n readonly bufferedAmountLow = new Event();\n onopen?: Callback;\n onclose?: Callback;\n onclosing?: Callback;\n onmessage?: CallbackWithValue<MessageEvent>;\n // todo impl\n onerror?: CallbackWithValue<RTCErrorEvent>;\n isCreatedByRemote = false;\n id: number;\n readyState: DCState = \"connecting\";\n\n bufferedAmount = 0;\n private _bufferedAmountLowThreshold = 0;\n\n // Statistics\n messagesSent = 0;\n bytesSent = 0;\n messagesReceived = 0;\n bytesReceived = 0;\n\n constructor(\n readonly sctp: RTCSctpTransport,\n private readonly parameters: RTCDataChannelParameters,\n public readonly sendOpen = true,\n ) {\n super();\n\n this.id = this.parameters.id;\n\n if (parameters.negotiated) {\n if (this.id == undefined || this.id < 0 || this.id > 65534) {\n throw new Error(\n \"ID must be in range 0-65534 if data channel is negotiated out-of-band\",\n );\n }\n this.sctp.dataChannelAddNegotiated(this);\n } else {\n if (sendOpen) {\n this.sendOpen = false;\n this.sctp.dataChannelOpen(this);\n }\n }\n }\n\n get ordered() {\n return this.parameters.ordered;\n }\n\n get maxRetransmits() {\n return this.parameters.maxRetransmits;\n }\n\n get maxPacketLifeTime() {\n return this.parameters.maxPacketLifeTime;\n }\n\n get label() {\n return this.parameters.label;\n }\n\n get protocol() {\n return this.parameters.protocol;\n }\n\n get negotiated() {\n return this.parameters.negotiated;\n }\n\n get bufferedAmountLowThreshold() {\n return this._bufferedAmountLowThreshold;\n }\n\n set bufferedAmountLowThreshold(value: number) {\n if (value < 0 || value > 4294967295) {\n throw new Error(\n \"bufferedAmountLowThreshold must be in range 0 - 4294967295\",\n );\n }\n this._bufferedAmountLowThreshold = value;\n }\n\n setId(id: number) {\n this.id = id;\n }\n\n setReadyState(state: DCState) {\n if (state !== this.readyState) {\n this.readyState = state;\n this.stateChange.execute(state);\n this.stateChanged.execute(state);\n\n switch (state) {\n case \"open\":\n if (this.onopen) this.onopen();\n this.emit(\"open\");\n break;\n case \"closed\":\n if (this.onclose) this.onclose();\n this.emit(\"close\");\n break;\n case \"closing\":\n if (this.onclosing) this.onclosing();\n break;\n }\n log(\"change state\", state);\n }\n }\n\n addBufferedAmount(amount: number) {\n const crossesThreshold =\n this.bufferedAmount > this.bufferedAmountLowThreshold &&\n this.bufferedAmount + amount <= this.bufferedAmountLowThreshold;\n this.bufferedAmount += amount;\n if (crossesThreshold) {\n this.bufferedAmountLow.execute();\n this.emit(\"bufferedamountlow\");\n }\n }\n\n send(data: Buffer | string) {\n const size = Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data);\n this.messagesSent++;\n this.bytesSent += size;\n this.sctp.datachannelSend(this, data);\n }\n\n close() {\n this.sctp.dataChannelClose(this);\n }\n}\n\nexport type DCState = \"open\" | \"closed\" | \"connecting\" | \"closing\";\n\nexport class RTCDataChannelParameters {\n label = \"\";\n maxPacketLifeTime?: number; // sec\n maxRetransmits?: number;\n ordered = true;\n protocol = \"\";\n negotiated = false;\n id!: number;\n constructor(props: Partial<RTCDataChannelParameters> = {}) {\n Object.assign(this, props);\n }\n}\n\nexport interface MessageEvent {\n data: string | Buffer;\n}\n\nexport interface RTCErrorEvent {\n error: any;\n}\n"]}
1
+ {"version":3,"file":"dataChannel.js","sourceRoot":"","sources":["../../../src/dataChannel.ts"],"names":[],"mappings":";;;AAeA,8DAEC;AAjBD,6CAAgD;AAEhD,qCAAuC;AAIvC,MAAM,GAAG,GAAG,IAAA,cAAK,EAAC,2CAA2C,CAAC,CAAC;AAS/D,SAAgB,yBAAyB,CAAC,IAAqB;IAC7D,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACvE,CAAC;AAED,MAAa,cAAe,SAAQ,oBAAW;IA0B7C,YACW,IAAsB,EACd,UAAoC,EACrC,WAAW,IAAI;QAE/B,KAAK,EAAE,CAAC;QAJR;;;;mBAAS,IAAI;WAAkB;QAC/B;;;;mBAAiB,UAAU;WAA0B;QACrD;;;;mBAAgB,QAAQ;WAAO;QA5BxB;;;;mBAAc,IAAI,cAAK,EAAa;WAAC;QACrC;;;;mBAAe,IAAI,cAAK,EAAa;WAAC;QACtC;;;;mBAAY,IAAI,cAAK,EAAqB;WAAC;QACpD,YAAY;QACH;;;;mBAAQ,IAAI,cAAK,EAAW;WAAC;QAC7B;;;;mBAAoB,IAAI,cAAK,EAAE;WAAC;QACzC;;;;;WAAkB;QAClB;;;;;WAAmB;QACnB;;;;;WAAqB;QACrB;;;;;WAA4C;QAC5C,YAAY;QACZ;;;;;WAA2C;QAC3C;;;;mBAAoB,KAAK;WAAC;QAC1B;;;;;WAAW;QACX;;;;mBAAsB,YAAY;WAAC;QAEnC;;;;mBAAiB,CAAC;WAAC;QACX;;;;mBAA8B,CAAC;WAAC;QAExC,aAAa;QACb;;;;mBAAe,CAAC;WAAC;QACjB;;;;mBAAY,CAAC;WAAC;QACd;;;;mBAAmB,CAAC;WAAC;QACrB;;;;mBAAgB,CAAC;WAAC;QAShB,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAE7B,IAAI,UAAU,CAAC,UAAU,EAAE,CAAC;YAC1B,IAAI,IAAI,CAAC,EAAE,IAAI,SAAS,IAAI,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC;gBAC3D,MAAM,IAAI,KAAK,CACb,uEAAuE,CACxE,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;gBACtB,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;IACjC,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC;IACxC,CAAC;IAED,IAAI,iBAAiB;QACnB,OAAO,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC;IAC3C,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;IAC/B,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;IAClC,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;IACpC,CAAC;IAED,IAAI,0BAA0B;QAC5B,OAAO,IAAI,CAAC,2BAA2B,CAAC;IAC1C,CAAC;IAED,IAAI,0BAA0B,CAAC,KAAa;QAC1C,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,UAAU,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,2BAA2B,GAAG,KAAK,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,EAAU;QACd,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACf,CAAC;IAED,aAAa,CAAC,KAAc;QAC1B,IAAI,KAAK,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;YAC9B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;YACxB,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAChC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAEjC,QAAQ,KAAK,EAAE,CAAC;gBACd,KAAK,MAAM;oBACT,IAAI,IAAI,CAAC,MAAM;wBAAE,IAAI,CAAC,MAAM,EAAE,CAAC;oBAC/B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBAClB,MAAM;gBACR,KAAK,QAAQ;oBACX,IAAI,IAAI,CAAC,OAAO;wBAAE,IAAI,CAAC,OAAO,EAAE,CAAC;oBACjC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACnB,MAAM;gBACR,KAAK,SAAS;oBACZ,IAAI,IAAI,CAAC,SAAS;wBAAE,IAAI,CAAC,SAAS,EAAE,CAAC;oBACrC,MAAM;YACV,CAAC;YACD,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,iBAAiB,CAAC,MAAc;QAC9B,MAAM,gBAAgB,GACpB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,0BAA0B;YACrD,IAAI,CAAC,cAAc,GAAG,MAAM,IAAI,IAAI,CAAC,0BAA0B,CAAC;QAClE,IAAI,CAAC,cAAc,IAAI,MAAM,CAAC;QAC9B,IAAI,gBAAgB,EAAE,CAAC;YACrB,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,CAAC;YACjC,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,IAAI,CAAC,IAAqB;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC;IACzB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;CACF;AAtID,wCAsIC;AAID,MAAa,wBAAwB;IAQnC,YAAY,QAA2C,EAAE;QAPzD;;;;mBAAQ,EAAE;WAAC;QACX;;;;;WAA2B,CAAC,MAAM;QAClC;;;;;WAAwB;QACxB;;;;mBAAU,IAAI;WAAC;QACf;;;;mBAAW,EAAE;WAAC;QACd;;;;mBAAa,KAAK;WAAC;QACnB;;;;;WAAY;QAEV,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;CACF;AAXD,4DAWC","sourcesContent":["import { Event, debug } from \"./imports/common\";\n\nimport { EventTarget } from \"./helper\";\nimport type { RTCSctpTransport } from \"./transport/sctp\";\nimport type { Callback, CallbackWithValue } from \"./types/util\";\n\nconst log = debug(\"werift:packages/webrtc/src/dataChannel.ts\");\n\nexport interface DataChannelStats {\n messagesSent: number;\n bytesSent: number;\n messagesReceived: number;\n bytesReceived: number;\n}\n\nexport function getDataChannelMessageSize(data: Buffer | string) {\n return Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data);\n}\n\nexport class RTCDataChannel extends EventTarget implements DataChannelStats {\n readonly stateChange = new Event<[DCState]>();\n readonly stateChanged = new Event<[DCState]>();\n readonly onMessage = new Event<[string | Buffer]>();\n // todo impl\n readonly error = new Event<[Error]>();\n readonly bufferedAmountLow = new Event();\n onopen?: Callback;\n onclose?: Callback;\n onclosing?: Callback;\n onmessage?: CallbackWithValue<MessageEvent>;\n // todo impl\n onerror?: CallbackWithValue<RTCErrorEvent>;\n isCreatedByRemote = false;\n id: number;\n readyState: DCState = \"connecting\";\n\n bufferedAmount = 0;\n private _bufferedAmountLowThreshold = 0;\n\n // Statistics\n messagesSent = 0;\n bytesSent = 0;\n messagesReceived = 0;\n bytesReceived = 0;\n\n constructor(\n readonly sctp: RTCSctpTransport,\n private readonly parameters: RTCDataChannelParameters,\n public readonly sendOpen = true,\n ) {\n super();\n\n this.id = this.parameters.id;\n\n if (parameters.negotiated) {\n if (this.id == undefined || this.id < 0 || this.id > 65534) {\n throw new Error(\n \"ID must be in range 0-65534 if data channel is negotiated out-of-band\",\n );\n }\n this.sctp.dataChannelAddNegotiated(this);\n } else {\n if (sendOpen) {\n this.sendOpen = false;\n this.sctp.dataChannelOpen(this);\n }\n }\n }\n\n get ordered() {\n return this.parameters.ordered;\n }\n\n get maxRetransmits() {\n return this.parameters.maxRetransmits;\n }\n\n get maxPacketLifeTime() {\n return this.parameters.maxPacketLifeTime;\n }\n\n get label() {\n return this.parameters.label;\n }\n\n get protocol() {\n return this.parameters.protocol;\n }\n\n get negotiated() {\n return this.parameters.negotiated;\n }\n\n get bufferedAmountLowThreshold() {\n return this._bufferedAmountLowThreshold;\n }\n\n set bufferedAmountLowThreshold(value: number) {\n if (value < 0 || value > 4294967295) {\n throw new Error(\n \"bufferedAmountLowThreshold must be in range 0 - 4294967295\",\n );\n }\n this._bufferedAmountLowThreshold = value;\n }\n\n setId(id: number) {\n this.id = id;\n }\n\n setReadyState(state: DCState) {\n if (state !== this.readyState) {\n this.readyState = state;\n this.stateChange.execute(state);\n this.stateChanged.execute(state);\n\n switch (state) {\n case \"open\":\n if (this.onopen) this.onopen();\n this.emit(\"open\");\n break;\n case \"closed\":\n if (this.onclose) this.onclose();\n this.emit(\"close\");\n break;\n case \"closing\":\n if (this.onclosing) this.onclosing();\n break;\n }\n log(\"change state\", state);\n }\n }\n\n addBufferedAmount(amount: number) {\n const crossesThreshold =\n this.bufferedAmount > this.bufferedAmountLowThreshold &&\n this.bufferedAmount + amount <= this.bufferedAmountLowThreshold;\n this.bufferedAmount += amount;\n if (crossesThreshold) {\n this.bufferedAmountLow.execute();\n this.emit(\"bufferedamountlow\");\n }\n }\n\n send(data: Buffer | string) {\n const size = this.sctp.datachannelSend(this, data);\n this.messagesSent++;\n this.bytesSent += size;\n }\n\n close() {\n this.sctp.dataChannelClose(this);\n }\n}\n\nexport type DCState = \"open\" | \"closed\" | \"connecting\" | \"closing\";\n\nexport class RTCDataChannelParameters {\n label = \"\";\n maxPacketLifeTime?: number; // sec\n maxRetransmits?: number;\n ordered = true;\n protocol = \"\";\n negotiated = false;\n id!: number;\n constructor(props: Partial<RTCDataChannelParameters> = {}) {\n Object.assign(this, props);\n }\n}\n\nexport interface MessageEvent {\n data: string | Buffer;\n}\n\nexport interface RTCErrorEvent {\n error: any;\n}\n"]}
@@ -23,6 +23,7 @@ export declare class RTCPeerConnection extends EventTarget {
23
23
  private readonly secureManager;
24
24
  private isClosed;
25
25
  private shouldNegotiationneeded;
26
+ private remoteBundleNegotiated;
26
27
  readonly iceGatheringStateChange: Event<["complete" | "new" | "gathering"]>;
27
28
  readonly iceConnectionStateChange: Event<["disconnected" | "closed" | "completed" | "new" | "connected" | "failed" | "checking"]>;
28
29
  readonly signalingStateChange: Event<["closed" | "stable" | "have-local-offer" | "have-remote-offer" | "have-local-pranswer" | "have-remote-pranswer"]>;
@@ -48,7 +49,7 @@ export declare class RTCPeerConnection extends EventTarget {
48
49
  get iceGathererState(): "complete" | "new" | "gathering";
49
50
  get iceGatheringState(): "complete" | "new" | "gathering";
50
51
  get dtlsTransports(): RTCDtlsTransport[];
51
- get sctpTransport(): import(".").RTCSctpTransport | undefined;
52
+ get sctpTransport(): import("./transport/sctp").RTCSctpTransport | undefined;
52
53
  get sctpRemotePort(): number | undefined;
53
54
  get iceTransports(): RTCIceTransport[];
54
55
  get extIdUriMap(): {
@@ -149,6 +150,8 @@ export interface PeerConfig {
149
150
  disableRecvRetransmit: boolean;
150
151
  }>;
151
152
  midSuffix: boolean;
153
+ /** Advertised local SCTP max-message-size in SDP. Use 0 for unlimited. */
154
+ maxMessageSize: number;
152
155
  }
153
156
  export declare const findCodecByMimeType: (codecs: RTCRtpCodecParameters[], target: RTCRtpCodecParameters) => RTCRtpCodecParameters | undefined;
154
157
  export type RTCIceServer = {
@@ -10,6 +10,7 @@ const sctpManager_1 = require("./sctpManager");
10
10
  const sdp_1 = require("./sdp");
11
11
  const sdpManager_1 = require("./sdpManager");
12
12
  const secureTransportManager_1 = require("./secureTransportManager");
13
+ const sctp_1 = require("./transport/sctp");
13
14
  const utils_1 = require("./utils");
14
15
  const log = (0, common_1.debug)("werift:packages/webrtc/src/peerConnection.ts");
15
16
  class RTCPeerConnection extends helper_1.EventTarget {
@@ -87,6 +88,12 @@ class RTCPeerConnection extends helper_1.EventTarget {
87
88
  writable: true,
88
89
  value: false
89
90
  });
91
+ Object.defineProperty(this, "remoteBundleNegotiated", {
92
+ enumerable: true,
93
+ configurable: true,
94
+ writable: true,
95
+ value: false
96
+ });
90
97
  Object.defineProperty(this, "iceGatheringStateChange", {
91
98
  enumerable: true,
92
99
  configurable: true,
@@ -337,6 +344,14 @@ class RTCPeerConnection extends helper_1.EventTarget {
337
344
  if (min >= max)
338
345
  throw new Error("The min must be less than max");
339
346
  }
347
+ if (!Number.isInteger(this.config.maxMessageSize) ||
348
+ this.config.maxMessageSize < 0) {
349
+ throw new Error("maxMessageSize must be a non-negative integer");
350
+ }
351
+ if (this.sctpManager?.sctpTransport) {
352
+ this.sctpManager.sctpTransport.maxMessageSize =
353
+ this.config.maxMessageSize;
354
+ }
340
355
  for (const [i, codecParams] of (0, helper_1.enumerate)([
341
356
  ...(this.config.codecs.audio || []),
342
357
  ...(this.config.codecs.video || []),
@@ -391,7 +406,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
391
406
  return description.toJSON();
392
407
  }
393
408
  createSctpTransport() {
394
- const sctp = this.sctpManager.createSctpTransport();
409
+ const sctp = this.sctpManager.createSctpTransport(this.config.maxMessageSize);
395
410
  const dtlsTransport = this.findOrCreateTransport();
396
411
  sctp.setDtlsTransport(dtlsTransport);
397
412
  return sctp;
@@ -416,13 +431,15 @@ class RTCPeerConnection extends helper_1.EventTarget {
416
431
  this.needNegotiation();
417
432
  }
418
433
  findOrCreateTransport() {
419
- const [existing] = this.iceTransports;
434
+ const existingDtlsTransport = this.dtlsTransports.find((transport) => transport.state !== "closed");
435
+ const existing = existingDtlsTransport?.iceTransport;
420
436
  // Gather ICE candidates for only one track. If the remote endpoint is not bundle-aware, negotiate only one media track.
421
437
  // https://w3c.github.io/webrtc-pc/#rtcbundlepolicy-enum
422
438
  if (this.sdpManager.bundlePolicy === "max-bundle" ||
423
- (this.sdpManager.bundlePolicy !== "disable" && this.remoteIsBundled)) {
424
- if (existing) {
425
- return this.dtlsTransports[0];
439
+ (this.sdpManager.bundlePolicy !== "disable" &&
440
+ (this.remoteIsBundled || this.remoteBundleNegotiated))) {
441
+ if (existingDtlsTransport) {
442
+ return existingDtlsTransport;
426
443
  }
427
444
  }
428
445
  const dtlsTransport = this.secureManager.createTransport();
@@ -593,6 +610,9 @@ class RTCPeerConnection extends helper_1.EventTarget {
593
610
  }
594
611
  // # parse and validate description
595
612
  const remoteSdp = this.sdpManager.setRemoteDescription(sessionDescription, this.signalingState);
613
+ if (remoteSdp.group.some((group) => group.semantic === "BUNDLE" && group.items.length > 0)) {
614
+ this.remoteBundleNegotiated = true;
615
+ }
596
616
  let bundleTransport;
597
617
  // # apply description
598
618
  const matchTransceiverWithMedia = (transceiver, media) => transceiver.kind === media.kind &&
@@ -832,6 +852,7 @@ function generateDefaultPeerConfig() {
832
852
  debug: {},
833
853
  midSuffix: false,
834
854
  forceTurnTCP: false,
855
+ maxMessageSize: sctp_1.DEFAULT_MAX_MESSAGE_SIZE,
835
856
  };
836
857
  }
837
858
  exports.defaultPeerConfig = generateDefaultPeerConfig();