werift 0.20.0 → 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.d.ts +45 -0
- package/lib/common/src/event.js +229 -0
- package/lib/common/src/event.js.map +1 -0
- package/lib/common/src/index.d.ts +1 -0
- package/lib/common/src/index.js +1 -0
- package/lib/common/src/index.js.map +1 -1
- package/lib/dtls/src/flight/client/flight5.js +6 -1
- package/lib/dtls/src/flight/client/flight5.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/imports/common.d.ts +1 -0
- package/lib/dtls/src/imports/common.js +18 -0
- package/lib/dtls/src/imports/common.js.map +1 -0
- 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/dtls/src/socket.d.ts +1 -1
- package/lib/dtls/src/socket.js +5 -5
- package/lib/dtls/src/socket.js.map +1 -1
- package/lib/ice/src/candidate.d.ts +3 -2
- package/lib/ice/src/candidate.js +19 -5
- package/lib/ice/src/candidate.js.map +1 -1
- package/lib/ice/src/helper.d.ts +6 -6
- package/lib/ice/src/helper.js +20 -17
- package/lib/ice/src/helper.js.map +1 -1
- package/lib/ice/src/ice.d.ts +29 -71
- package/lib/ice/src/ice.js +417 -417
- 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/imports/common.d.ts +1 -0
- package/lib/ice/src/imports/common.js +18 -0
- package/lib/ice/src/imports/common.js.map +1 -0
- package/lib/ice/src/index.d.ts +5 -0
- package/lib/ice/src/index.js +5 -0
- package/lib/ice/src/index.js.map +1 -1
- package/lib/ice/src/stun/message.d.ts +7 -0
- package/lib/ice/src/stun/message.js +20 -6
- package/lib/ice/src/stun/message.js.map +1 -1
- package/lib/ice/src/stun/protocol.d.ts +6 -6
- package/lib/ice/src/stun/protocol.js +29 -23
- package/lib/ice/src/stun/protocol.js.map +1 -1
- package/lib/ice/src/stun/transaction.js +10 -4
- package/lib/ice/src/stun/transaction.js.map +1 -1
- package/lib/ice/src/transport.d.ts +21 -4
- package/lib/ice/src/transport.js +115 -7
- package/lib/ice/src/transport.js.map +1 -1
- package/lib/ice/src/turn/protocol.d.ts +54 -37
- package/lib/ice/src/turn/protocol.js +219 -94
- package/lib/ice/src/turn/protocol.js.map +1 -1
- package/lib/ice/src/types/model.d.ts +9 -5
- package/lib/ice/src/types/model.js.map +1 -1
- package/lib/ice/src/utils.d.ts +1 -0
- package/lib/ice/src/utils.js +15 -16
- package/lib/ice/src/utils.js.map +1 -1
- package/lib/rtp/src/extra/container/mp4/container.d.ts +1 -1
- package/lib/rtp/src/extra/container/mp4/container.js +2 -5
- package/lib/rtp/src/extra/container/mp4/container.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/depacketizer.d.ts +1 -1
- package/lib/rtp/src/extra/processor/depacketizer.js +2 -2
- package/lib/rtp/src/extra/processor/depacketizer.js.map +1 -1
- package/lib/rtp/src/extra/processor/mp4.d.ts +1 -1
- package/lib/rtp/src/extra/processor/mp4.js +2 -5
- package/lib/rtp/src/extra/processor/mp4.js.map +1 -1
- package/lib/rtp/src/extra/processor/nack.d.ts +1 -1
- package/lib/rtp/src/extra/processor/nack.js +3 -3
- package/lib/rtp/src/extra/processor/nack.js.map +1 -1
- package/lib/rtp/src/extra/processor/rtcpCallback.d.ts +1 -1
- package/lib/rtp/src/extra/processor/rtcpCallback.js +2 -5
- package/lib/rtp/src/extra/processor/rtcpCallback.js.map +1 -1
- package/lib/rtp/src/extra/processor/rtpCallback.d.ts +1 -1
- package/lib/rtp/src/extra/processor/rtpCallback.js +2 -5
- package/lib/rtp/src/extra/processor/rtpCallback.js.map +1 -1
- package/lib/rtp/src/extra/processor/webm.d.ts +12 -17
- package/lib/rtp/src/extra/processor/webm.js +2 -5
- 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/imports/common.d.ts +1 -0
- package/lib/rtp/src/imports/common.js +18 -0
- package/lib/rtp/src/imports/common.js.map +1 -0
- 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/helper.js +2 -5
- package/lib/sctp/src/helper.js.map +1 -1
- package/lib/sctp/src/imports/common.d.ts +1 -0
- package/lib/sctp/src/imports/common.js +18 -0
- package/lib/sctp/src/imports/common.js.map +1 -0
- package/lib/sctp/src/index.d.ts +1 -1
- package/lib/sctp/src/index.js.map +1 -1
- package/lib/sctp/src/sctp.d.ts +1 -1
- package/lib/sctp/src/sctp.js +3 -3
- package/lib/sctp/src/sctp.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/dataChannel.d.ts +1 -1
- package/lib/webrtc/src/dataChannel.js +5 -5
- package/lib/webrtc/src/dataChannel.js.map +1 -1
- package/lib/webrtc/src/imports/common.d.ts +1 -0
- package/lib/webrtc/src/imports/common.js +18 -0
- package/lib/webrtc/src/imports/common.js.map +1 -0
- 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/receiver/nack.d.ts +1 -1
- package/lib/webrtc/src/media/receiver/nack.js +2 -2
- package/lib/webrtc/src/media/receiver/nack.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 +3 -4
- package/lib/webrtc/src/media/rtpReceiver.js +4 -7
- package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
- package/lib/webrtc/src/media/rtpSender.d.ts +1 -1
- package/lib/webrtc/src/media/rtpSender.js +5 -5
- package/lib/webrtc/src/media/rtpSender.js.map +1 -1
- package/lib/webrtc/src/media/rtpTransceiver.d.ts +1 -1
- package/lib/webrtc/src/media/rtpTransceiver.js +2 -5
- package/lib/webrtc/src/media/rtpTransceiver.js.map +1 -1
- package/lib/webrtc/src/media/sender/senderBWE.d.ts +1 -1
- package/lib/webrtc/src/media/sender/senderBWE.js +4 -7
- package/lib/webrtc/src/media/sender/senderBWE.js.map +1 -1
- package/lib/webrtc/src/media/track.d.ts +3 -3
- package/lib/webrtc/src/media/track.js +4 -7
- package/lib/webrtc/src/media/track.js.map +1 -1
- package/lib/webrtc/src/nonstandard/recorder/index.d.ts +3 -1
- package/lib/webrtc/src/nonstandard/recorder/index.js +2 -5
- package/lib/webrtc/src/nonstandard/recorder/index.js.map +1 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/index.d.ts +1 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/index.js.map +1 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.d.ts +1 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js +3 -2
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js.map +1 -1
- package/lib/webrtc/src/peerConnection.d.ts +15 -8
- package/lib/webrtc/src/peerConnection.js +107 -93
- 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 +6 -6
- package/lib/webrtc/src/transport/dtls.js +19 -26
- package/lib/webrtc/src/transport/dtls.js.map +1 -1
- package/lib/webrtc/src/transport/ice.d.ts +22 -11
- package/lib/webrtc/src/transport/ice.js +106 -38
- package/lib/webrtc/src/transport/ice.js.map +1 -1
- package/lib/webrtc/src/transport/sctp.d.ts +1 -1
- package/lib/webrtc/src/transport/sctp.js +2 -2
- package/lib/webrtc/src/transport/sctp.js.map +1 -1
- package/package.json +1 -1
- package/src/const.ts +2 -2
- package/src/dataChannel.ts +1 -1
- package/src/imports/common.ts +1 -0
- package/src/media/extension/rtpExtension.ts +6 -0
- package/src/media/receiver/nack.ts +1 -1
- package/src/media/router.ts +2 -3
- package/src/media/rtpReceiver.ts +5 -4
- package/src/media/rtpSender.ts +1 -1
- package/src/media/rtpTransceiver.ts +1 -1
- package/src/media/sender/senderBWE.ts +1 -1
- package/src/media/track.ts +9 -4
- package/src/nonstandard/recorder/index.ts +4 -1
- package/src/nonstandard/recorder/writer/index.ts +1 -1
- package/src/nonstandard/recorder/writer/webm.ts +48 -44
- package/src/peerConnection.ts +122 -89
- package/src/sdp.ts +16 -3
- package/src/transport/dtls.ts +22 -14
- package/src/transport/ice.ts +83 -31
- package/src/transport/sctp.ts +1 -1
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
|
-
const rx_mini_1 = require("rx.mini");
|
|
19
12
|
const promises_1 = __importDefault(require("timers/promises"));
|
|
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 rx_mini_1.Event()
|
|
150
|
-
});
|
|
151
|
-
Object.defineProperty(this, "stateChanged", {
|
|
152
|
-
enumerable: true,
|
|
153
|
-
configurable: true,
|
|
154
|
-
writable: true,
|
|
155
|
-
value: new rx_mini_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,14 +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)
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
415
|
+
const { stunServer, turnServer } = this.options;
|
|
416
|
+
this.stunServer = (0, iceBase_1.validateAddress)(stunServer) ?? [
|
|
417
|
+
"stun.l.google.com",
|
|
418
|
+
19302,
|
|
419
|
+
];
|
|
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;
|
|
375
477
|
}
|
|
376
478
|
setRemoteParams({ iceLite, usernameFragment, password, }) {
|
|
377
479
|
log("setRemoteParams", { iceLite, usernameFragment, password });
|
|
@@ -380,11 +482,11 @@ class Connection {
|
|
|
380
482
|
this.remotePassword = password;
|
|
381
483
|
}
|
|
382
484
|
// 4.1.1 Gathering Candidates
|
|
383
|
-
async gatherCandidates(
|
|
485
|
+
async gatherCandidates() {
|
|
384
486
|
if (!this.localCandidatesStart) {
|
|
385
487
|
this.localCandidatesStart = true;
|
|
386
|
-
this.promiseGatherCandidates = new
|
|
387
|
-
let address = (0, utils_1.getHostAddresses)(this.useIpv4, this.useIpv6);
|
|
488
|
+
this.promiseGatherCandidates = new common_1.Event();
|
|
489
|
+
let address = (0, utils_1.getHostAddresses)(this.options.useIpv4, this.options.useIpv6);
|
|
388
490
|
const { interfaceAddresses } = this.options;
|
|
389
491
|
if (interfaceAddresses) {
|
|
390
492
|
const filteredAddresses = address.filter((check) => Object.values(interfaceAddresses).includes(check));
|
|
@@ -395,18 +497,86 @@ class Connection {
|
|
|
395
497
|
if (this.options.additionalHostAddresses) {
|
|
396
498
|
address = Array.from(new Set([...this.options.additionalHostAddresses, ...address]));
|
|
397
499
|
}
|
|
398
|
-
const candidates = await this.getCandidates(address, 5
|
|
500
|
+
const candidates = await this.getCandidates(address, 5);
|
|
399
501
|
this.localCandidates = [...this.localCandidates, ...candidates];
|
|
400
|
-
this.
|
|
502
|
+
this.localCandidatesEnd = true;
|
|
401
503
|
this.promiseGatherCandidates.execute();
|
|
402
504
|
}
|
|
403
505
|
this.setState("completed");
|
|
404
506
|
}
|
|
405
|
-
|
|
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) {
|
|
406
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
|
+
});
|
|
407
576
|
await Promise.allSettled(addresses.map(async (address) => {
|
|
408
577
|
// # create transport
|
|
409
|
-
const protocol = new protocol_1.StunProtocol(
|
|
578
|
+
const protocol = new protocol_1.StunProtocol();
|
|
579
|
+
this.ensureProtocol(protocol);
|
|
410
580
|
try {
|
|
411
581
|
await protocol.connectionMade((0, net_1.isIPv4)(address), this.options.portRange, this.options.interfaceAddresses);
|
|
412
582
|
}
|
|
@@ -414,16 +584,14 @@ class Connection {
|
|
|
414
584
|
log("protocol STUN", error);
|
|
415
585
|
return;
|
|
416
586
|
}
|
|
417
|
-
protocol.
|
|
587
|
+
protocol.localIp = address;
|
|
418
588
|
this.protocols.push(protocol);
|
|
419
589
|
// # add host candidate
|
|
420
590
|
const candidateAddress = [address, protocol.getExtraInfo()[1]];
|
|
421
|
-
protocol.localCandidate = new candidate_1.Candidate((0, candidate_1.candidateFoundation)("host", "udp", candidateAddress[0]), 1, "udp", (0, candidate_1.candidatePriority)(
|
|
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);
|
|
422
592
|
this.pairLocalProtocol(protocol);
|
|
423
593
|
candidates.push(protocol.localCandidate);
|
|
424
|
-
|
|
425
|
-
cb(protocol.localCandidate);
|
|
426
|
-
}
|
|
594
|
+
this.onIceCandidate.execute(protocol.localCandidate);
|
|
427
595
|
}));
|
|
428
596
|
let candidatePromises = [];
|
|
429
597
|
// # query STUN server for server-reflexive candidates (IPv4 only)
|
|
@@ -433,9 +601,12 @@ class Connection {
|
|
|
433
601
|
const timer = setTimeout(f, timeout * 1000);
|
|
434
602
|
if (protocol.localCandidate?.host &&
|
|
435
603
|
(0, net_1.isIPv4)(protocol.localCandidate?.host)) {
|
|
436
|
-
const candidate = await serverReflexiveCandidate(protocol, stunServer).catch((error) =>
|
|
437
|
-
|
|
438
|
-
|
|
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
|
+
}
|
|
439
610
|
clearTimeout(timer);
|
|
440
611
|
r(candidate);
|
|
441
612
|
}
|
|
@@ -451,19 +622,37 @@ class Connection {
|
|
|
451
622
|
const { turnUsername, turnPassword } = this.options;
|
|
452
623
|
if (turnServer && turnUsername && turnPassword) {
|
|
453
624
|
const turnCandidate = (async () => {
|
|
454
|
-
const protocol = await (0, protocol_2.
|
|
625
|
+
const protocol = await (0, protocol_2.createStunOverTurnClient)({
|
|
626
|
+
address: turnServer,
|
|
627
|
+
username: turnUsername,
|
|
628
|
+
password: turnPassword,
|
|
629
|
+
}, {
|
|
455
630
|
portRange: this.options.portRange,
|
|
456
631
|
interfaceAddresses: this.options.interfaceAddresses,
|
|
632
|
+
transport: this.options.turnTransport === "tcp" ? "tcp" : "udp",
|
|
633
|
+
}).catch(async (e) => {
|
|
634
|
+
if (this.options.turnTransport !== "tcp") {
|
|
635
|
+
return await (0, protocol_2.createStunOverTurnClient)({
|
|
636
|
+
address: turnServer,
|
|
637
|
+
username: turnUsername,
|
|
638
|
+
password: turnPassword,
|
|
639
|
+
}, {
|
|
640
|
+
portRange: this.options.portRange,
|
|
641
|
+
interfaceAddresses: this.options.interfaceAddresses,
|
|
642
|
+
transport: "tcp",
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
else {
|
|
646
|
+
throw e;
|
|
647
|
+
}
|
|
457
648
|
});
|
|
649
|
+
this.ensureProtocol(protocol);
|
|
458
650
|
this.protocols.push(protocol);
|
|
459
651
|
const candidateAddress = protocol.turn.relayedAddress;
|
|
460
652
|
const relatedAddress = protocol.turn.mappedAddress;
|
|
461
653
|
log("turn candidateAddress", candidateAddress);
|
|
462
|
-
protocol.localCandidate = new candidate_1.Candidate((0, candidate_1.candidateFoundation)("relay", "udp", candidateAddress[0]), 1, "udp", (0, candidate_1.candidatePriority)(
|
|
463
|
-
|
|
464
|
-
cb(protocol.localCandidate);
|
|
465
|
-
}
|
|
466
|
-
protocol.receiver = this;
|
|
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);
|
|
467
656
|
return protocol.localCandidate;
|
|
468
657
|
})().catch((error) => {
|
|
469
658
|
log("query TURN server", error);
|
|
@@ -488,23 +677,32 @@ class Connection {
|
|
|
488
677
|
// This coroutine returns if a candidate pair was successfully nominated
|
|
489
678
|
// and raises an exception otherwise.
|
|
490
679
|
// """
|
|
491
|
-
log("start connect ice"
|
|
492
|
-
if (!this.
|
|
493
|
-
if (!this.localCandidatesStart)
|
|
680
|
+
log("start connect ice");
|
|
681
|
+
if (!this.localCandidatesEnd) {
|
|
682
|
+
if (!this.localCandidatesStart) {
|
|
494
683
|
throw new Error("Local candidates gathering was not performed");
|
|
495
|
-
|
|
684
|
+
}
|
|
685
|
+
if (this.promiseGatherCandidates) {
|
|
496
686
|
// wait for GatherCandidates finish
|
|
497
687
|
await this.promiseGatherCandidates.asPromise();
|
|
688
|
+
}
|
|
498
689
|
}
|
|
499
|
-
if (!this.remoteUsername || !this.remotePassword)
|
|
690
|
+
if (!this.remoteUsername || !this.remotePassword) {
|
|
500
691
|
throw new Error("Remote username or password is missing");
|
|
692
|
+
}
|
|
501
693
|
// # 5.7.1. Forming Candidate Pairs
|
|
502
|
-
this.remoteCandidates
|
|
694
|
+
for (const c of this.remoteCandidates) {
|
|
695
|
+
this.pairRemoteCandidate(c);
|
|
696
|
+
}
|
|
503
697
|
this.sortCheckList();
|
|
504
698
|
this.unfreezeInitial();
|
|
699
|
+
log("earlyChecks", this.localPassword, this.earlyChecks.length);
|
|
505
700
|
// # handle early checks
|
|
506
|
-
|
|
701
|
+
for (const earlyCheck of this.earlyChecks) {
|
|
702
|
+
this.checkIncoming(...earlyCheck);
|
|
703
|
+
}
|
|
507
704
|
this.earlyChecks = [];
|
|
705
|
+
this.earlyChecksDone = true;
|
|
508
706
|
// # perform checks
|
|
509
707
|
// 5.8. Scheduling Checks
|
|
510
708
|
for (;;) {
|
|
@@ -515,17 +713,19 @@ class Connection {
|
|
|
515
713
|
await promises_1.default.setTimeout(20);
|
|
516
714
|
}
|
|
517
715
|
// # wait for completion
|
|
518
|
-
let res = ICE_FAILED;
|
|
519
|
-
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) {
|
|
520
718
|
res = await this.checkListState.get();
|
|
521
719
|
}
|
|
522
720
|
// # cancel remaining checks
|
|
523
|
-
|
|
524
|
-
|
|
721
|
+
for (const check of this.checkList) {
|
|
722
|
+
check.handle?.resolve?.();
|
|
723
|
+
}
|
|
724
|
+
if (res !== iceBase_1.ICE_COMPLETED) {
|
|
525
725
|
throw new Error("ICE negotiation failed");
|
|
526
726
|
}
|
|
527
727
|
// # start consent freshness tests
|
|
528
|
-
this.
|
|
728
|
+
this.queryConsent();
|
|
529
729
|
this.setState("connected");
|
|
530
730
|
}
|
|
531
731
|
unfreezeInitial() {
|
|
@@ -533,16 +733,16 @@ class Connection {
|
|
|
533
733
|
const [firstPair] = this.checkList;
|
|
534
734
|
if (!firstPair)
|
|
535
735
|
return;
|
|
536
|
-
if (firstPair.state === CandidatePairState.FROZEN) {
|
|
537
|
-
|
|
736
|
+
if (firstPair.state === iceBase_1.CandidatePairState.FROZEN) {
|
|
737
|
+
firstPair.updateState(iceBase_1.CandidatePairState.WAITING);
|
|
538
738
|
}
|
|
539
739
|
// # unfreeze pairs with same component but different foundations
|
|
540
740
|
const seenFoundations = new Set(firstPair.localCandidate.foundation);
|
|
541
741
|
for (const pair of this.checkList) {
|
|
542
742
|
if (pair.component === firstPair.component &&
|
|
543
743
|
!seenFoundations.has(pair.localCandidate.foundation) &&
|
|
544
|
-
pair.state === CandidatePairState.FROZEN) {
|
|
545
|
-
|
|
744
|
+
pair.state === iceBase_1.CandidatePairState.FROZEN) {
|
|
745
|
+
pair.updateState(iceBase_1.CandidatePairState.WAITING);
|
|
546
746
|
seenFoundations.add(pair.localCandidate.foundation);
|
|
547
747
|
}
|
|
548
748
|
}
|
|
@@ -554,21 +754,22 @@ class Connection {
|
|
|
554
754
|
// # find the highest-priority pair that is in the waiting state
|
|
555
755
|
const pair = this.checkList
|
|
556
756
|
.filter((pair) => {
|
|
557
|
-
if (this.options.forceTurn &&
|
|
757
|
+
if (this.options.forceTurn &&
|
|
758
|
+
pair.protocol.type === protocol_1.StunProtocol.type)
|
|
558
759
|
return false;
|
|
559
760
|
return true;
|
|
560
761
|
})
|
|
561
|
-
.find((pair) => pair.state === CandidatePairState.WAITING);
|
|
762
|
+
.find((pair) => pair.state === iceBase_1.CandidatePairState.WAITING);
|
|
562
763
|
if (pair) {
|
|
563
|
-
pair.handle =
|
|
764
|
+
pair.handle = this.checkStart(pair);
|
|
564
765
|
return true;
|
|
565
766
|
}
|
|
566
767
|
}
|
|
567
768
|
{
|
|
568
769
|
// # find the highest-priority pair that is in the frozen state
|
|
569
|
-
const pair = this.checkList.find((pair) => pair.state === CandidatePairState.FROZEN);
|
|
770
|
+
const pair = this.checkList.find((pair) => pair.state === iceBase_1.CandidatePairState.FROZEN);
|
|
570
771
|
if (pair) {
|
|
571
|
-
pair.handle =
|
|
772
|
+
pair.handle = this.checkStart(pair);
|
|
572
773
|
return true;
|
|
573
774
|
}
|
|
574
775
|
}
|
|
@@ -584,19 +785,11 @@ class Connection {
|
|
|
584
785
|
// """
|
|
585
786
|
this.setState("closed");
|
|
586
787
|
// # stop consent freshness tests
|
|
587
|
-
|
|
588
|
-
this.queryConsentHandle.cancel();
|
|
589
|
-
try {
|
|
590
|
-
await this.queryConsentHandle.promise;
|
|
591
|
-
}
|
|
592
|
-
catch (error) {
|
|
593
|
-
// pass
|
|
594
|
-
}
|
|
595
|
-
}
|
|
788
|
+
this.queryConsentHandle?.resolve?.();
|
|
596
789
|
// # stop check list
|
|
597
790
|
if (this.checkList && !this.checkListDone) {
|
|
598
791
|
this.checkListState.put(new Promise((r) => {
|
|
599
|
-
r(ICE_FAILED);
|
|
792
|
+
r(iceBase_1.ICE_FAILED);
|
|
600
793
|
}));
|
|
601
794
|
}
|
|
602
795
|
this.nominated = undefined;
|
|
@@ -607,7 +800,8 @@ class Connection {
|
|
|
607
800
|
}
|
|
608
801
|
this.protocols = [];
|
|
609
802
|
this.localCandidates = [];
|
|
610
|
-
|
|
803
|
+
this.lookup?.close?.();
|
|
804
|
+
this.lookup = undefined;
|
|
611
805
|
}
|
|
612
806
|
setState(state) {
|
|
613
807
|
this.state = state;
|
|
@@ -625,8 +819,6 @@ class Connection {
|
|
|
625
819
|
}
|
|
626
820
|
if (remoteCandidate.host.includes(".local")) {
|
|
627
821
|
try {
|
|
628
|
-
if (this.state === "closed")
|
|
629
|
-
return;
|
|
630
822
|
if (!this.lookup) {
|
|
631
823
|
this.lookup = new lookup_1.MdnsLookup();
|
|
632
824
|
}
|
|
@@ -638,105 +830,21 @@ class Connection {
|
|
|
638
830
|
}
|
|
639
831
|
}
|
|
640
832
|
try {
|
|
641
|
-
validateRemoteCandidate(remoteCandidate);
|
|
833
|
+
(0, iceBase_1.validateRemoteCandidate)(remoteCandidate);
|
|
642
834
|
}
|
|
643
835
|
catch (error) {
|
|
644
836
|
return;
|
|
645
837
|
}
|
|
646
838
|
log("addRemoteCandidate", remoteCandidate);
|
|
647
|
-
this.
|
|
839
|
+
this._remoteCandidates.push(remoteCandidate);
|
|
648
840
|
this.pairRemoteCandidate(remoteCandidate);
|
|
649
841
|
this.sortCheckList();
|
|
650
842
|
}
|
|
651
|
-
async sendTo(data) {
|
|
652
|
-
// """
|
|
653
|
-
// Send a datagram on the specified component.
|
|
654
|
-
// If the connection is not established, a `ConnectionError` is raised.
|
|
655
|
-
// :param data: The data to be sent.
|
|
656
|
-
// :param component: The component on which to send the data.
|
|
657
|
-
// """
|
|
658
|
-
const activePair = this.nominated;
|
|
659
|
-
if (activePair) {
|
|
660
|
-
await activePair.protocol.sendData(data, activePair.remoteAddr);
|
|
661
|
-
}
|
|
662
|
-
else {
|
|
663
|
-
// log("Cannot send data, ice not connected");
|
|
664
|
-
return;
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
843
|
getDefaultCandidate() {
|
|
668
844
|
const candidates = this.localCandidates.sort((a, b) => a.priority - b.priority);
|
|
669
845
|
const [candidate] = candidates;
|
|
670
846
|
return candidate;
|
|
671
847
|
}
|
|
672
|
-
requestReceived(message, addr, protocol, rawData) {
|
|
673
|
-
if (message.messageMethod !== const_1.methods.BINDING) {
|
|
674
|
-
this.respondError(message, addr, protocol, [400, "Bad Request"]);
|
|
675
|
-
return;
|
|
676
|
-
}
|
|
677
|
-
// # authenticate request
|
|
678
|
-
try {
|
|
679
|
-
(0, message_1.parseMessage)(rawData, Buffer.from(this.localPassword, "utf8"));
|
|
680
|
-
if (!this.remoteUsername) {
|
|
681
|
-
const rxUsername = `${this.localUserName}:${this.remoteUsername}`;
|
|
682
|
-
if (message.getAttributeValue("USERNAME") != rxUsername) {
|
|
683
|
-
throw new Error("Wrong username");
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
catch (error) {
|
|
688
|
-
this.respondError(message, addr, protocol, [400, "Bad Request"]);
|
|
689
|
-
return;
|
|
690
|
-
}
|
|
691
|
-
const { iceControlling } = this;
|
|
692
|
-
// 7.2.1.1. Detecting and Repairing Role Conflicts
|
|
693
|
-
if (iceControlling && message.attributesKeys.includes("ICE-CONTROLLING")) {
|
|
694
|
-
if (this._tieBreaker >= message.getAttributeValue("ICE-CONTROLLING")) {
|
|
695
|
-
this.respondError(message, addr, protocol, [487, "Role Conflict"]);
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
698
|
-
else {
|
|
699
|
-
this.switchRole(false);
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
else if (!iceControlling &&
|
|
703
|
-
message.attributesKeys.includes("ICE-CONTROLLED")) {
|
|
704
|
-
if (this._tieBreaker < message.getAttributeValue("ICE-CONTROLLED")) {
|
|
705
|
-
this.respondError(message, addr, protocol, [487, "Role Conflict"]);
|
|
706
|
-
}
|
|
707
|
-
else {
|
|
708
|
-
this.switchRole(true);
|
|
709
|
-
return;
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
if (this.options.filterStunResponse &&
|
|
713
|
-
!this.options.filterStunResponse(message, addr, protocol)) {
|
|
714
|
-
return;
|
|
715
|
-
}
|
|
716
|
-
// # send binding response
|
|
717
|
-
const response = new message_1.Message(const_1.methods.BINDING, const_1.classes.RESPONSE, message.transactionId);
|
|
718
|
-
response
|
|
719
|
-
.setAttribute("XOR-MAPPED-ADDRESS", addr)
|
|
720
|
-
.addMessageIntegrity(Buffer.from(this.localPassword, "utf8"))
|
|
721
|
-
.addFingerprint();
|
|
722
|
-
protocol.sendStun(response, addr).catch((e) => {
|
|
723
|
-
log("sendStun error", e);
|
|
724
|
-
});
|
|
725
|
-
// todo fix
|
|
726
|
-
// if (this.checkList.length === 0) {
|
|
727
|
-
// this.earlyChecks.push([message, addr, protocol]);
|
|
728
|
-
// } else {
|
|
729
|
-
this.checkIncoming(message, addr, protocol);
|
|
730
|
-
// }
|
|
731
|
-
}
|
|
732
|
-
dataReceived(data, component) {
|
|
733
|
-
try {
|
|
734
|
-
this.onData.execute(data, component);
|
|
735
|
-
}
|
|
736
|
-
catch (error) {
|
|
737
|
-
log("dataReceived", error);
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
848
|
// for test only
|
|
741
849
|
set remoteCandidates(value) {
|
|
742
850
|
if (this.remoteCandidatesEnd)
|
|
@@ -744,12 +852,12 @@ class Connection {
|
|
|
744
852
|
this._remoteCandidates = [];
|
|
745
853
|
for (const remoteCandidate of value) {
|
|
746
854
|
try {
|
|
747
|
-
validateRemoteCandidate(remoteCandidate);
|
|
855
|
+
(0, iceBase_1.validateRemoteCandidate)(remoteCandidate);
|
|
748
856
|
}
|
|
749
857
|
catch (error) {
|
|
750
858
|
continue;
|
|
751
859
|
}
|
|
752
|
-
this.
|
|
860
|
+
this._remoteCandidates.push(remoteCandidate);
|
|
753
861
|
}
|
|
754
862
|
this.remoteCandidatesEnd = true;
|
|
755
863
|
}
|
|
@@ -757,36 +865,32 @@ class Connection {
|
|
|
757
865
|
return this._remoteCandidates;
|
|
758
866
|
}
|
|
759
867
|
sortCheckList() {
|
|
760
|
-
sortCandidatePairs(this.checkList, this.iceControlling);
|
|
868
|
+
(0, iceBase_1.sortCandidatePairs)(this.checkList, this.iceControlling);
|
|
761
869
|
}
|
|
762
870
|
findPair(protocol, remoteCandidate) {
|
|
763
871
|
const pair = this.checkList.find((pair) => (0, isEqual_1.default)(pair.protocol, protocol) &&
|
|
764
872
|
(0, isEqual_1.default)(pair.remoteCandidate, remoteCandidate));
|
|
765
873
|
return pair;
|
|
766
874
|
}
|
|
767
|
-
setPairState(pair, state) {
|
|
768
|
-
log("setPairState", pair.toJSON(), CandidatePairState[state]);
|
|
769
|
-
pair.updateState(state);
|
|
770
|
-
}
|
|
771
875
|
switchRole(iceControlling) {
|
|
772
876
|
log("switch role", iceControlling);
|
|
773
877
|
this.iceControlling = iceControlling;
|
|
774
878
|
this.sortCheckList();
|
|
775
879
|
}
|
|
776
|
-
resetNominatedPair() {
|
|
777
|
-
log("resetNominatedPair");
|
|
778
|
-
this.nominated = undefined;
|
|
779
|
-
this.nominating = false;
|
|
780
|
-
}
|
|
781
880
|
checkComplete(pair) {
|
|
782
881
|
pair.handle = undefined;
|
|
783
|
-
if (pair.state === CandidatePairState.SUCCEEDED) {
|
|
882
|
+
if (pair.state === iceBase_1.CandidatePairState.SUCCEEDED) {
|
|
784
883
|
// Updating the Nominated Flag
|
|
785
884
|
// https://www.rfc-editor.org/rfc/rfc8445#section-7.3.1.5,
|
|
786
885
|
// Once the nominated flag is set for a component of a data stream, it
|
|
787
886
|
// concludes the ICE processing for that component. See Section 8.
|
|
788
887
|
// So disallow overwriting of the pair nominated for that component
|
|
789
|
-
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) {
|
|
790
894
|
log("nominated", pair.toJSON());
|
|
791
895
|
this.nominated = pair;
|
|
792
896
|
this.nominating = false;
|
|
@@ -796,8 +900,8 @@ class Connection {
|
|
|
796
900
|
// nominated pairs for that media stream.
|
|
797
901
|
for (const p of this.checkList) {
|
|
798
902
|
if (p.component === pair.component &&
|
|
799
|
-
[CandidatePairState.WAITING, CandidatePairState.FROZEN].includes(p.state)) {
|
|
800
|
-
|
|
903
|
+
[iceBase_1.CandidatePairState.WAITING, iceBase_1.CandidatePairState.FROZEN].includes(p.state)) {
|
|
904
|
+
p.updateState(iceBase_1.CandidatePairState.FAILED);
|
|
801
905
|
}
|
|
802
906
|
}
|
|
803
907
|
}
|
|
@@ -807,27 +911,28 @@ class Connection {
|
|
|
807
911
|
if (this.nominated) {
|
|
808
912
|
if (!this.checkListDone) {
|
|
809
913
|
log("ICE completed");
|
|
810
|
-
this.checkListState.put(new Promise((r) => r(ICE_COMPLETED)));
|
|
914
|
+
this.checkListState.put(new Promise((r) => r(iceBase_1.ICE_COMPLETED)));
|
|
811
915
|
this.checkListDone = true;
|
|
812
916
|
}
|
|
813
917
|
return;
|
|
814
918
|
}
|
|
919
|
+
log("not completed", pair.toJSON());
|
|
815
920
|
// 7.1.3.2.3. Updating Pair States
|
|
816
921
|
for (const p of this.checkList) {
|
|
817
922
|
if (p.localCandidate.foundation === pair.localCandidate.foundation &&
|
|
818
|
-
p.state === CandidatePairState.FROZEN) {
|
|
819
|
-
|
|
923
|
+
p.state === iceBase_1.CandidatePairState.FROZEN) {
|
|
924
|
+
p.updateState(iceBase_1.CandidatePairState.WAITING);
|
|
820
925
|
}
|
|
821
926
|
}
|
|
822
927
|
}
|
|
823
928
|
{
|
|
824
|
-
const list = [CandidatePairState.SUCCEEDED, CandidatePairState.FAILED];
|
|
929
|
+
const list = [iceBase_1.CandidatePairState.SUCCEEDED, iceBase_1.CandidatePairState.FAILED];
|
|
825
930
|
if (this.checkList.find(({ state }) => !list.includes(state))) {
|
|
826
931
|
return;
|
|
827
932
|
}
|
|
828
933
|
}
|
|
829
934
|
if (!this.iceControlling) {
|
|
830
|
-
const target = CandidatePairState.SUCCEEDED;
|
|
935
|
+
const target = iceBase_1.CandidatePairState.SUCCEEDED;
|
|
831
936
|
if (this.checkList.find(({ state }) => state === target)) {
|
|
832
937
|
return;
|
|
833
938
|
}
|
|
@@ -835,17 +940,22 @@ class Connection {
|
|
|
835
940
|
if (!this.checkListDone) {
|
|
836
941
|
log("ICE failed");
|
|
837
942
|
this.checkListState.put(new Promise((r) => {
|
|
838
|
-
r(ICE_FAILED);
|
|
943
|
+
r(iceBase_1.ICE_FAILED);
|
|
839
944
|
}));
|
|
840
945
|
}
|
|
841
946
|
}
|
|
947
|
+
addPair(pair) {
|
|
948
|
+
this.checkList.push(pair);
|
|
949
|
+
this.sortCheckList();
|
|
950
|
+
}
|
|
842
951
|
// 7.2. STUN Server Procedures
|
|
843
952
|
// 7.2.1.3、7.2.1.4、および7.2.1.5
|
|
844
953
|
checkIncoming(message, addr, protocol) {
|
|
845
|
-
// log("checkIncoming", message.toJSON(), addr);
|
|
846
954
|
// """
|
|
847
955
|
// Handle a successful incoming check.
|
|
848
956
|
// """
|
|
957
|
+
const txUsername = message.getAttributeValue("USERNAME");
|
|
958
|
+
const { remoteUsername: localUsername } = decodeTxUsername(txUsername);
|
|
849
959
|
// find remote candidate
|
|
850
960
|
let remoteCandidate;
|
|
851
961
|
const [host, port] = addr;
|
|
@@ -857,20 +967,27 @@ class Connection {
|
|
|
857
967
|
}
|
|
858
968
|
if (!remoteCandidate) {
|
|
859
969
|
// 7.2.1.3. Learning Peer Reflexive Candidates
|
|
860
|
-
remoteCandidate = new candidate_1.Candidate((0, helper_1.randomString)(10), 1, "udp", message.getAttributeValue("PRIORITY"), host, port, "prflx");
|
|
861
|
-
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);
|
|
862
972
|
}
|
|
863
973
|
// find pair
|
|
864
974
|
let pair = this.findPair(protocol, remoteCandidate);
|
|
865
975
|
if (!pair) {
|
|
866
|
-
pair = new CandidatePair(protocol, remoteCandidate);
|
|
867
|
-
|
|
868
|
-
this.
|
|
869
|
-
this.sortCheckList();
|
|
976
|
+
pair = new iceBase_1.CandidatePair(protocol, remoteCandidate, this.iceControlling);
|
|
977
|
+
pair.updateState(iceBase_1.CandidatePairState.WAITING);
|
|
978
|
+
this.addPair(pair);
|
|
870
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
|
+
});
|
|
871
988
|
// 7.2.1.4. Triggered Checks
|
|
872
|
-
if ([CandidatePairState.WAITING, CandidatePairState.FAILED].includes(pair.state)) {
|
|
873
|
-
pair.handle =
|
|
989
|
+
if ([iceBase_1.CandidatePairState.WAITING, iceBase_1.CandidatePairState.FAILED].includes(pair.state)) {
|
|
990
|
+
pair.handle = this.checkStart(pair);
|
|
874
991
|
}
|
|
875
992
|
else {
|
|
876
993
|
pair;
|
|
@@ -879,7 +996,7 @@ class Connection {
|
|
|
879
996
|
if (message.attributesKeys.includes("USE-CANDIDATE") &&
|
|
880
997
|
!this.iceControlling) {
|
|
881
998
|
pair.remoteNominated = true;
|
|
882
|
-
if (pair.state === CandidatePairState.SUCCEEDED) {
|
|
999
|
+
if (pair.state === iceBase_1.CandidatePairState.SUCCEEDED) {
|
|
883
1000
|
pair.nominated = true;
|
|
884
1001
|
this.checkComplete(pair);
|
|
885
1002
|
}
|
|
@@ -888,13 +1005,13 @@ class Connection {
|
|
|
888
1005
|
tryPair(protocol, remoteCandidate) {
|
|
889
1006
|
if (protocol.localCandidate?.canPairWith(remoteCandidate) &&
|
|
890
1007
|
!this.findPair(protocol, remoteCandidate)) {
|
|
891
|
-
const pair = new CandidatePair(protocol, remoteCandidate);
|
|
1008
|
+
const pair = new iceBase_1.CandidatePair(protocol, remoteCandidate, this.iceControlling);
|
|
892
1009
|
if (this.options.filterCandidatePair &&
|
|
893
1010
|
!this.options.filterCandidatePair(pair)) {
|
|
894
1011
|
return;
|
|
895
1012
|
}
|
|
896
|
-
|
|
897
|
-
this.
|
|
1013
|
+
pair.updateState(iceBase_1.CandidatePairState.WAITING);
|
|
1014
|
+
this.addPair(pair);
|
|
898
1015
|
}
|
|
899
1016
|
}
|
|
900
1017
|
pairLocalProtocol(protocol) {
|
|
@@ -902,20 +1019,20 @@ class Connection {
|
|
|
902
1019
|
this.tryPair(protocol, remoteCandidate);
|
|
903
1020
|
}
|
|
904
1021
|
}
|
|
905
|
-
buildRequest(
|
|
906
|
-
const txUsername =
|
|
1022
|
+
buildRequest({ nominate, remoteUsername, localUsername, iceControlling, }) {
|
|
1023
|
+
const txUsername = encodeTxUsername({ remoteUsername, localUsername });
|
|
907
1024
|
const request = new message_1.Message(const_1.methods.BINDING, const_1.classes.REQUEST);
|
|
908
1025
|
request
|
|
909
1026
|
.setAttribute("USERNAME", txUsername)
|
|
910
|
-
.setAttribute("PRIORITY", (0, candidate_1.candidatePriority)(
|
|
911
|
-
if (
|
|
912
|
-
request.setAttribute("ICE-CONTROLLING", this.
|
|
1027
|
+
.setAttribute("PRIORITY", (0, candidate_1.candidatePriority)("prflx"));
|
|
1028
|
+
if (iceControlling) {
|
|
1029
|
+
request.setAttribute("ICE-CONTROLLING", this.tieBreaker);
|
|
913
1030
|
if (nominate) {
|
|
914
1031
|
request.setAttribute("USE-CANDIDATE", null);
|
|
915
1032
|
}
|
|
916
1033
|
}
|
|
917
1034
|
else {
|
|
918
|
-
request.setAttribute("ICE-CONTROLLED", this.
|
|
1035
|
+
request.setAttribute("ICE-CONTROLLED", this.tieBreaker);
|
|
919
1036
|
}
|
|
920
1037
|
return request;
|
|
921
1038
|
}
|
|
@@ -931,128 +1048,11 @@ class Connection {
|
|
|
931
1048
|
}
|
|
932
1049
|
}
|
|
933
1050
|
exports.Connection = Connection;
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
protocol: this.protocol.type,
|
|
941
|
-
remoteAddr: this.remoteAddr,
|
|
942
|
-
};
|
|
943
|
-
}
|
|
944
|
-
constructor(protocol, remoteCandidate) {
|
|
945
|
-
Object.defineProperty(this, "protocol", {
|
|
946
|
-
enumerable: true,
|
|
947
|
-
configurable: true,
|
|
948
|
-
writable: true,
|
|
949
|
-
value: protocol
|
|
950
|
-
});
|
|
951
|
-
Object.defineProperty(this, "remoteCandidate", {
|
|
952
|
-
enumerable: true,
|
|
953
|
-
configurable: true,
|
|
954
|
-
writable: true,
|
|
955
|
-
value: remoteCandidate
|
|
956
|
-
});
|
|
957
|
-
Object.defineProperty(this, "handle", {
|
|
958
|
-
enumerable: true,
|
|
959
|
-
configurable: true,
|
|
960
|
-
writable: true,
|
|
961
|
-
value: void 0
|
|
962
|
-
});
|
|
963
|
-
Object.defineProperty(this, "nominated", {
|
|
964
|
-
enumerable: true,
|
|
965
|
-
configurable: true,
|
|
966
|
-
writable: true,
|
|
967
|
-
value: false
|
|
968
|
-
});
|
|
969
|
-
Object.defineProperty(this, "remoteNominated", {
|
|
970
|
-
enumerable: true,
|
|
971
|
-
configurable: true,
|
|
972
|
-
writable: true,
|
|
973
|
-
value: false
|
|
974
|
-
});
|
|
975
|
-
// 5.7.4. Computing States
|
|
976
|
-
Object.defineProperty(this, "_state", {
|
|
977
|
-
enumerable: true,
|
|
978
|
-
configurable: true,
|
|
979
|
-
writable: true,
|
|
980
|
-
value: CandidatePairState.FROZEN
|
|
981
|
-
});
|
|
982
|
-
}
|
|
983
|
-
updateState(state) {
|
|
984
|
-
this._state = state;
|
|
985
|
-
}
|
|
986
|
-
get localCandidate() {
|
|
987
|
-
if (!this.protocol.localCandidate)
|
|
988
|
-
throw new Error("localCandidate not exist");
|
|
989
|
-
return this.protocol.localCandidate;
|
|
990
|
-
}
|
|
991
|
-
get remoteAddr() {
|
|
992
|
-
return [this.remoteCandidate.host, this.remoteCandidate.port];
|
|
993
|
-
}
|
|
994
|
-
get component() {
|
|
995
|
-
return this.localCandidate.component;
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
exports.CandidatePair = CandidatePair;
|
|
999
|
-
const ICE_COMPLETED = 1;
|
|
1000
|
-
const ICE_FAILED = 2;
|
|
1001
|
-
const CONSENT_INTERVAL = 5;
|
|
1002
|
-
const CONSENT_FAILURES = 6;
|
|
1003
|
-
var CandidatePairState;
|
|
1004
|
-
(function (CandidatePairState) {
|
|
1005
|
-
CandidatePairState[CandidatePairState["FROZEN"] = 0] = "FROZEN";
|
|
1006
|
-
CandidatePairState[CandidatePairState["WAITING"] = 1] = "WAITING";
|
|
1007
|
-
CandidatePairState[CandidatePairState["IN_PROGRESS"] = 2] = "IN_PROGRESS";
|
|
1008
|
-
CandidatePairState[CandidatePairState["SUCCEEDED"] = 3] = "SUCCEEDED";
|
|
1009
|
-
CandidatePairState[CandidatePairState["FAILED"] = 4] = "FAILED";
|
|
1010
|
-
})(CandidatePairState || (exports.CandidatePairState = CandidatePairState = {}));
|
|
1011
|
-
const defaultOptions = {
|
|
1012
|
-
useIpv4: true,
|
|
1013
|
-
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 };
|
|
1014
1057
|
};
|
|
1015
|
-
function validateRemoteCandidate(candidate) {
|
|
1016
|
-
// """
|
|
1017
|
-
// Check the remote candidate is supported.
|
|
1018
|
-
// """
|
|
1019
|
-
if (!["host", "relay", "srflx"].includes(candidate.type))
|
|
1020
|
-
throw new Error(`Unexpected candidate type "${candidate.type}"`);
|
|
1021
|
-
// ipaddress.ip_address(candidate.host)
|
|
1022
|
-
return candidate;
|
|
1023
|
-
}
|
|
1024
|
-
function sortCandidatePairs(pairs, iceControlling) {
|
|
1025
|
-
pairs.sort((a, b) => candidatePairPriority(a.localCandidate, a.remoteCandidate, iceControlling) -
|
|
1026
|
-
candidatePairPriority(b.localCandidate, b.remoteCandidate, iceControlling));
|
|
1027
|
-
}
|
|
1028
|
-
// 5.7.2. Computing Pair Priority and Ordering Pairs
|
|
1029
|
-
function candidatePairPriority(local, remote, iceControlling) {
|
|
1030
|
-
const G = (iceControlling && local.priority) || remote.priority;
|
|
1031
|
-
const D = (iceControlling && remote.priority) || local.priority;
|
|
1032
|
-
return (1 << 32) * Math.min(G, D) + 2 * Math.max(G, D) + (G > D ? 1 : 0);
|
|
1033
|
-
}
|
|
1034
|
-
async function serverReflexiveCandidate(protocol, stunServer) {
|
|
1035
|
-
// """
|
|
1036
|
-
// Query STUN server to obtain a server-reflexive candidate.
|
|
1037
|
-
// """
|
|
1038
|
-
// # perform STUN query
|
|
1039
|
-
const request = new message_1.Message(const_1.methods.BINDING, const_1.classes.REQUEST);
|
|
1040
|
-
try {
|
|
1041
|
-
const [response] = await protocol.request(request, stunServer);
|
|
1042
|
-
const localCandidate = protocol.localCandidate;
|
|
1043
|
-
if (!localCandidate)
|
|
1044
|
-
throw new Error("not exist");
|
|
1045
|
-
return new candidate_1.Candidate((0, candidate_1.candidateFoundation)("srflx", "udp", localCandidate.host), localCandidate.component, localCandidate.transport, (0, candidate_1.candidatePriority)(localCandidate.component, "srflx"), response.getAttributeValue("XOR-MAPPED-ADDRESS")[0], response.getAttributeValue("XOR-MAPPED-ADDRESS")[1], "srflx", localCandidate.host, localCandidate.port);
|
|
1046
|
-
}
|
|
1047
|
-
catch (error) {
|
|
1048
|
-
// todo fix
|
|
1049
|
-
log("error serverReflexiveCandidate", error);
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
function validateAddress(addr) {
|
|
1053
|
-
if (addr && Number.isNaN(addr[1])) {
|
|
1054
|
-
return [addr[0], 443];
|
|
1055
|
-
}
|
|
1056
|
-
return addr;
|
|
1057
|
-
}
|
|
1058
1058
|
//# sourceMappingURL=ice.js.map
|