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.
- package/lib/dtls/src/flight/server/flight6.js +12 -2
- package/lib/dtls/src/flight/server/flight6.js.map +1 -1
- package/lib/dtls/src/server.js +6 -1
- package/lib/dtls/src/server.js.map +1 -1
- package/lib/dtls/src/socket.d.ts +1 -0
- package/lib/dtls/src/socket.js +3 -0
- package/lib/dtls/src/socket.js.map +1 -1
- package/lib/index.mjs +434 -75
- package/lib/nonstandard/index.mjs +207 -40
- package/lib/rtp/src/index.d.ts +1 -0
- package/lib/rtp/src/index.js +1 -0
- package/lib/rtp/src/index.js.map +1 -1
- package/lib/rtp/src/srtp/cipher/ctr.d.ts +3 -3
- package/lib/rtp/src/srtp/cipher/ctr.js +25 -14
- package/lib/rtp/src/srtp/cipher/ctr.js.map +1 -1
- package/lib/rtp/src/srtp/cipher/gcm.d.ts +3 -3
- package/lib/rtp/src/srtp/cipher/gcm.js +57 -20
- package/lib/rtp/src/srtp/cipher/gcm.js.map +1 -1
- package/lib/rtp/src/srtp/cipher/index.d.ts +1 -1
- package/lib/rtp/src/srtp/cipher/index.js +1 -1
- package/lib/rtp/src/srtp/cipher/index.js.map +1 -1
- package/lib/rtp/src/srtp/context/srtp.d.ts +2 -1
- package/lib/rtp/src/srtp/context/srtp.js +22 -5
- package/lib/rtp/src/srtp/context/srtp.js.map +1 -1
- package/lib/rtp/src/srtp/error.d.ts +3 -0
- package/lib/rtp/src/srtp/error.js +11 -0
- package/lib/rtp/src/srtp/error.js.map +1 -0
- package/lib/rtp/src/srtp/packet.d.ts +5 -0
- package/lib/rtp/src/srtp/packet.js +48 -0
- package/lib/rtp/src/srtp/packet.js.map +1 -0
- package/lib/webrtc/src/dataChannel.d.ts +1 -0
- package/lib/webrtc/src/dataChannel.js +5 -2
- package/lib/webrtc/src/dataChannel.js.map +1 -1
- package/lib/webrtc/src/peerConnection.d.ts +4 -1
- package/lib/webrtc/src/peerConnection.js +26 -5
- package/lib/webrtc/src/peerConnection.js.map +1 -1
- package/lib/webrtc/src/sctpManager.d.ts +1 -1
- package/lib/webrtc/src/sctpManager.js +3 -2
- package/lib/webrtc/src/sctpManager.js.map +1 -1
- package/lib/webrtc/src/sdpManager.d.ts +1 -1
- package/lib/webrtc/src/sdpManager.js +3 -4
- package/lib/webrtc/src/sdpManager.js.map +1 -1
- package/lib/webrtc/src/secureTransportManager.js +1 -1
- package/lib/webrtc/src/secureTransportManager.js.map +1 -1
- package/lib/webrtc/src/transceiverManager.js +3 -2
- package/lib/webrtc/src/transceiverManager.js.map +1 -1
- package/lib/webrtc/src/transport/dtls.d.ts +1 -0
- package/lib/webrtc/src/transport/dtls.js +117 -12
- package/lib/webrtc/src/transport/dtls.js.map +1 -1
- package/lib/webrtc/src/transport/sctp.d.ts +9 -3
- package/lib/webrtc/src/transport/sctp.js +35 -7
- package/lib/webrtc/src/transport/sctp.js.map +1 -1
- package/lib/webrtc/src/utils.d.ts +2 -0
- package/lib/webrtc/src/utils.js +20 -0
- package/lib/webrtc/src/utils.js.map +1 -1
- 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
|
|
9
|
-
const
|
|
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
|
|
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
|
-
|
|
55
|
+
headerBuffer.copy(dst);
|
|
54
56
|
const iv = this.rtpInitializationVector(header, rolloverCounter);
|
|
55
|
-
const enc = cipherText.slice(header.payloadOffset,
|
|
56
|
-
const
|
|
57
|
-
|
|
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 [
|
|
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 =
|
|
81
|
-
const
|
|
82
|
-
const
|
|
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
|
-
|
|
86
|
-
|
|
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 =
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
}
|
|
@@ -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,
|
|
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
|
|
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 =
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
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":";;;
|
|
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,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 =
|
|
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":";;;
|
|
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("
|
|
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
|
|
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" &&
|
|
424
|
-
|
|
425
|
-
|
|
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();
|