werift 0.15.0 → 0.15.3
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/index.d.ts +1 -0
- package/lib/common/src/index.js +6 -1
- package/lib/common/src/index.js.map +1 -1
- package/lib/common/src/network.d.ts +5 -0
- package/lib/common/src/network.js +41 -0
- package/lib/common/src/network.js.map +1 -0
- package/lib/dtls/src/cipher/namedCurve.js +5 -1
- package/lib/dtls/src/cipher/namedCurve.js.map +1 -1
- package/lib/dtls/src/cipher/prf.js +5 -1
- package/lib/dtls/src/cipher/prf.js.map +1 -1
- package/lib/dtls/src/cipher/suites/aead.js +5 -1
- package/lib/dtls/src/cipher/suites/aead.js.map +1 -1
- package/lib/dtls/src/context/cipher.js +6 -5
- package/lib/dtls/src/context/cipher.js.map +1 -1
- package/lib/ice/src/exceptions.d.ts +4 -1
- package/lib/ice/src/exceptions.js +5 -3
- package/lib/ice/src/exceptions.js.map +1 -1
- package/lib/ice/src/ice.d.ts +1 -1
- package/lib/ice/src/ice.js +67 -26
- package/lib/ice/src/ice.js.map +1 -1
- package/lib/ice/src/index.js +5 -1
- package/lib/ice/src/index.js.map +1 -1
- package/lib/ice/src/stun/attributes.d.ts +16 -3
- package/lib/ice/src/stun/attributes.js +38 -2
- package/lib/ice/src/stun/attributes.js.map +1 -1
- package/lib/ice/src/stun/const.d.ts +1 -1
- package/lib/ice/src/stun/const.js +5 -2
- package/lib/ice/src/stun/const.js.map +1 -1
- package/lib/ice/src/stun/message.d.ts +6 -10
- package/lib/ice/src/stun/message.js +23 -17
- package/lib/ice/src/stun/message.js.map +1 -1
- package/lib/ice/src/stun/protocol.js +0 -1
- package/lib/ice/src/stun/protocol.js.map +1 -1
- package/lib/ice/src/stun/transaction.d.ts +0 -2
- package/lib/ice/src/stun/transaction.js +1 -1
- package/lib/ice/src/stun/transaction.js.map +1 -1
- package/lib/ice/src/transport.js +2 -2
- package/lib/ice/src/transport.js.map +1 -1
- package/lib/ice/src/turn/protocol.d.ts +8 -6
- package/lib/ice/src/turn/protocol.js +73 -71
- package/lib/ice/src/turn/protocol.js.map +1 -1
- package/lib/ice/src/utils.d.ts +0 -5
- package/lib/ice/src/utils.js +1 -38
- package/lib/ice/src/utils.js.map +1 -1
- package/lib/rtp/src/container/webm.js +5 -1
- package/lib/rtp/src/container/webm.js.map +1 -1
- package/lib/rtp/src/index.js +5 -1
- package/lib/rtp/src/index.js.map +1 -1
- package/lib/rtp/src/processor/webm.js +1 -2
- package/lib/rtp/src/processor/webm.js.map +1 -1
- package/lib/webrtc/src/index.js +5 -1
- package/lib/webrtc/src/index.js.map +1 -1
- package/lib/webrtc/src/media/parameters.d.ts +4 -0
- package/lib/webrtc/src/media/parameters.js.map +1 -1
- package/lib/webrtc/src/media/rtpSender.js +5 -1
- package/lib/webrtc/src/media/rtpSender.js.map +1 -1
- package/lib/webrtc/src/media/rtpTransceiver.js +5 -1
- package/lib/webrtc/src/media/rtpTransceiver.js.map +1 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js +5 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js.map +1 -1
- package/lib/webrtc/src/nonstandard/userMedia.js +1 -1
- package/lib/webrtc/src/nonstandard/userMedia.js.map +1 -1
- package/lib/webrtc/src/peerConnection.d.ts +4 -0
- package/lib/webrtc/src/peerConnection.js +9 -1
- package/lib/webrtc/src/peerConnection.js.map +1 -1
- package/lib/webrtc/src/transport/dtls.js +2 -6
- package/lib/webrtc/src/transport/dtls.js.map +1 -1
- package/lib/webrtc/src/transport/sctp.js +5 -1
- package/lib/webrtc/src/transport/sctp.js.map +1 -1
- package/package.json +9 -19
- package/src/media/parameters.ts +4 -0
- package/src/nonstandard/userMedia.ts +1 -1
- package/src/peerConnection.ts +9 -0
- package/src/transport/dtls.ts +2 -6
|
@@ -19,30 +19,32 @@ function parseMessage(data, integrityKey) {
|
|
|
19
19
|
if (data.length !== const_1.HEADER_LENGTH + length) {
|
|
20
20
|
return undefined;
|
|
21
21
|
}
|
|
22
|
-
const
|
|
22
|
+
const attributeRepository = new attributes_1.AttributeRepository();
|
|
23
23
|
for (let pos = const_1.HEADER_LENGTH; pos <= data.length - 4;) {
|
|
24
24
|
const [attrType, attrLen] = jspack_1.jspack.Unpack("!HH", data.slice(pos, pos + 4));
|
|
25
|
-
const
|
|
25
|
+
const payload = data.slice(pos + 4, pos + 4 + attrLen);
|
|
26
26
|
const padLen = 4 * Math.floor((attrLen + 3) / 4) - attrLen;
|
|
27
27
|
const attributesTypes = Object.keys(attributes_1.ATTRIBUTES_BY_TYPE);
|
|
28
28
|
if (attributesTypes.includes(attrType.toString())) {
|
|
29
29
|
const [, attrName, , attrUnpack] = attributes_1.ATTRIBUTES_BY_TYPE[attrType];
|
|
30
30
|
if (attrUnpack.name === attributes_1.unpackXorAddress.name) {
|
|
31
|
-
|
|
31
|
+
attributeRepository.setAttribute(attrName, attrUnpack(payload, transactionId));
|
|
32
32
|
}
|
|
33
33
|
else {
|
|
34
|
-
|
|
34
|
+
attributeRepository.setAttribute(attrName, attrUnpack(payload));
|
|
35
35
|
}
|
|
36
36
|
if (attrName === "FINGERPRINT") {
|
|
37
37
|
const fingerprint = messageFingerprint(data.slice(0, pos));
|
|
38
|
-
|
|
38
|
+
const expect = attributeRepository.getAttributeValue("FINGERPRINT");
|
|
39
|
+
if (expect !== fingerprint) {
|
|
39
40
|
return undefined;
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
else if (attrName === "MESSAGE-INTEGRITY") {
|
|
43
44
|
if (integrityKey) {
|
|
44
45
|
const integrity = messageIntegrity(data.slice(0, pos), integrityKey);
|
|
45
|
-
|
|
46
|
+
const expect = attributeRepository.getAttributeValue("MESSAGE-INTEGRITY");
|
|
47
|
+
if (!integrity.equals(expect)) {
|
|
46
48
|
return undefined;
|
|
47
49
|
}
|
|
48
50
|
}
|
|
@@ -50,18 +52,17 @@ function parseMessage(data, integrityKey) {
|
|
|
50
52
|
}
|
|
51
53
|
pos += 4 + attrLen + padLen;
|
|
52
54
|
}
|
|
55
|
+
const attributes = attributeRepository.getAttributes();
|
|
56
|
+
attributeRepository.clear();
|
|
53
57
|
return new Message(messageType & 0x3eef, messageType & 0x0110, transactionId, attributes);
|
|
54
58
|
}
|
|
55
59
|
exports.parseMessage = parseMessage;
|
|
56
|
-
class Message {
|
|
57
|
-
constructor(messageMethod, messageClass, transactionId = (0, helper_1.randomTransactionId)(), attributes =
|
|
60
|
+
class Message extends attributes_1.AttributeRepository {
|
|
61
|
+
constructor(messageMethod, messageClass, transactionId = (0, helper_1.randomTransactionId)(), attributes = []) {
|
|
62
|
+
super(attributes);
|
|
58
63
|
this.messageMethod = messageMethod;
|
|
59
64
|
this.messageClass = messageClass;
|
|
60
65
|
this.transactionId = transactionId;
|
|
61
|
-
this.attributes = attributes;
|
|
62
|
-
}
|
|
63
|
-
get attributesKeys() {
|
|
64
|
-
return Object.keys(this.attributes);
|
|
65
66
|
}
|
|
66
67
|
get transactionIdHex() {
|
|
67
68
|
return this.transactionId.toString("hex");
|
|
@@ -69,7 +70,7 @@ class Message {
|
|
|
69
70
|
get bytes() {
|
|
70
71
|
let data = Buffer.from([]);
|
|
71
72
|
for (const attrName of this.attributesKeys) {
|
|
72
|
-
const attrValue = this.
|
|
73
|
+
const attrValue = this.getAttributeValue(attrName);
|
|
73
74
|
const [attrType, , attrPack] = attributes_1.ATTRIBUTES_BY_NAME[attrName];
|
|
74
75
|
const v = attrPack.name === attributes_1.packXorAddress.name
|
|
75
76
|
? attrPack(attrValue, this.transactionId)
|
|
@@ -90,11 +91,16 @@ class Message {
|
|
|
90
91
|
]));
|
|
91
92
|
return Buffer.concat([buf, this.transactionId, data]);
|
|
92
93
|
}
|
|
93
|
-
addFingerprint() {
|
|
94
|
-
this.attributes["FINGERPRINT"] = messageFingerprint(this.bytes);
|
|
95
|
-
}
|
|
96
94
|
addMessageIntegrity(key) {
|
|
97
|
-
this.
|
|
95
|
+
this.setAttribute("MESSAGE-INTEGRITY", this.messageIntegrity(key));
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
98
|
+
messageIntegrity(key) {
|
|
99
|
+
const checkData = setBodyLength(this.bytes, this.bytes.length - const_1.HEADER_LENGTH + const_1.INTEGRITY_LENGTH);
|
|
100
|
+
return Buffer.from((0, crypto_1.createHmac)("sha1", key).update(checkData).digest("hex"), "hex");
|
|
101
|
+
}
|
|
102
|
+
addFingerprint() {
|
|
103
|
+
this.setAttribute("FINGERPRINT", messageFingerprint(this.bytes));
|
|
98
104
|
}
|
|
99
105
|
}
|
|
100
106
|
exports.Message = Message;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../../../../ice/src/stun/message.ts"],"names":[],"mappings":"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","sourcesContent":["import crc32 from \"buffer-crc32\";\nimport { createHmac } from \"crypto\";\nimport { jspack } from \"jspack\";\n\nimport { bufferXor, randomTransactionId } from \"../helper\";\nimport {\n ATTRIBUTES_BY_NAME,\n ATTRIBUTES_BY_TYPE,\n packXorAddress,\n unpackXorAddress,\n} from \"./attributes\";\nimport {\n ATTRIBUTES,\n classes,\n COOKIE,\n FINGERPRINT_LENGTH,\n FINGERPRINT_XOR,\n HEADER_LENGTH,\n INTEGRITY_LENGTH,\n methods,\n} from \"./const\";\n\nexport function parseMessage(\n data: Buffer,\n integrityKey?: Buffer\n): Message | undefined {\n if (data.length < HEADER_LENGTH) {\n return undefined;\n }\n const [messageType, length] = jspack.Unpack(\n \"!HHI\",\n data.slice(0, HEADER_LENGTH)\n );\n\n const transactionId = Buffer.from(\n data.slice(HEADER_LENGTH - 12, HEADER_LENGTH)\n );\n\n if (data.length !== HEADER_LENGTH + length) {\n return undefined;\n }\n\n const attributes: { [key: string]: any } = {};\n\n for (let pos = HEADER_LENGTH; pos <= data.length - 4; ) {\n const [attrType, attrLen] = jspack.Unpack(\"!HH\", data.slice(pos, pos + 4));\n const v = data.slice(pos + 4, pos + 4 + attrLen);\n const padLen = 4 * Math.floor((attrLen + 3) / 4) - attrLen;\n const attributesTypes = Object.keys(ATTRIBUTES_BY_TYPE);\n if (attributesTypes.includes(attrType.toString())) {\n const [, attrName, , attrUnpack] = ATTRIBUTES_BY_TYPE[attrType];\n if (attrUnpack.name === unpackXorAddress.name) {\n attributes[attrName] = attrUnpack(v, transactionId);\n } else {\n attributes[attrName] = attrUnpack(v);\n }\n\n if (attrName === \"FINGERPRINT\") {\n const fingerprint = messageFingerprint(data.slice(0, pos));\n if (attributes[attrName] !== fingerprint) {\n return undefined;\n }\n } else if (attrName === \"MESSAGE-INTEGRITY\") {\n if (integrityKey) {\n const integrity = messageIntegrity(data.slice(0, pos), integrityKey);\n if (!integrity.equals(attributes[attrName])) {\n return undefined;\n }\n }\n }\n }\n pos += 4 + attrLen + padLen;\n }\n\n return new Message(\n messageType & 0x3eef,\n messageType & 0x0110,\n transactionId,\n attributes\n );\n}\n\nexport class Message {\n constructor(\n public messageMethod: methods,\n public messageClass: classes,\n public transactionId: Buffer = randomTransactionId(),\n public attributes: { [key in typeof ATTRIBUTES[number]]?: any } = {}\n ) {}\n\n get attributesKeys(): typeof ATTRIBUTES[number][] {\n return Object.keys(this.attributes) as any;\n }\n\n get transactionIdHex() {\n return this.transactionId.toString(\"hex\");\n }\n\n get bytes() {\n let data = Buffer.from([]);\n for (const attrName of this.attributesKeys) {\n const attrValue = (this.attributes as any)[attrName];\n const [attrType, , attrPack] = ATTRIBUTES_BY_NAME[attrName];\n const v =\n attrPack.name === packXorAddress.name\n ? attrPack(attrValue, this.transactionId)\n : attrPack(attrValue);\n const attrLen = v.length;\n const padLen = 4 * Math.floor((attrLen + 3) / 4) - attrLen;\n data = Buffer.concat([\n data,\n Buffer.from(jspack.Pack(\"!HH\", [attrType, attrLen])),\n v,\n ...[...Array(padLen)].map(() => Buffer.from(\"\\x00\")),\n ]);\n }\n const buf = Buffer.from(\n jspack.Pack(\"!HHI\", [\n this.messageMethod | this.messageClass,\n data.length,\n COOKIE,\n ])\n );\n\n return Buffer.concat([buf, this.transactionId, data]);\n }\n\n addFingerprint() {\n this.attributes[\"FINGERPRINT\"] = messageFingerprint(this.bytes);\n }\n\n addMessageIntegrity(key: Buffer) {\n this.attributes[\"MESSAGE-INTEGRITY\"] = messageIntegrity(this.bytes, key);\n }\n}\n\nconst setBodyLength = (data: Buffer, length: number) => {\n return Buffer.concat([\n data.slice(0, 2),\n Buffer.from(jspack.Pack(\"!H\", [length])),\n data.slice(4),\n ]);\n};\n\nfunction messageFingerprint(data: Buffer) {\n const checkData = setBodyLength(\n data,\n data.length - HEADER_LENGTH + FINGERPRINT_LENGTH\n );\n const crc32Buf = crc32(checkData);\n const xorBuf = Buffer.alloc(4);\n xorBuf.writeInt32BE(FINGERPRINT_XOR, 0);\n const fingerprint = bufferXor(crc32Buf, xorBuf);\n return fingerprint.readUInt32BE(0);\n}\n\nfunction messageIntegrity(data: Buffer, key: Buffer) {\n const checkData = setBodyLength(\n data,\n data.length - HEADER_LENGTH + INTEGRITY_LENGTH\n );\n return Buffer.from(\n createHmac(\"sha1\", key).update(checkData).digest(\"hex\"),\n \"hex\"\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../../../../ice/src/stun/message.ts"],"names":[],"mappings":"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","sourcesContent":["import crc32 from \"buffer-crc32\";\nimport { createHmac } from \"crypto\";\nimport { jspack } from \"jspack\";\n\nimport { bufferXor, randomTransactionId } from \"../helper\";\nimport {\n AttributeKey,\n AttributePair,\n AttributeRepository,\n ATTRIBUTES_BY_NAME,\n ATTRIBUTES_BY_TYPE,\n packXorAddress,\n unpackXorAddress,\n} from \"./attributes\";\nimport {\n classes,\n COOKIE,\n FINGERPRINT_LENGTH,\n FINGERPRINT_XOR,\n HEADER_LENGTH,\n INTEGRITY_LENGTH,\n methods,\n} from \"./const\";\n\nexport function parseMessage(\n data: Buffer,\n integrityKey?: Buffer\n): Message | undefined {\n if (data.length < HEADER_LENGTH) {\n return undefined;\n }\n const [messageType, length] = jspack.Unpack(\n \"!HHI\",\n data.slice(0, HEADER_LENGTH)\n );\n\n const transactionId = Buffer.from(\n data.slice(HEADER_LENGTH - 12, HEADER_LENGTH)\n );\n\n if (data.length !== HEADER_LENGTH + length) {\n return undefined;\n }\n\n const attributeRepository = new AttributeRepository();\n\n for (let pos = HEADER_LENGTH; pos <= data.length - 4; ) {\n const [attrType, attrLen] = jspack.Unpack(\"!HH\", data.slice(pos, pos + 4));\n const payload = data.slice(pos + 4, pos + 4 + attrLen);\n const padLen = 4 * Math.floor((attrLen + 3) / 4) - attrLen;\n const attributesTypes = Object.keys(ATTRIBUTES_BY_TYPE);\n if (attributesTypes.includes(attrType.toString())) {\n const [, attrName, , attrUnpack] = ATTRIBUTES_BY_TYPE[attrType];\n if (attrUnpack.name === unpackXorAddress.name) {\n attributeRepository.setAttribute(\n attrName as AttributeKey,\n attrUnpack(payload, transactionId)\n );\n } else {\n attributeRepository.setAttribute(\n attrName as AttributeKey,\n attrUnpack(payload)\n );\n }\n\n if (attrName === \"FINGERPRINT\") {\n const fingerprint = messageFingerprint(data.slice(0, pos));\n const expect = attributeRepository.getAttributeValue(\"FINGERPRINT\");\n if (expect !== fingerprint) {\n return undefined;\n }\n } else if (attrName === \"MESSAGE-INTEGRITY\") {\n if (integrityKey) {\n const integrity = messageIntegrity(data.slice(0, pos), integrityKey);\n const expect =\n attributeRepository.getAttributeValue(\"MESSAGE-INTEGRITY\");\n if (!integrity.equals(expect)) {\n return undefined;\n }\n }\n }\n }\n pos += 4 + attrLen + padLen;\n }\n\n const attributes = attributeRepository.getAttributes();\n attributeRepository.clear();\n\n return new Message(\n messageType & 0x3eef,\n messageType & 0x0110,\n transactionId,\n attributes\n );\n}\n\nexport class Message extends AttributeRepository {\n constructor(\n public messageMethod: methods,\n public messageClass: classes,\n public transactionId: Buffer = randomTransactionId(),\n attributes: AttributePair[] = []\n ) {\n super(attributes);\n }\n\n get transactionIdHex() {\n return this.transactionId.toString(\"hex\");\n }\n\n get bytes() {\n let data = Buffer.from([]);\n for (const attrName of this.attributesKeys) {\n const attrValue = this.getAttributeValue(attrName);\n const [attrType, , attrPack] = ATTRIBUTES_BY_NAME[attrName];\n const v =\n attrPack.name === packXorAddress.name\n ? attrPack(attrValue, this.transactionId)\n : attrPack(attrValue);\n const attrLen = v.length;\n const padLen = 4 * Math.floor((attrLen + 3) / 4) - attrLen;\n data = Buffer.concat([\n data,\n Buffer.from(jspack.Pack(\"!HH\", [attrType, attrLen])),\n v,\n ...[...Array(padLen)].map(() => Buffer.from(\"\\x00\")),\n ]);\n }\n const buf = Buffer.from(\n jspack.Pack(\"!HHI\", [\n this.messageMethod | this.messageClass,\n data.length,\n COOKIE,\n ])\n );\n\n return Buffer.concat([buf, this.transactionId, data]);\n }\n\n addMessageIntegrity(key: Buffer) {\n this.setAttribute(\"MESSAGE-INTEGRITY\", this.messageIntegrity(key));\n return this;\n }\n\n messageIntegrity(key: Buffer) {\n const checkData = setBodyLength(\n this.bytes,\n this.bytes.length - HEADER_LENGTH + INTEGRITY_LENGTH\n );\n return Buffer.from(\n createHmac(\"sha1\", key).update(checkData).digest(\"hex\"),\n \"hex\"\n );\n }\n\n addFingerprint() {\n this.setAttribute(\"FINGERPRINT\", messageFingerprint(this.bytes));\n }\n}\n\nconst setBodyLength = (data: Buffer, length: number) => {\n return Buffer.concat([\n data.slice(0, 2),\n Buffer.from(jspack.Pack(\"!H\", [length])),\n data.slice(4),\n ]);\n};\n\nfunction messageFingerprint(data: Buffer) {\n const checkData = setBodyLength(\n data,\n data.length - HEADER_LENGTH + FINGERPRINT_LENGTH\n );\n const crc32Buf = crc32(checkData);\n const xorBuf = Buffer.alloc(4);\n xorBuf.writeInt32BE(FINGERPRINT_XOR, 0);\n const fingerprint = bufferXor(crc32Buf, xorBuf);\n return fingerprint.readUInt32BE(0);\n}\n\nfunction messageIntegrity(data: Buffer, key: Buffer) {\n const checkData = setBodyLength(\n data,\n data.length - HEADER_LENGTH + INTEGRITY_LENGTH\n );\n return Buffer.from(\n createHmac(\"sha1\", key).update(checkData).digest(\"hex\"),\n \"hex\"\n );\n}\n"]}
|
|
@@ -77,7 +77,6 @@ class StunProtocol {
|
|
|
77
77
|
request.addFingerprint();
|
|
78
78
|
}
|
|
79
79
|
const transaction = new transaction_1.Transaction(request, addr, this, retransmissions);
|
|
80
|
-
transaction.integrityKey = integrityKey;
|
|
81
80
|
this.transactions[request.transactionIdHex] = transaction;
|
|
82
81
|
try {
|
|
83
82
|
return await transaction.run();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../../ice/src/stun/protocol.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../../ice/src/stun/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import debug from \"debug\";\nimport { Event } from \"rx.mini\";\n\nimport { Candidate } from \"../candidate\";\nimport { Connection } from \"../ice\";\nimport { UdpTransport } from \"../transport\";\nimport { Address, Protocol } from \"../types/model\";\nimport { classes } from \"./const\";\nimport { Message, parseMessage } from \"./message\";\nimport { Transaction } from \"./transaction\";\n\nconst log = debug(\"packages/ice/src/stun/protocol.ts\");\n\nexport class StunProtocol implements Protocol {\n readonly type = \"stun\";\n transport!: UdpTransport;\n transactions: { [key: string]: Transaction } = {};\n get transactionsKeys() {\n return Object.keys(this.transactions);\n }\n localCandidate?: Candidate;\n sentMessage?: Message;\n localAddress?: string;\n\n private readonly closed = new Event();\n\n constructor(public receiver: Connection) {}\n\n connectionLost() {\n this.closed.execute();\n this.closed.complete();\n }\n\n connectionMade = async (useIpv4: boolean, portRange?: [number, number]) => {\n if (useIpv4) {\n this.transport = await UdpTransport.init(\"udp4\", portRange);\n } else {\n this.transport = await UdpTransport.init(\"udp6\", portRange);\n }\n\n this.transport.onData = (data, addr) => this.datagramReceived(data, addr);\n };\n\n private datagramReceived(data: Buffer, addr: Address) {\n if (!this.localCandidate) throw new Error(\"not exist\");\n\n const message = parseMessage(data);\n if (!message) {\n this.receiver.dataReceived(data, this.localCandidate.component);\n return;\n }\n // log(\"parseMessage\", addr, message);\n if (\n (message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR) &&\n this.transactionsKeys.includes(message.transactionIdHex)\n ) {\n const transaction = this.transactions[message.transactionIdHex];\n transaction.responseReceived(message, addr);\n } else if (message.messageClass === classes.REQUEST) {\n this.receiver.requestReceived(message, addr, this, data);\n }\n }\n\n getExtraInfo(): Address {\n const { address: host, port } = this.transport.address();\n return [host, port];\n }\n\n async sendStun(message: Message, addr: Address) {\n const data = message.bytes;\n await this.transport.send(data, addr).catch(() => {\n log(\"sendStun failed\", addr, message);\n });\n }\n\n async sendData(data: Buffer, addr: Address) {\n await this.transport.send(data, addr);\n }\n\n async request(\n request: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissions?: number\n ) {\n // \"\"\"\n // Execute a STUN transaction and return the response.\n // \"\"\"\n if (this.transactionsKeys.includes(request.transactionIdHex))\n throw new Error(\"already request ed\");\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n request.addFingerprint();\n }\n\n const transaction: Transaction = new Transaction(\n request,\n addr,\n this,\n retransmissions\n );\n this.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } finally {\n delete this.transactions[request.transactionIdHex];\n }\n }\n\n async close() {\n Object.values(this.transactions).forEach((transaction) => {\n transaction.cancel();\n });\n await this.transport.close();\n }\n}\n"]}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import { Address, Protocol } from "../types/model";
|
|
3
2
|
import { Message } from "./message";
|
|
4
3
|
export declare class Transaction {
|
|
@@ -6,7 +5,6 @@ export declare class Transaction {
|
|
|
6
5
|
private addr;
|
|
7
6
|
private protocol;
|
|
8
7
|
private retransmissions?;
|
|
9
|
-
integrityKey?: Buffer;
|
|
10
8
|
private timeoutDelay;
|
|
11
9
|
private timeoutHandle?;
|
|
12
10
|
private tries;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../../../../ice/src/stun/transaction.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,qCAAgC;AAEhC,8CAAsE;AAEtE,mCAAwD;AAGxD,MAAM,GAAG,GAAG,IAAA,eAAK,EAAC,iDAAiD,CAAC,CAAC;AAErE,MAAa,WAAW;
|
|
1
|
+
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../../../../ice/src/stun/transaction.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,qCAAgC;AAEhC,8CAAsE;AAEtE,mCAAwD;AAGxD,MAAM,GAAG,GAAG,IAAA,eAAK,EAAC,iDAAiD,CAAC,CAAC;AAErE,MAAa,WAAW;IAQtB,YACU,OAAgB,EAChB,IAAa,EACb,QAAkB,EAClB,eAAwB;QAHxB,YAAO,GAAP,OAAO,CAAS;QAChB,SAAI,GAAJ,IAAI,CAAS;QACb,aAAQ,GAAR,QAAQ,CAAU;QAClB,oBAAe,GAAf,eAAe,CAAS;QAX1B,iBAAY,GAAG,iBAAS,CAAC;QAEzB,UAAK,GAAG,CAAC,CAAC;QACD,aAAQ,GACvB,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,iBAAS,CAAC,CAAC;QAC/C,eAAU,GAAG,IAAI,eAAK,EAAsB,CAAC;QAS9D,qBAAgB,GAAG,CAAC,OAAgB,EAAE,IAAa,EAAE,EAAE;YACrD,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC9B,IAAI,OAAO,CAAC,YAAY,KAAK,eAAO,CAAC,QAAQ,EAAE;oBAC7C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;oBACvC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;iBAC5B;qBAAM;oBACL,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,8BAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;iBAC7D;aACF;QACH,CAAC,CAAC;QAEF,QAAG,GAAG,KAAK,IAAI,EAAE;YACf,IAAI;gBACF,IAAI,CAAC,KAAK,EAAE,CAAC;gBACb,OAAO,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;aAC1C;oBAAS;gBACR,IAAI,IAAI,CAAC,aAAa,EAAE;oBACtB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;iBAClC;aACF;QACH,CAAC,CAAC;QAEM,UAAK,GAAG,GAAG,EAAE;YACnB,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE;gBAC/B,GAAG,CAAC,sBAAsB,IAAI,CAAC,KAAK,aAAa,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAClE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,+BAAkB,EAAE,CAAC,CAAC;gBAChD,OAAO;aACR;YACD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAChD,IAAI,CAAC,aAAa,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YAC/D,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC;YACvB,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC,CAAC;IAlCC,CAAC;IAoCJ,MAAM;QACJ,IAAI,IAAI,CAAC,aAAa;YAAE,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC3D,CAAC;CACF;AApDD,kCAoDC","sourcesContent":["import debug from \"debug\";\nimport { Event } from \"rx.mini\";\n\nimport { TransactionFailed, TransactionTimeout } from \"../exceptions\";\nimport { Address, Protocol } from \"../types/model\";\nimport { classes, RETRY_MAX, RETRY_RTO } from \"./const\";\nimport { Message } from \"./message\";\n\nconst log = debug(\"werift-ice:packages/ice/src/stun/transaction.ts\");\n\nexport class Transaction {\n private timeoutDelay = RETRY_RTO;\n private timeoutHandle?: any;\n private tries = 0;\n private readonly triesMax =\n 1 + (this.retransmissions ? this.retransmissions : RETRY_MAX);\n private readonly onResponse = new Event<[Message, Address]>();\n\n constructor(\n private request: Message,\n private addr: Address,\n private protocol: Protocol,\n private retransmissions?: number\n ) {}\n\n responseReceived = (message: Message, addr: Address) => {\n if (this.onResponse.length > 0) {\n if (message.messageClass === classes.RESPONSE) {\n this.onResponse.execute(message, addr);\n this.onResponse.complete();\n } else {\n this.onResponse.error(new TransactionFailed(message, addr));\n }\n }\n };\n\n run = async () => {\n try {\n this.retry();\n return await this.onResponse.asPromise();\n } finally {\n if (this.timeoutHandle) {\n clearTimeout(this.timeoutHandle);\n }\n }\n };\n\n private retry = () => {\n if (this.tries >= this.triesMax) {\n log(`retry failed times:${this.tries} maxLimit:${this.triesMax}`);\n this.onResponse.error(new TransactionTimeout());\n return;\n }\n this.protocol.sendStun(this.request, this.addr);\n this.timeoutHandle = setTimeout(this.retry, this.timeoutDelay);\n this.timeoutDelay *= 2;\n this.tries++;\n };\n\n cancel() {\n if (this.timeoutHandle) clearTimeout(this.timeoutHandle);\n }\n}\n"]}
|
package/lib/ice/src/transport.js
CHANGED
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.UdpTransport = void 0;
|
|
7
7
|
const debug_1 = __importDefault(require("debug"));
|
|
8
8
|
const dgram_1 = require("dgram");
|
|
9
|
-
const
|
|
9
|
+
const src_1 = require("../../common/src");
|
|
10
10
|
const log = (0, debug_1.default)("werift-ice:packages/ice/src/transport.ts");
|
|
11
11
|
class UdpTransport {
|
|
12
12
|
constructor(type, portRange) {
|
|
@@ -53,7 +53,7 @@ class UdpTransport {
|
|
|
53
53
|
}
|
|
54
54
|
async init() {
|
|
55
55
|
if (this.portRange) {
|
|
56
|
-
const port = await (0,
|
|
56
|
+
const port = await (0, src_1.findPort)(this.portRange[0], this.portRange[1], this.type);
|
|
57
57
|
this.socket.bind(port);
|
|
58
58
|
}
|
|
59
59
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../../ice/src/transport.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,iCAAiD;
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../../ice/src/transport.ts"],"names":[],"mappings":"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","sourcesContent":["import debug from \"debug\";\nimport { createSocket, SocketType } from \"dgram\";\n\nimport { findPort } from \"../../common/src\";\nimport { Address } from \"./types/model\";\n\nconst log = debug(\"werift-ice:packages/ice/src/transport.ts\");\n\nexport class UdpTransport implements Transport {\n private socket = createSocket(this.type);\n onData: (data: Buffer, addr: Address) => void = () => {};\n\n constructor(private type: SocketType, private portRange?: [number, number]) {\n this.socket.on(\"message\", (data, info) => {\n if (info.family === \"IPv6\") {\n [info.address] = info.address.split(\"%\"); // example fe80::1d3a:8751:4ffd:eb80%wlp82s0\n }\n try {\n this.onData(data, [info.address, info.port]);\n } catch (error) {\n log(\"onData error\", error);\n }\n });\n }\n\n static async init(type: SocketType, portRange?: [number, number]) {\n const transport = new UdpTransport(type, portRange);\n await transport.init();\n return transport;\n }\n\n private async init() {\n if (this.portRange) {\n const port = await findPort(\n this.portRange[0],\n this.portRange[1],\n this.type\n );\n this.socket.bind(port);\n } else {\n this.socket.bind();\n }\n await new Promise((r) => this.socket.once(\"listening\", r));\n }\n\n send = (data: Buffer, addr: Address) =>\n new Promise<void>((r, f) => {\n this.socket.send(data, addr[1], addr[0], (error) => {\n if (error) {\n log(\"send error\", addr, data);\n f(error);\n } else {\n r();\n }\n });\n });\n\n address() {\n return this.socket.address();\n }\n\n close = () =>\n new Promise<void>((r) => {\n this.socket.once(\"close\", r);\n try {\n this.socket.close();\n } catch (error) {\n r();\n }\n });\n}\n\nexport interface Transport {\n onData: (data: Buffer, addr: Address) => void;\n send: (data: Buffer, addr: Address) => Promise<void>;\n}\n"]}
|
|
@@ -38,23 +38,24 @@ declare class TurnClient implements Protocol {
|
|
|
38
38
|
mappedAddress: Address;
|
|
39
39
|
refreshHandle?: Future;
|
|
40
40
|
channelNumber: number;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
addrByChannel: {
|
|
45
|
-
[key: number]: Address;
|
|
41
|
+
channel?: {
|
|
42
|
+
number: number;
|
|
43
|
+
address: Address;
|
|
46
44
|
};
|
|
47
45
|
localCandidate: Candidate;
|
|
48
46
|
onDatagramReceived: (data: Buffer, addr: Address) => void;
|
|
47
|
+
private channelBinding?;
|
|
49
48
|
constructor(server: Address, username: string, password: string, lifetime: number, transport: Transport);
|
|
50
49
|
connectionMade(): Promise<void>;
|
|
51
50
|
private handleChannelData;
|
|
52
51
|
private handleSTUNMessage;
|
|
53
52
|
private datagramReceived;
|
|
54
53
|
connect(): Promise<void>;
|
|
54
|
+
createPermission(peerAddress: Address): Promise<Message>;
|
|
55
55
|
refresh: () => PCancelable<unknown>;
|
|
56
|
-
request(request: Message, addr: Address
|
|
56
|
+
request(request: Message, addr: Address): Promise<[Message, Address]>;
|
|
57
57
|
sendData(data: Buffer, addr: Address): Promise<void>;
|
|
58
|
+
private getChannel;
|
|
58
59
|
private channelBind;
|
|
59
60
|
sendStun(message: Message, addr: Address): void;
|
|
60
61
|
}
|
|
@@ -64,4 +65,5 @@ export declare function createTurnEndpoint(serverAddr: Address, username: string
|
|
|
64
65
|
transport?: "udp";
|
|
65
66
|
portRange?: [number, number];
|
|
66
67
|
}): Promise<TurnTransport>;
|
|
68
|
+
export declare function makeIntegrityKey(username: string, realm: string, password: string): Buffer;
|
|
67
69
|
export {};
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.createTurnEndpoint = void 0;
|
|
6
|
+
exports.makeIntegrityKey = exports.createTurnEndpoint = void 0;
|
|
7
7
|
const crypto_1 = require("crypto");
|
|
8
8
|
const debug_1 = __importDefault(require("debug"));
|
|
9
9
|
const jspack_1 = require("jspack");
|
|
@@ -48,7 +48,6 @@ class TurnTransport {
|
|
|
48
48
|
request.addFingerprint();
|
|
49
49
|
}
|
|
50
50
|
const transaction = new transaction_1.Transaction(request, addr, this);
|
|
51
|
-
transaction.integrityKey = integrityKey;
|
|
52
51
|
this.turn.transactions[request.transactionIdHex] = transaction;
|
|
53
52
|
try {
|
|
54
53
|
return await transaction.run();
|
|
@@ -76,8 +75,6 @@ class TurnClient {
|
|
|
76
75
|
this.onData = new rx_mini_1.default();
|
|
77
76
|
this.transactions = {};
|
|
78
77
|
this.channelNumber = 0x4000;
|
|
79
|
-
this.channelByAddr = {};
|
|
80
|
-
this.addrByChannel = {};
|
|
81
78
|
this.onDatagramReceived = () => { };
|
|
82
79
|
this.refresh = () => new p_cancelable_1.default(async (r, f, onCancel) => {
|
|
83
80
|
let run = true;
|
|
@@ -89,10 +86,8 @@ class TurnClient {
|
|
|
89
86
|
// refresh before expire
|
|
90
87
|
await (0, promises_1.setTimeout)((5 / 6) * this.lifetime * 1000);
|
|
91
88
|
const request = new message_1.Message(const_1.methods.REFRESH, const_1.classes.REQUEST);
|
|
92
|
-
request.
|
|
93
|
-
await this.request(request, this.server
|
|
94
|
-
// todo fix
|
|
95
|
-
log);
|
|
89
|
+
request.setAttribute("LIFETIME", this.lifetime);
|
|
90
|
+
await this.request(request, this.server);
|
|
96
91
|
}
|
|
97
92
|
});
|
|
98
93
|
}
|
|
@@ -102,11 +97,10 @@ class TurnClient {
|
|
|
102
97
|
};
|
|
103
98
|
}
|
|
104
99
|
handleChannelData(data) {
|
|
105
|
-
const [
|
|
106
|
-
|
|
107
|
-
if (peerAddr) {
|
|
100
|
+
const [, length] = jspack_1.jspack.Unpack("!HH", data.slice(0, 4));
|
|
101
|
+
if (this.channel?.address) {
|
|
108
102
|
const payload = data.slice(4, 4 + length);
|
|
109
|
-
this.onDatagramReceived(payload,
|
|
103
|
+
this.onDatagramReceived(payload, this.channel.address);
|
|
110
104
|
}
|
|
111
105
|
}
|
|
112
106
|
handleSTUNMessage(data, addr) {
|
|
@@ -123,8 +117,8 @@ class TurnClient {
|
|
|
123
117
|
else if (message.messageClass === const_1.classes.REQUEST) {
|
|
124
118
|
this.onDatagramReceived(data, addr);
|
|
125
119
|
}
|
|
126
|
-
if (message.
|
|
127
|
-
const buf = message.
|
|
120
|
+
if (message.getAttributeValue("DATA")) {
|
|
121
|
+
const buf = message.getAttributeValue("DATA");
|
|
128
122
|
this.onDatagramReceived(buf, addr);
|
|
129
123
|
}
|
|
130
124
|
}
|
|
@@ -135,54 +129,59 @@ class TurnClient {
|
|
|
135
129
|
datagramReceived(data, addr) {
|
|
136
130
|
if (data.length >= 4 && isChannelData(data)) {
|
|
137
131
|
this.handleChannelData(data);
|
|
138
|
-
return;
|
|
139
132
|
}
|
|
140
|
-
|
|
133
|
+
else {
|
|
134
|
+
this.handleSTUNMessage(data, addr);
|
|
135
|
+
}
|
|
141
136
|
}
|
|
142
137
|
async connect() {
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
138
|
+
const withoutCred = new message_1.Message(const_1.methods.ALLOCATE, const_1.classes.REQUEST);
|
|
139
|
+
withoutCred
|
|
140
|
+
.setAttribute("LIFETIME", this.lifetime)
|
|
141
|
+
.setAttribute("REQUESTED-TRANSPORT", UDP_TRANSPORT);
|
|
142
|
+
const err = await this.request(withoutCred, this.server).catch((e) => e);
|
|
143
|
+
// resolve dns address
|
|
144
|
+
this.server = err.addr;
|
|
145
|
+
if (err.response.getAttributeValue("NONCE")) {
|
|
146
|
+
this.nonce = err.response.getAttributeValue("NONCE");
|
|
149
147
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
response = error.response;
|
|
153
|
-
if (!response) {
|
|
154
|
-
throw error;
|
|
155
|
-
}
|
|
156
|
-
if (response.attributes["ERROR-CODE"][0] === 401) {
|
|
157
|
-
this.nonce = response.attributes.NONCE;
|
|
158
|
-
this.realm = response.attributes.REALM;
|
|
159
|
-
this.integrityKey = makeIntegrityKey(this.username, this.realm, this.password);
|
|
160
|
-
request.transactionId = (0, helper_1.randomTransactionId)();
|
|
161
|
-
try {
|
|
162
|
-
[response] = await this.request(request, this.server, this.integrityKey);
|
|
163
|
-
}
|
|
164
|
-
catch (error) {
|
|
165
|
-
log(error);
|
|
166
|
-
// todo fix
|
|
167
|
-
}
|
|
168
|
-
}
|
|
148
|
+
if (err.response.getAttributeValue("REALM")) {
|
|
149
|
+
this.realm = err.response.getAttributeValue("REALM");
|
|
169
150
|
}
|
|
170
|
-
this.
|
|
171
|
-
|
|
151
|
+
this.integrityKey = makeIntegrityKey(this.username, this.realm, this.password);
|
|
152
|
+
const request = new message_1.Message(const_1.methods.ALLOCATE, const_1.classes.REQUEST);
|
|
153
|
+
request.setAttribute("REQUESTED-TRANSPORT", UDP_TRANSPORT);
|
|
154
|
+
const [response] = await this.request(request, this.server);
|
|
155
|
+
this.relayedAddress = response.getAttributeValue("XOR-RELAYED-ADDRESS");
|
|
156
|
+
this.mappedAddress = response.getAttributeValue("XOR-MAPPED-ADDRESS");
|
|
172
157
|
this.refreshHandle = (0, helper_1.future)(this.refresh());
|
|
173
158
|
}
|
|
174
|
-
async
|
|
175
|
-
|
|
159
|
+
async createPermission(peerAddress) {
|
|
160
|
+
const request = new message_1.Message(const_1.methods.CREATE_PERMISSION, const_1.classes.REQUEST);
|
|
161
|
+
request
|
|
162
|
+
.setAttribute("XOR-PEER-ADDRESS", peerAddress)
|
|
163
|
+
.setAttribute("USERNAME", this.username)
|
|
164
|
+
.setAttribute("REALM", this.realm)
|
|
165
|
+
.setAttribute("NONCE", this.nonce);
|
|
166
|
+
const [response] = await this.request(request, this.server).catch((e) => {
|
|
167
|
+
request;
|
|
168
|
+
throw e;
|
|
169
|
+
});
|
|
170
|
+
return response;
|
|
171
|
+
}
|
|
172
|
+
async request(request, addr) {
|
|
173
|
+
if (this.transactions[request.transactionIdHex]) {
|
|
176
174
|
throw new Error("exist");
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
request
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
175
|
+
}
|
|
176
|
+
if (this.integrityKey) {
|
|
177
|
+
request
|
|
178
|
+
.setAttribute("USERNAME", this.username)
|
|
179
|
+
.setAttribute("REALM", this.realm)
|
|
180
|
+
.setAttribute("NONCE", this.nonce)
|
|
181
|
+
.addMessageIntegrity(this.integrityKey)
|
|
182
|
+
.addFingerprint();
|
|
183
183
|
}
|
|
184
184
|
const transaction = new transaction_1.Transaction(request, addr, this);
|
|
185
|
-
transaction.integrityKey = integrityKey;
|
|
186
185
|
this.transactions[request.transactionIdHex] = transaction;
|
|
187
186
|
try {
|
|
188
187
|
return await transaction.run();
|
|
@@ -192,29 +191,31 @@ class TurnClient {
|
|
|
192
191
|
}
|
|
193
192
|
}
|
|
194
193
|
async sendData(data, addr) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
channel = this.channelNumber++;
|
|
198
|
-
this.channelByAddr[addr.join()] = channel;
|
|
199
|
-
this.addrByChannel[channel] = addr;
|
|
200
|
-
await this.channelBind(channel, addr);
|
|
201
|
-
log("bind", channel);
|
|
202
|
-
}
|
|
203
|
-
const header = jspack_1.jspack.Pack("!HH", [channel, data.length]);
|
|
194
|
+
const channel = await this.getChannel(addr);
|
|
195
|
+
const header = jspack_1.jspack.Pack("!HH", [channel.number, data.length]);
|
|
204
196
|
this.transport.send(Buffer.concat([Buffer.from(header), data]), this.server);
|
|
205
197
|
}
|
|
198
|
+
async getChannel(addr) {
|
|
199
|
+
if (this.channelBinding) {
|
|
200
|
+
await this.channelBinding;
|
|
201
|
+
}
|
|
202
|
+
if (!this.channel) {
|
|
203
|
+
this.channel = { number: this.channelNumber++, address: addr };
|
|
204
|
+
this.channelBinding = this.channelBind(this.channel.number, addr);
|
|
205
|
+
await this.channelBinding;
|
|
206
|
+
this.channelBinding = undefined;
|
|
207
|
+
log("channelBind", this.channel);
|
|
208
|
+
}
|
|
209
|
+
return this.channel;
|
|
210
|
+
}
|
|
206
211
|
async channelBind(channelNumber, addr) {
|
|
207
212
|
const request = new message_1.Message(const_1.methods.CHANNEL_BIND, const_1.classes.REQUEST);
|
|
208
|
-
request
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
catch (error) {
|
|
216
|
-
log(error);
|
|
217
|
-
// todo fix
|
|
213
|
+
request
|
|
214
|
+
.setAttribute("CHANNEL-NUMBER", channelNumber)
|
|
215
|
+
.setAttribute("XOR-PEER-ADDRESS", addr);
|
|
216
|
+
const [response] = await this.request(request, this.server);
|
|
217
|
+
if (response.messageMethod !== const_1.methods.CHANNEL_BIND) {
|
|
218
|
+
throw new Error();
|
|
218
219
|
}
|
|
219
220
|
}
|
|
220
221
|
sendStun(message, addr) {
|
|
@@ -238,6 +239,7 @@ function makeIntegrityKey(username, realm, password) {
|
|
|
238
239
|
.update(Buffer.from([username, realm, password].join(":")))
|
|
239
240
|
.digest();
|
|
240
241
|
}
|
|
242
|
+
exports.makeIntegrityKey = makeIntegrityKey;
|
|
241
243
|
function isChannelData(data) {
|
|
242
244
|
return (data[0] & 0xc0) == 0x40;
|
|
243
245
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../../ice/src/turn/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"crypto\";\nimport debug from \"debug\";\nimport { jspack } from \"jspack\";\nimport PCancelable from \"p-cancelable\";\nimport Event from \"rx.mini\";\nimport { setTimeout } from \"timers/promises\";\n\nimport { Candidate } from \"../candidate\";\nimport { TransactionFailed } from \"../exceptions\";\nimport { Future, future, randomTransactionId } from \"../helper\";\nimport { Connection } from \"../ice\";\nimport { classes, methods } from \"../stun/const\";\nimport { Message, parseMessage } from \"../stun/message\";\nimport { Transaction } from \"../stun/transaction\";\nimport { Transport, UdpTransport } from \"../transport\";\nimport { Address, Protocol } from \"../types/model\";\n\nconst log = debug(\"werift-ice:packages/ice/src/turn/protocol.ts\");\n\nconst TCP_TRANSPORT = 0x06000000;\nconst UDP_TRANSPORT = 0x11000000;\n\nclass TurnTransport implements Protocol {\n readonly type = \"turn\";\n localCandidate!: Candidate;\n receiver?: Connection;\n\n constructor(public turn: TurnClient) {\n turn.onDatagramReceived = this.datagramReceived;\n }\n\n private datagramReceived = (data: Buffer, addr: Address) => {\n const message = parseMessage(data);\n if (!message) {\n this.receiver?.dataReceived(data, this.localCandidate.component);\n return;\n }\n\n if (\n (message?.messageClass === classes.RESPONSE ||\n message?.messageClass === classes.ERROR) &&\n this.turn.transactions[message.transactionIdHex]\n ) {\n const transaction = this.turn.transactions[message.transactionIdHex];\n transaction.responseReceived(message, addr);\n } else if (message?.messageClass === classes.REQUEST) {\n this.receiver?.requestReceived(message, addr, this, data);\n }\n };\n\n async request(request: Message, addr: Address, integrityKey?: Buffer) {\n if (this.turn.transactions[request.transactionIdHex])\n throw new Error(\"exist\");\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n request.addFingerprint();\n }\n\n const transaction = new Transaction(request, addr, this);\n transaction.integrityKey = integrityKey;\n this.turn.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } finally {\n delete this.turn.transactions[request.transactionIdHex];\n }\n }\n async connectionMade() {}\n async sendData(data: Buffer, addr: Address) {\n await this.turn.sendData(data, addr);\n }\n async sendStun(message: Message, addr: Address) {\n await this.turn.sendData(message.bytes, addr);\n }\n}\n\nclass TurnClient implements Protocol {\n type = \"inner_turn\";\n readonly onData = new Event<[Buffer, Address]>();\n transactions: { [hexId: string]: Transaction } = {};\n integrityKey?: Buffer;\n nonce?: Buffer;\n realm?: string;\n relayedAddress!: Address;\n mappedAddress!: Address;\n refreshHandle?: Future;\n channelNumber = 0x4000;\n channelByAddr: { [key: string]: number } = {};\n addrByChannel: { [key: number]: Address } = {};\n localCandidate!: Candidate;\n\n onDatagramReceived: (data: Buffer, addr: Address) => void = () => {};\n\n constructor(\n public server: Address,\n public username: string,\n public password: string,\n public lifetime: number,\n public transport: Transport\n ) {}\n\n async connectionMade() {\n this.transport.onData = (data, addr) => {\n this.datagramReceived(data, addr);\n };\n }\n\n private handleChannelData(data: Buffer) {\n const [channel, length] = jspack.Unpack(\"!HH\", data.slice(0, 4));\n\n const peerAddr = this.addrByChannel[channel];\n\n if (peerAddr) {\n const payload = data.slice(4, 4 + length);\n this.onDatagramReceived(payload, peerAddr);\n }\n }\n\n private handleSTUNMessage(data: Buffer, addr: Address) {\n try {\n const message = parseMessage(data);\n if (!message) throw new Error(\"not stun message\");\n if (\n message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR\n ) {\n const transaction = this.transactions[message.transactionIdHex];\n if (transaction) transaction.responseReceived(message, addr);\n } else if (message.messageClass === classes.REQUEST) {\n this.onDatagramReceived(data, addr);\n }\n\n if (message.attributes.DATA) {\n const buf: Buffer = message.attributes.DATA;\n this.onDatagramReceived(buf, addr);\n }\n } catch (error) {\n log(\"parse error\", data.toString());\n }\n }\n\n private datagramReceived(data: Buffer, addr: Address) {\n if (data.length >= 4 && isChannelData(data)) {\n this.handleChannelData(data);\n return;\n }\n\n this.handleSTUNMessage(data, addr);\n }\n\n async connect() {\n const request = new Message(methods.ALLOCATE, classes.REQUEST);\n request.attributes[\"LIFETIME\"] = this.lifetime;\n request.attributes[\"REQUESTED-TRANSPORT\"] = UDP_TRANSPORT;\n\n let response: Message;\n try {\n [response] = await this.request(request, this.server, this.integrityKey);\n } catch (error) {\n log(\"error\", error);\n response = (error as TransactionFailed).response;\n if (!response) {\n throw error;\n }\n if (response.attributes[\"ERROR-CODE\"][0] === 401) {\n this.nonce = response.attributes.NONCE;\n this.realm = response.attributes.REALM;\n this.integrityKey = makeIntegrityKey(\n this.username,\n this.realm!,\n this.password\n );\n request.transactionId = randomTransactionId();\n\n try {\n [response] = await this.request(\n request,\n this.server,\n this.integrityKey\n );\n } catch (error) {\n log(error);\n // todo fix\n }\n }\n }\n\n this.relayedAddress = response.attributes[\"XOR-RELAYED-ADDRESS\"];\n this.mappedAddress = response.attributes[\"XOR-MAPPED-ADDRESS\"];\n\n this.refreshHandle = future(this.refresh());\n }\n\n refresh = () =>\n new PCancelable(async (r, f, onCancel) => {\n let run = true;\n onCancel(() => {\n run = false;\n f(\"cancel\");\n });\n\n while (run) {\n // refresh before expire\n await setTimeout((5 / 6) * this.lifetime * 1000);\n\n const request = new Message(methods.REFRESH, classes.REQUEST);\n request.attributes.LIFETIME = this.lifetime;\n\n await this.request(request, this.server, this.integrityKey).catch(\n // todo fix\n log\n );\n }\n });\n\n async request(\n request: Message,\n addr: Address,\n integrityKey?: Buffer\n ): Promise<[Message, Address]> {\n if (this.transactions[request.transactionIdHex]) throw new Error(\"exist\");\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n\n request.attributes[\"USERNAME\"] = this.username;\n request.attributes[\"REALM\"] = this.realm;\n request.attributes[\"NONCE\"] = this.nonce;\n\n request.addFingerprint();\n }\n\n const transaction = new Transaction(request, addr, this);\n transaction.integrityKey = integrityKey;\n this.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } finally {\n delete this.transactions[request.transactionIdHex];\n }\n }\n\n async sendData(data: Buffer, addr: Address) {\n let channel = this.channelByAddr[addr.join()];\n if (!channel) {\n channel = this.channelNumber++;\n this.channelByAddr[addr.join()] = channel;\n this.addrByChannel[channel] = addr;\n\n await this.channelBind(channel, addr);\n log(\"bind\", channel);\n }\n\n const header = jspack.Pack(\"!HH\", [channel, data.length]);\n\n this.transport.send(\n Buffer.concat([Buffer.from(header), data]),\n this.server\n );\n }\n\n private async channelBind(channelNumber: number, addr: Address) {\n const request = new Message(methods.CHANNEL_BIND, classes.REQUEST);\n request.attributes[\"CHANNEL-NUMBER\"] = channelNumber;\n request.attributes[\"XOR-PEER-ADDRESS\"] = addr;\n try {\n const [response] = await this.request(\n request,\n this.server,\n this.integrityKey\n );\n if (response.messageMethod !== methods.CHANNEL_BIND) throw new Error();\n } catch (error) {\n log(error);\n // todo fix\n }\n }\n\n sendStun(message: Message, addr: Address) {\n this.transport.send(message.bytes, addr);\n }\n}\n\nexport async function createTurnEndpoint(\n serverAddr: Address,\n username: string,\n password: string,\n {\n lifetime,\n portRange,\n }: {\n lifetime?: number;\n ssl?: boolean;\n transport?: \"udp\";\n portRange?: [number, number];\n }\n) {\n if (lifetime == undefined) {\n lifetime = 600;\n }\n\n const transport = await UdpTransport.init(\"udp4\", portRange);\n\n const turnClient = new TurnClient(\n serverAddr,\n username,\n password,\n lifetime,\n transport\n );\n\n await turnClient.connectionMade();\n await turnClient.connect();\n const turnTransport = new TurnTransport(turnClient);\n\n return turnTransport;\n}\n\nfunction makeIntegrityKey(username: string, realm: string, password: string) {\n return createHash(\"md5\")\n .update(Buffer.from([username, realm, password].join(\":\")))\n .digest();\n}\n\nfunction isChannelData(data: Buffer) {\n return (data[0] & 0xc0) == 0x40;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../../ice/src/turn/protocol.ts"],"names":[],"mappings":";;;;;;AAAA,mCAAoC;AACpC,kDAA0B;AAC1B,mCAAgC;AAChC,gEAAuC;AACvC,sDAA4B;AAC5B,8CAA6C;AAI7C,sCAA2C;AAE3C,yCAAiD;AACjD,6CAAwD;AACxD,qDAAkD;AAClD,4CAAuD;AAGvD,MAAM,GAAG,GAAG,IAAA,eAAK,EAAC,8CAA8C,CAAC,CAAC;AAElE,MAAM,aAAa,GAAG,UAAU,CAAC;AACjC,MAAM,aAAa,GAAG,UAAU,CAAC;AAEjC,MAAM,aAAa;IAKjB,YAAmB,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;QAJ1B,SAAI,GAAG,MAAM,CAAC;QAQf,qBAAgB,GAAG,CAAC,IAAY,EAAE,IAAa,EAAE,EAAE;YACzD,MAAM,OAAO,GAAG,IAAA,sBAAY,EAAC,IAAI,CAAC,CAAC;YACnC,IAAI,CAAC,OAAO,EAAE;gBACZ,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;gBACjE,OAAO;aACR;YAED,IACE,CAAC,OAAO,EAAE,YAAY,KAAK,eAAO,CAAC,QAAQ;gBACzC,OAAO,EAAE,YAAY,KAAK,eAAO,CAAC,KAAK,CAAC;gBAC1C,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAChD;gBACA,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;gBACrE,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;aAC7C;iBAAM,IAAI,OAAO,EAAE,YAAY,KAAK,eAAO,CAAC,OAAO,EAAE;gBACpD,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;aAC3D;QACH,CAAC,CAAC;QApBA,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,gBAAgB,CAAC;IAClD,CAAC;IAqBD,KAAK,CAAC,OAAO,CAAC,OAAgB,EAAE,IAAa,EAAE,YAAqB;QAClE,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;QAE3B,IAAI,YAAY,EAAE;YAChB,OAAO,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC;YAC1C,OAAO,CAAC,cAAc,EAAE,CAAC;SAC1B;QAED,MAAM,WAAW,GAAG,IAAI,yBAAW,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,WAAW,CAAC;QAE/D,IAAI;YACF,OAAO,MAAM,WAAW,CAAC,GAAG,EAAE,CAAC;SAChC;gBAAS;YACR,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;SACzD;IACH,CAAC;IACD,KAAK,CAAC,cAAc,KAAI,CAAC;IACzB,KAAK,CAAC,QAAQ,CAAC,IAAY,EAAE,IAAa;QACxC,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACvC,CAAC;IACD,KAAK,CAAC,QAAQ,CAAC,OAAgB,EAAE,IAAa;QAC5C,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAChD,CAAC;CACF;AAED,MAAM,UAAU;IAkBd,YACS,MAAe,EACf,QAAgB,EAChB,QAAgB,EAChB,QAAgB,EAChB,SAAoB;QAJpB,WAAM,GAAN,MAAM,CAAS;QACf,aAAQ,GAAR,QAAQ,CAAQ;QAChB,aAAQ,GAAR,QAAQ,CAAQ;QAChB,aAAQ,GAAR,QAAQ,CAAQ;QAChB,cAAS,GAAT,SAAS,CAAW;QAtB7B,SAAI,GAAG,YAAY,CAAC;QACX,WAAM,GAAG,IAAI,iBAAK,EAAqB,CAAC;QACjD,iBAAY,GAAqC,EAAE,CAAC;QAOpD,kBAAa,GAAG,MAAM,CAAC;QAIvB,uBAAkB,GAA0C,GAAG,EAAE,GAAE,CAAC,CAAC;QA4GrE,YAAO,GAAG,GAAG,EAAE,CACb,IAAI,sBAAW,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE;YACvC,IAAI,GAAG,GAAG,IAAI,CAAC;YACf,QAAQ,CAAC,GAAG,EAAE;gBACZ,GAAG,GAAG,KAAK,CAAC;gBACZ,CAAC,CAAC,QAAQ,CAAC,CAAC;YACd,CAAC,CAAC,CAAC;YAEH,OAAO,GAAG,EAAE;gBACV,wBAAwB;gBACxB,MAAM,IAAA,qBAAU,EAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;gBAEjD,MAAM,OAAO,GAAG,IAAI,iBAAO,CAAC,eAAO,CAAC,OAAO,EAAE,eAAO,CAAC,OAAO,CAAC,CAAC;gBAC9D,OAAO,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAEhD,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;aAC1C;QACH,CAAC,CAAC,CAAC;IAnHF,CAAC;IAEJ,KAAK,CAAC,cAAc;QAClB,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;YACrC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC,CAAC;IACJ,CAAC;IAEO,iBAAiB,CAAC,IAAY;QACpC,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG,eAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAE1D,IAAI,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC;YAC1C,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;SACxD;IACH,CAAC;IAEO,iBAAiB,CAAC,IAAY,EAAE,IAAa;QACnD,IAAI;YACF,MAAM,OAAO,GAAG,IAAA,sBAAY,EAAC,IAAI,CAAC,CAAC;YACnC,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;YAClD,IACE,OAAO,CAAC,YAAY,KAAK,eAAO,CAAC,QAAQ;gBACzC,OAAO,CAAC,YAAY,KAAK,eAAO,CAAC,KAAK,EACtC;gBACA,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;gBAChE,IAAI,WAAW;oBAAE,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;aAC9D;iBAAM,IAAI,OAAO,CAAC,YAAY,KAAK,eAAO,CAAC,OAAO,EAAE;gBACnD,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;aACrC;YAED,IAAI,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE;gBACrC,MAAM,GAAG,GAAW,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;gBACtD,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;aACpC;SACF;QAAC,OAAO,KAAK,EAAE;YACd,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;SACrC;IACH,CAAC;IAEO,gBAAgB,CAAC,IAAY,EAAE,IAAa;QAClD,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE;YAC3C,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;SAC9B;aAAM;YACL,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;SACpC;IACH,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,WAAW,GAAG,IAAI,iBAAO,CAAC,eAAO,CAAC,QAAQ,EAAE,eAAO,CAAC,OAAO,CAAC,CAAC;QACnE,WAAW;aACR,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC;aACvC,YAAY,CAAC,qBAAqB,EAAE,aAAa,CAAC,CAAC;QAEtD,MAAM,GAAG,GAAsB,MAAM,IAAI,CAAC,OAAO,CAC/C,WAAW,EACX,IAAI,CAAC,MAAM,CACZ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QAElB,sBAAsB;QACtB,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC;QAEvB,IAAI,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE;YAC3C,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;SACtD;QACD,IAAI,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE;YAC3C,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;SACtD;QACD,IAAI,CAAC,YAAY,GAAG,gBAAgB,CAClC,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,KAAM,EACX,IAAI,CAAC,QAAQ,CACd,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,iBAAO,CAAC,eAAO,CAAC,QAAQ,EAAE,eAAO,CAAC,OAAO,CAAC,CAAC;QAC/D,OAAO,CAAC,YAAY,CAAC,qBAAqB,EAAE,aAAa,CAAC,CAAC;QAE3D,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5D,IAAI,CAAC,cAAc,GAAG,QAAQ,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,CAAC;QACxE,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC,iBAAiB,CAAC,oBAAoB,CAAC,CAAC;QAEtE,IAAI,CAAC,aAAa,GAAG,IAAA,eAAM,EAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,WAAoB;QACzC,MAAM,OAAO,GAAG,IAAI,iBAAO,CAAC,eAAO,CAAC,iBAAiB,EAAE,eAAO,CAAC,OAAO,CAAC,CAAC;QACxE,OAAO;aACJ,YAAY,CAAC,kBAAkB,EAAE,WAAW,CAAC;aAC7C,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC;aACvC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC;aACjC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACrC,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;YACtE,OAAO,CAAC;YACR,MAAM,CAAC,CAAC;QACV,CAAC,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC;IAqBD,KAAK,CAAC,OAAO,CAAC,OAAgB,EAAE,IAAa;QAC3C,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE;YAC/C,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;SAC1B;QACD,IAAI,IAAI,CAAC,YAAY,EAAE;YACrB,OAAO;iBACJ,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC;iBACvC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC;iBACjC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC;iBACjC,mBAAmB,CAAC,IAAI,CAAC,YAAY,CAAC;iBACtC,cAAc,EAAE,CAAC;SACrB;QAED,MAAM,WAAW,GAAG,IAAI,yBAAW,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,WAAW,CAAC;QAE1D,IAAI;YACF,OAAO,MAAM,WAAW,CAAC,GAAG,EAAE,CAAC;SAChC;gBAAS;YACR,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;SACpD;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAY,EAAE,IAAa;QACxC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAE5C,MAAM,MAAM,GAAG,eAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC,SAAS,CAAC,IAAI,CACjB,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,EAC1C,IAAI,CAAC,MAAM,CACZ,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,IAAa;QACpC,IAAI,IAAI,CAAC,cAAc,EAAE;YACvB,MAAM,IAAI,CAAC,cAAc,CAAC;SAC3B;QACD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YACjB,IAAI,CAAC,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAE/D,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAClE,MAAM,IAAI,CAAC,cAAc,CAAC;YAC1B,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;YAChC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;SAClC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,aAAqB,EAAE,IAAa;QAC5D,MAAM,OAAO,GAAG,IAAI,iBAAO,CAAC,eAAO,CAAC,YAAY,EAAE,eAAO,CAAC,OAAO,CAAC,CAAC;QACnE,OAAO;aACJ,YAAY,CAAC,gBAAgB,EAAE,aAAa,CAAC;aAC7C,YAAY,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;QAC1C,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5D,IAAI,QAAQ,CAAC,aAAa,KAAK,eAAO,CAAC,YAAY,EAAE;YACnD,MAAM,IAAI,KAAK,EAAE,CAAC;SACnB;IACH,CAAC;IAED,QAAQ,CAAC,OAAgB,EAAE,IAAa;QACtC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;CACF;AAEM,KAAK,UAAU,kBAAkB,CACtC,UAAmB,EACnB,QAAgB,EAChB,QAAgB,EAChB,EACE,QAAQ,EACR,SAAS,GAMV;IAED,IAAI,QAAQ,IAAI,SAAS,EAAE;QACzB,QAAQ,GAAG,GAAG,CAAC;KAChB;IAED,MAAM,SAAS,GAAG,MAAM,wBAAY,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAE7D,MAAM,UAAU,GAAG,IAAI,UAAU,CAC/B,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,SAAS,CACV,CAAC;IAEF,MAAM,UAAU,CAAC,cAAc,EAAE,CAAC;IAClC,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC;IAC3B,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC,UAAU,CAAC,CAAC;IAEpD,OAAO,aAAa,CAAC;AACvB,CAAC;AAjCD,gDAiCC;AAED,SAAgB,gBAAgB,CAC9B,QAAgB,EAChB,KAAa,EACb,QAAgB;IAEhB,OAAO,IAAA,mBAAU,EAAC,KAAK,CAAC;SACrB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;SAC1D,MAAM,EAAE,CAAC;AACd,CAAC;AARD,4CAQC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC;AAClC,CAAC","sourcesContent":["import { createHash } from \"crypto\";\nimport debug from \"debug\";\nimport { jspack } from \"jspack\";\nimport PCancelable from \"p-cancelable\";\nimport Event from \"rx.mini\";\nimport { setTimeout } from \"timers/promises\";\n\nimport { Candidate } from \"../candidate\";\nimport { TransactionFailed } from \"../exceptions\";\nimport { Future, future } from \"../helper\";\nimport { Connection } from \"../ice\";\nimport { classes, methods } from \"../stun/const\";\nimport { Message, parseMessage } from \"../stun/message\";\nimport { Transaction } from \"../stun/transaction\";\nimport { Transport, UdpTransport } from \"../transport\";\nimport { Address, Protocol } from \"../types/model\";\n\nconst log = debug(\"werift-ice:packages/ice/src/turn/protocol.ts\");\n\nconst TCP_TRANSPORT = 0x06000000;\nconst UDP_TRANSPORT = 0x11000000;\n\nclass TurnTransport implements Protocol {\n readonly type = \"turn\";\n localCandidate!: Candidate;\n receiver?: Connection;\n\n constructor(public turn: TurnClient) {\n turn.onDatagramReceived = this.datagramReceived;\n }\n\n private datagramReceived = (data: Buffer, addr: Address) => {\n const message = parseMessage(data);\n if (!message) {\n this.receiver?.dataReceived(data, this.localCandidate.component);\n return;\n }\n\n if (\n (message?.messageClass === classes.RESPONSE ||\n message?.messageClass === classes.ERROR) &&\n this.turn.transactions[message.transactionIdHex]\n ) {\n const transaction = this.turn.transactions[message.transactionIdHex];\n transaction.responseReceived(message, addr);\n } else if (message?.messageClass === classes.REQUEST) {\n this.receiver?.requestReceived(message, addr, this, data);\n }\n };\n\n async request(request: Message, addr: Address, integrityKey?: Buffer) {\n if (this.turn.transactions[request.transactionIdHex])\n throw new Error(\"exist\");\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n request.addFingerprint();\n }\n\n const transaction = new Transaction(request, addr, this);\n this.turn.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } finally {\n delete this.turn.transactions[request.transactionIdHex];\n }\n }\n async connectionMade() {}\n async sendData(data: Buffer, addr: Address) {\n await this.turn.sendData(data, addr);\n }\n async sendStun(message: Message, addr: Address) {\n await this.turn.sendData(message.bytes, addr);\n }\n}\n\nclass TurnClient implements Protocol {\n type = \"inner_turn\";\n readonly onData = new Event<[Buffer, Address]>();\n transactions: { [hexId: string]: Transaction } = {};\n integrityKey?: Buffer;\n nonce?: Buffer;\n realm?: string;\n relayedAddress!: Address;\n mappedAddress!: Address;\n refreshHandle?: Future;\n channelNumber = 0x4000;\n channel?: { number: number; address: Address };\n localCandidate!: Candidate;\n\n onDatagramReceived: (data: Buffer, addr: Address) => void = () => {};\n\n private channelBinding?: Promise<void>;\n\n constructor(\n public server: Address,\n public username: string,\n public password: string,\n public lifetime: number,\n public transport: Transport\n ) {}\n\n async connectionMade() {\n this.transport.onData = (data, addr) => {\n this.datagramReceived(data, addr);\n };\n }\n\n private handleChannelData(data: Buffer) {\n const [, length] = jspack.Unpack(\"!HH\", data.slice(0, 4));\n\n if (this.channel?.address) {\n const payload = data.slice(4, 4 + length);\n this.onDatagramReceived(payload, this.channel.address);\n }\n }\n\n private handleSTUNMessage(data: Buffer, addr: Address) {\n try {\n const message = parseMessage(data);\n if (!message) throw new Error(\"not stun message\");\n if (\n message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR\n ) {\n const transaction = this.transactions[message.transactionIdHex];\n if (transaction) transaction.responseReceived(message, addr);\n } else if (message.messageClass === classes.REQUEST) {\n this.onDatagramReceived(data, addr);\n }\n\n if (message.getAttributeValue(\"DATA\")) {\n const buf: Buffer = message.getAttributeValue(\"DATA\");\n this.onDatagramReceived(buf, addr);\n }\n } catch (error) {\n log(\"parse error\", data.toString());\n }\n }\n\n private datagramReceived(data: Buffer, addr: Address) {\n if (data.length >= 4 && isChannelData(data)) {\n this.handleChannelData(data);\n } else {\n this.handleSTUNMessage(data, addr);\n }\n }\n\n async connect() {\n const withoutCred = new Message(methods.ALLOCATE, classes.REQUEST);\n withoutCred\n .setAttribute(\"LIFETIME\", this.lifetime)\n .setAttribute(\"REQUESTED-TRANSPORT\", UDP_TRANSPORT);\n\n const err: TransactionFailed = await this.request(\n withoutCred,\n this.server\n ).catch((e) => e);\n\n // resolve dns address\n this.server = err.addr;\n\n if (err.response.getAttributeValue(\"NONCE\")) {\n this.nonce = err.response.getAttributeValue(\"NONCE\");\n }\n if (err.response.getAttributeValue(\"REALM\")) {\n this.realm = err.response.getAttributeValue(\"REALM\");\n }\n this.integrityKey = makeIntegrityKey(\n this.username,\n this.realm!,\n this.password\n );\n\n const request = new Message(methods.ALLOCATE, classes.REQUEST);\n request.setAttribute(\"REQUESTED-TRANSPORT\", UDP_TRANSPORT);\n\n const [response] = await this.request(request, this.server);\n this.relayedAddress = response.getAttributeValue(\"XOR-RELAYED-ADDRESS\");\n this.mappedAddress = response.getAttributeValue(\"XOR-MAPPED-ADDRESS\");\n\n this.refreshHandle = future(this.refresh());\n }\n\n async createPermission(peerAddress: Address) {\n const request = new Message(methods.CREATE_PERMISSION, classes.REQUEST);\n request\n .setAttribute(\"XOR-PEER-ADDRESS\", peerAddress)\n .setAttribute(\"USERNAME\", this.username)\n .setAttribute(\"REALM\", this.realm)\n .setAttribute(\"NONCE\", this.nonce);\n const [response] = await this.request(request, this.server).catch((e) => {\n request;\n throw e;\n });\n return response;\n }\n\n refresh = () =>\n new PCancelable(async (r, f, onCancel) => {\n let run = true;\n onCancel(() => {\n run = false;\n f(\"cancel\");\n });\n\n while (run) {\n // refresh before expire\n await setTimeout((5 / 6) * this.lifetime * 1000);\n\n const request = new Message(methods.REFRESH, classes.REQUEST);\n request.setAttribute(\"LIFETIME\", this.lifetime);\n\n await this.request(request, this.server);\n }\n });\n\n async request(request: Message, addr: Address): Promise<[Message, Address]> {\n if (this.transactions[request.transactionIdHex]) {\n throw new Error(\"exist\");\n }\n if (this.integrityKey) {\n request\n .setAttribute(\"USERNAME\", this.username)\n .setAttribute(\"REALM\", this.realm)\n .setAttribute(\"NONCE\", this.nonce)\n .addMessageIntegrity(this.integrityKey)\n .addFingerprint();\n }\n\n const transaction = new Transaction(request, addr, this);\n this.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } finally {\n delete this.transactions[request.transactionIdHex];\n }\n }\n\n async sendData(data: Buffer, addr: Address) {\n const channel = await this.getChannel(addr);\n\n const header = jspack.Pack(\"!HH\", [channel.number, data.length]);\n this.transport.send(\n Buffer.concat([Buffer.from(header), data]),\n this.server\n );\n }\n\n private async getChannel(addr: Address) {\n if (this.channelBinding) {\n await this.channelBinding;\n }\n if (!this.channel) {\n this.channel = { number: this.channelNumber++, address: addr };\n\n this.channelBinding = this.channelBind(this.channel.number, addr);\n await this.channelBinding;\n this.channelBinding = undefined;\n log(\"channelBind\", this.channel);\n }\n return this.channel;\n }\n\n private async channelBind(channelNumber: number, addr: Address) {\n const request = new Message(methods.CHANNEL_BIND, classes.REQUEST);\n request\n .setAttribute(\"CHANNEL-NUMBER\", channelNumber)\n .setAttribute(\"XOR-PEER-ADDRESS\", addr);\n const [response] = await this.request(request, this.server);\n if (response.messageMethod !== methods.CHANNEL_BIND) {\n throw new Error();\n }\n }\n\n sendStun(message: Message, addr: Address) {\n this.transport.send(message.bytes, addr);\n }\n}\n\nexport async function createTurnEndpoint(\n serverAddr: Address,\n username: string,\n password: string,\n {\n lifetime,\n portRange,\n }: {\n lifetime?: number;\n ssl?: boolean;\n transport?: \"udp\";\n portRange?: [number, number];\n }\n) {\n if (lifetime == undefined) {\n lifetime = 600;\n }\n\n const transport = await UdpTransport.init(\"udp4\", portRange);\n\n const turnClient = new TurnClient(\n serverAddr,\n username,\n password,\n lifetime,\n transport\n );\n\n await turnClient.connectionMade();\n await turnClient.connect();\n const turnTransport = new TurnTransport(turnClient);\n\n return turnTransport;\n}\n\nexport function makeIntegrityKey(\n username: string,\n realm: string,\n password: string\n) {\n return createHash(\"md5\")\n .update(Buffer.from([username, realm, password].join(\":\")))\n .digest();\n}\n\nfunction isChannelData(data: Buffer) {\n return (data[0] & 0xc0) == 0x40;\n}\n"]}
|