@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.
Files changed (55) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/config.d.ts +1 -0
  4. package/dist/config.js +2 -1
  5. package/dist/config.js.map +1 -1
  6. package/dist/index.js +5 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/interceptors/index.d.ts +2 -0
  9. package/dist/interceptors/index.js +15 -0
  10. package/dist/interceptors/index.js.map +1 -0
  11. package/dist/interceptors/locusRetry.d.ts +27 -0
  12. package/dist/interceptors/locusRetry.js +94 -0
  13. package/dist/interceptors/locusRetry.js.map +1 -0
  14. package/dist/interpretation/index.js +1 -1
  15. package/dist/interpretation/siLanguage.js +1 -1
  16. package/dist/meeting/index.js +6 -2
  17. package/dist/meeting/index.js.map +1 -1
  18. package/dist/meetings/index.d.ts +1 -11
  19. package/dist/meetings/index.js +4 -3
  20. package/dist/meetings/index.js.map +1 -1
  21. package/dist/reachability/clusterReachability.d.ts +109 -0
  22. package/dist/reachability/clusterReachability.js +357 -0
  23. package/dist/reachability/clusterReachability.js.map +1 -0
  24. package/dist/reachability/index.d.ts +32 -121
  25. package/dist/reachability/index.js +173 -459
  26. package/dist/reachability/index.js.map +1 -1
  27. package/dist/reachability/util.d.ts +8 -0
  28. package/dist/reachability/util.js +29 -0
  29. package/dist/reachability/util.js.map +1 -0
  30. package/dist/statsAnalyzer/index.d.ts +22 -0
  31. package/dist/statsAnalyzer/index.js +60 -0
  32. package/dist/statsAnalyzer/index.js.map +1 -1
  33. package/dist/statsAnalyzer/mqaUtil.js +4 -0
  34. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  35. package/dist/webinar/index.js +1 -1
  36. package/package.json +25 -22
  37. package/src/config.ts +1 -0
  38. package/src/index.ts +4 -0
  39. package/src/interceptors/index.ts +3 -0
  40. package/src/interceptors/locusRetry.ts +67 -0
  41. package/src/meeting/index.ts +10 -2
  42. package/src/meetings/index.ts +4 -3
  43. package/src/reachability/clusterReachability.ts +320 -0
  44. package/src/reachability/index.ts +124 -421
  45. package/src/reachability/util.ts +24 -0
  46. package/src/statsAnalyzer/index.ts +64 -1
  47. package/src/statsAnalyzer/mqaUtil.ts +4 -0
  48. package/test/unit/spec/interceptors/locusRetry.ts +131 -0
  49. package/test/unit/spec/meeting/index.js +8 -1
  50. package/test/unit/spec/meetings/index.js +28 -25
  51. package/test/unit/spec/reachability/clusterReachability.ts +279 -0
  52. package/test/unit/spec/reachability/index.ts +159 -226
  53. package/test/unit/spec/reachability/util.ts +40 -0
  54. package/test/unit/spec/roap/request.ts +26 -3
  55. package/test/unit/spec/stats-analyzer/index.js +100 -20
@@ -9,11 +9,10 @@ exports.default = void 0;
9
9
  var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator"));
10
10
  var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
11
11
  var _values = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/values"));
12
- var _now = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/date/now"));
12
+ var _entries = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/entries"));
13
13
  var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys"));
14
14
  var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
15
- var _assign = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/assign"));
16
- var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/toConsumableArray"));
15
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/slicedToArray"));
17
16
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/asyncToGenerator"));
18
17
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));
19
18
  var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
