@webex/plugin-meetings 2.60.0-next.9 → 2.60.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 +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +2 -1
- package/dist/config.js.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/interceptors/index.d.ts +2 -0
- package/dist/interceptors/index.js +15 -0
- package/dist/interceptors/index.js.map +1 -0
- package/dist/interceptors/locusRetry.d.ts +27 -0
- package/dist/interceptors/locusRetry.js +94 -0
- package/dist/interceptors/locusRetry.js.map +1 -0
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/meeting/index.js +6 -2
- package/dist/meeting/index.js.map +1 -1
- package/dist/meetings/index.d.ts +1 -11
- package/dist/meetings/index.js +4 -3
- package/dist/meetings/index.js.map +1 -1
- package/dist/reachability/clusterReachability.d.ts +109 -0
- package/dist/reachability/clusterReachability.js +357 -0
- package/dist/reachability/clusterReachability.js.map +1 -0
- package/dist/reachability/index.d.ts +32 -121
- package/dist/reachability/index.js +173 -459
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/util.d.ts +8 -0
- package/dist/reachability/util.js +29 -0
- package/dist/reachability/util.js.map +1 -0
- package/dist/statsAnalyzer/index.d.ts +22 -0
- package/dist/statsAnalyzer/index.js +60 -0
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +4 -0
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/webinar/index.js +1 -1
- package/package.json +25 -22
- package/src/config.ts +1 -0
- package/src/index.ts +4 -0
- package/src/interceptors/index.ts +3 -0
- package/src/interceptors/locusRetry.ts +67 -0
- package/src/meeting/index.ts +10 -2
- package/src/meetings/index.ts +4 -3
- package/src/reachability/clusterReachability.ts +320 -0
- package/src/reachability/index.ts +124 -421
- package/src/reachability/util.ts +24 -0
- package/src/statsAnalyzer/index.ts +64 -1
- package/src/statsAnalyzer/mqaUtil.ts +4 -0
- package/test/unit/spec/interceptors/locusRetry.ts +131 -0
- package/test/unit/spec/meeting/index.js +8 -1
- package/test/unit/spec/meetings/index.js +28 -25
- package/test/unit/spec/reachability/clusterReachability.ts +279 -0
- package/test/unit/spec/reachability/index.ts +159 -226
- package/test/unit/spec/reachability/util.ts +40 -0
- package/test/unit/spec/roap/request.ts +26 -3
- package/test/unit/spec/stats-analyzer/index.js +100 -20
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {assert} from '@webex/test-helper-chai';
|
|
2
2
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
3
3
|
import sinon from 'sinon';
|
|
4
|
-
import Reachability, {
|
|
4
|
+
import Reachability, {ReachabilityResults, ReachabilityResultsForBackend} from '@webex/plugin-meetings/src/reachability/';
|
|
5
5
|
import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
|
|
6
|
+
import * as ClusterReachabilityModule from '@webex/plugin-meetings/src/reachability/clusterReachability';
|
|
6
7
|
|
|
7
8
|
import { IP_VERSION } from '@webex/plugin-meetings/src/constants';
|
|
8
9
|
|
|
@@ -35,19 +36,19 @@ describe('isAnyPublicClusterReachable', () => {
|
|
|
35
36
|
};
|
|
36
37
|
|
|
37
38
|
it('returns true when udp is reachable', async () => {
|
|
38
|
-
await checkIsClusterReachable({x: {udp: {
|
|
39
|
+
await checkIsClusterReachable({x: {udp: {result: 'reachable'}, tcp: {result: 'unreachable'}}}, true);
|
|
39
40
|
});
|
|
40
41
|
|
|
41
42
|
it('returns true when tcp is reachable', async () => {
|
|
42
|
-
await checkIsClusterReachable({x: {udp: {
|
|
43
|
+
await checkIsClusterReachable({x: {udp: {result: 'unreachable'}, tcp: {result: 'reachable'}}}, true);
|
|
43
44
|
});
|
|
44
45
|
|
|
45
46
|
it('returns true when both tcp and udp are reachable', async () => {
|
|
46
|
-
await checkIsClusterReachable({x: {udp: {
|
|
47
|
+
await checkIsClusterReachable({x: {udp: {result: 'reachable'}, tcp: {result: 'reachable'}}}, true);
|
|
47
48
|
});
|
|
48
49
|
|
|
49
50
|
it('returns false when both tcp and udp are unreachable', async () => {
|
|
50
|
-
await checkIsClusterReachable({x: {udp: {
|
|
51
|
+
await checkIsClusterReachable({x: {udp: {result: 'unreachable'}, tcp: {result: 'unreachable'}}}, false);
|
|
51
52
|
});
|
|
52
53
|
|
|
53
54
|
it('returns false when reachability result is empty', async () => {
|
|
@@ -62,13 +63,13 @@ describe('isAnyPublicClusterReachable', () => {
|
|
|
62
63
|
it('returns false if there are no public cluster results, only video mesh', async () => {
|
|
63
64
|
await checkIsClusterReachable({
|
|
64
65
|
x: {
|
|
65
|
-
udp: {
|
|
66
|
-
tcp: {
|
|
66
|
+
udp: {result: 'reachable'},
|
|
67
|
+
tcp: {result: 'reachable'},
|
|
67
68
|
isVideoMesh: true,
|
|
68
69
|
},
|
|
69
70
|
y: {
|
|
70
|
-
udp: {
|
|
71
|
-
tcp: {
|
|
71
|
+
udp: {result: 'unreachable'},
|
|
72
|
+
tcp: {result: 'reachable'},
|
|
72
73
|
isVideoMesh: true,
|
|
73
74
|
}
|
|
74
75
|
}, false);
|
|
@@ -77,18 +78,18 @@ describe('isAnyPublicClusterReachable', () => {
|
|
|
77
78
|
it('returns false if there public cluster reachability failed, only video mesh succeeded', async () => {
|
|
78
79
|
await checkIsClusterReachable({
|
|
79
80
|
x: {
|
|
80
|
-
udp: {
|
|
81
|
-
tcp: {
|
|
81
|
+
udp: {result: 'unreachable'},
|
|
82
|
+
tcp: {result: 'reachable'},
|
|
82
83
|
isVideoMesh: true,
|
|
83
84
|
},
|
|
84
85
|
y: {
|
|
85
|
-
udp: {
|
|
86
|
-
tcp: {
|
|
86
|
+
udp: {result: 'reachable'},
|
|
87
|
+
tcp: {result: 'unreachable'},
|
|
87
88
|
isVideoMesh: true,
|
|
88
89
|
},
|
|
89
90
|
publicOne: {
|
|
90
|
-
udp: {
|
|
91
|
-
tcp: {
|
|
91
|
+
udp: {result: 'unreachable'},
|
|
92
|
+
tcp: {result: 'unreachable'},
|
|
92
93
|
isVideoMesh: false,
|
|
93
94
|
}
|
|
94
95
|
}, false);
|
|
@@ -97,18 +98,18 @@ describe('isAnyPublicClusterReachable', () => {
|
|
|
97
98
|
it('returns true if there is at least 1 public cluster result, while video mesh is not reachable', async () => {
|
|
98
99
|
await checkIsClusterReachable({
|
|
99
100
|
x: {
|
|
100
|
-
udp: {
|
|
101
|
-
tcp: {
|
|
101
|
+
udp: {result: 'reachable'},
|
|
102
|
+
tcp: {result: 'reachable'},
|
|
102
103
|
isVideoMesh: true,
|
|
103
104
|
},
|
|
104
105
|
y: {
|
|
105
|
-
udp: {
|
|
106
|
-
tcp: {
|
|
106
|
+
udp: {result: 'unreachable'},
|
|
107
|
+
tcp: {result: 'reachable'},
|
|
107
108
|
isVideoMesh: true,
|
|
108
109
|
},
|
|
109
110
|
publicOne: {
|
|
110
|
-
udp: {
|
|
111
|
-
tcp: {
|
|
111
|
+
udp: {result: 'unreachable'},
|
|
112
|
+
tcp: {result: 'reachable'},
|
|
112
113
|
isVideoMesh: false,
|
|
113
114
|
}
|
|
114
115
|
}, true);
|
|
@@ -129,6 +130,10 @@ describe('gatherReachability', () => {
|
|
|
129
130
|
);
|
|
130
131
|
});
|
|
131
132
|
|
|
133
|
+
afterEach(() => {
|
|
134
|
+
sinon.restore();
|
|
135
|
+
});
|
|
136
|
+
|
|
132
137
|
it('stores the reachability', async () => {
|
|
133
138
|
const reachability = new Reachability(webex);
|
|
134
139
|
|
|
@@ -145,7 +150,7 @@ describe('gatherReachability', () => {
|
|
|
145
150
|
};
|
|
146
151
|
|
|
147
152
|
reachability.reachabilityRequest.getClusters = sinon.stub().returns(getClustersResult);
|
|
148
|
-
(reachability as any).
|
|
153
|
+
(reachability as any).performReachabilityChecks = sinon.stub().returns(reachabilityResults);
|
|
149
154
|
|
|
150
155
|
const result = await reachability.gatherReachability();
|
|
151
156
|
|
|
@@ -164,161 +169,89 @@ describe('gatherReachability', () => {
|
|
|
164
169
|
assert.equal(JSON.stringify(getClustersResult.joinCookie), storedResultForJoinCookie);
|
|
165
170
|
});
|
|
166
171
|
|
|
167
|
-
it('
|
|
168
|
-
|
|
172
|
+
it('starts ClusterReachability on each media cluster', async () => {
|
|
173
|
+
webex.config.meetings.experimental = {enableTcpReachability: true};
|
|
169
174
|
|
|
170
175
|
const getClustersResult = {
|
|
171
|
-
clusters: {
|
|
172
|
-
|
|
173
|
-
'
|
|
174
|
-
'
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
176
|
+
clusters: {
|
|
177
|
+
'cluster 1': {
|
|
178
|
+
udp: ['udp1.1', 'udp1.2'],
|
|
179
|
+
tcp: ['tcp1.1', 'tcp1.2'],
|
|
180
|
+
xtls: ['xtls1.1', 'xtls1.2'],
|
|
181
|
+
isVideoMesh: false,
|
|
182
|
+
},
|
|
183
|
+
'cluster 2': {
|
|
184
|
+
udp: ['udp2.1', 'udp2.2'],
|
|
185
|
+
tcp: ['tcp2.1', 'tcp2.2'],
|
|
186
|
+
xtls: ['xtls2.1', 'xtls2.2'],
|
|
187
|
+
isVideoMesh: true,
|
|
188
|
+
},
|
|
189
|
+
},
|
|
185
190
|
joinCookie: {id: 'id'},
|
|
186
191
|
};
|
|
187
192
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const createPeerConnectionStub = sinon.stub(reachability, 'createPeerConnection');
|
|
193
|
+
const reachability = new Reachability(webex);
|
|
191
194
|
|
|
192
|
-
|
|
195
|
+
reachability.reachabilityRequest.getClusters = sinon.stub().returns(getClustersResult);
|
|
193
196
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
username: '',
|
|
201
|
-
credential: '',
|
|
202
|
-
urls: ['stun:170.72.164.3:5004'],
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
username: '',
|
|
206
|
-
credential: '',
|
|
207
|
-
urls: ['stun:170.72.164.3:9000'],
|
|
208
|
-
}
|
|
209
|
-
],
|
|
210
|
-
iceCandidatePoolSize: '0',
|
|
211
|
-
iceTransportPolicy: 'all'
|
|
212
|
-
}
|
|
213
|
-
})
|
|
214
|
-
});
|
|
197
|
+
const startStub = sinon.stub().resolves({});
|
|
198
|
+
const clusterReachabilityCtorStub = sinon
|
|
199
|
+
.stub(ClusterReachabilityModule, 'ClusterReachability')
|
|
200
|
+
.callsFake(() => ({
|
|
201
|
+
start: startStub,
|
|
202
|
+
}));
|
|
215
203
|
|
|
216
|
-
|
|
217
|
-
let testingClass: TestReachability;
|
|
204
|
+
await reachability.gatherReachability();
|
|
218
205
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
beforeEach(() => {
|
|
228
|
-
testingClass = new TestReachability({webex});
|
|
206
|
+
assert.calledTwice(clusterReachabilityCtorStub);
|
|
207
|
+
assert.calledWith(clusterReachabilityCtorStub, 'cluster 1', {
|
|
208
|
+
udp: ['udp1.1', 'udp1.2'],
|
|
209
|
+
tcp: ['tcp1.1', 'tcp1.2'],
|
|
210
|
+
xtls: ['xtls1.1', 'xtls1.2'],
|
|
211
|
+
isVideoMesh: false,
|
|
229
212
|
});
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
elapsed: '12312',
|
|
236
|
-
publicIPs: ['1.1.1.1'],
|
|
237
|
-
isVideoMesh: true,
|
|
238
|
-
},
|
|
239
|
-
{
|
|
240
|
-
clusterId: 'id2',
|
|
241
|
-
elapsed: null,
|
|
242
|
-
publicIPs: ['1.1.1.1'],
|
|
243
|
-
isVideoMesh: false,
|
|
244
|
-
},
|
|
245
|
-
{
|
|
246
|
-
clusterId: 'id2',
|
|
247
|
-
elapsed: '14123',
|
|
248
|
-
publicIPs: undefined,
|
|
249
|
-
isVideoMesh: false,
|
|
250
|
-
},
|
|
251
|
-
]);
|
|
252
|
-
|
|
253
|
-
assert.deepEqual(res, {
|
|
254
|
-
id1: {
|
|
255
|
-
tcp: {
|
|
256
|
-
untested: 'true',
|
|
257
|
-
},
|
|
258
|
-
xtls: {
|
|
259
|
-
untested: 'true',
|
|
260
|
-
},
|
|
261
|
-
udp: {
|
|
262
|
-
clientMediaIPs: ['1.1.1.1'],
|
|
263
|
-
latencyInMilliseconds: '12312',
|
|
264
|
-
reachable: 'true',
|
|
265
|
-
},
|
|
266
|
-
isVideoMesh: true,
|
|
267
|
-
},
|
|
268
|
-
id2: {
|
|
269
|
-
xtls: {
|
|
270
|
-
untested: 'true',
|
|
271
|
-
},
|
|
272
|
-
tcp: {
|
|
273
|
-
untested: 'true',
|
|
274
|
-
},
|
|
275
|
-
udp: {
|
|
276
|
-
latencyInMilliseconds: '14123',
|
|
277
|
-
reachable: 'true',
|
|
278
|
-
},
|
|
279
|
-
isVideoMesh: false,
|
|
280
|
-
},
|
|
281
|
-
});
|
|
213
|
+
assert.calledWith(clusterReachabilityCtorStub, 'cluster 2', {
|
|
214
|
+
udp: ['udp2.1', 'udp2.2'],
|
|
215
|
+
tcp: ['tcp2.1', 'tcp2.2'],
|
|
216
|
+
xtls: ['xtls2.1', 'xtls2.2'],
|
|
217
|
+
isVideoMesh: true,
|
|
282
218
|
});
|
|
283
219
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
connectionState: 'not_closed',
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
testingClass.testAddPublicIP(peerConnection as RTCPeerConnection, '1.1.1.1');
|
|
220
|
+
assert.calledTwice(startStub);
|
|
221
|
+
});
|
|
290
222
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
publicIPs: ['1.1.1.1'],
|
|
294
|
-
});
|
|
295
|
-
});
|
|
223
|
+
it('does not do TCP reachability if it is disabled in config', async () => {
|
|
224
|
+
webex.config.meetings.experimental = {enableTcpReachability: false};
|
|
296
225
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
226
|
+
const getClustersResult = {
|
|
227
|
+
clusters: {
|
|
228
|
+
'cluster name': {
|
|
229
|
+
udp: ['testUDP1', 'testUDP2'],
|
|
230
|
+
tcp: ['testTCP1', 'testTCP2'],
|
|
231
|
+
xtls: ['testXTLS1', 'testXTLS2'],
|
|
232
|
+
isVideoMesh: false,
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
joinCookie: {id: 'id'},
|
|
236
|
+
};
|
|
302
237
|
|
|
303
|
-
|
|
238
|
+
const reachability = new Reachability(webex);
|
|
304
239
|
|
|
305
|
-
|
|
306
|
-
connectionState: 'not_closed',
|
|
307
|
-
publicIPs: ['2.2.2.2', '1.1.1.1'],
|
|
308
|
-
});
|
|
309
|
-
});
|
|
240
|
+
reachability.reachabilityRequest.getClusters = sinon.stub().returns(getClustersResult);
|
|
310
241
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
242
|
+
const clusterReachabilityCtorStub = sinon
|
|
243
|
+
.stub(ClusterReachabilityModule, 'ClusterReachability')
|
|
244
|
+
.callsFake(() => ({
|
|
245
|
+
start: sinon.stub().resolves({}),
|
|
246
|
+
}));
|
|
315
247
|
|
|
316
|
-
|
|
248
|
+
await reachability.gatherReachability();
|
|
317
249
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
250
|
+
assert.calledOnceWithExactly(clusterReachabilityCtorStub, 'cluster name', {
|
|
251
|
+
isVideoMesh: false,
|
|
252
|
+
udp: ['testUDP1', 'testUDP2'],
|
|
253
|
+
tcp: [], // empty list because TCP is disabled in config
|
|
254
|
+
xtls: ['testXTLS1', 'testXTLS2'],
|
|
322
255
|
});
|
|
323
256
|
});
|
|
324
257
|
});
|
|
@@ -334,7 +267,7 @@ describe('getReachabilityResults', () => {
|
|
|
334
267
|
sinon.restore();
|
|
335
268
|
});
|
|
336
269
|
|
|
337
|
-
const runCheck = async (mockStorage: any, expectedResult:
|
|
270
|
+
const runCheck = async (mockStorage: any, expectedResult: ReachabilityResultsForBackend) => {
|
|
338
271
|
if (mockStorage) {
|
|
339
272
|
await webex.boundedStorage.put(
|
|
340
273
|
'Reachability',
|
|
@@ -359,36 +292,36 @@ describe('getReachabilityResults', () => {
|
|
|
359
292
|
assert.isUndefined(result);
|
|
360
293
|
});
|
|
361
294
|
|
|
362
|
-
it('returns results from local storage,
|
|
295
|
+
it('returns results from local storage, converted to the backend data format', async () => {
|
|
363
296
|
await runCheck(
|
|
364
297
|
// mock storage:
|
|
365
298
|
{
|
|
366
299
|
cluster1: {
|
|
367
|
-
udp: {
|
|
368
|
-
tcp: {
|
|
369
|
-
xtls: {
|
|
300
|
+
udp: {result: 'reachable', latencyInMilliseconds: 100},
|
|
301
|
+
tcp: {result: 'unreachable'},
|
|
302
|
+
xtls: {result: 'untested'},
|
|
370
303
|
},
|
|
371
304
|
cluster2: {
|
|
372
|
-
udp: {
|
|
373
|
-
tcp: {
|
|
374
|
-
xtls: {
|
|
305
|
+
udp: {result: 'reachable', latencyInMilliseconds: 200},
|
|
306
|
+
tcp: {result: 'unreachable'},
|
|
307
|
+
xtls: {result: 'untested'},
|
|
375
308
|
isVideoMesh: true,
|
|
376
309
|
},
|
|
377
310
|
cluster3: {
|
|
378
|
-
udp: {
|
|
379
|
-
tcp: {
|
|
380
|
-
xtls: {
|
|
311
|
+
udp: {result: 'unreachable'},
|
|
312
|
+
tcp: {result: 'reachable', latencyInMilliseconds: 100, clientMediaIPs: ['10.10.10.10']},
|
|
313
|
+
xtls: {result: 'untested'},
|
|
381
314
|
isVideoMesh: true,
|
|
382
315
|
someOtherField: 'any value',
|
|
383
316
|
},
|
|
384
317
|
cluster4: {
|
|
385
|
-
udp: {
|
|
386
|
-
tcp: {
|
|
387
|
-
xtls: {
|
|
318
|
+
udp: {result: 'reachable', latencyInMilliseconds: 300},
|
|
319
|
+
tcp: {result: 'untested'},
|
|
320
|
+
xtls: {result: 'untested'},
|
|
388
321
|
someOtherField: 'any value',
|
|
389
322
|
},
|
|
390
323
|
},
|
|
391
|
-
// expected result (same as above, but with isVideoMesh and someOtherField stripped out):
|
|
324
|
+
// expected result (same as above, but with values converted and isVideoMesh and someOtherField stripped out):
|
|
392
325
|
{
|
|
393
326
|
cluster1: {
|
|
394
327
|
udp: {reachable: 'true', latencyInMilliseconds: '100'},
|
|
@@ -406,8 +339,8 @@ describe('getReachabilityResults', () => {
|
|
|
406
339
|
xtls: {untested: 'true'},
|
|
407
340
|
},
|
|
408
341
|
cluster4: {
|
|
409
|
-
udp: {reachable: '
|
|
410
|
-
tcp: {
|
|
342
|
+
udp: {reachable: 'true', latencyInMilliseconds: '300'},
|
|
343
|
+
tcp: {untested: 'true'},
|
|
411
344
|
xtls: {untested: 'true'},
|
|
412
345
|
},
|
|
413
346
|
}
|
|
@@ -464,47 +397,47 @@ describe('getReachabilityMetrics', () => {
|
|
|
464
397
|
// mock storage:
|
|
465
398
|
{
|
|
466
399
|
public1: {
|
|
467
|
-
udp: {
|
|
468
|
-
tcp: {
|
|
469
|
-
xtls: {
|
|
400
|
+
udp: {result: 'reachable', latencyInMilliseconds: 100},
|
|
401
|
+
tcp: {result: 'untested'},
|
|
402
|
+
xtls: {result: 'untested'},
|
|
470
403
|
},
|
|
471
404
|
vmn1: {
|
|
472
|
-
udp: {
|
|
473
|
-
tcp: {
|
|
474
|
-
xtls: {
|
|
405
|
+
udp: {result: 'reachable', latencyInMilliseconds: 200},
|
|
406
|
+
tcp: {result: 'unreachable'},
|
|
407
|
+
xtls: {result: 'untested'},
|
|
475
408
|
isVideoMesh: true,
|
|
476
409
|
},
|
|
477
410
|
vmn2: {
|
|
478
|
-
udp: {
|
|
479
|
-
tcp: {
|
|
480
|
-
xtls: {
|
|
411
|
+
udp: {result: 'untested'},
|
|
412
|
+
tcp: {result: 'reachable', latencyInMilliseconds: 100, clientMediaIPs: ['10.10.10.10']},
|
|
413
|
+
xtls: {result: 'untested'},
|
|
481
414
|
isVideoMesh: true,
|
|
482
415
|
someOtherField: 'any value',
|
|
483
416
|
},
|
|
484
417
|
public2: {
|
|
485
|
-
udp: {
|
|
486
|
-
tcp: {
|
|
487
|
-
xtls: {
|
|
418
|
+
udp: {result: 'unreachable'},
|
|
419
|
+
tcp: {result: 'unreachable'},
|
|
420
|
+
xtls: {result: 'untested'},
|
|
488
421
|
someOtherField: 'any value',
|
|
489
422
|
},
|
|
490
423
|
public3: {
|
|
491
|
-
udp: {
|
|
492
|
-
tcp: {
|
|
493
|
-
xtls: {
|
|
424
|
+
udp: {result: 'reachable', latencyInMilliseconds: 400, clientMediaIPs: ['10.10.10.10']},
|
|
425
|
+
tcp: {result: 'reachable', latencyInMilliseconds: 100, clientMediaIPs: ['10.10.10.10']},
|
|
426
|
+
xtls: {result: 'untested'},
|
|
494
427
|
isVideoMesh: false,
|
|
495
428
|
someOtherField: 'any value',
|
|
496
429
|
},
|
|
497
430
|
public4: {
|
|
498
|
-
udp: {
|
|
499
|
-
tcp: {
|
|
500
|
-
xtls: {
|
|
431
|
+
udp: {result: 'reachable', latencyInMilliseconds: 40, clientMediaIPs: ['10.10.10.11']},
|
|
432
|
+
tcp: {result: 'reachable', latencyInMilliseconds: 100, clientMediaIPs: ['10.10.10.11']},
|
|
433
|
+
xtls: {result: 'untested'},
|
|
501
434
|
isVideoMesh: false,
|
|
502
435
|
someOtherField: 'any value',
|
|
503
436
|
},
|
|
504
437
|
public5: {
|
|
505
|
-
udp: {
|
|
506
|
-
tcp: {
|
|
507
|
-
xtls: {
|
|
438
|
+
udp: {result: 'unreachable'},
|
|
439
|
+
tcp: {result: 'untested'},
|
|
440
|
+
xtls: {result: 'untested'},
|
|
508
441
|
isVideoMesh: false,
|
|
509
442
|
someOtherField: 'any value',
|
|
510
443
|
},
|
|
@@ -528,33 +461,33 @@ describe('getReachabilityMetrics', () => {
|
|
|
528
461
|
// mock storage:
|
|
529
462
|
{
|
|
530
463
|
public1: {
|
|
531
|
-
udp: {
|
|
532
|
-
tcp: {
|
|
533
|
-
xtls: {
|
|
464
|
+
udp: {result: 'reachable', latencyInMilliseconds: 400, clientMediaIPs: ['10.10.10.10']},
|
|
465
|
+
tcp: {result: 'reachable', latencyInMilliseconds: 100, clientMediaIPs: ['10.10.10.10']},
|
|
466
|
+
xtls: {result: 'untested'},
|
|
534
467
|
isVideoMesh: false,
|
|
535
468
|
},
|
|
536
469
|
public2: {
|
|
537
|
-
udp: {
|
|
538
|
-
tcp: {
|
|
539
|
-
xtls: {
|
|
470
|
+
udp: {result: 'reachable', latencyInMilliseconds: 100},
|
|
471
|
+
tcp: {result: 'untested'},
|
|
472
|
+
xtls: {result: 'untested'},
|
|
540
473
|
},
|
|
541
474
|
public3: {
|
|
542
|
-
udp: {
|
|
543
|
-
tcp: {
|
|
544
|
-
xtls: {
|
|
475
|
+
udp: {result: 'unreachable'},
|
|
476
|
+
tcp: {result: 'unreachable'},
|
|
477
|
+
xtls: {result: 'untested'},
|
|
545
478
|
someOtherField: 'any value',
|
|
546
479
|
},
|
|
547
480
|
public4: {
|
|
548
|
-
udp: {
|
|
549
|
-
tcp: {
|
|
550
|
-
xtls: {
|
|
481
|
+
udp: {result: 'untested'},
|
|
482
|
+
tcp: {result: 'unreachable'},
|
|
483
|
+
xtls: {result: 'untested'},
|
|
551
484
|
isVideoMesh: false,
|
|
552
485
|
someOtherField: 'any value',
|
|
553
486
|
},
|
|
554
487
|
public5: {
|
|
555
|
-
udp: {
|
|
556
|
-
tcp: {
|
|
557
|
-
xtls: {
|
|
488
|
+
udp: {result: 'reachable', latencyInMilliseconds: '400', clientMediaIPs: ['10.10.10.10']},
|
|
489
|
+
tcp: {result: 'untested'},
|
|
490
|
+
xtls: {result: 'untested'},
|
|
558
491
|
},
|
|
559
492
|
},
|
|
560
493
|
// expected result:
|
|
@@ -576,34 +509,34 @@ describe('getReachabilityMetrics', () => {
|
|
|
576
509
|
// mock storage:
|
|
577
510
|
{
|
|
578
511
|
vmn1: {
|
|
579
|
-
udp: {
|
|
580
|
-
tcp: {
|
|
581
|
-
xtls: {
|
|
512
|
+
udp: {result: 'unreachable'},
|
|
513
|
+
tcp: {result: 'reachable', latencyInMilliseconds: 100, clientMediaIPs: ['10.10.10.10']},
|
|
514
|
+
xtls: {result: 'untested'},
|
|
582
515
|
isVideoMesh: true,
|
|
583
516
|
},
|
|
584
517
|
vmn2: {
|
|
585
|
-
udp: {
|
|
586
|
-
tcp: {
|
|
587
|
-
xtls: {
|
|
518
|
+
udp: {result: 'reachable', latencyInMilliseconds: 200, clientMediaIPs: ['10.10.10.10']},
|
|
519
|
+
tcp: {result: 'untested'},
|
|
520
|
+
xtls: {result: 'untested'},
|
|
588
521
|
isVideoMesh: true,
|
|
589
522
|
},
|
|
590
523
|
vmn3: {
|
|
591
|
-
udp: {
|
|
592
|
-
tcp: {
|
|
593
|
-
xtls: {
|
|
524
|
+
udp: {result: 'reachable', latencyInMilliseconds: 300, clientMediaIPs: ['10.10.10.10']},
|
|
525
|
+
tcp: {result: 'unreachable'},
|
|
526
|
+
xtls: {result: 'untested'},
|
|
594
527
|
isVideoMesh: true,
|
|
595
528
|
},
|
|
596
529
|
vmn4: {
|
|
597
|
-
udp: {
|
|
598
|
-
tcp: {
|
|
599
|
-
xtls: {
|
|
530
|
+
udp: {result: 'untested'},
|
|
531
|
+
tcp: {result: 'unreachable'},
|
|
532
|
+
xtls: {result: 'untested'},
|
|
600
533
|
isVideoMesh: true,
|
|
601
534
|
someOtherField: 'any value',
|
|
602
535
|
},
|
|
603
536
|
vmn5: {
|
|
604
|
-
udp: {
|
|
605
|
-
tcp: {
|
|
606
|
-
xtls: {
|
|
537
|
+
udp: {result: 'reachable', latencyInMilliseconds: 200, clientMediaIPs: ['10.10.10.10']},
|
|
538
|
+
tcp: {result: 'unreachable'},
|
|
539
|
+
xtls: {result: 'untested'},
|
|
607
540
|
isVideoMesh: true,
|
|
608
541
|
someOtherField: 'any value',
|
|
609
542
|
},
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {assert} from '@webex/test-helper-chai';
|
|
2
|
+
|
|
3
|
+
import {convertStunUrlToTurn} from '@webex/plugin-meetings/src/reachability/util';
|
|
4
|
+
|
|
5
|
+
describe('plugin-meetings/src/reachability/util', () => {
|
|
6
|
+
describe('#convertStunUrlToTurn()', () => {
|
|
7
|
+
[
|
|
8
|
+
{
|
|
9
|
+
title: 'a stun url with port',
|
|
10
|
+
stunUrl: 'stun:external-media91.public.wjfkm-a-10.prod.infra.webex.com:5004',
|
|
11
|
+
expectedUrlPart: 'external-media91.public.wjfkm-a-10.prod.infra.webex.com:5004',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
title: 'a stun url without port',
|
|
15
|
+
stunUrl: 'stun:something.somewhere.com',
|
|
16
|
+
expectedUrlPart: 'something.somewhere.com',
|
|
17
|
+
},
|
|
18
|
+
].forEach(({title, stunUrl, expectedUrlPart}) => {
|
|
19
|
+
it(`should convert ${title} to a TCP turn url`, () => {
|
|
20
|
+
const turnUrl = convertStunUrlToTurn(stunUrl, 'tcp');
|
|
21
|
+
|
|
22
|
+
assert.equal(turnUrl, `turn:${expectedUrlPart}?transport=tcp`);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it(`should convert ${title} to a UDP turn url`, () => {
|
|
26
|
+
const turnUrl = convertStunUrlToTurn(stunUrl, 'udp');
|
|
27
|
+
|
|
28
|
+
assert.equal(turnUrl, `turn:${expectedUrlPart}`);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('show fail if stunUrl is not a valid url', () => {
|
|
33
|
+
assert.throws(() => convertStunUrlToTurn('not a url', 'tcp'), 'Invalid URL: not a url');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('show fail if stunUrl is not a STUN url', () => {
|
|
37
|
+
assert.throws(() => convertStunUrlToTurn('http://webex.com', 'tcp'), 'Not a STUN URL: http://webex.com');
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
});
|