@webex/plugin-meetings 3.0.0-beta.261 → 3.0.0-beta.263
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/common/errors/no-meeting-info.js +51 -0
- package/dist/common/errors/no-meeting-info.js.map +1 -0
- package/dist/constants.js +8 -1
- package/dist/constants.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/meeting/index.js +171 -129
- package/dist/meeting/index.js.map +1 -1
- package/dist/meetings/index.js +39 -21
- package/dist/meetings/index.js.map +1 -1
- package/dist/reachability/index.js +95 -33
- package/dist/reachability/index.js.map +1 -1
- package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
- package/dist/types/constants.d.ts +6 -0
- package/dist/types/meeting/index.d.ts +2 -2
- package/dist/types/meetings/index.d.ts +3 -1
- package/dist/types/reachability/index.d.ts +18 -1
- package/package.json +19 -19
- package/src/common/errors/no-meeting-info.ts +24 -0
- package/src/constants.ts +6 -0
- package/src/meeting/index.ts +32 -26
- package/src/meetings/index.ts +18 -4
- package/src/reachability/index.ts +64 -1
- package/test/unit/spec/meeting/index.js +23 -13
- package/test/unit/spec/meetings/index.js +73 -33
- package/test/unit/spec/reachability/index.ts +208 -2
|
@@ -27,8 +27,6 @@ var _constants = require("../constants");
|
|
|
27
27
|
var _request = _interopRequireDefault(require("./request"));
|
|
28
28
|
var DEFAULT_TIMEOUT = 3000;
|
|
29
29
|
var VIDEO_MESH_TIMEOUT = 1000;
|
|
30
|
-
|
|
31
|
-
// result for a specific transport protocol (like udp or tcp)
|
|
32
30
|
/**
|
|
33
31
|
* @class Reachability
|
|
34
32
|
* @export
|
|
@@ -126,6 +124,70 @@ var Reachability = /*#__PURE__*/function () {
|
|
|
126
124
|
}
|
|
127
125
|
return gatherReachability;
|
|
128
126
|
}()
|
|
127
|
+
/**
|
|
128
|
+
* Returns statistics about last reachability results. The returned value is an object
|
|
129
|
+
* with a flat list of properties so that it can be easily sent with metrics
|
|
130
|
+
*
|
|
131
|
+
* @returns {Promise} Promise with metrics values, it never rejects/throws.
|
|
132
|
+
*/
|
|
133
|
+
}, {
|
|
134
|
+
key: "getReachabilityMetrics",
|
|
135
|
+
value: function () {
|
|
136
|
+
var _getReachabilityMetrics = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
|
|
137
|
+
var stats, updateStats, resultsJson, internalResults;
|
|
138
|
+
return _regenerator.default.wrap(function _callee2$(_context2) {
|
|
139
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
140
|
+
case 0:
|
|
141
|
+
stats = {
|
|
142
|
+
reachability_public_udp_success: 0,
|
|
143
|
+
reachability_public_udp_failed: 0,
|
|
144
|
+
reachability_public_tcp_success: 0,
|
|
145
|
+
reachability_public_tcp_failed: 0,
|
|
146
|
+
reachability_vmn_udp_success: 0,
|
|
147
|
+
reachability_vmn_udp_failed: 0,
|
|
148
|
+
reachability_vmn_tcp_success: 0,
|
|
149
|
+
reachability_vmn_tcp_failed: 0
|
|
150
|
+
};
|
|
151
|
+
updateStats = function updateStats(clusterType, result) {
|
|
152
|
+
var _result$udp, _result$tcp;
|
|
153
|
+
if ((_result$udp = result.udp) !== null && _result$udp !== void 0 && _result$udp.reachable) {
|
|
154
|
+
var outcome = result.udp.reachable === 'true' ? 'success' : 'failed';
|
|
155
|
+
stats["reachability_".concat(clusterType, "_udp_").concat(outcome)] += 1;
|
|
156
|
+
}
|
|
157
|
+
if ((_result$tcp = result.tcp) !== null && _result$tcp !== void 0 && _result$tcp.reachable) {
|
|
158
|
+
var _outcome = result.tcp.reachable === 'true' ? 'success' : 'failed';
|
|
159
|
+
stats["reachability_".concat(clusterType, "_tcp_").concat(_outcome)] += 1;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
_context2.prev = 2;
|
|
163
|
+
_context2.next = 5;
|
|
164
|
+
return this.webex.boundedStorage.get(_constants.REACHABILITY.namespace, _constants.REACHABILITY.localStorageResult);
|
|
165
|
+
case 5:
|
|
166
|
+
resultsJson = _context2.sent;
|
|
167
|
+
internalResults = JSON.parse(resultsJson);
|
|
168
|
+
(0, _values.default)(internalResults).forEach(function (result) {
|
|
169
|
+
updateStats(result.isVideoMesh ? 'vmn' : 'public', result);
|
|
170
|
+
});
|
|
171
|
+
_context2.next = 13;
|
|
172
|
+
break;
|
|
173
|
+
case 10:
|
|
174
|
+
_context2.prev = 10;
|
|
175
|
+
_context2.t0 = _context2["catch"](2);
|
|
176
|
+
// empty storage, that's ok
|
|
177
|
+
_loggerProxy.default.logger.warn('Roap:request#getReachabilityMetrics --> Error parsing reachability data: ', _context2.t0);
|
|
178
|
+
case 13:
|
|
179
|
+
return _context2.abrupt("return", stats);
|
|
180
|
+
case 14:
|
|
181
|
+
case "end":
|
|
182
|
+
return _context2.stop();
|
|
183
|
+
}
|
|
184
|
+
}, _callee2, this, [[2, 10]]);
|
|
185
|
+
}));
|
|
186
|
+
function getReachabilityMetrics() {
|
|
187
|
+
return _getReachabilityMetrics.apply(this, arguments);
|
|
188
|
+
}
|
|
189
|
+
return getReachabilityMetrics;
|
|
190
|
+
}()
|
|
129
191
|
/**
|
|
130
192
|
* Reachability results as an object in the format that backend expects
|
|
131
193
|
*
|
|
@@ -134,36 +196,36 @@ var Reachability = /*#__PURE__*/function () {
|
|
|
134
196
|
}, {
|
|
135
197
|
key: "getReachabilityResults",
|
|
136
198
|
value: function () {
|
|
137
|
-
var _getReachabilityResults = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function
|
|
199
|
+
var _getReachabilityResults = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3() {
|
|
138
200
|
var results, reachabilityResultsProps, resultsJson, internalResults;
|
|
139
|
-
return _regenerator.default.wrap(function
|
|
140
|
-
while (1) switch (
|
|
201
|
+
return _regenerator.default.wrap(function _callee3$(_context3) {
|
|
202
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
141
203
|
case 0:
|
|
142
204
|
// these are the only props that backend needs in the reachability results:
|
|
143
205
|
reachabilityResultsProps = ['udp', 'tcp', 'xtls'];
|
|
144
|
-
|
|
145
|
-
|
|
206
|
+
_context3.prev = 1;
|
|
207
|
+
_context3.next = 4;
|
|
146
208
|
return this.webex.boundedStorage.get(_constants.REACHABILITY.namespace, _constants.REACHABILITY.localStorageResult);
|
|
147
209
|
case 4:
|
|
148
|
-
resultsJson =
|
|
210
|
+
resultsJson = _context3.sent;
|
|
149
211
|
internalResults = JSON.parse(resultsJson);
|
|
150
212
|
results = (0, _mapValues2.default)(internalResults, function (result) {
|
|
151
213
|
return (0, _pick2.default)(result, reachabilityResultsProps);
|
|
152
214
|
});
|
|
153
|
-
|
|
215
|
+
_context3.next = 12;
|
|
154
216
|
break;
|
|
155
217
|
case 9:
|
|
156
|
-
|
|
157
|
-
|
|
218
|
+
_context3.prev = 9;
|
|
219
|
+
_context3.t0 = _context3["catch"](1);
|
|
158
220
|
// empty storage, that's ok
|
|
159
|
-
_loggerProxy.default.logger.warn('Roap:request#attachReachabilityData --> Error parsing reachability data: ',
|
|
221
|
+
_loggerProxy.default.logger.warn('Roap:request#attachReachabilityData --> Error parsing reachability data: ', _context3.t0);
|
|
160
222
|
case 12:
|
|
161
|
-
return
|
|
223
|
+
return _context3.abrupt("return", results);
|
|
162
224
|
case 13:
|
|
163
225
|
case "end":
|
|
164
|
-
return
|
|
226
|
+
return _context3.stop();
|
|
165
227
|
}
|
|
166
|
-
},
|
|
228
|
+
}, _callee3, this, [[1, 9]]);
|
|
167
229
|
}));
|
|
168
230
|
function getReachabilityResults() {
|
|
169
231
|
return _getReachabilityResults.apply(this, arguments);
|
|
@@ -179,33 +241,33 @@ var Reachability = /*#__PURE__*/function () {
|
|
|
179
241
|
}, {
|
|
180
242
|
key: "isAnyPublicClusterReachable",
|
|
181
243
|
value: function () {
|
|
182
|
-
var _isAnyPublicClusterReachable = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function
|
|
244
|
+
var _isAnyPublicClusterReachable = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4() {
|
|
183
245
|
var reachable, reachabilityData, reachabilityResults;
|
|
184
|
-
return _regenerator.default.wrap(function
|
|
185
|
-
while (1) switch (
|
|
246
|
+
return _regenerator.default.wrap(function _callee4$(_context4) {
|
|
247
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
186
248
|
case 0:
|
|
187
249
|
reachable = false; // @ts-ignore
|
|
188
|
-
|
|
250
|
+
_context4.next = 3;
|
|
189
251
|
return this.webex.boundedStorage.get(this.namespace, _constants.REACHABILITY.localStorageResult).catch(function () {});
|
|
190
252
|
case 3:
|
|
191
|
-
reachabilityData =
|
|
253
|
+
reachabilityData = _context4.sent;
|
|
192
254
|
if (reachabilityData) {
|
|
193
255
|
try {
|
|
194
256
|
reachabilityResults = JSON.parse(reachabilityData);
|
|
195
257
|
reachable = (0, _values.default)(reachabilityResults).some(function (result) {
|
|
196
|
-
var _result$
|
|
197
|
-
return !result.isVideoMesh && (((_result$
|
|
258
|
+
var _result$udp2, _result$tcp2;
|
|
259
|
+
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');
|
|
198
260
|
});
|
|
199
261
|
} catch (e) {
|
|
200
262
|
_loggerProxy.default.logger.error("Roap:request#attachReachabilityData --> Error in parsing reachability data: ".concat(e));
|
|
201
263
|
}
|
|
202
264
|
}
|
|
203
|
-
return
|
|
265
|
+
return _context4.abrupt("return", reachable);
|
|
204
266
|
case 6:
|
|
205
267
|
case "end":
|
|
206
|
-
return
|
|
268
|
+
return _context4.stop();
|
|
207
269
|
}
|
|
208
|
-
},
|
|
270
|
+
}, _callee4, this);
|
|
209
271
|
}));
|
|
210
272
|
function isAnyPublicClusterReachable() {
|
|
211
273
|
return _isAnyPublicClusterReachable.apply(this, arguments);
|
|
@@ -288,10 +350,10 @@ var Reachability = /*#__PURE__*/function () {
|
|
|
288
350
|
var _this = this;
|
|
289
351
|
var clusters = (0, _toConsumableArray2.default)((0, _keys.default)(clusterList));
|
|
290
352
|
clusters = clusters.map( /*#__PURE__*/function () {
|
|
291
|
-
var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function
|
|
353
|
+
var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee5(key) {
|
|
292
354
|
var cluster, config, peerConnection, description;
|
|
293
|
-
return _regenerator.default.wrap(function
|
|
294
|
-
while (1) switch (
|
|
355
|
+
return _regenerator.default.wrap(function _callee5$(_context5) {
|
|
356
|
+
while (1) switch (_context5.prev = _context5.next) {
|
|
295
357
|
case 0:
|
|
296
358
|
cluster = clusterList[key];
|
|
297
359
|
config = _this.buildPeerConnectionConfig(cluster);
|
|
@@ -299,23 +361,23 @@ var Reachability = /*#__PURE__*/function () {
|
|
|
299
361
|
key: key,
|
|
300
362
|
config: config
|
|
301
363
|
});
|
|
302
|
-
|
|
364
|
+
_context5.next = 5;
|
|
303
365
|
return peerConnection.createOffer({
|
|
304
366
|
offerToReceiveAudio: true
|
|
305
367
|
});
|
|
306
368
|
case 5:
|
|
307
|
-
description =
|
|
369
|
+
description = _context5.sent;
|
|
308
370
|
// @ts-ignore
|
|
309
371
|
peerConnection.begin = (0, _now.default)();
|
|
310
372
|
peerConnection.setLocalDescription(description);
|
|
311
|
-
return
|
|
373
|
+
return _context5.abrupt("return", _this.iceGatheringState(peerConnection, cluster.isVideoMesh).catch(function (iceGatheringStateError) {
|
|
312
374
|
_loggerProxy.default.logger.log("Reachability:index#getLocalSDPForClusters --> Error in getLocalSDP : ".concat(iceGatheringStateError));
|
|
313
375
|
}));
|
|
314
376
|
case 9:
|
|
315
377
|
case "end":
|
|
316
|
-
return
|
|
378
|
+
return _context5.stop();
|
|
317
379
|
}
|
|
318
|
-
},
|
|
380
|
+
}, _callee5);
|
|
319
381
|
}));
|
|
320
382
|
return function (_x) {
|
|
321
383
|
return _ref.apply(this, arguments);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["DEFAULT_TIMEOUT","VIDEO_MESH_TIMEOUT","Reachability","webex","REACHABILITY","namespace","reachabilityRequest","ReachabilityRequest","clusterLatencyResults","setup","boundedStorage","del","localStorageResult","localStorageJoinCookie","getClusters","MeetingUtil","getIpVersion","clusters","joinCookie","performReachabilityCheck","results","put","LoggerProxy","logger","log","error","reachabilityResultsProps","get","resultsJson","internalResults","JSON","parse","result","warn","reachable","catch","reachabilityData","reachabilityResults","some","isVideoMesh","udp","tcp","e","cluster","iceServers","map","url","username","credential","urls","iceCandidatePoolSize","iceTransportPolicy","key","config","peerConnection","window","RTCPeerConnection","peerConnectionError","startTime","begin","clusterList","buildPeerConnectionConfig","createPeerConnection","createOffer","offerToReceiveAudio","description","setLocalDescription","iceGatheringState","iceGatheringStateError","all","then","parseIceResultsToInternalReachabilityResults","reachabilityLatencyResults","logUnreachableClusters","unreachableList","forEach","unreachable","push","onicegatheringstatechange","COMPLETE","ICE_GATHERING_STATE","iceConnectionState","elapsed","getElapsedTime","setLatencyAndClose","onicecandidate","SERVER_REFLEXIVE","candidate","String","type","toLowerCase","addPublicIP","address","ELAPSED","timeout","resolve","peerConnectionProxy","Proxy","target","property","targetMember","bind","set","value","clusterId","publicIPs","Reflect","handleIceGatheringStateChange","handleOnIceCandidate","setTimeout","CLOSED","CONNECTION_STATE","connectionState","list","getUnreachablClusters","iceResults","reachabilityMap","latencyResult","latencyInMilliseconds","toString","clientMediaIPs","untested","xtls","length","getLocalSDPForClusters","localSDPData","publicIP","modifiedPeerConnection","REACHABLE","UNREACHABLE","resultKey","intialState","close"],"sources":["index.ts"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\n/* eslint-disable class-methods-use-this */\n/* globals window */\nimport {uniq, mapValues, pick} from 'lodash';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport MeetingUtil from '../meeting/util';\n\nimport {ICE_GATHERING_STATE, CONNECTION_STATE, REACHABILITY} from '../constants';\n\nimport ReachabilityRequest from './request';\n\nconst DEFAULT_TIMEOUT = 3000;\nconst VIDEO_MESH_TIMEOUT = 1000;\n\n// result for a specific transport protocol (like udp or tcp)\nexport type TransportResult = {\n reachable: 'true' | 'false';\n latencyInMilliseconds?: string;\n clientMediaIPs?: string[];\n untested?: 'true';\n};\n\n// reachability result for a specifc media cluster\ntype ReachabilityResult = {\n udp: TransportResult;\n tcp: TransportResult;\n xtls: {\n untested: 'true';\n };\n};\n// this is the type that is required by the backend when we send them reachability results\nexport type ReachabilityResults = Record<string, ReachabilityResult>;\n\n// this is the type used by Reachability class internally and stored in local storage\ntype InternalReachabilityResults = Record<\n string,\n ReachabilityResult & {\n isVideoMesh?: boolean;\n }\n>;\n\nexport type ICECandidateResult = {\n clusterId: string;\n isVideoMesh: boolean;\n elapsed?: string | null;\n publicIPs?: string[];\n};\n/**\n * @class Reachability\n * @export\n */\nexport default class Reachability {\n namespace = REACHABILITY.namespace;\n webex: object;\n reachabilityRequest: any;\n clusterLatencyResults: any;\n\n /**\n * Creates an instance of Reachability.\n * @param {object} webex\n * @memberof Reachability\n */\n constructor(webex: object) {\n this.webex = webex;\n\n /**\n * internal request object for the server\n * @instance\n * @type {Array}\n * @private\n * @memberof Reachability\n */\n this.reachabilityRequest = new ReachabilityRequest(this.webex);\n\n /**\n * internal object of clusters latency results\n * @instance\n * @type {object}\n * @private\n * @memberof Reachability\n */\n this.clusterLatencyResults = {};\n }\n\n /**\n * fetches reachability data\n * @returns {Object} reachability data\n * @public\n * @async\n * @memberof Reachability\n */\n public async gatherReachability(): Promise<InternalReachabilityResults> {\n this.setup();\n\n // Remove stored reachability results to ensure no stale data\n // @ts-ignore\n await this.webex.boundedStorage.del(this.namespace, REACHABILITY.localStorageResult);\n // @ts-ignore\n await this.webex.boundedStorage.del(this.namespace, REACHABILITY.localStorageJoinCookie);\n\n // Fetch clusters and measure latency\n try {\n const {clusters, joinCookie} = await this.reachabilityRequest.getClusters(\n MeetingUtil.getIpVersion(this.webex)\n );\n\n // Perform Reachability Check\n const results = await this.performReachabilityCheck(clusters);\n\n // @ts-ignore\n await this.webex.boundedStorage.put(\n this.namespace,\n REACHABILITY.localStorageResult,\n JSON.stringify(results)\n );\n // @ts-ignore\n await this.webex.boundedStorage.put(\n this.namespace,\n REACHABILITY.localStorageJoinCookie,\n JSON.stringify(joinCookie)\n );\n\n LoggerProxy.logger.log(\n 'Reachability:index#gatherReachability --> Reachability checks completed'\n );\n\n return results;\n } catch (getClusterError) {\n LoggerProxy.logger.error(\n `Reachability:index#gatherReachability --> Error in calling getClusters(): ${getClusterError}`\n );\n\n return {};\n }\n }\n\n /**\n * Reachability results as an object in the format that backend expects\n *\n * @returns {any} reachability results that need to be sent to the backend\n */\n async getReachabilityResults(): Promise<ReachabilityResults | undefined> {\n let results: ReachabilityResults;\n\n // these are the only props that backend needs in the reachability results:\n const reachabilityResultsProps: Array<keyof ReachabilityResult> = ['udp', 'tcp', 'xtls'];\n\n try {\n // @ts-ignore\n const resultsJson = await this.webex.boundedStorage.get(\n REACHABILITY.namespace,\n REACHABILITY.localStorageResult\n );\n\n const internalResults: InternalReachabilityResults = JSON.parse(resultsJson);\n\n results = mapValues(internalResults, (result) => pick(result, reachabilityResultsProps));\n } catch (e) {\n // empty storage, that's ok\n LoggerProxy.logger.warn(\n 'Roap:request#attachReachabilityData --> Error parsing reachability data: ',\n e\n );\n }\n\n return results;\n }\n\n /**\n * fetches reachability data and checks for cluster reachability\n * @returns {boolean}\n * @public\n * @memberof Reachability\n */\n async isAnyPublicClusterReachable() {\n let reachable = false;\n // @ts-ignore\n const reachabilityData = await this.webex.boundedStorage\n .get(this.namespace, REACHABILITY.localStorageResult)\n .catch(() => {});\n\n if (reachabilityData) {\n try {\n const reachabilityResults: InternalReachabilityResults = JSON.parse(reachabilityData);\n\n reachable = Object.values(reachabilityResults).some(\n (result) =>\n !result.isVideoMesh &&\n (result.udp?.reachable === 'true' || result.tcp?.reachable === 'true')\n );\n } catch (e) {\n LoggerProxy.logger.error(\n `Roap:request#attachReachabilityData --> Error in parsing reachability data: ${e}`\n );\n }\n }\n\n return reachable;\n }\n\n /**\n * Generate peerConnection config settings\n * @param {object} cluster\n * @returns {object} peerConnectionConfig\n * @private\n * @memberof Reachability\n */\n private buildPeerConnectionConfig(cluster: any) {\n const iceServers = uniq(cluster.udp).map((url) => ({\n username: '',\n credential: '',\n urls: [url],\n }));\n\n return {\n iceServers: [...iceServers],\n iceCandidatePoolSize: '0',\n iceTransportPolicy: 'all',\n };\n }\n\n /**\n * Creates an RTCPeerConnection\n * @param {object} cluster\n * @returns {RTCPeerConnection} peerConnection\n * @private\n * @memberof Reachability\n */\n private createPeerConnection(cluster: any) {\n const {key, config} = cluster;\n\n try {\n const peerConnection = new window.RTCPeerConnection(config);\n\n // @ts-ignore\n peerConnection.key = key;\n\n return peerConnection;\n } catch (peerConnectionError) {\n LoggerProxy.logger.log(\n `Reachability:index#createPeerConnection --> Error creating peerConnection: ${peerConnectionError}`\n );\n\n return null;\n }\n }\n\n /**\n * Gets total elapsed time\n * @param {RTCPeerConnection} peerConnection\n * @returns {Number} Milliseconds\n * @private\n * @memberof Reachability\n */\n private getElapsedTime(peerConnection: any) {\n const startTime = peerConnection.begin;\n\n delete peerConnection.begin;\n\n return Date.now() - startTime;\n }\n\n /**\n * creates offer and generates localSDP\n * @param {object} clusterList cluster List\n * @returns {Promise} Reachability latency results\n * @private\n * @memberof Reachability\n */\n private getLocalSDPForClusters(clusterList: object): Promise<InternalReachabilityResults> {\n let clusters: any[] = [...Object.keys(clusterList)];\n\n clusters = clusters.map(async (key) => {\n const cluster = clusterList[key];\n const config = this.buildPeerConnectionConfig(cluster);\n const peerConnection = this.createPeerConnection({key, config});\n const description = await peerConnection.createOffer({offerToReceiveAudio: true});\n\n // @ts-ignore\n peerConnection.begin = Date.now();\n peerConnection.setLocalDescription(description);\n\n return this.iceGatheringState(peerConnection, cluster.isVideoMesh).catch(\n (iceGatheringStateError) => {\n LoggerProxy.logger.log(\n `Reachability:index#getLocalSDPForClusters --> Error in getLocalSDP : ${iceGatheringStateError}`\n );\n }\n );\n });\n\n return Promise.all(clusters)\n .then(this.parseIceResultsToInternalReachabilityResults)\n .then((reachabilityLatencyResults) => {\n this.logUnreachableClusters();\n\n // return results\n return reachabilityLatencyResults;\n });\n }\n\n /**\n * Get list of all unreachable clusters\n * @returns {array} Unreachable clusters\n * @private\n * @memberof Reachability\n */\n private getUnreachablClusters() {\n const unreachableList = [];\n const clusters = this.clusterLatencyResults;\n\n Object.keys(clusters).forEach((key) => {\n const cluster = clusters[key];\n\n if (cluster.unreachable && !cluster.reachable) {\n unreachableList.push(key);\n }\n });\n\n return unreachableList;\n }\n\n /**\n * Attach an event handler for the icegatheringstatechange\n * event and measure latency.\n * @param {RTCPeerConnection} peerConnection\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private handleIceGatheringStateChange(peerConnection: RTCPeerConnection) {\n peerConnection.onicegatheringstatechange = () => {\n const {COMPLETE} = ICE_GATHERING_STATE;\n\n if (peerConnection.iceConnectionState === COMPLETE) {\n const elapsed = this.getElapsedTime(peerConnection);\n\n // @ts-ignore\n LoggerProxy.logger.log(\n // @ts-ignore\n `Reachability:index#onIceGatheringStateChange --> Successfully pinged ${peerConnection.key}:`,\n elapsed\n );\n this.setLatencyAndClose(peerConnection, elapsed);\n }\n };\n }\n\n /**\n * Attach an event handler for the icecandidate\n * event and measure latency.\n * @param {RTCPeerConnection} peerConnection\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private handleOnIceCandidate(peerConnection: RTCPeerConnection) {\n peerConnection.onicecandidate = (e) => {\n const SERVER_REFLEXIVE = 'srflx';\n\n if (e.candidate && String(e.candidate.type).toLowerCase() === SERVER_REFLEXIVE) {\n const elapsed = this.getElapsedTime(peerConnection);\n\n LoggerProxy.logger.log(\n // @ts-ignore\n `Reachability:index#onIceCandidate --> Successfully pinged ${peerConnection.key}:`,\n elapsed\n );\n // order is important\n this.addPublicIP(peerConnection, e.candidate.address);\n this.setLatencyAndClose(peerConnection, elapsed);\n }\n };\n }\n\n /**\n * An event handler on an RTCPeerConnection when the state of the ICE\n * candidate gathering process changes. Used to measure connection\n * speed.\n * @private\n * @param {RTCPeerConnection} peerConnection\n * @param {boolean} isVideoMesh\n * @returns {Promise}\n */\n private iceGatheringState(peerConnection: RTCPeerConnection, isVideoMesh: boolean) {\n const ELAPSED = 'elapsed';\n\n const timeout = isVideoMesh ? VIDEO_MESH_TIMEOUT : DEFAULT_TIMEOUT;\n\n return new Promise<ICECandidateResult>((resolve) => {\n const peerConnectionProxy = new window.Proxy(peerConnection, {\n // eslint-disable-next-line require-jsdoc\n get(target, property) {\n const targetMember = target[property];\n\n if (typeof targetMember === 'function') {\n return targetMember.bind(target);\n }\n\n return targetMember;\n },\n set: (target, property, value) => {\n // only intercept elapsed property\n if (property === ELAPSED) {\n resolve({\n // @ts-ignore\n clusterId: peerConnection.key,\n isVideoMesh,\n // @ts-ignore\n publicIPs: target.publicIPs,\n elapsed: value,\n });\n\n return true;\n }\n\n // pass thru\n return window.Reflect.set(target, property, value);\n },\n });\n\n // Using peerConnection proxy so handle functions below\n // won't be coupled to our promise implementation\n this.handleIceGatheringStateChange(peerConnectionProxy);\n this.handleOnIceCandidate(peerConnectionProxy);\n\n // Set maximum timeout\n window.setTimeout(() => {\n const {CLOSED} = CONNECTION_STATE;\n\n // Close any open peerConnections\n if (peerConnectionProxy.connectionState !== CLOSED) {\n // order is important\n this.addPublicIP(peerConnectionProxy, null);\n this.setLatencyAndClose(peerConnectionProxy, null);\n }\n }, timeout);\n });\n }\n\n /**\n * Make a log of unreachable clusters.\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private logUnreachableClusters() {\n const list = this.getUnreachablClusters();\n\n list.forEach((cluster) => {\n LoggerProxy.logger.log(\n `Reachability:index#logUnreachableClusters --> No ice candidate for ${cluster}.`\n );\n });\n }\n\n /**\n * Calculates time to establish connection\n * @param {Array<ICECandidateResult>} iceResults iceResults\n * @returns {object} reachabilityMap\n * @protected\n * @memberof Reachability\n */\n protected parseIceResultsToInternalReachabilityResults(\n iceResults: Array<ICECandidateResult>\n ): InternalReachabilityResults {\n const reachabilityMap = {};\n\n iceResults.forEach(({clusterId, isVideoMesh, elapsed, publicIPs}) => {\n const latencyResult = {};\n\n if (!elapsed) {\n Object.assign(latencyResult, {reachable: 'false'});\n } else {\n Object.assign(latencyResult, {\n reachable: 'true',\n latencyInMilliseconds: elapsed.toString(),\n });\n }\n\n if (publicIPs) {\n Object.assign(latencyResult, {\n clientMediaIPs: publicIPs,\n });\n }\n\n reachabilityMap[clusterId] = {\n udp: latencyResult,\n tcp: {untested: 'true'},\n xtls: {untested: 'true'},\n isVideoMesh,\n };\n });\n\n return reachabilityMap;\n }\n\n /**\n * fetches reachability data\n * @param {object} clusterList\n * @returns {Promise<InternalReachabilityResults>} reachability check results\n * @private\n * @memberof Reachability\n */\n private performReachabilityCheck(clusterList: object): Promise<InternalReachabilityResults> {\n if (!clusterList || !Object.keys(clusterList).length) {\n return Promise.resolve({});\n }\n\n return new Promise((resolve) => {\n this.getLocalSDPForClusters(clusterList)\n .then((localSDPData) => {\n if (!localSDPData || !Object.keys(localSDPData).length) {\n // TODO: handle the error condition properly and try retry\n LoggerProxy.logger.log(\n 'Reachability:index#performReachabilityCheck --> Local SDP is empty or has missing elements..returning'\n );\n resolve({});\n } else {\n resolve(localSDPData);\n }\n })\n .catch((error) => {\n LoggerProxy.logger.error(\n `Reachability:index#performReachabilityCheck --> Error in getLocalSDPForClusters: ${error}`\n );\n resolve({});\n });\n });\n }\n\n /**\n * Adds public IP (client media IPs)\n * @param {RTCPeerConnection} peerConnection\n * @param {string} publicIP\n * @returns {void}\n */\n protected addPublicIP(peerConnection: RTCPeerConnection, publicIP?: string | null) {\n const modifiedPeerConnection: RTCPeerConnection & {publicIPs?: string[]} = peerConnection;\n const {CLOSED} = CONNECTION_STATE;\n\n if (modifiedPeerConnection.connectionState === CLOSED) {\n LoggerProxy.logger.log(\n `Reachability:index#addPublicIP --> Attempting to set publicIP of ${publicIP} on closed peerConnection.`\n );\n }\n\n if (publicIP) {\n if (modifiedPeerConnection.publicIPs) {\n modifiedPeerConnection.publicIPs.push(publicIP);\n } else {\n modifiedPeerConnection.publicIPs = [publicIP];\n }\n } else {\n modifiedPeerConnection.publicIPs = null;\n }\n }\n\n /**\n * Records latency and closes the peerConnection\n * @param {RTCPeerConnection} peerConnection\n * @param {number} elapsed Latency in milliseconds\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private setLatencyAndClose(peerConnection: RTCPeerConnection, elapsed: number) {\n const REACHABLE = 'reachable';\n const UNREACHABLE = 'unreachable';\n const {CLOSED} = CONNECTION_STATE;\n // @ts-ignore\n const {key} = peerConnection;\n const resultKey = elapsed === null ? UNREACHABLE : REACHABLE;\n const intialState = {[REACHABLE]: 0, [UNREACHABLE]: 0};\n\n if (peerConnection.connectionState === CLOSED) {\n LoggerProxy.logger.log(\n `Reachability:index#setLatencyAndClose --> Attempting to set latency of ${elapsed} on closed peerConnection.`\n );\n\n return;\n }\n\n this.clusterLatencyResults[key] = this.clusterLatencyResults[key] || intialState;\n this.clusterLatencyResults[key][resultKey] += 1;\n\n // Set to null in case this fired from\n // an event other than onIceCandidate\n peerConnection.onicecandidate = null;\n peerConnection.close();\n // @ts-ignore\n peerConnection.elapsed = elapsed;\n }\n\n /**\n * utility function\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private setup() {\n this.clusterLatencyResults = {};\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["DEFAULT_TIMEOUT","VIDEO_MESH_TIMEOUT","Reachability","webex","REACHABILITY","namespace","reachabilityRequest","ReachabilityRequest","clusterLatencyResults","setup","boundedStorage","del","localStorageResult","localStorageJoinCookie","getClusters","MeetingUtil","getIpVersion","clusters","joinCookie","performReachabilityCheck","results","put","LoggerProxy","logger","log","error","stats","reachability_public_udp_success","reachability_public_udp_failed","reachability_public_tcp_success","reachability_public_tcp_failed","reachability_vmn_udp_success","reachability_vmn_udp_failed","reachability_vmn_tcp_success","reachability_vmn_tcp_failed","updateStats","clusterType","result","udp","reachable","outcome","tcp","get","resultsJson","internalResults","JSON","parse","forEach","isVideoMesh","warn","reachabilityResultsProps","catch","reachabilityData","reachabilityResults","some","e","cluster","iceServers","map","url","username","credential","urls","iceCandidatePoolSize","iceTransportPolicy","key","config","peerConnection","window","RTCPeerConnection","peerConnectionError","startTime","begin","clusterList","buildPeerConnectionConfig","createPeerConnection","createOffer","offerToReceiveAudio","description","setLocalDescription","iceGatheringState","iceGatheringStateError","all","then","parseIceResultsToInternalReachabilityResults","reachabilityLatencyResults","logUnreachableClusters","unreachableList","unreachable","push","onicegatheringstatechange","COMPLETE","ICE_GATHERING_STATE","iceConnectionState","elapsed","getElapsedTime","setLatencyAndClose","onicecandidate","SERVER_REFLEXIVE","candidate","String","type","toLowerCase","addPublicIP","address","ELAPSED","timeout","resolve","peerConnectionProxy","Proxy","target","property","targetMember","bind","set","value","clusterId","publicIPs","Reflect","handleIceGatheringStateChange","handleOnIceCandidate","setTimeout","CLOSED","CONNECTION_STATE","connectionState","list","getUnreachablClusters","iceResults","reachabilityMap","latencyResult","latencyInMilliseconds","toString","clientMediaIPs","untested","xtls","length","getLocalSDPForClusters","localSDPData","publicIP","modifiedPeerConnection","REACHABLE","UNREACHABLE","resultKey","intialState","close"],"sources":["index.ts"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\n/* eslint-disable class-methods-use-this */\n/* globals window */\nimport {uniq, mapValues, pick} from 'lodash';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport MeetingUtil from '../meeting/util';\n\nimport {ICE_GATHERING_STATE, CONNECTION_STATE, REACHABILITY} from '../constants';\n\nimport ReachabilityRequest from './request';\n\nconst DEFAULT_TIMEOUT = 3000;\nconst VIDEO_MESH_TIMEOUT = 1000;\n\nexport type ReachabilityMetrics = {\n reachability_public_udp_success: number;\n reachability_public_udp_failed: number;\n reachability_public_tcp_success: number;\n reachability_public_tcp_failed: number;\n reachability_vmn_udp_success: number;\n reachability_vmn_udp_failed: number;\n reachability_vmn_tcp_success: number;\n reachability_vmn_tcp_failed: number;\n};\n\n// result for a specific transport protocol (like udp or tcp)\nexport type TransportResult = {\n reachable?: 'true' | 'false';\n latencyInMilliseconds?: string;\n clientMediaIPs?: string[];\n untested?: 'true';\n};\n\n// reachability result for a specifc media cluster\ntype ReachabilityResult = {\n udp: TransportResult;\n tcp: TransportResult;\n xtls: {\n untested: 'true';\n };\n};\n// this is the type that is required by the backend when we send them reachability results\nexport type ReachabilityResults = Record<string, ReachabilityResult>;\n\n// this is the type used by Reachability class internally and stored in local storage\ntype InternalReachabilityResults = Record<\n string,\n ReachabilityResult & {\n isVideoMesh?: boolean;\n }\n>;\n\nexport type ICECandidateResult = {\n clusterId: string;\n isVideoMesh: boolean;\n elapsed?: string | null;\n publicIPs?: string[];\n};\n/**\n * @class Reachability\n * @export\n */\nexport default class Reachability {\n namespace = REACHABILITY.namespace;\n webex: object;\n reachabilityRequest: any;\n clusterLatencyResults: any;\n\n /**\n * Creates an instance of Reachability.\n * @param {object} webex\n * @memberof Reachability\n */\n constructor(webex: object) {\n this.webex = webex;\n\n /**\n * internal request object for the server\n * @instance\n * @type {Array}\n * @private\n * @memberof Reachability\n */\n this.reachabilityRequest = new ReachabilityRequest(this.webex);\n\n /**\n * internal object of clusters latency results\n * @instance\n * @type {object}\n * @private\n * @memberof Reachability\n */\n this.clusterLatencyResults = {};\n }\n\n /**\n * fetches reachability data\n * @returns {Object} reachability data\n * @public\n * @async\n * @memberof Reachability\n */\n public async gatherReachability(): Promise<InternalReachabilityResults> {\n this.setup();\n\n // Remove stored reachability results to ensure no stale data\n // @ts-ignore\n await this.webex.boundedStorage.del(this.namespace, REACHABILITY.localStorageResult);\n // @ts-ignore\n await this.webex.boundedStorage.del(this.namespace, REACHABILITY.localStorageJoinCookie);\n\n // Fetch clusters and measure latency\n try {\n const {clusters, joinCookie} = await this.reachabilityRequest.getClusters(\n MeetingUtil.getIpVersion(this.webex)\n );\n\n // Perform Reachability Check\n const results = await this.performReachabilityCheck(clusters);\n\n // @ts-ignore\n await this.webex.boundedStorage.put(\n this.namespace,\n REACHABILITY.localStorageResult,\n JSON.stringify(results)\n );\n // @ts-ignore\n await this.webex.boundedStorage.put(\n this.namespace,\n REACHABILITY.localStorageJoinCookie,\n JSON.stringify(joinCookie)\n );\n\n LoggerProxy.logger.log(\n 'Reachability:index#gatherReachability --> Reachability checks completed'\n );\n\n return results;\n } catch (getClusterError) {\n LoggerProxy.logger.error(\n `Reachability:index#gatherReachability --> Error in calling getClusters(): ${getClusterError}`\n );\n\n return {};\n }\n }\n\n /**\n * Returns statistics about last reachability results. The returned value is an object\n * with a flat list of properties so that it can be easily sent with metrics\n *\n * @returns {Promise} Promise with metrics values, it never rejects/throws.\n */\n async getReachabilityMetrics(): Promise<ReachabilityMetrics> {\n const stats: ReachabilityMetrics = {\n reachability_public_udp_success: 0,\n reachability_public_udp_failed: 0,\n reachability_public_tcp_success: 0,\n reachability_public_tcp_failed: 0,\n reachability_vmn_udp_success: 0,\n reachability_vmn_udp_failed: 0,\n reachability_vmn_tcp_success: 0,\n reachability_vmn_tcp_failed: 0,\n };\n\n const updateStats = (clusterType: 'public' | 'vmn', result: ReachabilityResult) => {\n if (result.udp?.reachable) {\n const outcome = result.udp.reachable === 'true' ? 'success' : 'failed';\n stats[`reachability_${clusterType}_udp_${outcome}`] += 1;\n }\n if (result.tcp?.reachable) {\n const outcome = result.tcp.reachable === 'true' ? 'success' : 'failed';\n stats[`reachability_${clusterType}_tcp_${outcome}`] += 1;\n }\n };\n\n try {\n // @ts-ignore\n const resultsJson = await this.webex.boundedStorage.get(\n REACHABILITY.namespace,\n REACHABILITY.localStorageResult\n );\n\n const internalResults: InternalReachabilityResults = JSON.parse(resultsJson);\n\n Object.values(internalResults).forEach((result) => {\n updateStats(result.isVideoMesh ? 'vmn' : 'public', result);\n });\n } catch (e) {\n // empty storage, that's ok\n LoggerProxy.logger.warn(\n 'Roap:request#getReachabilityMetrics --> Error parsing reachability data: ',\n e\n );\n }\n\n return stats;\n }\n\n /**\n * Reachability results as an object in the format that backend expects\n *\n * @returns {any} reachability results that need to be sent to the backend\n */\n async getReachabilityResults(): Promise<ReachabilityResults | undefined> {\n let results: ReachabilityResults;\n\n // these are the only props that backend needs in the reachability results:\n const reachabilityResultsProps: Array<keyof ReachabilityResult> = ['udp', 'tcp', 'xtls'];\n\n try {\n // @ts-ignore\n const resultsJson = await this.webex.boundedStorage.get(\n REACHABILITY.namespace,\n REACHABILITY.localStorageResult\n );\n\n const internalResults: InternalReachabilityResults = JSON.parse(resultsJson);\n\n results = mapValues(internalResults, (result) => pick(result, reachabilityResultsProps));\n } catch (e) {\n // empty storage, that's ok\n LoggerProxy.logger.warn(\n 'Roap:request#attachReachabilityData --> Error parsing reachability data: ',\n e\n );\n }\n\n return results;\n }\n\n /**\n * fetches reachability data and checks for cluster reachability\n * @returns {boolean}\n * @public\n * @memberof Reachability\n */\n async isAnyPublicClusterReachable() {\n let reachable = false;\n // @ts-ignore\n const reachabilityData = await this.webex.boundedStorage\n .get(this.namespace, REACHABILITY.localStorageResult)\n .catch(() => {});\n\n if (reachabilityData) {\n try {\n const reachabilityResults: InternalReachabilityResults = JSON.parse(reachabilityData);\n\n reachable = Object.values(reachabilityResults).some(\n (result) =>\n !result.isVideoMesh &&\n (result.udp?.reachable === 'true' || result.tcp?.reachable === 'true')\n );\n } catch (e) {\n LoggerProxy.logger.error(\n `Roap:request#attachReachabilityData --> Error in parsing reachability data: ${e}`\n );\n }\n }\n\n return reachable;\n }\n\n /**\n * Generate peerConnection config settings\n * @param {object} cluster\n * @returns {object} peerConnectionConfig\n * @private\n * @memberof Reachability\n */\n private buildPeerConnectionConfig(cluster: any) {\n const iceServers = uniq(cluster.udp).map((url) => ({\n username: '',\n credential: '',\n urls: [url],\n }));\n\n return {\n iceServers: [...iceServers],\n iceCandidatePoolSize: '0',\n iceTransportPolicy: 'all',\n };\n }\n\n /**\n * Creates an RTCPeerConnection\n * @param {object} cluster\n * @returns {RTCPeerConnection} peerConnection\n * @private\n * @memberof Reachability\n */\n private createPeerConnection(cluster: any) {\n const {key, config} = cluster;\n\n try {\n const peerConnection = new window.RTCPeerConnection(config);\n\n // @ts-ignore\n peerConnection.key = key;\n\n return peerConnection;\n } catch (peerConnectionError) {\n LoggerProxy.logger.log(\n `Reachability:index#createPeerConnection --> Error creating peerConnection: ${peerConnectionError}`\n );\n\n return null;\n }\n }\n\n /**\n * Gets total elapsed time\n * @param {RTCPeerConnection} peerConnection\n * @returns {Number} Milliseconds\n * @private\n * @memberof Reachability\n */\n private getElapsedTime(peerConnection: any) {\n const startTime = peerConnection.begin;\n\n delete peerConnection.begin;\n\n return Date.now() - startTime;\n }\n\n /**\n * creates offer and generates localSDP\n * @param {object} clusterList cluster List\n * @returns {Promise} Reachability latency results\n * @private\n * @memberof Reachability\n */\n private getLocalSDPForClusters(clusterList: object): Promise<InternalReachabilityResults> {\n let clusters: any[] = [...Object.keys(clusterList)];\n\n clusters = clusters.map(async (key) => {\n const cluster = clusterList[key];\n const config = this.buildPeerConnectionConfig(cluster);\n const peerConnection = this.createPeerConnection({key, config});\n const description = await peerConnection.createOffer({offerToReceiveAudio: true});\n\n // @ts-ignore\n peerConnection.begin = Date.now();\n peerConnection.setLocalDescription(description);\n\n return this.iceGatheringState(peerConnection, cluster.isVideoMesh).catch(\n (iceGatheringStateError) => {\n LoggerProxy.logger.log(\n `Reachability:index#getLocalSDPForClusters --> Error in getLocalSDP : ${iceGatheringStateError}`\n );\n }\n );\n });\n\n return Promise.all(clusters)\n .then(this.parseIceResultsToInternalReachabilityResults)\n .then((reachabilityLatencyResults) => {\n this.logUnreachableClusters();\n\n // return results\n return reachabilityLatencyResults;\n });\n }\n\n /**\n * Get list of all unreachable clusters\n * @returns {array} Unreachable clusters\n * @private\n * @memberof Reachability\n */\n private getUnreachablClusters() {\n const unreachableList = [];\n const clusters = this.clusterLatencyResults;\n\n Object.keys(clusters).forEach((key) => {\n const cluster = clusters[key];\n\n if (cluster.unreachable && !cluster.reachable) {\n unreachableList.push(key);\n }\n });\n\n return unreachableList;\n }\n\n /**\n * Attach an event handler for the icegatheringstatechange\n * event and measure latency.\n * @param {RTCPeerConnection} peerConnection\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private handleIceGatheringStateChange(peerConnection: RTCPeerConnection) {\n peerConnection.onicegatheringstatechange = () => {\n const {COMPLETE} = ICE_GATHERING_STATE;\n\n if (peerConnection.iceConnectionState === COMPLETE) {\n const elapsed = this.getElapsedTime(peerConnection);\n\n // @ts-ignore\n LoggerProxy.logger.log(\n // @ts-ignore\n `Reachability:index#onIceGatheringStateChange --> Successfully pinged ${peerConnection.key}:`,\n elapsed\n );\n this.setLatencyAndClose(peerConnection, elapsed);\n }\n };\n }\n\n /**\n * Attach an event handler for the icecandidate\n * event and measure latency.\n * @param {RTCPeerConnection} peerConnection\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private handleOnIceCandidate(peerConnection: RTCPeerConnection) {\n peerConnection.onicecandidate = (e) => {\n const SERVER_REFLEXIVE = 'srflx';\n\n if (e.candidate && String(e.candidate.type).toLowerCase() === SERVER_REFLEXIVE) {\n const elapsed = this.getElapsedTime(peerConnection);\n\n LoggerProxy.logger.log(\n // @ts-ignore\n `Reachability:index#onIceCandidate --> Successfully pinged ${peerConnection.key}:`,\n elapsed\n );\n // order is important\n this.addPublicIP(peerConnection, e.candidate.address);\n this.setLatencyAndClose(peerConnection, elapsed);\n }\n };\n }\n\n /**\n * An event handler on an RTCPeerConnection when the state of the ICE\n * candidate gathering process changes. Used to measure connection\n * speed.\n * @private\n * @param {RTCPeerConnection} peerConnection\n * @param {boolean} isVideoMesh\n * @returns {Promise}\n */\n private iceGatheringState(peerConnection: RTCPeerConnection, isVideoMesh: boolean) {\n const ELAPSED = 'elapsed';\n\n const timeout = isVideoMesh ? VIDEO_MESH_TIMEOUT : DEFAULT_TIMEOUT;\n\n return new Promise<ICECandidateResult>((resolve) => {\n const peerConnectionProxy = new window.Proxy(peerConnection, {\n // eslint-disable-next-line require-jsdoc\n get(target, property) {\n const targetMember = target[property];\n\n if (typeof targetMember === 'function') {\n return targetMember.bind(target);\n }\n\n return targetMember;\n },\n set: (target, property, value) => {\n // only intercept elapsed property\n if (property === ELAPSED) {\n resolve({\n // @ts-ignore\n clusterId: peerConnection.key,\n isVideoMesh,\n // @ts-ignore\n publicIPs: target.publicIPs,\n elapsed: value,\n });\n\n return true;\n }\n\n // pass thru\n return window.Reflect.set(target, property, value);\n },\n });\n\n // Using peerConnection proxy so handle functions below\n // won't be coupled to our promise implementation\n this.handleIceGatheringStateChange(peerConnectionProxy);\n this.handleOnIceCandidate(peerConnectionProxy);\n\n // Set maximum timeout\n window.setTimeout(() => {\n const {CLOSED} = CONNECTION_STATE;\n\n // Close any open peerConnections\n if (peerConnectionProxy.connectionState !== CLOSED) {\n // order is important\n this.addPublicIP(peerConnectionProxy, null);\n this.setLatencyAndClose(peerConnectionProxy, null);\n }\n }, timeout);\n });\n }\n\n /**\n * Make a log of unreachable clusters.\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private logUnreachableClusters() {\n const list = this.getUnreachablClusters();\n\n list.forEach((cluster) => {\n LoggerProxy.logger.log(\n `Reachability:index#logUnreachableClusters --> No ice candidate for ${cluster}.`\n );\n });\n }\n\n /**\n * Calculates time to establish connection\n * @param {Array<ICECandidateResult>} iceResults iceResults\n * @returns {object} reachabilityMap\n * @protected\n * @memberof Reachability\n */\n protected parseIceResultsToInternalReachabilityResults(\n iceResults: Array<ICECandidateResult>\n ): InternalReachabilityResults {\n const reachabilityMap = {};\n\n iceResults.forEach(({clusterId, isVideoMesh, elapsed, publicIPs}) => {\n const latencyResult = {};\n\n if (!elapsed) {\n Object.assign(latencyResult, {reachable: 'false'});\n } else {\n Object.assign(latencyResult, {\n reachable: 'true',\n latencyInMilliseconds: elapsed.toString(),\n });\n }\n\n if (publicIPs) {\n Object.assign(latencyResult, {\n clientMediaIPs: publicIPs,\n });\n }\n\n reachabilityMap[clusterId] = {\n udp: latencyResult,\n tcp: {untested: 'true'},\n xtls: {untested: 'true'},\n isVideoMesh,\n };\n });\n\n return reachabilityMap;\n }\n\n /**\n * fetches reachability data\n * @param {object} clusterList\n * @returns {Promise<InternalReachabilityResults>} reachability check results\n * @private\n * @memberof Reachability\n */\n private performReachabilityCheck(clusterList: object): Promise<InternalReachabilityResults> {\n if (!clusterList || !Object.keys(clusterList).length) {\n return Promise.resolve({});\n }\n\n return new Promise((resolve) => {\n this.getLocalSDPForClusters(clusterList)\n .then((localSDPData) => {\n if (!localSDPData || !Object.keys(localSDPData).length) {\n // TODO: handle the error condition properly and try retry\n LoggerProxy.logger.log(\n 'Reachability:index#performReachabilityCheck --> Local SDP is empty or has missing elements..returning'\n );\n resolve({});\n } else {\n resolve(localSDPData);\n }\n })\n .catch((error) => {\n LoggerProxy.logger.error(\n `Reachability:index#performReachabilityCheck --> Error in getLocalSDPForClusters: ${error}`\n );\n resolve({});\n });\n });\n }\n\n /**\n * Adds public IP (client media IPs)\n * @param {RTCPeerConnection} peerConnection\n * @param {string} publicIP\n * @returns {void}\n */\n protected addPublicIP(peerConnection: RTCPeerConnection, publicIP?: string | null) {\n const modifiedPeerConnection: RTCPeerConnection & {publicIPs?: string[]} = peerConnection;\n const {CLOSED} = CONNECTION_STATE;\n\n if (modifiedPeerConnection.connectionState === CLOSED) {\n LoggerProxy.logger.log(\n `Reachability:index#addPublicIP --> Attempting to set publicIP of ${publicIP} on closed peerConnection.`\n );\n }\n\n if (publicIP) {\n if (modifiedPeerConnection.publicIPs) {\n modifiedPeerConnection.publicIPs.push(publicIP);\n } else {\n modifiedPeerConnection.publicIPs = [publicIP];\n }\n } else {\n modifiedPeerConnection.publicIPs = null;\n }\n }\n\n /**\n * Records latency and closes the peerConnection\n * @param {RTCPeerConnection} peerConnection\n * @param {number} elapsed Latency in milliseconds\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private setLatencyAndClose(peerConnection: RTCPeerConnection, elapsed: number) {\n const REACHABLE = 'reachable';\n const UNREACHABLE = 'unreachable';\n const {CLOSED} = CONNECTION_STATE;\n // @ts-ignore\n const {key} = peerConnection;\n const resultKey = elapsed === null ? UNREACHABLE : REACHABLE;\n const intialState = {[REACHABLE]: 0, [UNREACHABLE]: 0};\n\n if (peerConnection.connectionState === CLOSED) {\n LoggerProxy.logger.log(\n `Reachability:index#setLatencyAndClose --> Attempting to set latency of ${elapsed} on closed peerConnection.`\n );\n\n return;\n }\n\n this.clusterLatencyResults[key] = this.clusterLatencyResults[key] || intialState;\n this.clusterLatencyResults[key][resultKey] += 1;\n\n // Set to null in case this fired from\n // an event other than onIceCandidate\n peerConnection.onicecandidate = null;\n peerConnection.close();\n // @ts-ignore\n peerConnection.elapsed = elapsed;\n }\n\n /**\n * utility function\n * @returns {undefined}\n * @private\n * @memberof Reachability\n */\n private setup() {\n this.clusterLatencyResults = {};\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extended Error object for general parameter errors
|
|
3
|
+
*/
|
|
4
|
+
export default class NoMeetingInfoError extends Error {
|
|
5
|
+
code: any;
|
|
6
|
+
error: any;
|
|
7
|
+
sdkMessage: any;
|
|
8
|
+
/**
|
|
9
|
+
* @constructor
|
|
10
|
+
* @param {String} [message]
|
|
11
|
+
* @param {Object} [error]
|
|
12
|
+
*/
|
|
13
|
+
constructor(message?: string, error?: any);
|
|
14
|
+
}
|
|
@@ -278,6 +278,7 @@ export declare const MEETING_REMOVED_REASON: {
|
|
|
278
278
|
NO_MEETINGS_TO_SYNC: string;
|
|
279
279
|
MEETING_CONNECTION_FAILED: string;
|
|
280
280
|
LOCUS_DTO_SYNC_FAILED: string;
|
|
281
|
+
MISSING_MEETING_INFO: string;
|
|
281
282
|
};
|
|
282
283
|
export declare const CALL_REMOVED_REASON: {
|
|
283
284
|
CALL_INACTIVE: string;
|
|
@@ -361,6 +362,11 @@ export declare const ERROR_DICTIONARY: {
|
|
|
361
362
|
MESSAGE: string;
|
|
362
363
|
CODE: number;
|
|
363
364
|
};
|
|
365
|
+
NO_MEETING_INFO: {
|
|
366
|
+
NAME: string;
|
|
367
|
+
MESSAGE: string;
|
|
368
|
+
CODE: number;
|
|
369
|
+
};
|
|
364
370
|
};
|
|
365
371
|
export declare const FLOOR_ACTION: {
|
|
366
372
|
GRANTED: string;
|
|
@@ -966,7 +966,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
966
966
|
mediaOptions?: AddMediaOptions;
|
|
967
967
|
}): Promise<{
|
|
968
968
|
join: any;
|
|
969
|
-
media:
|
|
969
|
+
media: void;
|
|
970
970
|
}>;
|
|
971
971
|
/**
|
|
972
972
|
* Initiates the reconnection of the media in the meeting
|
|
@@ -1138,7 +1138,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1138
1138
|
* @public
|
|
1139
1139
|
* @memberof Meeting
|
|
1140
1140
|
*/
|
|
1141
|
-
addMedia(options?: AddMediaOptions): Promise<
|
|
1141
|
+
addMedia(options?: AddMediaOptions): Promise<void>;
|
|
1142
1142
|
/**
|
|
1143
1143
|
* Informs if the peer connection is in a state that can be updated with updateMedia (audio/video/share)
|
|
1144
1144
|
* @returns {Boolean}
|
|
@@ -293,17 +293,19 @@ export default class Meetings extends WebexPlugin {
|
|
|
293
293
|
* @param {Boolean} useRandomDelayForInfo - whether a random delay should be added to fetching meeting info
|
|
294
294
|
* @param {Object} infoExtraParams extra parameters to be provided when fetching meeting info
|
|
295
295
|
* @param {string} correlationId - the optional specified correlationId
|
|
296
|
+
* @param {Boolean} failOnMissingMeetingInfo - whether to throw an error if meeting info fails to fetch (for calls that are not 1:1 or content share)
|
|
296
297
|
* @returns {Promise<Meeting>} A new Meeting.
|
|
297
298
|
* @public
|
|
298
299
|
* @memberof Meetings
|
|
299
300
|
*/
|
|
300
|
-
create(destination: string, type?: string, useRandomDelayForInfo?: boolean, infoExtraParams?: {}, correlationId?: string): any;
|
|
301
|
+
create(destination: string, type?: string, useRandomDelayForInfo?: boolean, infoExtraParams?: {}, correlationId?: string, failOnMissingMeetingInfo?: boolean): any;
|
|
301
302
|
/**
|
|
302
303
|
* @param {String} destination see create()
|
|
303
304
|
* @param {String} type see create()
|
|
304
305
|
* @param {Boolean} useRandomDelayForInfo whether a random delay should be added to fetching meeting info
|
|
305
306
|
* @param {Object} infoExtraParams extra parameters to be provided when fetching meeting info
|
|
306
307
|
* @param {String} correlationId the optional specified correlationId
|
|
308
|
+
* @param {Boolean} failOnMissingMeetingInfo - whether to throw an error if meeting info fails to fetch (for calls that are not 1:1 or content share)
|
|
307
309
|
* @returns {Promise} a new meeting instance complete with meeting info and destination
|
|
308
310
|
* @private
|
|
309
311
|
* @memberof Meetings
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
3
|
*/
|
|
4
|
+
export type ReachabilityMetrics = {
|
|
5
|
+
reachability_public_udp_success: number;
|
|
6
|
+
reachability_public_udp_failed: number;
|
|
7
|
+
reachability_public_tcp_success: number;
|
|
8
|
+
reachability_public_tcp_failed: number;
|
|
9
|
+
reachability_vmn_udp_success: number;
|
|
10
|
+
reachability_vmn_udp_failed: number;
|
|
11
|
+
reachability_vmn_tcp_success: number;
|
|
12
|
+
reachability_vmn_tcp_failed: number;
|
|
13
|
+
};
|
|
4
14
|
export type TransportResult = {
|
|
5
|
-
reachable
|
|
15
|
+
reachable?: 'true' | 'false';
|
|
6
16
|
latencyInMilliseconds?: string;
|
|
7
17
|
clientMediaIPs?: string[];
|
|
8
18
|
untested?: 'true';
|
|
@@ -47,6 +57,13 @@ export default class Reachability {
|
|
|
47
57
|
* @memberof Reachability
|
|
48
58
|
*/
|
|
49
59
|
gatherReachability(): Promise<InternalReachabilityResults>;
|
|
60
|
+
/**
|
|
61
|
+
* Returns statistics about last reachability results. The returned value is an object
|
|
62
|
+
* with a flat list of properties so that it can be easily sent with metrics
|
|
63
|
+
*
|
|
64
|
+
* @returns {Promise} Promise with metrics values, it never rejects/throws.
|
|
65
|
+
*/
|
|
66
|
+
getReachabilityMetrics(): Promise<ReachabilityMetrics>;
|
|
50
67
|
/**
|
|
51
68
|
* Reachability results as an object in the format that backend expects
|
|
52
69
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/plugin-meetings",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.263",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
|
|
6
6
|
"contributors": [
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"build": "yarn run -T tsc --declaration true --declarationDir ./dist/types"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@webex/plugin-meetings": "3.0.0-beta.
|
|
36
|
-
"@webex/test-helper-chai": "3.0.0-beta.
|
|
37
|
-
"@webex/test-helper-mocha": "3.0.0-beta.
|
|
38
|
-
"@webex/test-helper-mock-webex": "3.0.0-beta.
|
|
39
|
-
"@webex/test-helper-retry": "3.0.0-beta.
|
|
40
|
-
"@webex/test-helper-test-users": "3.0.0-beta.
|
|
35
|
+
"@webex/plugin-meetings": "3.0.0-beta.263",
|
|
36
|
+
"@webex/test-helper-chai": "3.0.0-beta.263",
|
|
37
|
+
"@webex/test-helper-mocha": "3.0.0-beta.263",
|
|
38
|
+
"@webex/test-helper-mock-webex": "3.0.0-beta.263",
|
|
39
|
+
"@webex/test-helper-retry": "3.0.0-beta.263",
|
|
40
|
+
"@webex/test-helper-test-users": "3.0.0-beta.263",
|
|
41
41
|
"chai": "^4.3.4",
|
|
42
42
|
"chai-as-promised": "^7.1.1",
|
|
43
43
|
"jsdom-global": "3.0.2",
|
|
@@ -46,19 +46,19 @@
|
|
|
46
46
|
"typescript": "^4.7.4"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@webex/common": "3.0.0-beta.
|
|
49
|
+
"@webex/common": "3.0.0-beta.263",
|
|
50
50
|
"@webex/internal-media-core": "2.0.4",
|
|
51
|
-
"@webex/internal-plugin-conversation": "3.0.0-beta.
|
|
52
|
-
"@webex/internal-plugin-device": "3.0.0-beta.
|
|
53
|
-
"@webex/internal-plugin-llm": "3.0.0-beta.
|
|
54
|
-
"@webex/internal-plugin-mercury": "3.0.0-beta.
|
|
55
|
-
"@webex/internal-plugin-metrics": "3.0.0-beta.
|
|
56
|
-
"@webex/internal-plugin-support": "3.0.0-beta.
|
|
57
|
-
"@webex/internal-plugin-user": "3.0.0-beta.
|
|
58
|
-
"@webex/media-helpers": "3.0.0-beta.
|
|
59
|
-
"@webex/plugin-people": "3.0.0-beta.
|
|
60
|
-
"@webex/plugin-rooms": "3.0.0-beta.
|
|
61
|
-
"@webex/webex-core": "3.0.0-beta.
|
|
51
|
+
"@webex/internal-plugin-conversation": "3.0.0-beta.263",
|
|
52
|
+
"@webex/internal-plugin-device": "3.0.0-beta.263",
|
|
53
|
+
"@webex/internal-plugin-llm": "3.0.0-beta.263",
|
|
54
|
+
"@webex/internal-plugin-mercury": "3.0.0-beta.263",
|
|
55
|
+
"@webex/internal-plugin-metrics": "3.0.0-beta.263",
|
|
56
|
+
"@webex/internal-plugin-support": "3.0.0-beta.263",
|
|
57
|
+
"@webex/internal-plugin-user": "3.0.0-beta.263",
|
|
58
|
+
"@webex/media-helpers": "3.0.0-beta.263",
|
|
59
|
+
"@webex/plugin-people": "3.0.0-beta.263",
|
|
60
|
+
"@webex/plugin-rooms": "3.0.0-beta.263",
|
|
61
|
+
"@webex/webex-core": "3.0.0-beta.263",
|
|
62
62
|
"ampersand-collection": "^2.0.2",
|
|
63
63
|
"bowser": "^2.11.0",
|
|
64
64
|
"btoa": "^1.2.1",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {ERROR_DICTIONARY} from '../../constants';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Extended Error object for general parameter errors
|
|
5
|
+
*/
|
|
6
|
+
export default class NoMeetingInfoError extends Error {
|
|
7
|
+
code: any;
|
|
8
|
+
error: any;
|
|
9
|
+
sdkMessage: any;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @constructor
|
|
13
|
+
* @param {String} [message]
|
|
14
|
+
* @param {Object} [error]
|
|
15
|
+
*/
|
|
16
|
+
constructor(message: string = ERROR_DICTIONARY.NO_MEETING_INFO.MESSAGE, error: any = null) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.name = ERROR_DICTIONARY.NO_MEETING_INFO.NAME;
|
|
19
|
+
this.sdkMessage = ERROR_DICTIONARY.NO_MEETING_INFO.MESSAGE;
|
|
20
|
+
this.error = error;
|
|
21
|
+
this.stack = error ? error.stack : new Error().stack;
|
|
22
|
+
this.code = ERROR_DICTIONARY.NO_MEETING_INFO.CODE;
|
|
23
|
+
}
|
|
24
|
+
}
|
package/src/constants.ts
CHANGED
|
@@ -389,6 +389,7 @@ export const MEETING_REMOVED_REASON = {
|
|
|
389
389
|
NO_MEETINGS_TO_SYNC: 'NO_MEETINGS_TO_SYNC', // After the syncMeeting no meeting exists
|
|
390
390
|
MEETING_CONNECTION_FAILED: 'MEETING_CONNECTION_FAILED', // meeting failed to connect due to ice failures or firewall issue
|
|
391
391
|
LOCUS_DTO_SYNC_FAILED: 'LOCUS_DTO_SYNC_FAILED', // failed to get any Locus DTO for that meeting
|
|
392
|
+
MISSING_MEETING_INFO: 'MISSING_MEETING_INFO', // meeting info failed to be fetched
|
|
392
393
|
};
|
|
393
394
|
|
|
394
395
|
// One one one calls ends for the following reasons
|
|
@@ -485,6 +486,11 @@ export const ERROR_DICTIONARY = {
|
|
|
485
486
|
MESSAGE: 'Edit lock token mismatch',
|
|
486
487
|
CODE: 9,
|
|
487
488
|
},
|
|
489
|
+
NO_MEETING_INFO: {
|
|
490
|
+
NAME: 'NoMeetingInfo',
|
|
491
|
+
MESSAGE: 'No meeting info found for the meeting',
|
|
492
|
+
CODE: 10,
|
|
493
|
+
},
|
|
488
494
|
};
|
|
489
495
|
|
|
490
496
|
export const FLOOR_ACTION = {
|