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