@@ -23,22 +22,16 @@ var _loggerProxy = _interopRequireDefault(require("../common/logs/logger-proxy")
23
22
  var _util = _interopRequireDefault(require("../meeting/util"));
24
23
  var _constants = require("../constants");
25
24
  var _request = _interopRequireDefault(require("./request"));
25
+ var _clusterReachability = require("./clusterReachability");
26
26
  /*!
27
27
  * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
28
28
  */
29
-
30
29
  /* eslint-disable class-methods-use-this */
31
- /* globals window */
32
-
33
- var DEFAULT_TIMEOUT = 3000;
34
- var VIDEO_MESH_TIMEOUT = 1000;
35
-
36
- // result for a specific transport protocol (like udp or tcp)
37
-
38
- // reachability result for a specifc media cluster
39
-
30
+ /**
31
+ * This is the type that matches what backend expects us to send to them. It is a bit weird, because
32
+ * it uses strings instead of booleans and numbers, but that's what they require.
33
+ */
40
34
  // this is the type that is required by the backend when we send them reachability results
41
-
42
35
  // this is the type used by Reachability class internally and stored in local storage
43
36
  /**
44
37
  * @class Reachability
@@ -55,7 +48,7 @@ var Reachability = exports.default = /*#__PURE__*/function () {
55
48
  (0, _defineProperty2.default)(this, "namespace", _constants.REACHABILITY.namespace);
56
49
  (0, _defineProperty2.default)(this, "webex", void 0);
57
50
  (0, _defineProperty2.default)(this, "reachabilityRequest", void 0);
58
- (0, _defineProperty2.default)(this, "clusterLatencyResults", void 0);
51
+ (0, _defineProperty2.default)(this, "clusterReachability", void 0);
59
52
  this.webex = webex;
60
53
 
61
54
  /**
@@ -66,22 +59,13 @@ var Reachability = exports.default = /*#__PURE__*/function () {
66
59
  * @memberof Reachability
67
60
  */
68
61
  this.reachabilityRequest = new _request.default(this.webex);
69
-
70
- /**
71
- * internal object of clusters latency results
72
- * @instance
73
- * @type {object}
74
- * @private
75
- * @memberof Reachability
76
- */
77
- this.clusterLatencyResults = {};
62
+ this.clusterReachability = {};
78
63
  }
79
64
 
80
65
  /**
81
- * fetches reachability data
82
- * @returns {Object} reachability data
66
+ * Gets a list of media clusters from the backend and performs reachability checks on all the clusters
67
+ * @returns {Promise<ReachabilityResults>} reachability results
83
68
  * @public
84
- * @async
85
69
  * @memberof Reachability
86
70
  */
87
71
  (0, _createClass2.default)(Reachability, [{
@@ -92,45 +76,41 @@ var Reachability = exports.default = /*#__PURE__*/function () {
92
76
  return _regenerator.default.wrap(function _callee$(_context) {
93
77
  while (1) switch (_context.prev = _context.next) {
94
78
  case 0:
95
- this.setup();
96
-
97
- // Remove stored reachability results to ensure no stale data
98
- // @ts-ignore
99
- _context.next = 3;
79
+ _context.next = 2;
100
80
  return this.webex.boundedStorage.del(this.namespace, _constants.REACHABILITY.localStorageResult);
101
- case 3:
102
- _context.next = 5;
81
+ case 2:
82
+ _context.next = 4;
103
83
  return this.webex.boundedStorage.del(this.namespace, _constants.REACHABILITY.localStorageJoinCookie);
104
- case 5:
105
- _context.prev = 5;
106
- _context.next = 8;
84
+ case 4:
85
+ _context.prev = 4;
86
+ _context.next = 7;
107
87
  return this.reachabilityRequest.getClusters(_util.default.getIpVersion(this.webex));
108
- case 8:
88
+ case 7:
109
89
  _yield$this$reachabil = _context.sent;
110
90
  clusters = _yield$this$reachabil.clusters;
111
91
  joinCookie = _yield$this$reachabil.joinCookie;
112
- _context.next = 13;
113
- return this.performReachabilityCheck(clusters);
114
- case 13:
92
+ _context.next = 12;
93
+ return this.performReachabilityChecks(clusters);
94
+ case 12:
115
95
  results = _context.sent;
116
- _context.next = 16;
96
+ _context.next = 15;
117
97
  return this.webex.boundedStorage.put(this.namespace, _constants.REACHABILITY.localStorageResult, (0, _stringify.default)(results));
118
- case 16:
119
- _context.next = 18;
98
+ case 15:
99
+ _context.next = 17;
120
100
  return this.webex.boundedStorage.put(this.namespace, _constants.REACHABILITY.localStorageJoinCookie, (0, _stringify.default)(joinCookie));
121
- case 18:
101
+ case 17:
122
102
  _loggerProxy.default.logger.log('Reachability:index#gatherReachability --> Reachability checks completed');
123
103
  return _context.abrupt("return", results);
124
- case 22:
125
- _context.prev = 22;
126
- _context.t0 = _context["catch"](5);
127
- _loggerProxy.default.logger.error("Reachability:index#gatherReachability --> Error in calling getClusters(): ".concat(_context.t0));
104
+ case 21:
105
+ _context.prev = 21;
106
+ _context.t0 = _context["catch"](4);
107
+ _loggerProxy.default.logger.error("Reachability:index#gatherReachability --> Error:", _context.t0);
128
108
  return _context.abrupt("return", {});
129
- case 26:
109
+ case 25:
130
110
  case "end":
131
111
  return _context.stop();
132
112
  }
133
- }, _callee, this, [[5, 22]]);
113
+ }, _callee, this, [[4, 21]]);
134
114
  }));
135
115
  function gatherReachability() {
136
116
  return _gatherReachability.apply(this, arguments);
@@ -148,7 +128,7 @@ var Reachability = exports.default = /*#__PURE__*/function () {
148
128
  key: "getReachabilityMetrics",
149
129
  value: (function () {
150
130
  var _getReachabilityMetrics = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
151
- var stats, updateStats, resultsJson, internalResults;
131
+ var stats, updateStats, resultsJson, results;
152
132
  return _regenerator.default.wrap(function _callee2$(_context2) {
153
133
  while (1) switch (_context2.prev = _context2.next) {
154
134
  case 0:
@@ -163,13 +143,12 @@ var Reachability = exports.default = /*#__PURE__*/function () {
163
143
  reachability_vmn_tcp_failed: 0
164
144
  };
165
145
  updateStats = function updateStats(clusterType, result) {
166
- var _result$udp, _result$tcp;
167
- if ((_result$udp = result.udp) !== null && _result$udp !== void 0 && _result$udp.reachable) {
168
- var outcome = result.udp.reachable === 'true' ? 'success' : 'failed';
146
+ if (result.udp && result.udp.result !== 'untested') {
147
+ var outcome = result.udp.result === 'reachable' ? 'success' : 'failed';
169
148
  stats["reachability_".concat(clusterType, "_udp_").concat(outcome)] += 1;
170
149
  }
171
- if ((_result$tcp = result.tcp) !== null && _result$tcp !== void 0 && _result$tcp.reachable) {
172
- var _outcome = result.tcp.reachable === 'true' ? 'success' : 'failed';
150
+ if (result.tcp && result.tcp.result !== 'untested') {
151
+ var _outcome = result.tcp.result === 'reachable' ? 'success' : 'failed';
173
152
  stats["reachability_".concat(clusterType, "_tcp_").concat(_outcome)] += 1;
174
153
  }
175
154
  };
@@ -178,8 +157,8 @@ var Reachability = exports.default = /*#__PURE__*/function () {
178
157
  return this.webex.boundedStorage.get(_constants.REACHABILITY.namespace, _constants.REACHABILITY.localStorageResult);
179
158
  case 5:
180
159
  resultsJson = _context2.sent;
181
- internalResults = JSON.parse(resultsJson);
182
- (0, _values.default)(internalResults).forEach(function (result) {
160
+ results = JSON.parse(resultsJson);
161
+ (0, _values.default)(results).forEach(function (result) {
183
162
  updateStats(result.isVideoMesh ? 'vmn' : 'public', result);
184
163
  });
185
164
  _context2.next = 13;
@@ -202,45 +181,91 @@ var Reachability = exports.default = /*#__PURE__*/function () {
202
181
  }
203
182
  return getReachabilityMetrics;
204
183
  }()
184
+ /**
185
+ * Maps our internal transport result to the format that backend expects
186
+ * @param {TransportResult} transportResult
187
+ * @returns {TransportResultForBackend}
188
+ */
189
+ )
190
+ }, {
191
+ key: "mapTransportResultToBackendDataFormat",
192
+ value: function mapTransportResultToBackendDataFormat(transportResult) {
193
+ var output = {};
194
+ for (var _i = 0, _Object$entries = (0, _entries.default)(transportResult); _i < _Object$entries.length; _i++) {
195
+ var _Object$entries$_i = (0, _slicedToArray2.default)(_Object$entries[_i], 2),
196
+ _key = _Object$entries$_i[0],
197
+ value = _Object$entries$_i[1];
198
+ switch (_key) {
199
+ case 'result':
200
+ switch (value) {
201
+ case 'reachable':
202
+ output.reachable = 'true';
203
+ break;
204
+ case 'unreachable':
205
+ output.reachable = 'false';
206
+ break;
207
+ case 'untested':
208
+ output.untested = 'true';
209
+ break;
210
+ }
211
+ break;
212
+ case 'latencyInMilliseconds':
213
+ output.latencyInMilliseconds = value.toString();
214
+ break;
215
+ default:
216
+ output[_key] = value;
217
+ }
218
+ }
219
+ return output;
220
+ }
221
+
205
222
  /**
206
223
  * Reachability results as an object in the format that backend expects
207
224
  *
208
225
  * @returns {any} reachability results that need to be sent to the backend
209
226
  */
210
- )
211
227
  }, {
212
228
  key: "getReachabilityResults",
213
229
  value: (function () {
214
230
  var _getReachabilityResults = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3() {
215
- var results, reachabilityResultsProps, resultsJson, internalResults;
231
+ var _this = this;
232
+ var results, resultsJson, allClusterResults;
216
233
  return _regenerator.default.wrap(function _callee3$(_context3) {
217
234
  while (1) switch (_context3.prev = _context3.next) {
218
235
  case 0:
219
- // these are the only props that backend needs in the reachability results:
220
- reachabilityResultsProps = ['udp', 'tcp', 'xtls'];
221
- _context3.prev = 1;
222
- _context3.next = 4;
236
+ _context3.prev = 0;
237
+ _context3.next = 3;
223
238
  return this.webex.boundedStorage.get(_constants.REACHABILITY.namespace, _constants.REACHABILITY.localStorageResult);
224
- case 4:
239
+ case 3:
225
240
  resultsJson = _context3.sent;
226
- internalResults = JSON.parse(resultsJson);
227
- results = (0, _lodash.mapValues)(internalResults, function (result) {
228
- return (0, _lodash.pick)(result, reachabilityResultsProps);
241
+ allClusterResults = JSON.parse(resultsJson);
242
+ results = (0, _lodash.mapValues)(allClusterResults, function (clusterResult) {
243
+ return {
244
+ udp: _this.mapTransportResultToBackendDataFormat(clusterResult.udp || {
245
+ result: 'untested'
246
+ }),
247
+ tcp: _this.mapTransportResultToBackendDataFormat(clusterResult.tcp || {
248
+ result: 'untested'
249
+ }),
250
+ xtls: _this.mapTransportResultToBackendDataFormat(clusterResult.xtls || {
251
+ result: 'untested'
252
+ })
253
+ };
229
254
  });
230
- _context3.next = 12;
255
+ _context3.next = 11;
231
256
  break;
232
- case 9:
233
- _context3.prev = 9;
234
- _context3.t0 = _context3["catch"](1);
257
+ case 8:
258
+ _context3.prev = 8;
259
+ _context3.t0 = _context3["catch"](0);
235
260
  // empty storage, that's ok
236
261
  _loggerProxy.default.logger.warn('Roap:request#attachReachabilityData --> Error parsing reachability data: ', _context3.t0);
237
- case 12:
262
+ case 11:
238
263
  return _context3.abrupt("return", results);
239
- case 13:
264
+ case 12:
240
265
  case "end":
241
266
  return _context3.stop();
242
267
  }
243
- }, _callee3, this, [[1, 9]]);
268
+ }, _callee3, this, [[0, 8]]);
244
269
  }));
245
270
  function getReachabilityResults() {
246
271
  return _getReachabilityResults.apply(this, arguments);
@@ -271,8 +296,8 @@ var Reachability = exports.default = /*#__PURE__*/function () {
271
296
  try {
272
297
  reachabilityResults = JSON.parse(reachabilityData);
273
298
  reachable = (0, _values.default)(reachabilityResults).some(function (result) {
274
- var _result$udp2, _result$tcp2;
275
- return !result.isVideoMesh && (((_result$udp2 = result.udp) === null || _result$udp2 === void 0 ? void 0 : _result$udp2.reachable) === 'true' || ((_result$tcp2 = result.tcp) === null || _result$tcp2 === void 0 ? void 0 : _result$tcp2.reachable) === 'true');
299
+ var _result$udp, _result$tcp;
300
+ return !result.isVideoMesh && (((_result$udp = result.udp) === null || _result$udp === void 0 ? void 0 : _result$udp.result) === 'reachable' || ((_result$tcp = result.tcp) === null || _result$tcp === void 0 ? void 0 : _result$tcp.result) === 'reachable');
276
301
  });
277
302
  } catch (e) {
278
303
  _loggerProxy.default.logger.error("Roap:request#attachReachabilityData --> Error in parsing reachability data: ".concat(e));
@@ -290,255 +315,36 @@ var Reachability = exports.default = /*#__PURE__*/function () {
290
315
  }
291
316
  return isAnyPublicClusterReachable;
292
317
  }()
293
- /**
294
- * Generate peerConnection config settings
295
- * @param {object} cluster
296
- * @returns {object} peerConnectionConfig
297
- * @private
298
- * @memberof Reachability
299
- */
300
- )
301
- }, {
302
- key: "buildPeerConnectionConfig",
303
- value: function buildPeerConnectionConfig(cluster) {
304
- var iceServers = (0, _lodash.uniq)(cluster.udp).map(function (url) {
305
- return {
306
- username: '',
307
- credential: '',
308
- urls: [url]
309
- };
310
- });
311
- return {
312
- iceServers: (0, _toConsumableArray2.default)(iceServers),
313
- iceCandidatePoolSize: '0',
314
- iceTransportPolicy: 'all'
315
- };
316
- }
317
-
318
- /**
319
- * Creates an RTCPeerConnection
320
- * @param {object} cluster
321
- * @returns {RTCPeerConnection} peerConnection
322
- * @private
323
- * @memberof Reachability
324
- */
325
- }, {
326
- key: "createPeerConnection",
327
- value: function createPeerConnection(cluster) {
328
- var key = cluster.key,
329
- config = cluster.config;
330
- try {
331
- var peerConnection = new window.RTCPeerConnection(config);
332
-
333
- // @ts-ignore
334
- peerConnection.key = key;
335
- return peerConnection;
336
- } catch (peerConnectionError) {
337
- _loggerProxy.default.logger.log("Reachability:index#createPeerConnection --> Error creating peerConnection: ".concat(peerConnectionError));
338
- return null;
339
- }
340
- }
341
-
342
- /**
343
- * Gets total elapsed time
344
- * @param {RTCPeerConnection} peerConnection
345
- * @returns {Number} Milliseconds
346
- * @private
347
- * @memberof Reachability
348
- */
349
- }, {
350
- key: "getElapsedTime",
351
- value: function getElapsedTime(peerConnection) {
352
- var startTime = peerConnection.begin;
353
- delete peerConnection.begin;
354
- return (0, _now.default)() - startTime;
355
- }
356
-
357
- /**
358
- * creates offer and generates localSDP
359
- * @param {object} clusterList cluster List
360
- * @returns {Promise} Reachability latency results
361
- * @private
362
- * @memberof Reachability
363
- */
364
- }, {
365
- key: "getLocalSDPForClusters",
366
- value: function getLocalSDPForClusters(clusterList) {
367
- var _this = this;
368
- var clusters = (0, _toConsumableArray2.default)((0, _keys.default)(clusterList));
369
- clusters = clusters.map( /*#__PURE__*/function () {
370
- var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee5(key) {
371
- var cluster, config, peerConnection, description;
372
- return _regenerator.default.wrap(function _callee5$(_context5) {
373
- while (1) switch (_context5.prev = _context5.next) {
374
- case 0:
375
- cluster = clusterList[key];
376
- config = _this.buildPeerConnectionConfig(cluster);
377
- peerConnection = _this.createPeerConnection({
378
- key: key,
379
- config: config
380
- });
381
- _context5.next = 5;
382
- return peerConnection.createOffer({
383
- offerToReceiveAudio: true
384
- });
385
- case 5:
386
- description = _context5.sent;
387
- // @ts-ignore
388
- peerConnection.begin = (0, _now.default)();
389
- peerConnection.setLocalDescription(description);
390
- return _context5.abrupt("return", _this.iceGatheringState(peerConnection, cluster.isVideoMesh).catch(function (iceGatheringStateError) {
391
- _loggerProxy.default.logger.log("Reachability:index#getLocalSDPForClusters --> Error in getLocalSDP : ".concat(iceGatheringStateError));
392
- }));
393
- case 9:
394
- case "end":
395
- return _context5.stop();
396
- }
397
- }, _callee5);
398
- }));
399
- return function (_x) {
400
- return _ref.apply(this, arguments);
401
- };
402
- }());
403
- return _promise.default.all(clusters).then(this.parseIceResultsToInternalReachabilityResults).then(function (reachabilityLatencyResults) {
404
- _this.logUnreachableClusters();
405
-
406
- // return results
407
- return reachabilityLatencyResults;
408
- });
409
- }
410
-
411
318
  /**
412
319
  * Get list of all unreachable clusters
413
320
  * @returns {array} Unreachable clusters
414
321
  * @private
415
322
  * @memberof Reachability
416
323
  */
324
+ )
417
325
  }, {
418
- key: "getUnreachablClusters",
419
- value: function getUnreachablClusters() {
326
+ key: "getUnreachableClusters",
327
+ value: function getUnreachableClusters() {
420
328
  var unreachableList = [];
421
- var clusters = this.clusterLatencyResults;
422
- (0, _keys.default)(clusters).forEach(function (key) {
423
- var cluster = clusters[key];
424
- if (cluster.unreachable && !cluster.reachable) {
425
- unreachableList.push(key);
426
- }
427
- });
428
- return unreachableList;
429
- }
430
-
431
- /**
432
- * Attach an event handler for the icegatheringstatechange
433
- * event and measure latency.
434
- * @param {RTCPeerConnection} peerConnection
435
- * @returns {undefined}
436
- * @private
437
- * @memberof Reachability
438
- */
439
- }, {
440
- key: "handleIceGatheringStateChange",
441
- value: function handleIceGatheringStateChange(peerConnection) {
442
- var _this2 = this;
443
- peerConnection.onicegatheringstatechange = function () {
444
- var COMPLETE = _constants.ICE_GATHERING_STATE.COMPLETE;
445
- if (peerConnection.iceConnectionState === COMPLETE) {
446
- var elapsed = _this2.getElapsedTime(peerConnection);
447
-
448
- // @ts-ignore
449
- _loggerProxy.default.logger.log( // @ts-ignore
450
- "Reachability:index#onIceGatheringStateChange --> Successfully pinged ".concat(peerConnection.key, ":"), elapsed);
451
- _this2.setLatencyAndClose(peerConnection, elapsed);
329
+ (0, _entries.default)(this.clusterReachability).forEach(function (_ref) {
330
+ var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
331
+ key = _ref2[0],
332
+ clusterReachability = _ref2[1];
333
+ var result = clusterReachability.getResult();
334
+ if (result.udp.result === 'unreachable') {
335
+ unreachableList.push({
336
+ name: key,
337
+ protocol: 'udp'
338
+ });
452
339
  }
453
- };
454
- }
455
-
456
- /**
457
- * Attach an event handler for the icecandidate
458
- * event and measure latency.
459
- * @param {RTCPeerConnection} peerConnection
460
- * @returns {undefined}
461
- * @private
462
- * @memberof Reachability
463
- */
464
- }, {
465
- key: "handleOnIceCandidate",
466
- value: function handleOnIceCandidate(peerConnection) {
467
- var _this3 = this;
468
- peerConnection.onicecandidate = function (e) {
469
- var SERVER_REFLEXIVE = 'srflx';
470
- if (e.candidate && String(e.candidate.type).toLowerCase() === SERVER_REFLEXIVE) {
471
- var elapsed = _this3.getElapsedTime(peerConnection);
472
- _loggerProxy.default.logger.log( // @ts-ignore
473
- "Reachability:index#onIceCandidate --> Successfully pinged ".concat(peerConnection.key, ":"), elapsed);
474
- // order is important
475
- _this3.addPublicIP(peerConnection, e.candidate.address);
476
- _this3.setLatencyAndClose(peerConnection, elapsed);
340
+ if (result.tcp.result === 'unreachable') {
341
+ unreachableList.push({
342
+ name: key,
343
+ protocol: 'tcp'
344
+ });
477
345
  }
478
- };
479
- }
480
-
481
- /**
482
- * An event handler on an RTCPeerConnection when the state of the ICE
483
- * candidate gathering process changes. Used to measure connection
484
- * speed.
485
- * @private
486
- * @param {RTCPeerConnection} peerConnection
487
- * @param {boolean} isVideoMesh
488
- * @returns {Promise}
489
- */
490
- }, {
491
- key: "iceGatheringState",
492
- value: function iceGatheringState(peerConnection, isVideoMesh) {
493
- var _this4 = this;
494
- var ELAPSED = 'elapsed';
495
- var timeout = isVideoMesh ? VIDEO_MESH_TIMEOUT : DEFAULT_TIMEOUT;
496
- return new _promise.default(function (resolve) {
497
- var peerConnectionProxy = new window.Proxy(peerConnection, {
498
- // eslint-disable-next-line require-jsdoc
499
- get: function get(target, property) {
500
- var targetMember = target[property];
501
- if (typeof targetMember === 'function') {
502
- return targetMember.bind(target);
503
- }
504
- return targetMember;
505
- },
506
- set: function set(target, property, value) {
507
- // only intercept elapsed property
508
- if (property === ELAPSED) {
509
- resolve({
510
- // @ts-ignore
511
- clusterId: peerConnection.key,
512
- isVideoMesh: isVideoMesh,
513
- // @ts-ignore
514
- publicIPs: target.publicIPs,
515
- elapsed: value
516
- });
517
- return true;
518
- }
519
-
520
- // pass thru
521
- return window.Reflect.set(target, property, value);
522
- }
523
- });
524
-
525
- // Using peerConnection proxy so handle functions below
526
- // won't be coupled to our promise implementation
527
- _this4.handleIceGatheringStateChange(peerConnectionProxy);
528
- _this4.handleOnIceCandidate(peerConnectionProxy);
529
-
530
- // Set maximum timeout
531
- window.setTimeout(function () {
532
- var CLOSED = _constants.CONNECTION_STATE.CLOSED;
533
-
534
- // Close any open peerConnections
535
- if (peerConnectionProxy.connectionState !== CLOSED) {
536
- // order is important
537
- _this4.addPublicIP(peerConnectionProxy, null);
538
- _this4.setLatencyAndClose(peerConnectionProxy, null);
539
- }
540
- }, timeout);
541
346
  });
347
+ return unreachableList;
542
348
  }
543
349
 
544
350
  /**
@@ -550,157 +356,65 @@ var Reachability = exports.default = /*#__PURE__*/function () {
550
356
  }, {
551
357
  key: "logUnreachableClusters",
552
358
  value: function logUnreachableClusters() {
553
- var list = this.getUnreachablClusters();
554
- list.forEach(function (cluster) {
555
- _loggerProxy.default.logger.log("Reachability:index#logUnreachableClusters --> No ice candidate for ".concat(cluster, "."));
556
- });
557
- }
558
-
559
- /**
560
- * Calculates time to establish connection
561
- * @param {Array<ICECandidateResult>} iceResults iceResults
562
- * @returns {object} reachabilityMap
563
- * @protected
564
- * @memberof Reachability
565
- */
566
- }, {
567
- key: "parseIceResultsToInternalReachabilityResults",
568
- value: function parseIceResultsToInternalReachabilityResults(iceResults) {
569
- var reachabilityMap = {};
570
- iceResults.forEach(function (_ref2) {
571
- var clusterId = _ref2.clusterId,
572
- isVideoMesh = _ref2.isVideoMesh,
573
- elapsed = _ref2.elapsed,
574
- publicIPs = _ref2.publicIPs;
575
- var latencyResult = {};
576
- if (!elapsed) {
577
- (0, _assign.default)(latencyResult, {
578
- reachable: 'false'
579
- });
580
- } else {
581
- (0, _assign.default)(latencyResult, {
582
- reachable: 'true',
583
- latencyInMilliseconds: elapsed.toString()
584
- });
585
- }
586
- if (publicIPs) {
587
- (0, _assign.default)(latencyResult, {
588
- clientMediaIPs: publicIPs
589
- });
590
- }
591
- reachabilityMap[clusterId] = {
592
- udp: latencyResult,
593
- tcp: {
594
- untested: 'true'
595
- },
596
- xtls: {
597
- untested: 'true'
598
- },
599
- isVideoMesh: isVideoMesh
600
- };
359
+ var list = this.getUnreachableClusters();
360
+ list.forEach(function (_ref3) {
361
+ var name = _ref3.name,
362
+ protocol = _ref3.protocol;
363
+ _loggerProxy.default.logger.log("Reachability:index#logUnreachableClusters --> failed to reach ".concat(name, " over ").concat(protocol));
601
364
  });
602
- return reachabilityMap;
603
365
  }
604
366
 
605
367
  /**
606
- * fetches reachability data
607
- * @param {object} clusterList
608
- * @returns {Promise<InternalReachabilityResults>} reachability check results
609
- * @private
610
- * @memberof Reachability
368
+ * Performs reachability checks for all clusters
369
+ * @param {ClusterList} clusterList
370
+ * @returns {Promise<ReachabilityResults>} reachability check results
611
371
  */
612
372
  }, {
613
- key: "performReachabilityCheck",
614
- value: function performReachabilityCheck(clusterList) {
615
- var _this5 = this;
616
- if (!clusterList || !(0, _keys.default)(clusterList).length) {
617
- return _promise.default.resolve({});
618
- }
619
- return new _promise.default(function (resolve) {
620
- _this5.getLocalSDPForClusters(clusterList).then(function (localSDPData) {
621
- if (!localSDPData || !(0, _keys.default)(localSDPData).length) {
622
- // TODO: handle the error condition properly and try retry
623
- _loggerProxy.default.logger.log('Reachability:index#performReachabilityCheck --> Local SDP is empty or has missing elements..returning');
624
- resolve({});
625
- } else {
626
- resolve(localSDPData);
373
+ key: "performReachabilityChecks",
374
+ value: (function () {
375
+ var _performReachabilityChecks = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee5(clusterList) {
376
+ var _this2 = this;
377
+ var results, includeTcpReachability, clusterReachabilityChecks;
378
+ return _regenerator.default.wrap(function _callee5$(_context5) {
379
+ while (1) switch (_context5.prev = _context5.next) {
380
+ case 0:
381
+ results = {};
382
+ if (!(!clusterList || !(0, _keys.default)(clusterList).length)) {
383
+ _context5.next = 3;
384
+ break;
385
+ }
386
+ return _context5.abrupt("return", _promise.default.resolve(results));
387
+ case 3:
388
+ // @ts-ignore
389
+ includeTcpReachability = this.webex.config.meetings.experimental.enableTcpReachability;
390
+ _loggerProxy.default.logger.log("Reachability:index#performReachabilityChecks --> doing UDP".concat(includeTcpReachability ? ' and TCP' : '', " reachability checks"));
391
+ clusterReachabilityChecks = (0, _keys.default)(clusterList).map(function (key) {
392
+ var cluster = clusterList[key];
393
+ if (!includeTcpReachability) {
394
+ cluster.tcp = [];
395
+ }
396
+ _this2.clusterReachability[key] = new _clusterReachability.ClusterReachability(key, cluster);
397
+ return _this2.clusterReachability[key].start().then(function (result) {
398
+ results[key] = result;
399
+ results[key].isVideoMesh = cluster.isVideoMesh;
400
+ });
401
+ });
402
+ _context5.next = 8;
403
+ return _promise.default.all(clusterReachabilityChecks);
404
+ case 8:
405
+ this.logUnreachableClusters();
406
+ return _context5.abrupt("return", results);
407
+ case 10:
408
+ case "end":
409
+ return _context5.stop();
627
410
  }
628
- }).catch(function (error) {
629
- _loggerProxy.default.logger.error("Reachability:index#performReachabilityCheck --> Error in getLocalSDPForClusters: ".concat(error));
630
- resolve({});
631
- });
632
- });
633
- }
634
-
635
- /**
636
- * Adds public IP (client media IPs)
637
- * @param {RTCPeerConnection} peerConnection
638
- * @param {string} publicIP
639
- * @returns {void}
640
- */
641
- }, {
642
- key: "addPublicIP",
643
- value: function addPublicIP(peerConnection, publicIP) {
644
- var modifiedPeerConnection = peerConnection;
645
- var CLOSED = _constants.CONNECTION_STATE.CLOSED;
646
- if (modifiedPeerConnection.connectionState === CLOSED) {
647
- _loggerProxy.default.logger.log("Reachability:index#addPublicIP --> Attempting to set publicIP of ".concat(publicIP, " on closed peerConnection."));
648
- }
649
- if (publicIP) {
650
- if (modifiedPeerConnection.publicIPs) {
651
- modifiedPeerConnection.publicIPs.push(publicIP);
652
- } else {
653
- modifiedPeerConnection.publicIPs = [publicIP];
654
- }
655
- } else {
656
- modifiedPeerConnection.publicIPs = null;
657
- }
658
- }
659
-
660
- /**
661
- * Records latency and closes the peerConnection
662
- * @param {RTCPeerConnection} peerConnection
663
- * @param {number} elapsed Latency in milliseconds
664
- * @returns {undefined}
665
- * @private
666
- * @memberof Reachability
667
- */
668
- }, {
669
- key: "setLatencyAndClose",
670
- value: function setLatencyAndClose(peerConnection, elapsed) {
671
- var REACHABLE = 'reachable';
672
- var UNREACHABLE = 'unreachable';
673
- var CLOSED = _constants.CONNECTION_STATE.CLOSED;
674
- // @ts-ignore
675
- var key = peerConnection.key;
676
- var resultKey = elapsed === null ? UNREACHABLE : REACHABLE;
677
- var intialState = (0, _defineProperty2.default)((0, _defineProperty2.default)({}, REACHABLE, 0), UNREACHABLE, 0);
678
- if (peerConnection.connectionState === CLOSED) {
679
- _loggerProxy.default.logger.log("Reachability:index#setLatencyAndClose --> Attempting to set latency of ".concat(elapsed, " on closed peerConnection."));
680
- return;
411
+ }, _callee5, this);
412
+ }));
413
+ function performReachabilityChecks(_x) {
414
+ return _performReachabilityChecks.apply(this, arguments);
681
415
  }
682
- this.clusterLatencyResults[key] = this.clusterLatencyResults[key] || intialState;
683
- this.clusterLatencyResults[key][resultKey] += 1;
684
-
685
- // Set to null in case this fired from
686
- // an event other than onIceCandidate
687
- peerConnection.onicecandidate = null;
688
- peerConnection.close();
689
- // @ts-ignore
690
- peerConnection.elapsed = elapsed;
691
- }
692
-
693
- /**
694
- * utility function
695
- * @returns {undefined}
696
- * @private
697
- * @memberof Reachability
698
- */
699
- }, {
700
- key: "setup",
701
- value: function setup() {
702
- this.clusterLatencyResults = {};
703
- }
416
+ return performReachabilityChecks;
417
+ }())
704
418
  }]);
705
419
  return Reachability;
706
420
  }();