werift 0.20.1 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/common/src/event.js +0 -3
- package/lib/common/src/event.js.map +1 -1
- package/lib/dtls/src/flight/server/flight2.js +5 -3
- package/lib/dtls/src/flight/server/flight2.js.map +1 -1
- package/lib/dtls/src/index.d.ts +1 -1
- package/lib/dtls/src/index.js.map +1 -1
- package/lib/dtls/src/record/receive.js +1 -1
- package/lib/dtls/src/record/receive.js.map +1 -1
- package/lib/ice/src/candidate.d.ts +2 -1
- package/lib/ice/src/candidate.js +17 -4
- package/lib/ice/src/candidate.js.map +1 -1
- package/lib/ice/src/helper.d.ts +6 -6
- package/lib/ice/src/helper.js +18 -15
- package/lib/ice/src/helper.js.map +1 -1
- package/lib/ice/src/ice.d.ts +28 -75
- package/lib/ice/src/ice.js +388 -418
- package/lib/ice/src/ice.js.map +1 -1
- package/lib/ice/src/iceBase.d.ts +109 -0
- package/lib/ice/src/iceBase.js +166 -0
- package/lib/ice/src/iceBase.js.map +1 -0
- package/lib/ice/src/index.d.ts +1 -0
- package/lib/ice/src/index.js +1 -0
- package/lib/ice/src/index.js.map +1 -1
- package/lib/ice/src/stun/message.d.ts +6 -0
- package/lib/ice/src/stun/message.js +4 -0
- package/lib/ice/src/stun/message.js.map +1 -1
- package/lib/ice/src/stun/protocol.d.ts +5 -6
- package/lib/ice/src/stun/protocol.js +18 -18
- package/lib/ice/src/stun/protocol.js.map +1 -1
- package/lib/ice/src/stun/transaction.js +6 -1
- package/lib/ice/src/stun/transaction.js.map +1 -1
- package/lib/ice/src/turn/protocol.d.ts +6 -5
- package/lib/ice/src/turn/protocol.js +54 -36
- package/lib/ice/src/turn/protocol.js.map +1 -1
- package/lib/ice/src/types/model.d.ts +4 -0
- package/lib/ice/src/types/model.js.map +1 -1
- package/lib/rtp/src/extra/container/webm/container.d.ts +3 -1
- package/lib/rtp/src/extra/container/webm/container.js +8 -2
- package/lib/rtp/src/extra/container/webm/container.js.map +1 -1
- package/lib/rtp/src/extra/container/webm/ebml/id.d.ts +6 -0
- package/lib/rtp/src/extra/container/webm/ebml/id.js +6 -0
- package/lib/rtp/src/extra/container/webm/ebml/id.js.map +1 -1
- package/lib/rtp/src/extra/processor/webm.d.ts +11 -16
- package/lib/rtp/src/extra/processor/webm.js.map +1 -1
- package/lib/rtp/src/extra/processor/webmCallback.d.ts +1 -10
- package/lib/rtp/src/extra/processor/webmCallback.js.map +1 -1
- package/lib/rtp/src/rtp/headerExtension.d.ts +45 -3
- package/lib/rtp/src/rtp/headerExtension.js +15 -0
- package/lib/rtp/src/rtp/headerExtension.js.map +1 -1
- package/lib/sctp/src/index.d.ts +1 -1
- package/lib/sctp/src/index.js.map +1 -1
- package/lib/webrtc/src/const.d.ts +2 -2
- package/lib/webrtc/src/const.js.map +1 -1
- package/lib/webrtc/src/media/extension/rtpExtension.d.ts +1 -0
- package/lib/webrtc/src/media/extension/rtpExtension.js +6 -0
- package/lib/webrtc/src/media/extension/rtpExtension.js.map +1 -1
- package/lib/webrtc/src/media/router.d.ts +0 -3
- package/lib/webrtc/src/media/router.js.map +1 -1
- package/lib/webrtc/src/media/rtpReceiver.d.ts +1 -2
- package/lib/webrtc/src/media/rtpReceiver.js +2 -2
- package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
- package/lib/webrtc/src/media/track.d.ts +2 -2
- package/lib/webrtc/src/media/track.js.map +1 -1
- package/lib/webrtc/src/nonstandard/recorder/index.d.ts +1 -0
- package/lib/webrtc/src/nonstandard/recorder/index.js.map +1 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js +1 -0
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js.map +1 -1
- package/lib/webrtc/src/peerConnection.d.ts +12 -6
- package/lib/webrtc/src/peerConnection.js +94 -82
- package/lib/webrtc/src/peerConnection.js.map +1 -1
- package/lib/webrtc/src/sdp.js +15 -3
- package/lib/webrtc/src/sdp.js.map +1 -1
- package/lib/webrtc/src/transport/dtls.d.ts +5 -5
- package/lib/webrtc/src/transport/dtls.js +7 -18
- package/lib/webrtc/src/transport/dtls.js.map +1 -1
- package/lib/webrtc/src/transport/ice.d.ts +20 -9
- package/lib/webrtc/src/transport/ice.js +97 -32
- package/lib/webrtc/src/transport/ice.js.map +1 -1
- package/package.json +1 -1
- package/src/const.ts +2 -2
- package/src/media/extension/rtpExtension.ts +6 -0
- package/src/media/router.ts +2 -3
- package/src/media/rtpReceiver.ts +4 -3
- package/src/media/track.ts +7 -2
- package/src/nonstandard/recorder/index.ts +1 -0
- package/src/nonstandard/recorder/writer/webm.ts +47 -43
- package/src/peerConnection.ts +118 -88
- package/src/sdp.ts +16 -3
- package/src/transport/dtls.ts +11 -9
- package/src/transport/ice.ts +73 -26
package/lib/ice/src/ice.js
CHANGED
|
@@ -3,23 +3,18 @@ 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.
|
|
7
|
-
exports.validateRemoteCandidate = validateRemoteCandidate;
|
|
8
|
-
exports.sortCandidatePairs = sortCandidatePairs;
|
|
9
|
-
exports.candidatePairPriority = candidatePairPriority;
|
|
10
|
-
exports.serverReflexiveCandidate = serverReflexiveCandidate;
|
|
11
|
-
exports.validateAddress = validateAddress;
|
|
6
|
+
exports.Connection = void 0;
|
|
12
7
|
const crypto_1 = require("crypto");
|
|
13
8
|
const net_1 = require("net");
|
|
14
9
|
const debug_1 = __importDefault(require("debug"));
|
|
15
10
|
const int64_buffer_1 = require("int64-buffer");
|
|
16
11
|
const isEqual_1 = __importDefault(require("lodash/isEqual"));
|
|
17
|
-
const p_cancelable_1 = __importDefault(require("p-cancelable"));
|
|
18
12
|
const promises_1 = __importDefault(require("timers/promises"));
|
|
19
13
|
const common_1 = require("./imports/common");
|
|
20
14
|
const candidate_1 = require("./candidate");
|
|
21
15
|
const lookup_1 = require("./dns/lookup");
|
|
22
16
|
const helper_1 = require("./helper");
|
|
17
|
+
const iceBase_1 = require("./iceBase");
|
|
23
18
|
const const_1 = require("./stun/const");
|
|
24
19
|
const message_1 = require("./stun/message");
|
|
25
20
|
const protocol_1 = require("./stun/protocol");
|
|
@@ -27,14 +22,14 @@ const protocol_2 = require("./turn/protocol");
|
|
|
27
22
|
const utils_1 = require("./utils");
|
|
28
23
|
const log = (0, debug_1.default)("werift-ice : packages/ice/src/ice.ts : log");
|
|
29
24
|
class Connection {
|
|
30
|
-
constructor(
|
|
31
|
-
Object.defineProperty(this, "
|
|
25
|
+
constructor(_iceControlling, options) {
|
|
26
|
+
Object.defineProperty(this, "_iceControlling", {
|
|
32
27
|
enumerable: true,
|
|
33
28
|
configurable: true,
|
|
34
29
|
writable: true,
|
|
35
|
-
value:
|
|
30
|
+
value: _iceControlling
|
|
36
31
|
});
|
|
37
|
-
Object.defineProperty(this, "
|
|
32
|
+
Object.defineProperty(this, "localUsername", {
|
|
38
33
|
enumerable: true,
|
|
39
34
|
configurable: true,
|
|
40
35
|
writable: true,
|
|
@@ -46,23 +41,23 @@ class Connection {
|
|
|
46
41
|
writable: true,
|
|
47
42
|
value: (0, helper_1.randomString)(22)
|
|
48
43
|
});
|
|
49
|
-
Object.defineProperty(this, "
|
|
44
|
+
Object.defineProperty(this, "remoteIsLite", {
|
|
50
45
|
enumerable: true,
|
|
51
46
|
configurable: true,
|
|
52
47
|
writable: true,
|
|
53
|
-
value:
|
|
48
|
+
value: false
|
|
54
49
|
});
|
|
55
|
-
Object.defineProperty(this, "
|
|
50
|
+
Object.defineProperty(this, "remotePassword", {
|
|
56
51
|
enumerable: true,
|
|
57
52
|
configurable: true,
|
|
58
53
|
writable: true,
|
|
59
54
|
value: ""
|
|
60
55
|
});
|
|
61
|
-
Object.defineProperty(this, "
|
|
56
|
+
Object.defineProperty(this, "remoteUsername", {
|
|
62
57
|
enumerable: true,
|
|
63
58
|
configurable: true,
|
|
64
59
|
writable: true,
|
|
65
|
-
value:
|
|
60
|
+
value: ""
|
|
66
61
|
});
|
|
67
62
|
Object.defineProperty(this, "checkList", {
|
|
68
63
|
enumerable: true,
|
|
@@ -88,37 +83,37 @@ class Connection {
|
|
|
88
83
|
writable: true,
|
|
89
84
|
value: void 0
|
|
90
85
|
});
|
|
91
|
-
Object.defineProperty(this, "
|
|
86
|
+
Object.defineProperty(this, "options", {
|
|
92
87
|
enumerable: true,
|
|
93
88
|
configurable: true,
|
|
94
89
|
writable: true,
|
|
95
90
|
value: void 0
|
|
96
91
|
});
|
|
97
|
-
Object.defineProperty(this, "
|
|
92
|
+
Object.defineProperty(this, "remoteCandidatesEnd", {
|
|
98
93
|
enumerable: true,
|
|
99
94
|
configurable: true,
|
|
100
95
|
writable: true,
|
|
101
|
-
value:
|
|
96
|
+
value: false
|
|
102
97
|
});
|
|
103
|
-
Object.defineProperty(this, "
|
|
98
|
+
Object.defineProperty(this, "localCandidatesEnd", {
|
|
104
99
|
enumerable: true,
|
|
105
100
|
configurable: true,
|
|
106
101
|
writable: true,
|
|
107
|
-
value:
|
|
102
|
+
value: false
|
|
108
103
|
});
|
|
109
|
-
Object.defineProperty(this, "
|
|
104
|
+
Object.defineProperty(this, "generation", {
|
|
110
105
|
enumerable: true,
|
|
111
106
|
configurable: true,
|
|
112
107
|
writable: true,
|
|
113
|
-
value:
|
|
108
|
+
value: -1
|
|
114
109
|
});
|
|
115
|
-
Object.defineProperty(this, "
|
|
110
|
+
Object.defineProperty(this, "userHistory", {
|
|
116
111
|
enumerable: true,
|
|
117
112
|
configurable: true,
|
|
118
113
|
writable: true,
|
|
119
|
-
value:
|
|
114
|
+
value: {}
|
|
120
115
|
});
|
|
121
|
-
Object.defineProperty(this, "
|
|
116
|
+
Object.defineProperty(this, "tieBreaker", {
|
|
122
117
|
enumerable: true,
|
|
123
118
|
configurable: true,
|
|
124
119
|
writable: true,
|
|
@@ -136,24 +131,6 @@ class Connection {
|
|
|
136
131
|
writable: true,
|
|
137
132
|
value: void 0
|
|
138
133
|
});
|
|
139
|
-
Object.defineProperty(this, "restarted", {
|
|
140
|
-
enumerable: true,
|
|
141
|
-
configurable: true,
|
|
142
|
-
writable: true,
|
|
143
|
-
value: false
|
|
144
|
-
});
|
|
145
|
-
Object.defineProperty(this, "onData", {
|
|
146
|
-
enumerable: true,
|
|
147
|
-
configurable: true,
|
|
148
|
-
writable: true,
|
|
149
|
-
value: new common_1.Event()
|
|
150
|
-
});
|
|
151
|
-
Object.defineProperty(this, "stateChanged", {
|
|
152
|
-
enumerable: true,
|
|
153
|
-
configurable: true,
|
|
154
|
-
writable: true,
|
|
155
|
-
value: new common_1.Event()
|
|
156
|
-
});
|
|
157
134
|
Object.defineProperty(this, "_remoteCandidates", {
|
|
158
135
|
enumerable: true,
|
|
159
136
|
configurable: true,
|
|
@@ -191,6 +168,12 @@ class Connection {
|
|
|
191
168
|
writable: true,
|
|
192
169
|
value: []
|
|
193
170
|
});
|
|
171
|
+
Object.defineProperty(this, "earlyChecksDone", {
|
|
172
|
+
enumerable: true,
|
|
173
|
+
configurable: true,
|
|
174
|
+
writable: true,
|
|
175
|
+
value: false
|
|
176
|
+
});
|
|
194
177
|
Object.defineProperty(this, "localCandidatesStart", {
|
|
195
178
|
enumerable: true,
|
|
196
179
|
configurable: true,
|
|
@@ -215,66 +198,101 @@ class Connection {
|
|
|
215
198
|
writable: true,
|
|
216
199
|
value: void 0
|
|
217
200
|
});
|
|
201
|
+
Object.defineProperty(this, "onData", {
|
|
202
|
+
enumerable: true,
|
|
203
|
+
configurable: true,
|
|
204
|
+
writable: true,
|
|
205
|
+
value: new common_1.Event()
|
|
206
|
+
});
|
|
207
|
+
Object.defineProperty(this, "stateChanged", {
|
|
208
|
+
enumerable: true,
|
|
209
|
+
configurable: true,
|
|
210
|
+
writable: true,
|
|
211
|
+
value: new common_1.Event()
|
|
212
|
+
});
|
|
213
|
+
Object.defineProperty(this, "onIceCandidate", {
|
|
214
|
+
enumerable: true,
|
|
215
|
+
configurable: true,
|
|
216
|
+
writable: true,
|
|
217
|
+
value: new common_1.Event()
|
|
218
|
+
});
|
|
218
219
|
// 4.1.1.4 ? 生存確認 life check
|
|
219
220
|
Object.defineProperty(this, "queryConsent", {
|
|
220
221
|
enumerable: true,
|
|
221
222
|
configurable: true,
|
|
222
223
|
writable: true,
|
|
223
|
-
value: () =>
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
if (
|
|
247
|
-
|
|
224
|
+
value: () => {
|
|
225
|
+
if (this.queryConsentHandle) {
|
|
226
|
+
this.queryConsentHandle.resolve();
|
|
227
|
+
}
|
|
228
|
+
this.queryConsentHandle = (0, helper_1.cancelable)(async (_, __, onCancel) => {
|
|
229
|
+
let failures = 0;
|
|
230
|
+
let canceled = false;
|
|
231
|
+
const cancelEvent = new AbortController();
|
|
232
|
+
onCancel.once(() => {
|
|
233
|
+
canceled = true;
|
|
234
|
+
failures += iceBase_1.CONSENT_FAILURES;
|
|
235
|
+
cancelEvent.abort();
|
|
236
|
+
this.queryConsentHandle = undefined;
|
|
237
|
+
});
|
|
238
|
+
const { localUsername, remoteUsername, iceControlling } = this;
|
|
239
|
+
// """
|
|
240
|
+
// Periodically check consent (RFC 7675).
|
|
241
|
+
// """
|
|
242
|
+
try {
|
|
243
|
+
while (this.state !== "closed" && !canceled) {
|
|
244
|
+
// # randomize between 0.8 and 1.2 times CONSENT_INTERVAL
|
|
245
|
+
await promises_1.default.setTimeout(iceBase_1.CONSENT_INTERVAL * (0.8 + 0.4 * Math.random()) * 1000, undefined, { signal: cancelEvent.signal });
|
|
246
|
+
const nominated = this.nominated;
|
|
247
|
+
if (!nominated || canceled) {
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
const request = this.buildRequest({
|
|
251
|
+
nominate: false,
|
|
252
|
+
localUsername,
|
|
253
|
+
remoteUsername,
|
|
254
|
+
iceControlling,
|
|
255
|
+
});
|
|
256
|
+
try {
|
|
257
|
+
await nominated.protocol.request(request, nominated.remoteAddr, Buffer.from(this.remotePassword, "utf8"), 0);
|
|
258
|
+
failures = 0;
|
|
259
|
+
if (this.state === "disconnected") {
|
|
260
|
+
this.setState("connected");
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
if (nominated.id === this.nominated?.id) {
|
|
265
|
+
log("no stun response");
|
|
266
|
+
failures++;
|
|
267
|
+
this.setState("disconnected");
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (failures >= iceBase_1.CONSENT_FAILURES) {
|
|
272
|
+
log("Consent to send expired");
|
|
273
|
+
this.queryConsentHandle = undefined;
|
|
274
|
+
this.setState("closed");
|
|
275
|
+
break;
|
|
248
276
|
}
|
|
249
|
-
}
|
|
250
|
-
catch (error) {
|
|
251
|
-
log("no stun response");
|
|
252
|
-
failures++;
|
|
253
|
-
this.setState("disconnected");
|
|
254
|
-
}
|
|
255
|
-
if (failures >= CONSENT_FAILURES) {
|
|
256
|
-
log("Consent to send expired");
|
|
257
|
-
this.queryConsentHandle = undefined;
|
|
258
|
-
// 切断検知
|
|
259
|
-
r(await this.close());
|
|
260
|
-
return;
|
|
261
277
|
}
|
|
262
278
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
279
|
+
catch (error) { }
|
|
280
|
+
});
|
|
281
|
+
}
|
|
266
282
|
});
|
|
267
283
|
Object.defineProperty(this, "send", {
|
|
268
284
|
enumerable: true,
|
|
269
285
|
configurable: true,
|
|
270
286
|
writable: true,
|
|
271
287
|
value: async (data) => {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
288
|
+
const activePair = this.nominated;
|
|
289
|
+
if (activePair) {
|
|
290
|
+
await activePair.protocol.sendData(data, activePair.remoteAddr);
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
// log("Cannot send data, ice not connected");
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
278
296
|
}
|
|
279
297
|
});
|
|
280
298
|
// 3. Terminology : Check
|
|
@@ -282,26 +300,42 @@ class Connection {
|
|
|
282
300
|
enumerable: true,
|
|
283
301
|
configurable: true,
|
|
284
302
|
writable: true,
|
|
285
|
-
value: (pair) =>
|
|
286
|
-
onCancel(() => f("cancel"));
|
|
303
|
+
value: (pair) => (0, helper_1.cancelable)(async (r) => {
|
|
287
304
|
// """
|
|
288
305
|
// Starts a check.
|
|
289
306
|
// """
|
|
290
307
|
log("check start", pair.toJSON());
|
|
291
|
-
|
|
292
|
-
const nominate = this.iceControlling && !this.remoteIsLite;
|
|
293
|
-
const request = this.buildRequest(pair, nominate);
|
|
308
|
+
pair.updateState(iceBase_1.CandidatePairState.IN_PROGRESS);
|
|
294
309
|
const result = {};
|
|
310
|
+
const { remotePassword, remoteUsername, generation } = this;
|
|
311
|
+
const localUsername = pair.localCandidate.ufrag ?? this.localUsername;
|
|
312
|
+
const nominate = this.iceControlling && !this.remoteIsLite;
|
|
313
|
+
const request = this.buildRequest({
|
|
314
|
+
nominate,
|
|
315
|
+
localUsername,
|
|
316
|
+
remoteUsername,
|
|
317
|
+
iceControlling: this.iceControlling,
|
|
318
|
+
});
|
|
295
319
|
try {
|
|
296
|
-
const [response, addr] = await pair.protocol.request(request, pair.remoteAddr, Buffer.from(
|
|
297
|
-
log("response", response, addr
|
|
320
|
+
const [response, addr] = await pair.protocol.request(request, pair.remoteAddr, Buffer.from(remotePassword, "utf8"), 4);
|
|
321
|
+
log("response received", request.toJSON(), response.toJSON(), addr, {
|
|
322
|
+
localUsername,
|
|
323
|
+
remoteUsername,
|
|
324
|
+
remotePassword,
|
|
325
|
+
generation,
|
|
326
|
+
});
|
|
298
327
|
result.response = response;
|
|
299
328
|
result.addr = addr;
|
|
300
329
|
}
|
|
301
330
|
catch (error) {
|
|
302
331
|
const exc = error;
|
|
303
332
|
// 7.1.3.1. Failure Cases
|
|
304
|
-
log("failure case", exc.response)
|
|
333
|
+
log("failure case", request.toJSON(), exc.response ? JSON.stringify(exc.response.toJSON(), null, 2) : error, {
|
|
334
|
+
localUsername,
|
|
335
|
+
remoteUsername,
|
|
336
|
+
remotePassword,
|
|
337
|
+
generation,
|
|
338
|
+
});
|
|
305
339
|
if (exc.response?.getAttributeValue("ERROR-CODE")[0] === 487) {
|
|
306
340
|
if (request.attributesKeys.includes("ICE-CONTROLLED")) {
|
|
307
341
|
this.switchRole(true);
|
|
@@ -309,14 +343,20 @@ class Connection {
|
|
|
309
343
|
else if (request.attributesKeys.includes("ICE-CONTROLLING")) {
|
|
310
344
|
this.switchRole(false);
|
|
311
345
|
}
|
|
312
|
-
await this.checkStart(pair);
|
|
346
|
+
await this.checkStart(pair).awaitable;
|
|
347
|
+
r();
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
if (exc.response?.getAttributeValue("ERROR-CODE")[0] === 401) {
|
|
351
|
+
log("retry 401", pair.toJSON());
|
|
352
|
+
await this.checkStart(pair).awaitable;
|
|
313
353
|
r();
|
|
314
354
|
return;
|
|
315
355
|
}
|
|
316
356
|
else {
|
|
317
357
|
// timeout
|
|
318
|
-
log("CandidatePairState.FAILED", pair.toJSON());
|
|
319
|
-
|
|
358
|
+
log("checkStart CandidatePairState.FAILED", pair.toJSON());
|
|
359
|
+
pair.updateState(iceBase_1.CandidatePairState.FAILED);
|
|
320
360
|
this.checkComplete(pair);
|
|
321
361
|
r();
|
|
322
362
|
return;
|
|
@@ -324,7 +364,7 @@ class Connection {
|
|
|
324
364
|
}
|
|
325
365
|
// # check remote address matches
|
|
326
366
|
if (!(0, isEqual_1.default)(result.addr, pair.remoteAddr)) {
|
|
327
|
-
|
|
367
|
+
pair.updateState(iceBase_1.CandidatePairState.FAILED);
|
|
328
368
|
this.checkComplete(pair);
|
|
329
369
|
r();
|
|
330
370
|
return;
|
|
@@ -337,18 +377,23 @@ class Connection {
|
|
|
337
377
|
else if (this.iceControlling && !this.nominating) {
|
|
338
378
|
// # perform regular nomination
|
|
339
379
|
this.nominating = true;
|
|
340
|
-
const request = this.buildRequest(
|
|
380
|
+
const request = this.buildRequest({
|
|
381
|
+
nominate: true,
|
|
382
|
+
localUsername,
|
|
383
|
+
remoteUsername,
|
|
384
|
+
iceControlling: this.iceControlling,
|
|
385
|
+
});
|
|
341
386
|
try {
|
|
342
387
|
await pair.protocol.request(request, pair.remoteAddr, Buffer.from(this.remotePassword, "utf8"));
|
|
343
388
|
}
|
|
344
389
|
catch (error) {
|
|
345
|
-
|
|
390
|
+
pair.updateState(iceBase_1.CandidatePairState.FAILED);
|
|
346
391
|
this.checkComplete(pair);
|
|
347
392
|
return;
|
|
348
393
|
}
|
|
349
394
|
pair.nominated = true;
|
|
350
395
|
}
|
|
351
|
-
|
|
396
|
+
pair.updateState(iceBase_1.CandidatePairState.SUCCEEDED);
|
|
352
397
|
this.checkComplete(pair);
|
|
353
398
|
r();
|
|
354
399
|
})
|
|
@@ -364,17 +409,71 @@ class Connection {
|
|
|
364
409
|
}
|
|
365
410
|
});
|
|
366
411
|
this.options = {
|
|
367
|
-
...defaultOptions,
|
|
412
|
+
...iceBase_1.defaultOptions,
|
|
368
413
|
...options,
|
|
369
414
|
};
|
|
370
|
-
const { stunServer, turnServer
|
|
371
|
-
this.stunServer = validateAddress(stunServer) ?? [
|
|
415
|
+
const { stunServer, turnServer } = this.options;
|
|
416
|
+
this.stunServer = (0, iceBase_1.validateAddress)(stunServer) ?? [
|
|
372
417
|
"stun.l.google.com",
|
|
373
418
|
19302,
|
|
374
419
|
];
|
|
375
|
-
this.turnServer = validateAddress(turnServer);
|
|
376
|
-
this.
|
|
377
|
-
|
|
420
|
+
this.turnServer = (0, iceBase_1.validateAddress)(turnServer);
|
|
421
|
+
this.restart();
|
|
422
|
+
}
|
|
423
|
+
get iceControlling() {
|
|
424
|
+
return this._iceControlling;
|
|
425
|
+
}
|
|
426
|
+
set iceControlling(value) {
|
|
427
|
+
if (this.generation > 0 || this.nominated) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
this._iceControlling = value;
|
|
431
|
+
for (const pair of this.checkList) {
|
|
432
|
+
pair.iceControlling = value;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
async restart() {
|
|
436
|
+
this.generation++;
|
|
437
|
+
this.localUsername = (0, helper_1.randomString)(4);
|
|
438
|
+
this.localPassword = (0, helper_1.randomString)(22);
|
|
439
|
+
if (this.options.localPasswordPrefix) {
|
|
440
|
+
this.localPassword =
|
|
441
|
+
this.options.localPasswordPrefix +
|
|
442
|
+
this.localPassword.slice(this.options.localPasswordPrefix.length);
|
|
443
|
+
}
|
|
444
|
+
this.userHistory[this.localUsername] = this.localPassword;
|
|
445
|
+
this.remoteUsername = "";
|
|
446
|
+
this.remotePassword = "";
|
|
447
|
+
this.localCandidates = [];
|
|
448
|
+
this._remoteCandidates = [];
|
|
449
|
+
this.remoteCandidatesEnd = false;
|
|
450
|
+
this.localCandidatesEnd = false;
|
|
451
|
+
this.state = "new";
|
|
452
|
+
this.lookup?.close?.();
|
|
453
|
+
this.lookup = undefined;
|
|
454
|
+
this.nominated = undefined;
|
|
455
|
+
this.nominating = false;
|
|
456
|
+
this.checkList = [];
|
|
457
|
+
this.checkListDone = false;
|
|
458
|
+
this.checkListState = new helper_1.PQueue();
|
|
459
|
+
this.earlyChecks = [];
|
|
460
|
+
this.earlyChecksDone = false;
|
|
461
|
+
this.localCandidatesStart = false;
|
|
462
|
+
// protocolsはincomingのearlyCheckに使うかもしれないので残す
|
|
463
|
+
for (const protocol of this.protocols) {
|
|
464
|
+
if (protocol.localCandidate) {
|
|
465
|
+
protocol.localCandidate.generation = this.generation;
|
|
466
|
+
protocol.localCandidate.ufrag = this.localUsername;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
this.queryConsentHandle?.resolve?.();
|
|
470
|
+
this.queryConsentHandle = undefined;
|
|
471
|
+
this.promiseGatherCandidates = undefined;
|
|
472
|
+
}
|
|
473
|
+
resetNominatedPair() {
|
|
474
|
+
log("resetNominatedPair");
|
|
475
|
+
this.nominated = undefined;
|
|
476
|
+
this.nominating = false;
|
|
378
477
|
}
|
|
379
478
|
setRemoteParams({ iceLite, usernameFragment, password, }) {
|
|
380
479
|
log("setRemoteParams", { iceLite, usernameFragment, password });
|
|
@@ -383,11 +482,11 @@ class Connection {
|
|
|
383
482
|
this.remotePassword = password;
|
|
384
483
|
}
|
|
385
484
|
// 4.1.1 Gathering Candidates
|
|
386
|
-
async gatherCandidates(
|
|
485
|
+
async gatherCandidates() {
|
|
387
486
|
if (!this.localCandidatesStart) {
|
|
388
487
|
this.localCandidatesStart = true;
|
|
389
488
|
this.promiseGatherCandidates = new common_1.Event();
|
|
390
|
-
let address = (0, utils_1.getHostAddresses)(this.useIpv4, this.useIpv6);
|
|
489
|
+
let address = (0, utils_1.getHostAddresses)(this.options.useIpv4, this.options.useIpv6);
|
|
391
490
|
const { interfaceAddresses } = this.options;
|
|
392
491
|
if (interfaceAddresses) {
|
|
393
492
|
const filteredAddresses = address.filter((check) => Object.values(interfaceAddresses).includes(check));
|
|
@@ -398,18 +497,86 @@ class Connection {
|
|
|
398
497
|
if (this.options.additionalHostAddresses) {
|
|
399
498
|
address = Array.from(new Set([...this.options.additionalHostAddresses, ...address]));
|
|
400
499
|
}
|
|
401
|
-
const candidates = await this.getCandidates(address, 5
|
|
500
|
+
const candidates = await this.getCandidates(address, 5);
|
|
402
501
|
this.localCandidates = [...this.localCandidates, ...candidates];
|
|
403
|
-
this.
|
|
502
|
+
this.localCandidatesEnd = true;
|
|
404
503
|
this.promiseGatherCandidates.execute();
|
|
405
504
|
}
|
|
406
505
|
this.setState("completed");
|
|
407
506
|
}
|
|
408
|
-
|
|
507
|
+
ensureProtocol(protocol) {
|
|
508
|
+
protocol.onRequestReceived.subscribe((msg, addr, data) => {
|
|
509
|
+
if (msg.messageMethod !== const_1.methods.BINDING) {
|
|
510
|
+
this.respondError(msg, addr, protocol, [400, "Bad Request"]);
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
const txUsername = msg.getAttributeValue("USERNAME");
|
|
514
|
+
// 相手にとってのremoteは自分にとってのlocal
|
|
515
|
+
const { remoteUsername: localUsername } = decodeTxUsername(txUsername);
|
|
516
|
+
const localPassword = this.userHistory[localUsername] ?? this.localPassword;
|
|
517
|
+
const { iceControlling } = this;
|
|
518
|
+
// 7.2.1.1. Detecting and Repairing Role Conflicts
|
|
519
|
+
if (iceControlling && msg.attributesKeys.includes("ICE-CONTROLLING")) {
|
|
520
|
+
if (this.tieBreaker >= msg.getAttributeValue("ICE-CONTROLLING")) {
|
|
521
|
+
this.respondError(msg, addr, protocol, [487, "Role Conflict"]);
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
else {
|
|
525
|
+
this.switchRole(false);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
else if (!iceControlling &&
|
|
529
|
+
msg.attributesKeys.includes("ICE-CONTROLLED")) {
|
|
530
|
+
if (this.tieBreaker < msg.getAttributeValue("ICE-CONTROLLED")) {
|
|
531
|
+
this.respondError(msg, addr, protocol, [487, "Role Conflict"]);
|
|
532
|
+
}
|
|
533
|
+
else {
|
|
534
|
+
this.switchRole(true);
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
if (this.options.filterStunResponse &&
|
|
539
|
+
!this.options.filterStunResponse(msg, addr, protocol)) {
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
// # send binding response
|
|
543
|
+
const response = new message_1.Message(const_1.methods.BINDING, const_1.classes.RESPONSE, msg.transactionId);
|
|
544
|
+
response
|
|
545
|
+
.setAttribute("XOR-MAPPED-ADDRESS", addr)
|
|
546
|
+
.addMessageIntegrity(Buffer.from(localPassword, "utf8"))
|
|
547
|
+
.addFingerprint();
|
|
548
|
+
protocol.sendStun(response, addr).catch((e) => {
|
|
549
|
+
log("sendStun error", e);
|
|
550
|
+
});
|
|
551
|
+
if (this.checkList.length === 0 && !this.earlyChecksDone) {
|
|
552
|
+
this.earlyChecks.push([msg, addr, protocol]);
|
|
553
|
+
}
|
|
554
|
+
else {
|
|
555
|
+
this.checkIncoming(msg, addr, protocol);
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
protocol.onDataReceived.subscribe((data) => {
|
|
559
|
+
try {
|
|
560
|
+
this.onData.execute(data);
|
|
561
|
+
}
|
|
562
|
+
catch (error) {
|
|
563
|
+
log("dataReceived", error);
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
async getCandidates(addresses, timeout = 5) {
|
|
409
568
|
let candidates = [];
|
|
569
|
+
addresses = addresses.filter((address) => {
|
|
570
|
+
// ice restartで同じアドレスが追加されるのを防ぐ
|
|
571
|
+
if (this.protocols.find((protocol) => protocol.localIp === address)) {
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
return true;
|
|
575
|
+
});
|
|
410
576
|
await Promise.allSettled(addresses.map(async (address) => {
|
|
411
577
|
// # create transport
|
|
412
|
-
const protocol = new protocol_1.StunProtocol(
|
|
578
|
+
const protocol = new protocol_1.StunProtocol();
|
|
579
|
+
this.ensureProtocol(protocol);
|
|
413
580
|
try {
|
|
414
581
|
await protocol.connectionMade((0, net_1.isIPv4)(address), this.options.portRange, this.options.interfaceAddresses);
|
|
415
582
|
}
|
|
@@ -417,16 +584,14 @@ class Connection {
|
|
|
417
584
|
log("protocol STUN", error);
|
|
418
585
|
return;
|
|
419
586
|
}
|
|
420
|
-
protocol.
|
|
587
|
+
protocol.localIp = address;
|
|
421
588
|
this.protocols.push(protocol);
|
|
422
589
|
// # add host candidate
|
|
423
590
|
const candidateAddress = [address, protocol.getExtraInfo()[1]];
|
|
424
|
-
protocol.localCandidate = new candidate_1.Candidate((0, candidate_1.candidateFoundation)("host", "udp", candidateAddress[0]), 1, "udp", (0, candidate_1.candidatePriority)("host"), candidateAddress[0], candidateAddress[1], "host");
|
|
591
|
+
protocol.localCandidate = new candidate_1.Candidate((0, candidate_1.candidateFoundation)("host", "udp", candidateAddress[0]), 1, "udp", (0, candidate_1.candidatePriority)("host"), candidateAddress[0], candidateAddress[1], "host", undefined, undefined, undefined, this.generation, this.localUsername);
|
|
425
592
|
this.pairLocalProtocol(protocol);
|
|
426
593
|
candidates.push(protocol.localCandidate);
|
|
427
|
-
|
|
428
|
-
cb(protocol.localCandidate);
|
|
429
|
-
}
|
|
594
|
+
this.onIceCandidate.execute(protocol.localCandidate);
|
|
430
595
|
}));
|
|
431
596
|
let candidatePromises = [];
|
|
432
597
|
// # query STUN server for server-reflexive candidates (IPv4 only)
|
|
@@ -436,9 +601,12 @@ class Connection {
|
|
|
436
601
|
const timer = setTimeout(f, timeout * 1000);
|
|
437
602
|
if (protocol.localCandidate?.host &&
|
|
438
603
|
(0, net_1.isIPv4)(protocol.localCandidate?.host)) {
|
|
439
|
-
const candidate = await serverReflexiveCandidate(protocol, stunServer).catch((error) =>
|
|
440
|
-
|
|
441
|
-
|
|
604
|
+
const candidate = await (0, iceBase_1.serverReflexiveCandidate)(protocol, stunServer).catch((error) => {
|
|
605
|
+
log("error", error);
|
|
606
|
+
});
|
|
607
|
+
if (candidate) {
|
|
608
|
+
this.onIceCandidate.execute(candidate);
|
|
609
|
+
}
|
|
442
610
|
clearTimeout(timer);
|
|
443
611
|
r(candidate);
|
|
444
612
|
}
|
|
@@ -458,7 +626,6 @@ class Connection {
|
|
|
458
626
|
address: turnServer,
|
|
459
627
|
username: turnUsername,
|
|
460
628
|
password: turnPassword,
|
|
461
|
-
ice: this,
|
|
462
629
|
}, {
|
|
463
630
|
portRange: this.options.portRange,
|
|
464
631
|
interfaceAddresses: this.options.interfaceAddresses,
|
|
@@ -469,7 +636,6 @@ class Connection {
|
|
|
469
636
|
address: turnServer,
|
|
470
637
|
username: turnUsername,
|
|
471
638
|
password: turnPassword,
|
|
472
|
-
ice: this,
|
|
473
639
|
}, {
|
|
474
640
|
portRange: this.options.portRange,
|
|
475
641
|
interfaceAddresses: this.options.interfaceAddresses,
|
|
@@ -480,14 +646,13 @@ class Connection {
|
|
|
480
646
|
throw e;
|
|
481
647
|
}
|
|
482
648
|
});
|
|
649
|
+
this.ensureProtocol(protocol);
|
|
483
650
|
this.protocols.push(protocol);
|
|
484
651
|
const candidateAddress = protocol.turn.relayedAddress;
|
|
485
652
|
const relatedAddress = protocol.turn.mappedAddress;
|
|
486
653
|
log("turn candidateAddress", candidateAddress);
|
|
487
|
-
protocol.localCandidate = new candidate_1.Candidate((0, candidate_1.candidateFoundation)("relay", "udp", candidateAddress[0]), 1, "udp", (0, candidate_1.candidatePriority)("relay"), candidateAddress[0], candidateAddress[1], "relay", relatedAddress[0], relatedAddress[1]);
|
|
488
|
-
|
|
489
|
-
cb(protocol.localCandidate);
|
|
490
|
-
}
|
|
654
|
+
protocol.localCandidate = new candidate_1.Candidate((0, candidate_1.candidateFoundation)("relay", "udp", candidateAddress[0]), 1, "udp", (0, candidate_1.candidatePriority)("relay"), candidateAddress[0], candidateAddress[1], "relay", relatedAddress[0], relatedAddress[1], undefined, this.generation, this.localUsername);
|
|
655
|
+
this.onIceCandidate.execute(protocol.localCandidate);
|
|
491
656
|
return protocol.localCandidate;
|
|
492
657
|
})().catch((error) => {
|
|
493
658
|
log("query TURN server", error);
|
|
@@ -512,23 +677,32 @@ class Connection {
|
|
|
512
677
|
// This coroutine returns if a candidate pair was successfully nominated
|
|
513
678
|
// and raises an exception otherwise.
|
|
514
679
|
// """
|
|
515
|
-
log("start connect ice"
|
|
516
|
-
if (!this.
|
|
517
|
-
if (!this.localCandidatesStart)
|
|
680
|
+
log("start connect ice");
|
|
681
|
+
if (!this.localCandidatesEnd) {
|
|
682
|
+
if (!this.localCandidatesStart) {
|
|
518
683
|
throw new Error("Local candidates gathering was not performed");
|
|
519
|
-
|
|
684
|
+
}
|
|
685
|
+
if (this.promiseGatherCandidates) {
|
|
520
686
|
// wait for GatherCandidates finish
|
|
521
687
|
await this.promiseGatherCandidates.asPromise();
|
|
688
|
+
}
|
|
522
689
|
}
|
|
523
|
-
if (!this.remoteUsername || !this.remotePassword)
|
|
690
|
+
if (!this.remoteUsername || !this.remotePassword) {
|
|
524
691
|
throw new Error("Remote username or password is missing");
|
|
692
|
+
}
|
|
525
693
|
// # 5.7.1. Forming Candidate Pairs
|
|
526
|
-
this.remoteCandidates
|
|
694
|
+
for (const c of this.remoteCandidates) {
|
|
695
|
+
this.pairRemoteCandidate(c);
|
|
696
|
+
}
|
|
527
697
|
this.sortCheckList();
|
|
528
698
|
this.unfreezeInitial();
|
|
699
|
+
log("earlyChecks", this.localPassword, this.earlyChecks.length);
|
|
529
700
|
// # handle early checks
|
|
530
|
-
|
|
701
|
+
for (const earlyCheck of this.earlyChecks) {
|
|
702
|
+
this.checkIncoming(...earlyCheck);
|
|
703
|
+
}
|
|
531
704
|
this.earlyChecks = [];
|
|
705
|
+
this.earlyChecksDone = true;
|
|
532
706
|
// # perform checks
|
|
533
707
|
// 5.8. Scheduling Checks
|
|
534
708
|
for (;;) {
|
|
@@ -539,17 +713,19 @@ class Connection {
|
|
|
539
713
|
await promises_1.default.setTimeout(20);
|
|
540
714
|
}
|
|
541
715
|
// # wait for completion
|
|
542
|
-
let res = ICE_FAILED;
|
|
543
|
-
while (this.checkList.length > 0 && res === ICE_FAILED) {
|
|
716
|
+
let res = iceBase_1.ICE_FAILED;
|
|
717
|
+
while (this.checkList.length > 0 && res === iceBase_1.ICE_FAILED) {
|
|
544
718
|
res = await this.checkListState.get();
|
|
545
719
|
}
|
|
546
720
|
// # cancel remaining checks
|
|
547
|
-
|
|
548
|
-
|
|
721
|
+
for (const check of this.checkList) {
|
|
722
|
+
check.handle?.resolve?.();
|
|
723
|
+
}
|
|
724
|
+
if (res !== iceBase_1.ICE_COMPLETED) {
|
|
549
725
|
throw new Error("ICE negotiation failed");
|
|
550
726
|
}
|
|
551
727
|
// # start consent freshness tests
|
|
552
|
-
this.
|
|
728
|
+
this.queryConsent();
|
|
553
729
|
this.setState("connected");
|
|
554
730
|
}
|
|
555
731
|
unfreezeInitial() {
|
|
@@ -557,16 +733,16 @@ class Connection {
|
|
|
557
733
|
const [firstPair] = this.checkList;
|
|
558
734
|
if (!firstPair)
|
|
559
735
|
return;
|
|
560
|
-
if (firstPair.state === CandidatePairState.FROZEN) {
|
|
561
|
-
|
|
736
|
+
if (firstPair.state === iceBase_1.CandidatePairState.FROZEN) {
|
|
737
|
+
firstPair.updateState(iceBase_1.CandidatePairState.WAITING);
|
|
562
738
|
}
|
|
563
739
|
// # unfreeze pairs with same component but different foundations
|
|
564
740
|
const seenFoundations = new Set(firstPair.localCandidate.foundation);
|
|
565
741
|
for (const pair of this.checkList) {
|
|
566
742
|
if (pair.component === firstPair.component &&
|
|
567
743
|
!seenFoundations.has(pair.localCandidate.foundation) &&
|
|
568
|
-
pair.state === CandidatePairState.FROZEN) {
|
|
569
|
-
|
|
744
|
+
pair.state === iceBase_1.CandidatePairState.FROZEN) {
|
|
745
|
+
pair.updateState(iceBase_1.CandidatePairState.WAITING);
|
|
570
746
|
seenFoundations.add(pair.localCandidate.foundation);
|
|
571
747
|
}
|
|
572
748
|
}
|
|
@@ -583,17 +759,17 @@ class Connection {
|
|
|
583
759
|
return false;
|
|
584
760
|
return true;
|
|
585
761
|
})
|
|
586
|
-
.find((pair) => pair.state === CandidatePairState.WAITING);
|
|
762
|
+
.find((pair) => pair.state === iceBase_1.CandidatePairState.WAITING);
|
|
587
763
|
if (pair) {
|
|
588
|
-
pair.handle =
|
|
764
|
+
pair.handle = this.checkStart(pair);
|
|
589
765
|
return true;
|
|
590
766
|
}
|
|
591
767
|
}
|
|
592
768
|
{
|
|
593
769
|
// # find the highest-priority pair that is in the frozen state
|
|
594
|
-
const pair = this.checkList.find((pair) => pair.state === CandidatePairState.FROZEN);
|
|
770
|
+
const pair = this.checkList.find((pair) => pair.state === iceBase_1.CandidatePairState.FROZEN);
|
|
595
771
|
if (pair) {
|
|
596
|
-
pair.handle =
|
|
772
|
+
pair.handle = this.checkStart(pair);
|
|
597
773
|
return true;
|
|
598
774
|
}
|
|
599
775
|
}
|
|
@@ -609,19 +785,11 @@ class Connection {
|
|
|
609
785
|
// """
|
|
610
786
|
this.setState("closed");
|
|
611
787
|
// # stop consent freshness tests
|
|
612
|
-
|
|
613
|
-
this.queryConsentHandle.cancel();
|
|
614
|
-
try {
|
|
615
|
-
await this.queryConsentHandle.promise;
|
|
616
|
-
}
|
|
617
|
-
catch (error) {
|
|
618
|
-
// pass
|
|
619
|
-
}
|
|
620
|
-
}
|
|
788
|
+
this.queryConsentHandle?.resolve?.();
|
|
621
789
|
// # stop check list
|
|
622
790
|
if (this.checkList && !this.checkListDone) {
|
|
623
791
|
this.checkListState.put(new Promise((r) => {
|
|
624
|
-
r(ICE_FAILED);
|
|
792
|
+
r(iceBase_1.ICE_FAILED);
|
|
625
793
|
}));
|
|
626
794
|
}
|
|
627
795
|
this.nominated = undefined;
|
|
@@ -632,7 +800,8 @@ class Connection {
|
|
|
632
800
|
}
|
|
633
801
|
this.protocols = [];
|
|
634
802
|
this.localCandidates = [];
|
|
635
|
-
|
|
803
|
+
this.lookup?.close?.();
|
|
804
|
+
this.lookup = undefined;
|
|
636
805
|
}
|
|
637
806
|
setState(state) {
|
|
638
807
|
this.state = state;
|
|
@@ -650,8 +819,6 @@ class Connection {
|
|
|
650
819
|
}
|
|
651
820
|
if (remoteCandidate.host.includes(".local")) {
|
|
652
821
|
try {
|
|
653
|
-
if (this.state === "closed")
|
|
654
|
-
return;
|
|
655
822
|
if (!this.lookup) {
|
|
656
823
|
this.lookup = new lookup_1.MdnsLookup();
|
|
657
824
|
}
|
|
@@ -663,105 +830,21 @@ class Connection {
|
|
|
663
830
|
}
|
|
664
831
|
}
|
|
665
832
|
try {
|
|
666
|
-
validateRemoteCandidate(remoteCandidate);
|
|
833
|
+
(0, iceBase_1.validateRemoteCandidate)(remoteCandidate);
|
|
667
834
|
}
|
|
668
835
|
catch (error) {
|
|
669
836
|
return;
|
|
670
837
|
}
|
|
671
838
|
log("addRemoteCandidate", remoteCandidate);
|
|
672
|
-
this.
|
|
839
|
+
this._remoteCandidates.push(remoteCandidate);
|
|
673
840
|
this.pairRemoteCandidate(remoteCandidate);
|
|
674
841
|
this.sortCheckList();
|
|
675
842
|
}
|
|
676
|
-
async sendTo(data) {
|
|
677
|
-
// """
|
|
678
|
-
// Send a datagram on the specified component.
|
|
679
|
-
// If the connection is not established, a `ConnectionError` is raised.
|
|
680
|
-
// :param data: The data to be sent.
|
|
681
|
-
// :param component: The component on which to send the data.
|
|
682
|
-
// """
|
|
683
|
-
const activePair = this.nominated;
|
|
684
|
-
if (activePair) {
|
|
685
|
-
await activePair.protocol.sendData(data, activePair.remoteAddr);
|
|
686
|
-
}
|
|
687
|
-
else {
|
|
688
|
-
// log("Cannot send data, ice not connected");
|
|
689
|
-
return;
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
843
|
getDefaultCandidate() {
|
|
693
844
|
const candidates = this.localCandidates.sort((a, b) => a.priority - b.priority);
|
|
694
845
|
const [candidate] = candidates;
|
|
695
846
|
return candidate;
|
|
696
847
|
}
|
|
697
|
-
requestReceived(message, addr, protocol, rawData) {
|
|
698
|
-
if (message.messageMethod !== const_1.methods.BINDING) {
|
|
699
|
-
this.respondError(message, addr, protocol, [400, "Bad Request"]);
|
|
700
|
-
return;
|
|
701
|
-
}
|
|
702
|
-
// # authenticate request
|
|
703
|
-
try {
|
|
704
|
-
(0, message_1.parseMessage)(rawData, Buffer.from(this.localPassword, "utf8"));
|
|
705
|
-
if (!this.remoteUsername) {
|
|
706
|
-
const rxUsername = `${this.localUserName}:${this.remoteUsername}`;
|
|
707
|
-
if (message.getAttributeValue("USERNAME") != rxUsername) {
|
|
708
|
-
throw new Error("Wrong username");
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
catch (error) {
|
|
713
|
-
this.respondError(message, addr, protocol, [400, "Bad Request"]);
|
|
714
|
-
return;
|
|
715
|
-
}
|
|
716
|
-
const { iceControlling } = this;
|
|
717
|
-
// 7.2.1.1. Detecting and Repairing Role Conflicts
|
|
718
|
-
if (iceControlling && message.attributesKeys.includes("ICE-CONTROLLING")) {
|
|
719
|
-
if (this._tieBreaker >= message.getAttributeValue("ICE-CONTROLLING")) {
|
|
720
|
-
this.respondError(message, addr, protocol, [487, "Role Conflict"]);
|
|
721
|
-
return;
|
|
722
|
-
}
|
|
723
|
-
else {
|
|
724
|
-
this.switchRole(false);
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
else if (!iceControlling &&
|
|
728
|
-
message.attributesKeys.includes("ICE-CONTROLLED")) {
|
|
729
|
-
if (this._tieBreaker < message.getAttributeValue("ICE-CONTROLLED")) {
|
|
730
|
-
this.respondError(message, addr, protocol, [487, "Role Conflict"]);
|
|
731
|
-
}
|
|
732
|
-
else {
|
|
733
|
-
this.switchRole(true);
|
|
734
|
-
return;
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
if (this.options.filterStunResponse &&
|
|
738
|
-
!this.options.filterStunResponse(message, addr, protocol)) {
|
|
739
|
-
return;
|
|
740
|
-
}
|
|
741
|
-
// # send binding response
|
|
742
|
-
const response = new message_1.Message(const_1.methods.BINDING, const_1.classes.RESPONSE, message.transactionId);
|
|
743
|
-
response
|
|
744
|
-
.setAttribute("XOR-MAPPED-ADDRESS", addr)
|
|
745
|
-
.addMessageIntegrity(Buffer.from(this.localPassword, "utf8"))
|
|
746
|
-
.addFingerprint();
|
|
747
|
-
protocol.sendStun(response, addr).catch((e) => {
|
|
748
|
-
log("sendStun error", e);
|
|
749
|
-
});
|
|
750
|
-
// todo fix
|
|
751
|
-
// if (this.checkList.length === 0) {
|
|
752
|
-
// this.earlyChecks.push([message, addr, protocol]);
|
|
753
|
-
// } else {
|
|
754
|
-
this.checkIncoming(message, addr, protocol);
|
|
755
|
-
// }
|
|
756
|
-
}
|
|
757
|
-
dataReceived(data, component) {
|
|
758
|
-
try {
|
|
759
|
-
this.onData.execute(data, component);
|
|
760
|
-
}
|
|
761
|
-
catch (error) {
|
|
762
|
-
log("dataReceived", error);
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
848
|
// for test only
|
|
766
849
|
set remoteCandidates(value) {
|
|
767
850
|
if (this.remoteCandidatesEnd)
|
|
@@ -769,12 +852,12 @@ class Connection {
|
|
|
769
852
|
this._remoteCandidates = [];
|
|
770
853
|
for (const remoteCandidate of value) {
|
|
771
854
|
try {
|
|
772
|
-
validateRemoteCandidate(remoteCandidate);
|
|
855
|
+
(0, iceBase_1.validateRemoteCandidate)(remoteCandidate);
|
|
773
856
|
}
|
|
774
857
|
catch (error) {
|
|
775
858
|
continue;
|
|
776
859
|
}
|
|
777
|
-
this.
|
|
860
|
+
this._remoteCandidates.push(remoteCandidate);
|
|
778
861
|
}
|
|
779
862
|
this.remoteCandidatesEnd = true;
|
|
780
863
|
}
|
|
@@ -782,36 +865,32 @@ class Connection {
|
|
|
782
865
|
return this._remoteCandidates;
|
|
783
866
|
}
|
|
784
867
|
sortCheckList() {
|
|
785
|
-
sortCandidatePairs(this.checkList, this.iceControlling);
|
|
868
|
+
(0, iceBase_1.sortCandidatePairs)(this.checkList, this.iceControlling);
|
|
786
869
|
}
|
|
787
870
|
findPair(protocol, remoteCandidate) {
|
|
788
871
|
const pair = this.checkList.find((pair) => (0, isEqual_1.default)(pair.protocol, protocol) &&
|
|
789
872
|
(0, isEqual_1.default)(pair.remoteCandidate, remoteCandidate));
|
|
790
873
|
return pair;
|
|
791
874
|
}
|
|
792
|
-
setPairState(pair, state) {
|
|
793
|
-
log("setPairState", pair.toJSON(), CandidatePairState[state]);
|
|
794
|
-
pair.updateState(state);
|
|
795
|
-
}
|
|
796
875
|
switchRole(iceControlling) {
|
|
797
876
|
log("switch role", iceControlling);
|
|
798
877
|
this.iceControlling = iceControlling;
|
|
799
878
|
this.sortCheckList();
|
|
800
879
|
}
|
|
801
|
-
resetNominatedPair() {
|
|
802
|
-
log("resetNominatedPair");
|
|
803
|
-
this.nominated = undefined;
|
|
804
|
-
this.nominating = false;
|
|
805
|
-
}
|
|
806
880
|
checkComplete(pair) {
|
|
807
881
|
pair.handle = undefined;
|
|
808
|
-
if (pair.state === CandidatePairState.SUCCEEDED) {
|
|
882
|
+
if (pair.state === iceBase_1.CandidatePairState.SUCCEEDED) {
|
|
809
883
|
// Updating the Nominated Flag
|
|
810
884
|
// https://www.rfc-editor.org/rfc/rfc8445#section-7.3.1.5,
|
|
811
885
|
// Once the nominated flag is set for a component of a data stream, it
|
|
812
886
|
// concludes the ICE processing for that component. See Section 8.
|
|
813
887
|
// So disallow overwriting of the pair nominated for that component
|
|
814
|
-
if (pair.nominated &&
|
|
888
|
+
if (pair.nominated &&
|
|
889
|
+
// remoteのgenerationをチェックする.localのgenerationは更新が間に合わないかもしれないのでチェックしない
|
|
890
|
+
(pair.remoteCandidate.generation != undefined
|
|
891
|
+
? pair.remoteCandidate.generation === this.generation
|
|
892
|
+
: true) &&
|
|
893
|
+
this.nominated == undefined) {
|
|
815
894
|
log("nominated", pair.toJSON());
|
|
816
895
|
this.nominated = pair;
|
|
817
896
|
this.nominating = false;
|
|
@@ -821,8 +900,8 @@ class Connection {
|
|
|
821
900
|
// nominated pairs for that media stream.
|
|
822
901
|
for (const p of this.checkList) {
|
|
823
902
|
if (p.component === pair.component &&
|
|
824
|
-
[CandidatePairState.WAITING, CandidatePairState.FROZEN].includes(p.state)) {
|
|
825
|
-
|
|
903
|
+
[iceBase_1.CandidatePairState.WAITING, iceBase_1.CandidatePairState.FROZEN].includes(p.state)) {
|
|
904
|
+
p.updateState(iceBase_1.CandidatePairState.FAILED);
|
|
826
905
|
}
|
|
827
906
|
}
|
|
828
907
|
}
|
|
@@ -832,27 +911,28 @@ class Connection {
|
|
|
832
911
|
if (this.nominated) {
|
|
833
912
|
if (!this.checkListDone) {
|
|
834
913
|
log("ICE completed");
|
|
835
|
-
this.checkListState.put(new Promise((r) => r(ICE_COMPLETED)));
|
|
914
|
+
this.checkListState.put(new Promise((r) => r(iceBase_1.ICE_COMPLETED)));
|
|
836
915
|
this.checkListDone = true;
|
|
837
916
|
}
|
|
838
917
|
return;
|
|
839
918
|
}
|
|
919
|
+
log("not completed", pair.toJSON());
|
|
840
920
|
// 7.1.3.2.3. Updating Pair States
|
|
841
921
|
for (const p of this.checkList) {
|
|
842
922
|
if (p.localCandidate.foundation === pair.localCandidate.foundation &&
|
|
843
|
-
p.state === CandidatePairState.FROZEN) {
|
|
844
|
-
|
|
923
|
+
p.state === iceBase_1.CandidatePairState.FROZEN) {
|
|
924
|
+
p.updateState(iceBase_1.CandidatePairState.WAITING);
|
|
845
925
|
}
|
|
846
926
|
}
|
|
847
927
|
}
|
|
848
928
|
{
|
|
849
|
-
const list = [CandidatePairState.SUCCEEDED, CandidatePairState.FAILED];
|
|
929
|
+
const list = [iceBase_1.CandidatePairState.SUCCEEDED, iceBase_1.CandidatePairState.FAILED];
|
|
850
930
|
if (this.checkList.find(({ state }) => !list.includes(state))) {
|
|
851
931
|
return;
|
|
852
932
|
}
|
|
853
933
|
}
|
|
854
934
|
if (!this.iceControlling) {
|
|
855
|
-
const target = CandidatePairState.SUCCEEDED;
|
|
935
|
+
const target = iceBase_1.CandidatePairState.SUCCEEDED;
|
|
856
936
|
if (this.checkList.find(({ state }) => state === target)) {
|
|
857
937
|
return;
|
|
858
938
|
}
|
|
@@ -860,17 +940,22 @@ class Connection {
|
|
|
860
940
|
if (!this.checkListDone) {
|
|
861
941
|
log("ICE failed");
|
|
862
942
|
this.checkListState.put(new Promise((r) => {
|
|
863
|
-
r(ICE_FAILED);
|
|
943
|
+
r(iceBase_1.ICE_FAILED);
|
|
864
944
|
}));
|
|
865
945
|
}
|
|
866
946
|
}
|
|
947
|
+
addPair(pair) {
|
|
948
|
+
this.checkList.push(pair);
|
|
949
|
+
this.sortCheckList();
|
|
950
|
+
}
|
|
867
951
|
// 7.2. STUN Server Procedures
|
|
868
952
|
// 7.2.1.3、7.2.1.4、および7.2.1.5
|
|
869
953
|
checkIncoming(message, addr, protocol) {
|
|
870
|
-
// log("checkIncoming", message.toJSON(), addr);
|
|
871
954
|
// """
|
|
872
955
|
// Handle a successful incoming check.
|
|
873
956
|
// """
|
|
957
|
+
const txUsername = message.getAttributeValue("USERNAME");
|
|
958
|
+
const { remoteUsername: localUsername } = decodeTxUsername(txUsername);
|
|
874
959
|
// find remote candidate
|
|
875
960
|
let remoteCandidate;
|
|
876
961
|
const [host, port] = addr;
|
|
@@ -882,20 +967,27 @@ class Connection {
|
|
|
882
967
|
}
|
|
883
968
|
if (!remoteCandidate) {
|
|
884
969
|
// 7.2.1.3. Learning Peer Reflexive Candidates
|
|
885
|
-
remoteCandidate = new candidate_1.Candidate((0, helper_1.randomString)(10), 1, "udp", message.getAttributeValue("PRIORITY"), host, port, "prflx");
|
|
886
|
-
this.
|
|
970
|
+
remoteCandidate = new candidate_1.Candidate((0, helper_1.randomString)(10), 1, "udp", message.getAttributeValue("PRIORITY"), host, port, "prflx", undefined, undefined, undefined, undefined, undefined);
|
|
971
|
+
this._remoteCandidates.push(remoteCandidate);
|
|
887
972
|
}
|
|
888
973
|
// find pair
|
|
889
974
|
let pair = this.findPair(protocol, remoteCandidate);
|
|
890
975
|
if (!pair) {
|
|
891
|
-
pair = new CandidatePair(protocol, remoteCandidate);
|
|
892
|
-
|
|
893
|
-
this.
|
|
894
|
-
this.sortCheckList();
|
|
976
|
+
pair = new iceBase_1.CandidatePair(protocol, remoteCandidate, this.iceControlling);
|
|
977
|
+
pair.updateState(iceBase_1.CandidatePairState.WAITING);
|
|
978
|
+
this.addPair(pair);
|
|
895
979
|
}
|
|
980
|
+
pair.localCandidate.ufrag = localUsername;
|
|
981
|
+
log("Triggered Checks", message.toJSON(), pair.toJSON(), {
|
|
982
|
+
localUsername: this.localUsername,
|
|
983
|
+
remoteUsername: this.remoteUsername,
|
|
984
|
+
localPassword: this.localPassword,
|
|
985
|
+
remotePassword: this.remotePassword,
|
|
986
|
+
generation: this.generation,
|
|
987
|
+
});
|
|
896
988
|
// 7.2.1.4. Triggered Checks
|
|
897
|
-
if ([CandidatePairState.WAITING, CandidatePairState.FAILED].includes(pair.state)) {
|
|
898
|
-
pair.handle =
|
|
989
|
+
if ([iceBase_1.CandidatePairState.WAITING, iceBase_1.CandidatePairState.FAILED].includes(pair.state)) {
|
|
990
|
+
pair.handle = this.checkStart(pair);
|
|
899
991
|
}
|
|
900
992
|
else {
|
|
901
993
|
pair;
|
|
@@ -904,7 +996,7 @@ class Connection {
|
|
|
904
996
|
if (message.attributesKeys.includes("USE-CANDIDATE") &&
|
|
905
997
|
!this.iceControlling) {
|
|
906
998
|
pair.remoteNominated = true;
|
|
907
|
-
if (pair.state === CandidatePairState.SUCCEEDED) {
|
|
999
|
+
if (pair.state === iceBase_1.CandidatePairState.SUCCEEDED) {
|
|
908
1000
|
pair.nominated = true;
|
|
909
1001
|
this.checkComplete(pair);
|
|
910
1002
|
}
|
|
@@ -913,13 +1005,13 @@ class Connection {
|
|
|
913
1005
|
tryPair(protocol, remoteCandidate) {
|
|
914
1006
|
if (protocol.localCandidate?.canPairWith(remoteCandidate) &&
|
|
915
1007
|
!this.findPair(protocol, remoteCandidate)) {
|
|
916
|
-
const pair = new CandidatePair(protocol, remoteCandidate);
|
|
1008
|
+
const pair = new iceBase_1.CandidatePair(protocol, remoteCandidate, this.iceControlling);
|
|
917
1009
|
if (this.options.filterCandidatePair &&
|
|
918
1010
|
!this.options.filterCandidatePair(pair)) {
|
|
919
1011
|
return;
|
|
920
1012
|
}
|
|
921
|
-
|
|
922
|
-
this.
|
|
1013
|
+
pair.updateState(iceBase_1.CandidatePairState.WAITING);
|
|
1014
|
+
this.addPair(pair);
|
|
923
1015
|
}
|
|
924
1016
|
}
|
|
925
1017
|
pairLocalProtocol(protocol) {
|
|
@@ -927,20 +1019,20 @@ class Connection {
|
|
|
927
1019
|
this.tryPair(protocol, remoteCandidate);
|
|
928
1020
|
}
|
|
929
1021
|
}
|
|
930
|
-
buildRequest(
|
|
931
|
-
const txUsername =
|
|
1022
|
+
buildRequest({ nominate, remoteUsername, localUsername, iceControlling, }) {
|
|
1023
|
+
const txUsername = encodeTxUsername({ remoteUsername, localUsername });
|
|
932
1024
|
const request = new message_1.Message(const_1.methods.BINDING, const_1.classes.REQUEST);
|
|
933
1025
|
request
|
|
934
1026
|
.setAttribute("USERNAME", txUsername)
|
|
935
1027
|
.setAttribute("PRIORITY", (0, candidate_1.candidatePriority)("prflx"));
|
|
936
|
-
if (
|
|
937
|
-
request.setAttribute("ICE-CONTROLLING", this.
|
|
1028
|
+
if (iceControlling) {
|
|
1029
|
+
request.setAttribute("ICE-CONTROLLING", this.tieBreaker);
|
|
938
1030
|
if (nominate) {
|
|
939
1031
|
request.setAttribute("USE-CANDIDATE", null);
|
|
940
1032
|
}
|
|
941
1033
|
}
|
|
942
1034
|
else {
|
|
943
|
-
request.setAttribute("ICE-CONTROLLED", this.
|
|
1035
|
+
request.setAttribute("ICE-CONTROLLED", this.tieBreaker);
|
|
944
1036
|
}
|
|
945
1037
|
return request;
|
|
946
1038
|
}
|
|
@@ -956,133 +1048,11 @@ class Connection {
|
|
|
956
1048
|
}
|
|
957
1049
|
}
|
|
958
1050
|
exports.Connection = Connection;
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
protocol: this.protocol.type,
|
|
966
|
-
remoteAddr: this.remoteAddr,
|
|
967
|
-
};
|
|
968
|
-
}
|
|
969
|
-
constructor(protocol, remoteCandidate) {
|
|
970
|
-
Object.defineProperty(this, "protocol", {
|
|
971
|
-
enumerable: true,
|
|
972
|
-
configurable: true,
|
|
973
|
-
writable: true,
|
|
974
|
-
value: protocol
|
|
975
|
-
});
|
|
976
|
-
Object.defineProperty(this, "remoteCandidate", {
|
|
977
|
-
enumerable: true,
|
|
978
|
-
configurable: true,
|
|
979
|
-
writable: true,
|
|
980
|
-
value: remoteCandidate
|
|
981
|
-
});
|
|
982
|
-
Object.defineProperty(this, "handle", {
|
|
983
|
-
enumerable: true,
|
|
984
|
-
configurable: true,
|
|
985
|
-
writable: true,
|
|
986
|
-
value: void 0
|
|
987
|
-
});
|
|
988
|
-
Object.defineProperty(this, "nominated", {
|
|
989
|
-
enumerable: true,
|
|
990
|
-
configurable: true,
|
|
991
|
-
writable: true,
|
|
992
|
-
value: false
|
|
993
|
-
});
|
|
994
|
-
Object.defineProperty(this, "remoteNominated", {
|
|
995
|
-
enumerable: true,
|
|
996
|
-
configurable: true,
|
|
997
|
-
writable: true,
|
|
998
|
-
value: false
|
|
999
|
-
});
|
|
1000
|
-
// 5.7.4. Computing States
|
|
1001
|
-
Object.defineProperty(this, "_state", {
|
|
1002
|
-
enumerable: true,
|
|
1003
|
-
configurable: true,
|
|
1004
|
-
writable: true,
|
|
1005
|
-
value: CandidatePairState.FROZEN
|
|
1006
|
-
});
|
|
1007
|
-
}
|
|
1008
|
-
updateState(state) {
|
|
1009
|
-
this._state = state;
|
|
1010
|
-
}
|
|
1011
|
-
get localCandidate() {
|
|
1012
|
-
if (!this.protocol.localCandidate) {
|
|
1013
|
-
throw new Error("localCandidate not exist");
|
|
1014
|
-
}
|
|
1015
|
-
return this.protocol.localCandidate;
|
|
1016
|
-
}
|
|
1017
|
-
get remoteAddr() {
|
|
1018
|
-
return [this.remoteCandidate.host, this.remoteCandidate.port];
|
|
1019
|
-
}
|
|
1020
|
-
get component() {
|
|
1021
|
-
return this.localCandidate.component;
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
exports.CandidatePair = CandidatePair;
|
|
1025
|
-
const ICE_COMPLETED = 1;
|
|
1026
|
-
const ICE_FAILED = 2;
|
|
1027
|
-
const CONSENT_INTERVAL = 5;
|
|
1028
|
-
const CONSENT_FAILURES = 6;
|
|
1029
|
-
var CandidatePairState;
|
|
1030
|
-
(function (CandidatePairState) {
|
|
1031
|
-
CandidatePairState[CandidatePairState["FROZEN"] = 0] = "FROZEN";
|
|
1032
|
-
CandidatePairState[CandidatePairState["WAITING"] = 1] = "WAITING";
|
|
1033
|
-
CandidatePairState[CandidatePairState["IN_PROGRESS"] = 2] = "IN_PROGRESS";
|
|
1034
|
-
CandidatePairState[CandidatePairState["SUCCEEDED"] = 3] = "SUCCEEDED";
|
|
1035
|
-
CandidatePairState[CandidatePairState["FAILED"] = 4] = "FAILED";
|
|
1036
|
-
})(CandidatePairState || (exports.CandidatePairState = CandidatePairState = {}));
|
|
1037
|
-
const defaultOptions = {
|
|
1038
|
-
useIpv4: true,
|
|
1039
|
-
useIpv6: true,
|
|
1051
|
+
const encodeTxUsername = ({ remoteUsername, localUsername, }) => {
|
|
1052
|
+
return `${remoteUsername}:${localUsername}`;
|
|
1053
|
+
};
|
|
1054
|
+
const decodeTxUsername = (txUsername) => {
|
|
1055
|
+
const [remoteUsername, localUsername] = txUsername.split(":");
|
|
1056
|
+
return { remoteUsername, localUsername };
|
|
1040
1057
|
};
|
|
1041
|
-
function validateRemoteCandidate(candidate) {
|
|
1042
|
-
// """
|
|
1043
|
-
// Check the remote candidate is supported.
|
|
1044
|
-
// """
|
|
1045
|
-
if (!["host", "relay", "srflx"].includes(candidate.type))
|
|
1046
|
-
throw new Error(`Unexpected candidate type "${candidate.type}"`);
|
|
1047
|
-
// ipaddress.ip_address(candidate.host)
|
|
1048
|
-
return candidate;
|
|
1049
|
-
}
|
|
1050
|
-
function sortCandidatePairs(pairs, iceControlling) {
|
|
1051
|
-
return pairs
|
|
1052
|
-
.sort((a, b) => candidatePairPriority(a.localCandidate, a.remoteCandidate, iceControlling) -
|
|
1053
|
-
candidatePairPriority(b.localCandidate, b.remoteCandidate, iceControlling))
|
|
1054
|
-
.reverse();
|
|
1055
|
-
}
|
|
1056
|
-
// 5.7.2. Computing Pair Priority and Ordering Pairs
|
|
1057
|
-
function candidatePairPriority(local, remote, iceControlling) {
|
|
1058
|
-
const G = (iceControlling && local.priority) || remote.priority;
|
|
1059
|
-
const D = (iceControlling && remote.priority) || local.priority;
|
|
1060
|
-
return (1 << 32) * Math.min(G, D) + 2 * Math.max(G, D) + (G > D ? 1 : 0);
|
|
1061
|
-
}
|
|
1062
|
-
async function serverReflexiveCandidate(protocol, stunServer) {
|
|
1063
|
-
// """
|
|
1064
|
-
// Query STUN server to obtain a server-reflexive candidate.
|
|
1065
|
-
// """
|
|
1066
|
-
// # perform STUN query
|
|
1067
|
-
const request = new message_1.Message(const_1.methods.BINDING, const_1.classes.REQUEST);
|
|
1068
|
-
try {
|
|
1069
|
-
const [response] = await protocol.request(request, stunServer);
|
|
1070
|
-
const localCandidate = protocol.localCandidate;
|
|
1071
|
-
if (!localCandidate) {
|
|
1072
|
-
throw new Error("not exist");
|
|
1073
|
-
}
|
|
1074
|
-
const candidate = new candidate_1.Candidate((0, candidate_1.candidateFoundation)("srflx", "udp", localCandidate.host), localCandidate.component, localCandidate.transport, (0, candidate_1.candidatePriority)("srflx"), response.getAttributeValue("XOR-MAPPED-ADDRESS")[0], response.getAttributeValue("XOR-MAPPED-ADDRESS")[1], "srflx", localCandidate.host, localCandidate.port);
|
|
1075
|
-
return candidate;
|
|
1076
|
-
}
|
|
1077
|
-
catch (error) {
|
|
1078
|
-
// todo fix
|
|
1079
|
-
log("error serverReflexiveCandidate", error);
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
function validateAddress(addr) {
|
|
1083
|
-
if (addr && Number.isNaN(addr[1])) {
|
|
1084
|
-
return [addr[0], 443];
|
|
1085
|
-
}
|
|
1086
|
-
return addr;
|
|
1087
|
-
}
|
|
1088
1058
|
//# sourceMappingURL=ice.js.map
|