@webex/plugin-meetings 3.8.0-web-workers-keepalive.1 → 3.8.1-next.1
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/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +70 -6
- package/dist/breakouts/index.js.map +1 -1
- package/dist/common/errors/webex-errors.js +12 -2
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/config.js +4 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +22 -123
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.js +2 -0
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/types.js.map +1 -1
- package/dist/controls-options-manager/util.js +52 -0
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +30 -10
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +83 -12
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/selfUtils.js +432 -418
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +17 -17
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +94 -6
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/brbState.js +9 -2
- package/dist/meeting/brbState.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +17 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +568 -328
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +0 -17
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/muteState.js +4 -4
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +30 -0
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +9 -1
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +19 -13
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/utilv2.js +5 -1
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/index.js +76 -0
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/util.js +14 -0
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +45 -9
- package/dist/member/index.js.map +1 -1
- package/dist/member/types.js +3 -0
- package/dist/member/types.js.map +1 -1
- package/dist/member/util.js +335 -356
- package/dist/member/util.js.map +1 -1
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +137 -29
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +38 -0
- package/dist/members/request.js.map +1 -1
- package/dist/members/util.js +36 -1
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +1 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/reachability/clusterReachability.js +23 -31
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +42 -2
- package/dist/reachability/index.js.map +1 -1
- package/dist/reconnection-manager/index.js +2 -2
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/turnDiscovery.js +45 -27
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/roap/types.js +17 -0
- package/dist/roap/types.js.map +1 -0
- package/dist/types/common/errors/webex-errors.d.ts +7 -1
- package/dist/types/config.d.ts +2 -0
- package/dist/types/constants.d.ts +15 -85
- package/dist/types/controls-options-manager/enums.d.ts +3 -1
- package/dist/types/controls-options-manager/types.d.ts +7 -1
- package/dist/types/locus-info/index.d.ts +3 -3
- package/dist/types/locus-info/selfUtils.d.ts +216 -1
- package/dist/types/media/properties.d.ts +15 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +16 -0
- package/dist/types/meeting/index.d.ts +35 -1
- package/dist/types/meeting/muteState.d.ts +0 -1
- package/dist/types/meeting/request.d.ts +12 -1
- package/dist/types/meeting/request.type.d.ts +6 -0
- package/dist/types/meeting/util.d.ts +3 -1
- package/dist/types/meeting-info/meeting-info-v2.d.ts +2 -1
- package/dist/types/meetings/index.d.ts +28 -0
- package/dist/types/member/index.d.ts +20 -6
- package/dist/types/member/types.d.ts +73 -14
- package/dist/types/member/util.d.ts +156 -1
- package/dist/types/members/collection.d.ts +6 -5
- package/dist/types/members/index.d.ts +32 -43
- package/dist/types/members/request.d.ts +26 -0
- package/dist/types/members/util.d.ts +27 -0
- package/dist/types/metrics/constants.d.ts +1 -0
- package/dist/types/reachability/clusterReachability.d.ts +2 -6
- package/dist/types/reachability/index.d.ts +8 -0
- package/dist/types/roap/index.d.ts +3 -2
- package/dist/types/roap/turnDiscovery.d.ts +5 -17
- package/dist/types/roap/types.d.ts +16 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +24 -23
- package/src/breakouts/index.ts +69 -0
- package/src/common/errors/webex-errors.ts +8 -1
- package/src/config.ts +2 -0
- package/src/constants.ts +23 -90
- package/src/controls-options-manager/enums.ts +2 -0
- package/src/controls-options-manager/types.ts +11 -1
- package/src/controls-options-manager/util.ts +62 -0
- package/src/locus-info/controlsUtils.ts +48 -12
- package/src/locus-info/index.ts +88 -13
- package/src/locus-info/selfUtils.ts +496 -442
- package/src/media/index.ts +23 -21
- package/src/media/properties.ts +96 -0
- package/src/meeting/brbState.ts +11 -2
- package/src/meeting/in-meeting-actions.ts +32 -0
- package/src/meeting/index.ts +356 -87
- package/src/meeting/locusMediaRequest.ts +0 -18
- package/src/meeting/muteState.ts +4 -4
- package/src/meeting/request.ts +36 -1
- package/src/meeting/request.type.ts +7 -0
- package/src/meeting/util.ts +9 -1
- package/src/meeting-info/meeting-info-v2.ts +7 -2
- package/src/meeting-info/utilv2.ts +5 -0
- package/src/meetings/index.ts +76 -0
- package/src/meetings/util.ts +18 -0
- package/src/member/index.ts +57 -22
- package/src/member/types.ts +82 -16
- package/src/member/util.ts +357 -353
- package/src/members/collection.ts +4 -3
- package/src/members/index.ts +137 -18
- package/src/members/request.ts +44 -0
- package/src/members/util.ts +43 -1
- package/src/metrics/constants.ts +1 -0
- package/src/reachability/clusterReachability.ts +26 -25
- package/src/reachability/index.ts +55 -1
- package/src/reconnection-manager/index.ts +2 -2
- package/src/roap/index.ts +3 -7
- package/src/roap/turnDiscovery.ts +34 -39
- package/src/roap/types.ts +23 -0
- package/test/unit/spec/breakouts/index.ts +167 -95
- package/test/unit/spec/controls-options-manager/util.js +120 -0
- package/test/unit/spec/locus-info/controlsUtils.js +131 -9
- package/test/unit/spec/locus-info/index.js +195 -73
- package/test/unit/spec/locus-info/selfUtils.js +98 -24
- package/test/unit/spec/media/index.ts +150 -18
- package/test/unit/spec/media/properties.ts +130 -0
- package/test/unit/spec/meeting/brbState.ts +40 -2
- package/test/unit/spec/meeting/in-meeting-actions.ts +19 -4
- package/test/unit/spec/meeting/index.js +553 -36
- package/test/unit/spec/meeting/locusMediaRequest.ts +0 -30
- package/test/unit/spec/meeting/muteState.js +73 -2
- package/test/unit/spec/meeting/request.js +32 -1
- package/test/unit/spec/meeting/utils.js +79 -33
- package/test/unit/spec/meeting-info/meetinginfov2.js +41 -0
- package/test/unit/spec/meeting-info/utilv2.js +19 -0
- package/test/unit/spec/meetings/index.js +68 -1
- package/test/unit/spec/members/index.js +304 -78
- package/test/unit/spec/members/request.js +68 -22
- package/test/unit/spec/members/utils.js +75 -0
- package/test/unit/spec/reachability/clusterReachability.ts +41 -55
- package/test/unit/spec/reachability/index.ts +89 -0
- package/test/unit/spec/reconnection-manager/index.js +4 -4
- package/test/unit/spec/roap/turnDiscovery.ts +110 -28
@@ -357,5 +357,80 @@ describe('plugin-meetings', () => {
|
|
357
357
|
});
|
358
358
|
});
|
359
359
|
});
|
360
|
+
|
361
|
+
describe('#getMoveMemberToLobbyRequestBody', () => {
|
362
|
+
it('returns the correct options', () => {
|
363
|
+
const memberId = 'test1';
|
364
|
+
assert.deepEqual(MembersUtil.getMoveMemberToLobbyRequestBody(memberId), {
|
365
|
+
moveToLobby: {
|
366
|
+
participantIds: [memberId],
|
367
|
+
},
|
368
|
+
});
|
369
|
+
});
|
370
|
+
});
|
371
|
+
|
372
|
+
describe('#getMoveMemberToLobbyRequestParams', () => {
|
373
|
+
it('returns the correct params', () => {
|
374
|
+
const locusUrl = 'TestLocusUrl';
|
375
|
+
const memberId = 'test1';
|
376
|
+
const options = {
|
377
|
+
locusUrl: locusUrl,
|
378
|
+
memberId,
|
379
|
+
};
|
380
|
+
const body = {
|
381
|
+
moveToLobby: {participantIds: [memberId]},
|
382
|
+
};
|
383
|
+
|
384
|
+
const uri = `${options.locusUrl}/${PARTICIPANT}/${options.memberId}/${CONTROLS}`;
|
385
|
+
|
386
|
+
assert.deepEqual(MembersUtil.getMoveMemberToLobbyRequestParams(options, body), {
|
387
|
+
method: HTTP_VERBS.PATCH,
|
388
|
+
uri,
|
389
|
+
body,
|
390
|
+
});
|
391
|
+
});
|
392
|
+
});
|
393
|
+
|
394
|
+
describe('#cancelSIPInviteOptions', () => {
|
395
|
+
it('returns the correct options', () => {
|
396
|
+
const locusUrl = 'TestLocusUrl';
|
397
|
+
const memberId = 'test';
|
398
|
+
const invitee = {memberId};
|
399
|
+
|
400
|
+
assert.deepEqual(
|
401
|
+
MembersUtil.cancelSIPInviteOptions(
|
402
|
+
invitee,
|
403
|
+
locusUrl
|
404
|
+
),
|
405
|
+
{
|
406
|
+
invitee,
|
407
|
+
locusUrl,
|
408
|
+
}
|
409
|
+
);
|
410
|
+
});
|
411
|
+
});
|
412
|
+
|
413
|
+
describe('#generateCancelSIPInviteRequestParams', () => {
|
414
|
+
it('returns the correct params', () => {
|
415
|
+
const locusUrl = 'TestLocusUrl';
|
416
|
+
const memberId = 'test';
|
417
|
+
const options = {
|
418
|
+
locusUrl,
|
419
|
+
invitee: {memberId}
|
420
|
+
};
|
421
|
+
const body = {
|
422
|
+
actionType: 'REMOVE',
|
423
|
+
invitees: [{address: options.invitee.memberId}],
|
424
|
+
};
|
425
|
+
|
426
|
+
const uri = options.locusUrl;
|
427
|
+
|
428
|
+
assert.deepEqual(MembersUtil.generateCancelSIPInviteRequestParams(options), {
|
429
|
+
method: HTTP_VERBS.PUT,
|
430
|
+
uri,
|
431
|
+
body,
|
432
|
+
});
|
433
|
+
});
|
434
|
+
});
|
360
435
|
});
|
361
436
|
});
|
@@ -174,59 +174,6 @@ describe('ClusterReachability', () => {
|
|
174
174
|
assert.deepEqual(emittedEvents[Events.clientMediaIpsUpdated], []);
|
175
175
|
});
|
176
176
|
|
177
|
-
it('resolves and has correct result as soon as it finds that all udp, tcp and tls are reachable', async () => {
|
178
|
-
const promise = clusterReachability.start();
|
179
|
-
|
180
|
-
await clock.tickAsync(100);
|
181
|
-
fakePeerConnection.onicecandidate({candidate: {type: 'srflx', address: 'somePublicIp'}});
|
182
|
-
|
183
|
-
// check the right events were emitted
|
184
|
-
assert.equal(emittedEvents[Events.resultReady].length, 1);
|
185
|
-
assert.deepEqual(emittedEvents[Events.resultReady][0], {
|
186
|
-
protocol: 'udp',
|
187
|
-
result: 'reachable',
|
188
|
-
latencyInMilliseconds: 100,
|
189
|
-
clientMediaIPs: ['somePublicIp'],
|
190
|
-
});
|
191
|
-
|
192
|
-
// clientMediaIpsUpdated shouldn't be emitted, because the IP is already passed in the resultReady event
|
193
|
-
assert.equal(emittedEvents[Events.clientMediaIpsUpdated].length, 0);
|
194
|
-
|
195
|
-
await clock.tickAsync(100);
|
196
|
-
fakePeerConnection.onicecandidate({candidate: {type: 'relay', address: 'someTurnRelayIp'}});
|
197
|
-
|
198
|
-
// check the right event was emitted
|
199
|
-
assert.equal(emittedEvents[Events.resultReady].length, 2);
|
200
|
-
assert.deepEqual(emittedEvents[Events.resultReady][1], {
|
201
|
-
protocol: 'tcp',
|
202
|
-
result: 'reachable',
|
203
|
-
latencyInMilliseconds: 200,
|
204
|
-
});
|
205
|
-
assert.equal(emittedEvents[Events.clientMediaIpsUpdated].length, 0);
|
206
|
-
|
207
|
-
await clock.tickAsync(100);
|
208
|
-
fakePeerConnection.onicecandidate({
|
209
|
-
candidate: {type: 'relay', address: 'someTurnRelayIp', port: 443},
|
210
|
-
});
|
211
|
-
|
212
|
-
// check the right event was emitted
|
213
|
-
assert.equal(emittedEvents[Events.resultReady].length, 3);
|
214
|
-
assert.deepEqual(emittedEvents[Events.resultReady][2], {
|
215
|
-
protocol: 'xtls',
|
216
|
-
result: 'reachable',
|
217
|
-
latencyInMilliseconds: 300,
|
218
|
-
});
|
219
|
-
assert.equal(emittedEvents[Events.clientMediaIpsUpdated].length, 0);
|
220
|
-
|
221
|
-
await promise;
|
222
|
-
|
223
|
-
assert.deepEqual(clusterReachability.getResult(), {
|
224
|
-
udp: {result: 'reachable', latencyInMilliseconds: 100, clientMediaIPs: ['somePublicIp']},
|
225
|
-
tcp: {result: 'reachable', latencyInMilliseconds: 200},
|
226
|
-
xtls: {result: 'reachable', latencyInMilliseconds: 300},
|
227
|
-
});
|
228
|
-
});
|
229
|
-
|
230
177
|
it('resolves and returns correct results when aborted before it gets any candidates', async () => {
|
231
178
|
const promise = clusterReachability.start();
|
232
179
|
|
@@ -275,7 +222,7 @@ describe('ClusterReachability', () => {
|
|
275
222
|
|
276
223
|
await testUtils.flushPromises();
|
277
224
|
|
278
|
-
fakePeerConnection.
|
225
|
+
fakePeerConnection.iceGatheringState = 'complete';
|
279
226
|
fakePeerConnection.onicegatheringstatechange();
|
280
227
|
await promise;
|
281
228
|
|
@@ -293,7 +240,7 @@ describe('ClusterReachability', () => {
|
|
293
240
|
await clock.tickAsync(30);
|
294
241
|
fakePeerConnection.onicecandidate({candidate: {type: 'srflx', address: 'somePublicIp1'}});
|
295
242
|
|
296
|
-
fakePeerConnection.
|
243
|
+
fakePeerConnection.iceGatheringState = 'complete';
|
297
244
|
fakePeerConnection.onicegatheringstatechange();
|
298
245
|
await promise;
|
299
246
|
|
@@ -436,6 +383,9 @@ describe('ClusterReachability', () => {
|
|
436
383
|
candidate: {type: 'relay', address: 'someTurnRelayIp', port: 443},
|
437
384
|
});
|
438
385
|
|
386
|
+
fakePeerConnection.iceGatheringState = 'complete';
|
387
|
+
fakePeerConnection.onicegatheringstatechange();
|
388
|
+
|
439
389
|
await promise;
|
440
390
|
|
441
391
|
assert.deepEqual(clusterReachability.getResult(), {
|
@@ -474,6 +424,10 @@ describe('ClusterReachability', () => {
|
|
474
424
|
candidate: {type: 'relay', address: 'someTurnRelayIp', port: 443},
|
475
425
|
});
|
476
426
|
|
427
|
+
fakePeerConnection.iceGatheringState = 'complete';
|
428
|
+
fakePeerConnection.onicegatheringstatechange();
|
429
|
+
await clock.tickAsync(10);
|
430
|
+
|
477
431
|
await promise;
|
478
432
|
|
479
433
|
assert.deepEqual(clusterReachability.getResult(), {
|
@@ -486,5 +440,37 @@ describe('ClusterReachability', () => {
|
|
486
440
|
xtls: {result: 'reachable', latencyInMilliseconds: 20},
|
487
441
|
});
|
488
442
|
});
|
443
|
+
|
444
|
+
it('should gather correctly reached subnets', async () => {
|
445
|
+
const promise = clusterReachability.start();
|
446
|
+
|
447
|
+
await clock.tickAsync(10);
|
448
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'srflx', url: 'stun:1.2.3.4:5004'}});
|
449
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'srflx', url: 'stun:4.3.2.1:5004'}});
|
450
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'relay', address: 'someTurnRelayIp'}});
|
451
|
+
|
452
|
+
clusterReachability.abort();
|
453
|
+
await promise;
|
454
|
+
|
455
|
+
assert.deepEqual(Array.from(clusterReachability.reachedSubnets), [
|
456
|
+
'1.2.3.4',
|
457
|
+
'4.3.2.1',
|
458
|
+
'someTurnRelayIp'
|
459
|
+
]);
|
460
|
+
});
|
461
|
+
|
462
|
+
it('should store only unique subnet address', async () => {
|
463
|
+
const promise = clusterReachability.start();
|
464
|
+
|
465
|
+
await clock.tickAsync(10);
|
466
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'srflx', url: 'stun:1.2.3.4:5004'}});
|
467
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'srflx', url: 'stun:1.2.3.4:9000'}});
|
468
|
+
fakePeerConnection.onicecandidate({candidate: {type: 'relay', address: '1.2.3.4'}});
|
469
|
+
|
470
|
+
clusterReachability.abort();
|
471
|
+
await promise;
|
472
|
+
|
473
|
+
assert.deepEqual(Array.from(clusterReachability.reachedSubnets), ['1.2.3.4']);
|
474
|
+
});
|
489
475
|
});
|
490
476
|
});
|
@@ -1955,6 +1955,7 @@ describe('gatherReachability', () => {
|
|
1955
1955
|
receivedEvents[event] = receivedEvents[event] + 1 || 1;
|
1956
1956
|
});
|
1957
1957
|
};
|
1958
|
+
|
1958
1959
|
it('works as expected', async () => {
|
1959
1960
|
setListener('reachability:stopped');
|
1960
1961
|
setListener('reachability:done');
|
@@ -2016,6 +2017,59 @@ describe('gatherReachability', () => {
|
|
2016
2017
|
assert.equal(receivedEvents['reachability:done'], undefined);
|
2017
2018
|
assert.equal(receivedEvents['reachability:firstResultAvailable'], undefined);
|
2018
2019
|
});
|
2020
|
+
|
2021
|
+
it('does not fallback when no clusters were reached and min clusters were specified', async () => {
|
2022
|
+
setListener('reachability:stopped');
|
2023
|
+
setListener('reachability:done');
|
2024
|
+
setListener('reachability:firstResultAvailable');
|
2025
|
+
|
2026
|
+
const mockGetClustersResult = {
|
2027
|
+
discoveryOptions: {
|
2028
|
+
['early-call-min-clusters']: 1,
|
2029
|
+
},
|
2030
|
+
clusters: {
|
2031
|
+
clusterA: {
|
2032
|
+
udp: [],
|
2033
|
+
tcp: [],
|
2034
|
+
xtls: [],
|
2035
|
+
isVideoMesh: false,
|
2036
|
+
},
|
2037
|
+
clusterB: {
|
2038
|
+
udp: [],
|
2039
|
+
tcp: [],
|
2040
|
+
xtls: [],
|
2041
|
+
isVideoMesh: false,
|
2042
|
+
},
|
2043
|
+
},
|
2044
|
+
joinCookie: {id: 'id'},
|
2045
|
+
};
|
2046
|
+
|
2047
|
+
reachability.reachabilityRequest.getClusters = sinon.stub().returns(mockGetClustersResult);
|
2048
|
+
|
2049
|
+
const gatherReachabilityFallbackSpy = sinon.spy(reachability, 'gatherReachabilityFallback');
|
2050
|
+
|
2051
|
+
const resultPromise = reachability.gatherReachability('test');
|
2052
|
+
|
2053
|
+
await testUtils.flushPromises();
|
2054
|
+
|
2055
|
+
reachability.stopReachability();
|
2056
|
+
|
2057
|
+
await resultPromise;
|
2058
|
+
|
2059
|
+
// simulate a lot of time passing to check that all timers were stopped and nothing else happens
|
2060
|
+
clock.tick(99000);
|
2061
|
+
|
2062
|
+
assert.calledOnceWithExactly(mockClusterReachabilityInstances['clusterA'].abort);
|
2063
|
+
assert.calledOnceWithExactly(mockClusterReachabilityInstances['clusterB'].abort);
|
2064
|
+
|
2065
|
+
assert.calledOnceWithExactly(sendMetricSpy, true);
|
2066
|
+
|
2067
|
+
assert.equal(receivedEvents['reachability:stopped'], 1);
|
2068
|
+
assert.equal(receivedEvents['reachability:done'], undefined);
|
2069
|
+
assert.equal(receivedEvents['reachability:firstResultAvailable'], undefined);
|
2070
|
+
|
2071
|
+
assert.notCalled(gatherReachabilityFallbackSpy);
|
2072
|
+
});
|
2019
2073
|
});
|
2020
2074
|
});
|
2021
2075
|
|
@@ -2686,3 +2740,38 @@ describe('sendMetric', () => {
|
|
2686
2740
|
});
|
2687
2741
|
});
|
2688
2742
|
});
|
2743
|
+
|
2744
|
+
describe('isSubnetReachable', () => {
|
2745
|
+
let webex;
|
2746
|
+
let reachability;
|
2747
|
+
|
2748
|
+
beforeEach(() => {
|
2749
|
+
webex = new MockWebex();
|
2750
|
+
reachability = new TestReachability(webex);
|
2751
|
+
|
2752
|
+
reachability.setFakeClusterReachability({
|
2753
|
+
cluster1: {
|
2754
|
+
reachedSubnets: new Set(['1.2.3.4', '2.3.4.5']),
|
2755
|
+
},
|
2756
|
+
cluster2: {
|
2757
|
+
reachedSubnets: new Set(['3.4.5.6', '4.5.6.7']),
|
2758
|
+
},
|
2759
|
+
});
|
2760
|
+
});
|
2761
|
+
|
2762
|
+
afterEach(() => {
|
2763
|
+
sinon.restore();
|
2764
|
+
});
|
2765
|
+
|
2766
|
+
it('returns true if the subnet is reachable', () => {
|
2767
|
+
assert(reachability.isSubnetReachable('1.2.3.4'));
|
2768
|
+
});
|
2769
|
+
|
2770
|
+
it(`returns false if the subnet is unreachable`, () => {
|
2771
|
+
assert(!reachability.isSubnetReachable('11.2.3.4'));
|
2772
|
+
});
|
2773
|
+
|
2774
|
+
it('returns null if the subnet is not provided', () => {
|
2775
|
+
assert.isNull(reachability.isSubnetReachable(undefined));
|
2776
|
+
});
|
2777
|
+
});
|
@@ -60,7 +60,7 @@ describe('plugin-meetings', () => {
|
|
60
60
|
roap: {
|
61
61
|
doTurnDiscovery: sinon.stub().resolves({
|
62
62
|
turnServerInfo: {
|
63
|
-
|
63
|
+
urls: ['fake_turn_url1', 'fake_turn_url2'],
|
64
64
|
username: 'fake_turn_username',
|
65
65
|
password: 'fake_turn_password',
|
66
66
|
},
|
@@ -137,7 +137,7 @@ describe('plugin-meetings', () => {
|
|
137
137
|
assert.calledOnce(fakeMediaConnection.reconnect);
|
138
138
|
assert.calledWith(fakeMediaConnection.reconnect, [
|
139
139
|
{
|
140
|
-
urls: '
|
140
|
+
urls: ['fake_turn_url1', 'fake_turn_url2'],
|
141
141
|
username: 'fake_turn_username',
|
142
142
|
credential: 'fake_turn_password',
|
143
143
|
},
|
@@ -152,12 +152,12 @@ describe('plugin-meetings', () => {
|
|
152
152
|
});
|
153
153
|
|
154
154
|
// this can happen when we land on a video mesh node
|
155
|
-
it('does not use TURN server if TURN
|
155
|
+
it('does not use TURN server if TURN urls is an empty array', async () => {
|
156
156
|
const rm = new ReconnectionManager(fakeMeeting);
|
157
157
|
|
158
158
|
fakeMeeting.roap.doTurnDiscovery.resolves({
|
159
159
|
turnServerInfo: {
|
160
|
-
|
160
|
+
urls: [],
|
161
161
|
username: 'whatever',
|
162
162
|
password: 'whatever',
|
163
163
|
},
|
@@ -15,7 +15,8 @@ describe('TurnDiscovery', () => {
|
|
15
15
|
let mockRoapRequest: RoapRequest;
|
16
16
|
let testMeeting: any;
|
17
17
|
|
18
|
-
const
|
18
|
+
const FAKE_TURN_URL1 = 'turns:fakeTurnServer1.com:443?transport=tcp';
|
19
|
+
const FAKE_TURN_URL2 = 'turns:fakeTurnServer2.com:443?transport=tcp';
|
19
20
|
const FAKE_TURN_USERNAME = 'someUsernameFromServer';
|
20
21
|
const FAKE_TURN_PASSWORD = 'fakePasswordFromServer';
|
21
22
|
const FAKE_LOCUS_ID = '09493311-f5d5-3e58-b491-009cc628162e';
|
@@ -186,7 +187,8 @@ describe('TurnDiscovery', () => {
|
|
186
187
|
{
|
187
188
|
messageType: 'TURN_DISCOVERY_RESPONSE',
|
188
189
|
headers: [
|
189
|
-
`x-cisco-turn-url=${
|
190
|
+
`x-cisco-turn-url=${FAKE_TURN_URL1}`,
|
191
|
+
`x-cisco-turn-url=${FAKE_TURN_URL2}`,
|
190
192
|
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
191
193
|
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
192
194
|
],
|
@@ -195,7 +197,7 @@ describe('TurnDiscovery', () => {
|
|
195
197
|
);
|
196
198
|
|
197
199
|
await checkResult(result, 'OK', {
|
198
|
-
|
200
|
+
urls: [FAKE_TURN_URL1, FAKE_TURN_URL2],
|
199
201
|
username: FAKE_TURN_USERNAME,
|
200
202
|
password: FAKE_TURN_PASSWORD,
|
201
203
|
});
|
@@ -220,7 +222,7 @@ describe('TurnDiscovery', () => {
|
|
220
222
|
{
|
221
223
|
messageType: 'TURN_DISCOVERY_RESPONSE',
|
222
224
|
headers: [
|
223
|
-
`x-cisco-turn-url=${
|
225
|
+
`x-cisco-turn-url=${FAKE_TURN_URL1}`,
|
224
226
|
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
225
227
|
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
226
228
|
'noOkInTransaction',
|
@@ -230,7 +232,7 @@ describe('TurnDiscovery', () => {
|
|
230
232
|
);
|
231
233
|
|
232
234
|
await checkResult(result, undefined, {
|
233
|
-
|
235
|
+
urls: [FAKE_TURN_URL1],
|
234
236
|
username: FAKE_TURN_USERNAME,
|
235
237
|
password: FAKE_TURN_PASSWORD,
|
236
238
|
});
|
@@ -241,7 +243,7 @@ describe('TurnDiscovery', () => {
|
|
241
243
|
mediaConnections: [
|
242
244
|
{
|
243
245
|
mediaId: '464ff97f-4bda-466a-ad06-3a22184a2274',
|
244
|
-
remoteSdp: `{"roapMessage": {"messageType":"TURN_DISCOVERY_RESPONSE","seq":"0","headers": ["x-cisco-turn-url=${
|
246
|
+
remoteSdp: `{"roapMessage": {"messageType":"TURN_DISCOVERY_RESPONSE","seq":"0","headers": ["x-cisco-turn-url=${FAKE_TURN_URL1}","x-cisco-turn-username=${FAKE_TURN_USERNAME}","x-cisco-turn-password=${FAKE_TURN_PASSWORD}", "noOkInTransaction"]}}`,
|
245
247
|
},
|
246
248
|
],
|
247
249
|
});
|
@@ -256,7 +258,7 @@ describe('TurnDiscovery', () => {
|
|
256
258
|
mockRoapRequest.sendRoap.resetHistory();
|
257
259
|
|
258
260
|
await checkResult(result, undefined, {
|
259
|
-
|
261
|
+
urls: [FAKE_TURN_URL1],
|
260
262
|
username: FAKE_TURN_USERNAME,
|
261
263
|
password: FAKE_TURN_PASSWORD,
|
262
264
|
});
|
@@ -268,7 +270,7 @@ describe('TurnDiscovery', () => {
|
|
268
270
|
mediaConnections: [
|
269
271
|
{
|
270
272
|
mediaId: '464ff97f-4bda-466a-ad06-3a22184a2274',
|
271
|
-
remoteSdp: `{"roapMessage": {"messageType":"TURN_DISCOVERY_RESPONSE","seq":"0","headers": ["x-cisco-turn-url=${
|
273
|
+
remoteSdp: `{"roapMessage": {"messageType":"TURN_DISCOVERY_RESPONSE","seq":"0","headers": ["x-cisco-turn-url=${FAKE_TURN_URL1}","x-cisco-turn-username=${FAKE_TURN_USERNAME}","x-cisco-turn-password=${FAKE_TURN_PASSWORD}"]}}`,
|
272
274
|
},
|
273
275
|
],
|
274
276
|
};
|
@@ -290,7 +292,7 @@ describe('TurnDiscovery', () => {
|
|
290
292
|
sendRoapPromiseResolve(sendRoapResult);
|
291
293
|
|
292
294
|
await checkResult(result, 'OK', {
|
293
|
-
|
295
|
+
urls: [FAKE_TURN_URL1],
|
294
296
|
username: FAKE_TURN_USERNAME,
|
295
297
|
password: FAKE_TURN_PASSWORD,
|
296
298
|
});
|
@@ -350,16 +352,17 @@ describe('TurnDiscovery', () => {
|
|
350
352
|
{
|
351
353
|
messageType: 'TURN_DISCOVERY_RESPONSE',
|
352
354
|
headers: [
|
353
|
-
`x-cisco-turn-url=${
|
355
|
+
`x-cisco-turn-url=${FAKE_TURN_URL1}`,
|
354
356
|
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
355
357
|
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
358
|
+
`x-cisco-turn-url=${FAKE_TURN_URL2}`,
|
356
359
|
],
|
357
360
|
},
|
358
361
|
'from test'
|
359
362
|
);
|
360
363
|
|
361
364
|
await checkResult(result, 'OK', {
|
362
|
-
|
365
|
+
urls: [FAKE_TURN_URL1, FAKE_TURN_URL2],
|
363
366
|
username: FAKE_TURN_USERNAME,
|
364
367
|
password: FAKE_TURN_PASSWORD,
|
365
368
|
});
|
@@ -391,6 +394,44 @@ describe('TurnDiscovery', () => {
|
|
391
394
|
'failure: TURN_DISCOVERY_RESPONSE in http response has unexpected messageType: {"seq":"0","messageType":"ERROR"}'
|
392
395
|
);
|
393
396
|
});
|
397
|
+
|
398
|
+
it('resets turnInfo each time TURN discovery is done', async () => {
|
399
|
+
const runCheck = async (td, turnUrl, expectedResult) => {
|
400
|
+
mockRoapRequest.sendRoap = sinon.fake.resolves({
|
401
|
+
mediaConnections: [
|
402
|
+
{
|
403
|
+
mediaId: '464ff97f-4bda-466a-ad06-3a22184a2274',
|
404
|
+
remoteSdp: `{"roapMessage": {"messageType":"TURN_DISCOVERY_RESPONSE","seq":"0","headers": ["x-cisco-turn-url=${turnUrl}","x-cisco-turn-username=${FAKE_TURN_USERNAME}","x-cisco-turn-password=${FAKE_TURN_PASSWORD}", "noOkInTransaction"]}}`,
|
405
|
+
},
|
406
|
+
],
|
407
|
+
});
|
408
|
+
|
409
|
+
const result = td.doTurnDiscovery(testMeeting, false);
|
410
|
+
|
411
|
+
// check that TURN_DISCOVERY_REQUEST was sent
|
412
|
+
await checkRoapMessageSent('TURN_DISCOVERY_REQUEST', 0);
|
413
|
+
|
414
|
+
// @ts-ignore
|
415
|
+
mockRoapRequest.sendRoap.resetHistory();
|
416
|
+
|
417
|
+
await checkResult(result, undefined, expectedResult);
|
418
|
+
};
|
419
|
+
|
420
|
+
const td = new TurnDiscovery(mockRoapRequest);
|
421
|
+
|
422
|
+
await runCheck(td, FAKE_TURN_URL1, {
|
423
|
+
urls: [FAKE_TURN_URL1],
|
424
|
+
username: FAKE_TURN_USERNAME,
|
425
|
+
password: FAKE_TURN_PASSWORD,
|
426
|
+
});
|
427
|
+
|
428
|
+
// call it again with different turn url, the result should not have the previous url
|
429
|
+
await runCheck(td, FAKE_TURN_URL2, {
|
430
|
+
urls: [FAKE_TURN_URL2],
|
431
|
+
username: FAKE_TURN_USERNAME,
|
432
|
+
password: FAKE_TURN_PASSWORD,
|
433
|
+
});
|
434
|
+
});
|
394
435
|
});
|
395
436
|
});
|
396
437
|
|
@@ -415,7 +456,7 @@ describe('TurnDiscovery', () => {
|
|
415
456
|
{
|
416
457
|
messageType: 'TURN_DISCOVERY_RESPONSE',
|
417
458
|
headers: [
|
418
|
-
`x-cisco-turn-url=${
|
459
|
+
`x-cisco-turn-url=${FAKE_TURN_URL1}`,
|
419
460
|
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
420
461
|
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
421
462
|
],
|
@@ -428,7 +469,7 @@ describe('TurnDiscovery', () => {
|
|
428
469
|
|
429
470
|
const {turnServerInfo, turnDiscoverySkippedReason} = await result;
|
430
471
|
assert.deepEqual(turnServerInfo, {
|
431
|
-
|
472
|
+
urls: [FAKE_TURN_URL1],
|
432
473
|
username: FAKE_TURN_USERNAME,
|
433
474
|
password: FAKE_TURN_PASSWORD,
|
434
475
|
});
|
@@ -455,7 +496,7 @@ describe('TurnDiscovery', () => {
|
|
455
496
|
{
|
456
497
|
messageType: 'TURN_DISCOVERY_RESPONSE',
|
457
498
|
headers: [
|
458
|
-
`x-cisco-turn-url=${
|
499
|
+
`x-cisco-turn-url=${FAKE_TURN_URL1}`,
|
459
500
|
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
460
501
|
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
461
502
|
],
|
@@ -471,7 +512,7 @@ describe('TurnDiscovery', () => {
|
|
471
512
|
const {turnServerInfo, turnDiscoverySkippedReason} = await result;
|
472
513
|
|
473
514
|
assert.deepEqual(turnServerInfo, {
|
474
|
-
|
515
|
+
urls: [FAKE_TURN_URL1],
|
475
516
|
username: FAKE_TURN_USERNAME,
|
476
517
|
password: FAKE_TURN_PASSWORD,
|
477
518
|
});
|
@@ -493,7 +534,7 @@ describe('TurnDiscovery', () => {
|
|
493
534
|
messageType: 'TURN_DISCOVERY_RESPONSE',
|
494
535
|
headers: [
|
495
536
|
'x-cisco-turn-unexpected-header=xxx',
|
496
|
-
`x-cisco-turn-url=${
|
537
|
+
`x-cisco-turn-url=${FAKE_TURN_URL1}`,
|
497
538
|
'x-cisco-some-other-header',
|
498
539
|
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
499
540
|
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
@@ -510,7 +551,47 @@ describe('TurnDiscovery', () => {
|
|
510
551
|
|
511
552
|
const {turnServerInfo, turnDiscoverySkippedReason} = await result;
|
512
553
|
assert.deepEqual(turnServerInfo, {
|
513
|
-
|
554
|
+
urls: [FAKE_TURN_URL1],
|
555
|
+
username: FAKE_TURN_USERNAME,
|
556
|
+
password: FAKE_TURN_PASSWORD,
|
557
|
+
});
|
558
|
+
assert.isUndefined(turnDiscoverySkippedReason);
|
559
|
+
});
|
560
|
+
|
561
|
+
// this happens when we land on video-mesh nodes (VMN) - we will get a single empty url
|
562
|
+
it('filters out any empty TURN urls', async () => {
|
563
|
+
const td = new TurnDiscovery(mockRoapRequest);
|
564
|
+
const result = td.doTurnDiscovery(testMeeting, false);
|
565
|
+
|
566
|
+
// check that TURN_DISCOVERY_REQUEST was sent
|
567
|
+
await checkRoapMessageSent('TURN_DISCOVERY_REQUEST', 0);
|
568
|
+
// @ts-ignore
|
569
|
+
mockRoapRequest.sendRoap.resetHistory();
|
570
|
+
|
571
|
+
// simulate the response with some empty urls, normally there would be just 1, but we put more just for the sake of testing
|
572
|
+
td.handleTurnDiscoveryResponse(
|
573
|
+
{
|
574
|
+
messageType: 'TURN_DISCOVERY_RESPONSE',
|
575
|
+
headers: [
|
576
|
+
'x-cisco-turn-url=',
|
577
|
+
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
578
|
+
'x-cisco-turn-url=',
|
579
|
+
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
580
|
+
'x-cisco-turn-url=non-empty-url',
|
581
|
+
'x-cisco-turn-url=',
|
582
|
+
],
|
583
|
+
},
|
584
|
+
'from test'
|
585
|
+
);
|
586
|
+
|
587
|
+
await testUtils.flushPromises();
|
588
|
+
|
589
|
+
// check that we've sent OK and still parsed the headers we care about
|
590
|
+
await checkRoapMessageSent('OK', 0);
|
591
|
+
|
592
|
+
const {turnServerInfo, turnDiscoverySkippedReason} = await result;
|
593
|
+
assert.deepEqual(turnServerInfo, {
|
594
|
+
urls: ['non-empty-url'], // empty urls should be filtered out
|
514
595
|
username: FAKE_TURN_USERNAME,
|
515
596
|
password: FAKE_TURN_PASSWORD,
|
516
597
|
});
|
@@ -575,7 +656,7 @@ describe('TurnDiscovery', () => {
|
|
575
656
|
{
|
576
657
|
messageType: 'TURN_DISCOVERY_RESPONSE',
|
577
658
|
headers: [
|
578
|
-
`x-cisco-turn-url=${
|
659
|
+
`x-cisco-turn-url=${FAKE_TURN_URL1}`,
|
579
660
|
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
580
661
|
],
|
581
662
|
},
|
@@ -587,7 +668,7 @@ describe('TurnDiscovery', () => {
|
|
587
668
|
assert.isUndefined(turnServerInfo);
|
588
669
|
assert.equal(
|
589
670
|
turnDiscoverySkippedReason,
|
590
|
-
`failure: TURN_DISCOVERY_RESPONSE from test missing some headers: ["x-cisco-turn-url=${
|
671
|
+
`failure: TURN_DISCOVERY_RESPONSE from test missing some headers: ["x-cisco-turn-url=${FAKE_TURN_URL1}","x-cisco-turn-username=${FAKE_TURN_USERNAME}"]`
|
591
672
|
);
|
592
673
|
checkFailureMetricsSent();
|
593
674
|
});
|
@@ -655,7 +736,7 @@ describe('TurnDiscovery', () => {
|
|
655
736
|
{
|
656
737
|
messageType: 'TURN_DISCOVERY_RESPONSE',
|
657
738
|
headers: [
|
658
|
-
`x-cisco-turn-url=${
|
739
|
+
`x-cisco-turn-url=${FAKE_TURN_URL1}`,
|
659
740
|
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
660
741
|
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
661
742
|
],
|
@@ -707,7 +788,7 @@ describe('TurnDiscovery', () => {
|
|
707
788
|
{
|
708
789
|
messageType: 'TURN_DISCOVERY_RESPONSE',
|
709
790
|
headers: [
|
710
|
-
`x-cisco-turn-url=${
|
791
|
+
`x-cisco-turn-url=${FAKE_TURN_URL1}`,
|
711
792
|
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
712
793
|
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
713
794
|
],
|
@@ -816,7 +897,8 @@ describe('TurnDiscovery', () => {
|
|
816
897
|
errorType: undefined,
|
817
898
|
errorCause: undefined,
|
818
899
|
headers: [
|
819
|
-
`x-cisco-turn-url=${
|
900
|
+
`x-cisco-turn-url=${FAKE_TURN_URL1}`,
|
901
|
+
`x-cisco-turn-url=${FAKE_TURN_URL2}`,
|
820
902
|
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
821
903
|
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
822
904
|
'noOkInTransaction',
|
@@ -902,7 +984,7 @@ describe('TurnDiscovery', () => {
|
|
902
984
|
|
903
985
|
assert.deepEqual(result, {
|
904
986
|
turnServerInfo: {
|
905
|
-
|
987
|
+
urls: [FAKE_TURN_URL1, FAKE_TURN_URL2],
|
906
988
|
username: FAKE_TURN_USERNAME,
|
907
989
|
password: FAKE_TURN_PASSWORD,
|
908
990
|
},
|
@@ -914,7 +996,7 @@ describe('TurnDiscovery', () => {
|
|
914
996
|
|
915
997
|
it('works as expected when httpResponse is missing some headers', async () => {
|
916
998
|
roapMessage.headers = [
|
917
|
-
`x-cisco-turn-url=${
|
999
|
+
`x-cisco-turn-url=${FAKE_TURN_URL1}`, // missing headers for username and password
|
918
1000
|
];
|
919
1001
|
|
920
1002
|
const httpResponse = {mediaConnections: [{remoteSdp: JSON.stringify({roapMessage})}]};
|
@@ -930,7 +1012,7 @@ describe('TurnDiscovery', () => {
|
|
930
1012
|
assert.deepEqual(result, {
|
931
1013
|
turnServerInfo: undefined,
|
932
1014
|
turnDiscoverySkippedReason:
|
933
|
-
'failure: TURN_DISCOVERY_RESPONSE in http response missing some headers: ["x-cisco-turn-url=turns:
|
1015
|
+
'failure: TURN_DISCOVERY_RESPONSE in http response missing some headers: ["x-cisco-turn-url=turns:fakeTurnServer1.com:443?transport=tcp"]',
|
934
1016
|
});
|
935
1017
|
assert.calledOnceWithExactly(handleTurnDiscoveryResponseSpy, roapMessage, 'in http response');
|
936
1018
|
|
@@ -939,7 +1021,7 @@ describe('TurnDiscovery', () => {
|
|
939
1021
|
|
940
1022
|
it('sends OK when required', async () => {
|
941
1023
|
roapMessage.headers = [
|
942
|
-
`x-cisco-turn-url=${
|
1024
|
+
`x-cisco-turn-url=${FAKE_TURN_URL1}`,
|
943
1025
|
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
944
1026
|
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
945
1027
|
// noOkInTransaction is missing
|
@@ -951,7 +1033,7 @@ describe('TurnDiscovery', () => {
|
|
951
1033
|
|
952
1034
|
assert.deepEqual(result, {
|
953
1035
|
turnServerInfo: {
|
954
|
-
|
1036
|
+
urls: [FAKE_TURN_URL1],
|
955
1037
|
username: FAKE_TURN_USERNAME,
|
956
1038
|
password: FAKE_TURN_PASSWORD,
|
957
1039
|
},
|
@@ -982,7 +1064,7 @@ describe('TurnDiscovery', () => {
|
|
982
1064
|
mediaConnections: [
|
983
1065
|
{
|
984
1066
|
mediaId: '464ff97f-4bda-466a-ad06-3a22184a2274',
|
985
|
-
remoteSdp: `{"roapMessage": {"messageType":"TURN_DISCOVERY_RESPONSE","seq":"0","headers": ["x-cisco-turn-url=${
|
1067
|
+
remoteSdp: `{"roapMessage": {"messageType":"TURN_DISCOVERY_RESPONSE","seq":"0","headers": ["x-cisco-turn-url=${FAKE_TURN_URL1}","x-cisco-turn-username=${FAKE_TURN_USERNAME}","x-cisco-turn-password=${FAKE_TURN_PASSWORD}", "noOkInTransaction"]}}`,
|
986
1068
|
},
|
987
1069
|
],
|
988
1070
|
});
|