@webex/plugin-meetings 3.0.0-stream-classes.2 → 3.0.0-stream-classes.4
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/webex-errors.js +25 -5
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/constants.js +2 -0
- 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 +4 -8
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +1 -1
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/request.js +23 -13
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +33 -3
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/util.js +1 -1
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.js +16 -31
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/index.js +9 -6
- package/dist/meetings/index.js.map +1 -1
- package/dist/metrics/constants.js +1 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/reachability/index.js +2 -11
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.js.map +1 -1
- package/dist/reconnection-manager/index.js +26 -22
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/index.js +5 -7
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +1 -0
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +3 -4
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/types/common/errors/webex-errors.d.ts +12 -0
- package/dist/types/meetings/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/common/errors/webex-errors.ts +21 -0
- package/src/config.ts +2 -2
- package/src/constants.ts +2 -2
- package/src/meeting/index.ts +4 -4
- package/src/meeting/locusMediaRequest.ts +2 -3
- package/src/meeting/request.ts +15 -5
- package/src/meeting/util.ts +36 -2
- package/src/meeting-info/util.ts +1 -1
- package/src/meeting-info/utilv2.ts +10 -20
- package/src/meetings/index.ts +10 -6
- package/src/metrics/constants.ts +1 -0
- package/src/reachability/index.ts +4 -10
- package/src/reachability/request.ts +1 -1
- package/src/reconnection-manager/index.ts +13 -11
- package/src/roap/index.ts +2 -4
- package/src/roap/request.ts +2 -1
- package/src/roap/turnDiscovery.ts +2 -3
- package/test/unit/spec/meeting/index.js +8 -6
- package/test/unit/spec/meeting/locusMediaRequest.ts +1 -2
- package/test/unit/spec/meeting/request.js +23 -0
- package/test/unit/spec/meeting/utils.js +73 -4
- package/test/unit/spec/meetings/index.js +66 -1
- package/test/unit/spec/reachability/index.ts +8 -8
- package/test/unit/spec/reconnection-manager/index.js +21 -0
- package/test/unit/spec/roap/index.ts +5 -1
- package/test/unit/spec/roap/turnDiscovery.ts +11 -4
|
@@ -18,6 +18,7 @@ var _metrics = _interopRequireDefault(require("../metrics"));
|
|
|
18
18
|
var _constants = _interopRequireDefault(require("../metrics/constants"));
|
|
19
19
|
var _loggerProxy = _interopRequireDefault(require("../common/logs/logger-proxy"));
|
|
20
20
|
var _constants2 = require("../constants");
|
|
21
|
+
var _util = _interopRequireDefault(require("../meeting/util"));
|
|
21
22
|
// @ts-ignore - Types not available for @webex/common
|
|
22
23
|
|
|
23
24
|
var TURN_DISCOVERY_TIMEOUT = 10; // in seconds
|
|
@@ -158,7 +159,7 @@ var TurnDiscovery = /*#__PURE__*/function () {
|
|
|
158
159
|
meetingId: meeting.id,
|
|
159
160
|
locusMediaRequest: meeting.locusMediaRequest,
|
|
160
161
|
// @ts-ignore - because of meeting.webex
|
|
161
|
-
ipVersion:
|
|
162
|
+
ipVersion: _util.default.getIpVersion(meeting.webex)
|
|
162
163
|
}).then(function (_ref) {
|
|
163
164
|
var mediaConnections = _ref.mediaConnections;
|
|
164
165
|
if (mediaConnections) {
|
|
@@ -189,9 +190,7 @@ var TurnDiscovery = /*#__PURE__*/function () {
|
|
|
189
190
|
// @ts-ignore - fix type
|
|
190
191
|
mediaId: meeting.mediaId,
|
|
191
192
|
meetingId: meeting.id,
|
|
192
|
-
locusMediaRequest: meeting.locusMediaRequest
|
|
193
|
-
// @ts-ignore - because of meeting.webex
|
|
194
|
-
ipVersion: meeting.webex.meetings.reachability.getIpVersion()
|
|
193
|
+
locusMediaRequest: meeting.locusMediaRequest
|
|
195
194
|
});
|
|
196
195
|
}
|
|
197
196
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TURN_DISCOVERY_TIMEOUT","TURN_DISCOVERY_SEQ","TurnDiscovery","roapRequest","turnInfo","url","username","password","defer","LoggerProxy","logger","warn","reject","Error","responseTimer","setTimeout","info","promise","roapMessage","headers","expectedHeaders","headerName","field","foundHeaders","forEach","receivedHeader","expectedHeader","startsWith","substring","length","clearTimeout","undefined","resolve","meeting","isReconnecting","Defer","messageType","ROAP","ROAP_TYPES","TURN_DISCOVERY_REQUEST","version","ROAP_VERSION","seq","sendRoap","locusSelfUrl","selfUrl","mediaId","meetingId","id","locusMediaRequest","ipVersion","webex","meetings","reachability","getIpVersion","then","mediaConnections","updateMediaConnections","OK","isAnyClusterReachable","config","experimental","enableTurnDiscovery","getSkipReason","skipReason","turnDiscoverySkippedReason","turnServerInfo","sendRoapTurnDiscoveryRequest","waitForTurnDiscoveryResponse","sendRoapOK","catch","e","Metrics","sendBehavioralMetric","BEHAVIORAL_METRICS","TURN_DISCOVERY_FAILURE","correlation_id","correlationId","locus_id","locusUrl","split","pop","reason","message","stack"],"sources":["turnDiscovery.ts"],"sourcesContent":["// @ts-ignore - Types not available for @webex/common\nimport {Defer} from '@webex/common';\n\nimport Metrics from '../metrics';\nimport BEHAVIORAL_METRICS from '../metrics/constants';\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport {ROAP} from '../constants';\n\nimport RoapRequest from './request';\nimport Meeting from '../meeting';\n\nconst TURN_DISCOVERY_TIMEOUT = 10; // in seconds\n\n// Roap spec says that seq should start from 1, but TURN discovery works fine with seq=0\n// and this is handy for us, because TURN discovery is always done before the first SDP exchange,\n// so we can do it with seq=0 or not do it at all and then we create the RoapMediaConnection\n// and do the SDP offer with seq=1\nconst TURN_DISCOVERY_SEQ = 0;\n\n/**\n * Handles the process of finding out TURN server information from Linus.\n * This is achieved by sending a TURN_DISCOVERY_REQUEST.\n */\nexport default class TurnDiscovery {\n private roapRequest: RoapRequest;\n\n private defer?: Defer; // used for waiting for the response\n\n private turnInfo: {\n url: string;\n username: string;\n password: string;\n };\n\n private responseTimer?: ReturnType<typeof setTimeout>;\n\n /**\n * Constructor\n *\n * @param {RoapRequest} roapRequest\n */\n constructor(roapRequest: RoapRequest) {\n this.roapRequest = roapRequest;\n this.turnInfo = {\n url: '',\n username: '',\n password: '',\n };\n }\n\n /**\n * waits for TURN_DISCOVERY_RESPONSE message to arrive\n *\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n private waitForTurnDiscoveryResponse() {\n if (!this.defer) {\n LoggerProxy.logger.warn(\n 'Roap:turnDiscovery#waitForTurnDiscoveryResponse --> TURN discovery is not in progress'\n );\n\n return Promise.reject(\n new Error('waitForTurnDiscoveryResponse() called before sendRoapTurnDiscoveryRequest()')\n );\n }\n\n const {defer} = this;\n\n this.responseTimer = setTimeout(() => {\n LoggerProxy.logger.warn(\n `Roap:turnDiscovery#waitForTurnDiscoveryResponse --> timeout! no response arrived within ${TURN_DISCOVERY_TIMEOUT} seconds`\n );\n\n defer.reject(new Error('Timed out waiting for TURN_DISCOVERY_RESPONSE'));\n }, TURN_DISCOVERY_TIMEOUT * 1000);\n\n LoggerProxy.logger.info(\n 'Roap:turnDiscovery#waitForTurnDiscoveryResponse --> waiting for TURN_DISCOVERY_RESPONSE...'\n );\n\n return defer.promise;\n }\n\n /**\n * handles TURN_DISCOVERY_RESPONSE roap message\n *\n * @param {Object} roapMessage\n * @returns {void}\n * @public\n * @memberof Roap\n */\n public handleTurnDiscoveryResponse(roapMessage: object) {\n // @ts-ignore - Fix missing type\n const {headers} = roapMessage;\n\n if (!this.defer) {\n LoggerProxy.logger.warn(\n 'Roap:turnDiscovery#handleTurnDiscoveryResponse --> unexpected TURN discovery response'\n );\n\n return;\n }\n\n const expectedHeaders = [\n {headerName: 'x-cisco-turn-url', field: 'url'},\n {headerName: 'x-cisco-turn-username', field: 'username'},\n {headerName: 'x-cisco-turn-password', field: 'password'},\n ];\n\n let foundHeaders = 0;\n\n headers?.forEach((receivedHeader) => {\n // check if it matches any of our expected headers\n expectedHeaders.forEach((expectedHeader) => {\n if (receivedHeader.startsWith(`${expectedHeader.headerName}=`)) {\n this.turnInfo[expectedHeader.field] = receivedHeader.substring(\n expectedHeader.headerName.length + 1\n );\n foundHeaders += 1;\n }\n });\n });\n\n clearTimeout(this.responseTimer);\n this.responseTimer = undefined;\n\n if (foundHeaders !== expectedHeaders.length) {\n LoggerProxy.logger.warn(\n `Roap:turnDiscovery#handleTurnDiscoveryResponse --> missing some headers, received: ${JSON.stringify(\n headers\n )}`\n );\n this.defer.reject(\n new Error(`TURN_DISCOVERY_RESPONSE missing some headers: ${JSON.stringify(headers)}`)\n );\n } else {\n LoggerProxy.logger.info(\n `Roap:turnDiscovery#handleTurnDiscoveryResponse --> received a valid response, url=${this.turnInfo.url}`\n );\n this.defer.resolve();\n }\n }\n\n /**\n * sends the TURN_DISCOVERY_REQUEST roap request\n *\n * @param {Meeting} meeting\n * @param {Boolean} isReconnecting\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n sendRoapTurnDiscoveryRequest(meeting: Meeting, isReconnecting: boolean) {\n if (this.defer) {\n LoggerProxy.logger.warn(\n 'Roap:turnDiscovery#sendRoapTurnDiscoveryRequest --> already in progress'\n );\n\n return Promise.resolve();\n }\n\n this.defer = new Defer();\n\n const roapMessage = {\n messageType: ROAP.ROAP_TYPES.TURN_DISCOVERY_REQUEST,\n version: ROAP.ROAP_VERSION,\n seq: TURN_DISCOVERY_SEQ,\n };\n\n LoggerProxy.logger.info(\n 'Roap:turnDiscovery#sendRoapTurnDiscoveryRequest --> sending TURN_DISCOVERY_REQUEST'\n );\n\n return this.roapRequest\n .sendRoap({\n roapMessage,\n // @ts-ignore - Fix missing type\n locusSelfUrl: meeting.selfUrl,\n // @ts-ignore - Fix missing type\n mediaId: isReconnecting ? '' : meeting.mediaId,\n meetingId: meeting.id,\n locusMediaRequest: meeting.locusMediaRequest,\n // @ts-ignore - because of meeting.webex\n ipVersion: meeting.webex.meetings.reachability.getIpVersion(),\n })\n .then(({mediaConnections}) => {\n if (mediaConnections) {\n meeting.updateMediaConnections(mediaConnections);\n }\n });\n }\n\n /**\n * Sends the OK message that server expects to receive\n * after it sends us TURN_DISCOVERY_RESPONSE\n *\n * @param {Meeting} meeting\n * @returns {Promise}\n */\n sendRoapOK(meeting: Meeting) {\n LoggerProxy.logger.info('Roap:turnDiscovery#sendRoapOK --> sending OK');\n\n return this.roapRequest.sendRoap({\n roapMessage: {\n messageType: ROAP.ROAP_TYPES.OK,\n version: ROAP.ROAP_VERSION,\n seq: TURN_DISCOVERY_SEQ,\n },\n // @ts-ignore - fix type\n locusSelfUrl: meeting.selfUrl,\n // @ts-ignore - fix type\n mediaId: meeting.mediaId,\n meetingId: meeting.id,\n locusMediaRequest: meeting.locusMediaRequest,\n // @ts-ignore - because of meeting.webex\n ipVersion: meeting.webex.meetings.reachability.getIpVersion(),\n });\n }\n\n /**\n * Gets the reason why reachability is skipped.\n *\n * @param {Meeting} meeting\n * @returns {Promise<string>} Promise with empty string if reachability is not skipped or a reason if it is skipped\n */\n private async getSkipReason(meeting: Meeting): Promise<string> {\n // @ts-ignore - fix type\n const isAnyClusterReachable = await meeting.webex.meetings.reachability.isAnyClusterReachable();\n\n if (isAnyClusterReachable) {\n LoggerProxy.logger.info(\n 'Roap:turnDiscovery#getSkipReason --> reachability has not failed, skipping TURN discovery'\n );\n\n return 'reachability';\n }\n\n // @ts-ignore - fix type\n if (!meeting.config.experimental.enableTurnDiscovery) {\n LoggerProxy.logger.info(\n 'Roap:turnDiscovery#getSkipReason --> TURN discovery disabled in config, skipping it'\n );\n\n return 'config';\n }\n\n return '';\n }\n\n /**\n * Checks if TURN discovery is skipped.\n *\n * @param {Meeting} meeting\n * @returns {Boolean} true if TURN discovery is being skipped, false if it is being done\n */\n async isSkipped(meeting) {\n const skipReason = await this.getSkipReason(meeting);\n\n return !!skipReason;\n }\n\n /**\n * Retrieves TURN server information from the backend by doing\n * a roap message exchange:\n * client server\n * | -----TURN_DISCOVERY_REQUEST-----> |\n * | <----TURN_DISCOVERY_RESPONSE----- |\n * | --------------OK----------------> |\n *\n * This TURN discovery roap exchange is always done with seq=0.\n * The RoapMediaConnection SDP exchange always starts with seq=1,\n * so it works fine no matter if TURN discovery is done or not.\n *\n * @param {Meeting} meeting\n * @param {Boolean} isReconnecting should be set to true if this is a new\n * media connection just after a reconnection\n * @returns {Promise}\n */\n async doTurnDiscovery(meeting: Meeting, isReconnecting?: boolean) {\n const turnDiscoverySkippedReason = await this.getSkipReason(meeting);\n\n if (turnDiscoverySkippedReason) {\n return {\n turnServerInfo: undefined,\n turnDiscoverySkippedReason,\n };\n }\n\n return this.sendRoapTurnDiscoveryRequest(meeting, isReconnecting)\n .then(() => this.waitForTurnDiscoveryResponse())\n .then(() => this.sendRoapOK(meeting))\n .then(() => {\n this.defer = undefined;\n\n LoggerProxy.logger.info('Roap:turnDiscovery#doTurnDiscovery --> TURN discovery completed');\n\n return {turnServerInfo: this.turnInfo, turnDiscoverySkippedReason: undefined};\n })\n .catch((e) => {\n // we catch any errors and resolve with no turn information so that the normal call join flow can continue without TURN\n LoggerProxy.logger.info(\n `Roap:turnDiscovery#doTurnDiscovery --> TURN discovery failed, continuing without TURN: ${e}`\n );\n\n Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.TURN_DISCOVERY_FAILURE, {\n correlation_id: meeting.correlationId,\n locus_id: meeting.locusUrl.split('/').pop(),\n reason: e.message,\n stack: e.stack,\n });\n\n return {turnServerInfo: undefined, turnDiscoverySkippedReason: undefined};\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AACA;AAEA;AACA;AACA;AACA;AANA;;AAWA,IAAMA,sBAAsB,GAAG,EAAE,CAAC,CAAC;;AAEnC;AACA;AACA;AACA;AACA,IAAMC,kBAAkB,GAAG,CAAC;;AAE5B;AACA;AACA;AACA;AAHA,IAIqBC,aAAa;EAGT;;EAUvB;AACF;AACA;AACA;AACA;EACE,uBAAYC,WAAwB,EAAE;IAAA;IAAA;IAAA;IAAA;IAAA;IACpC,IAAI,CAACA,WAAW,GAAGA,WAAW;IAC9B,IAAI,CAACC,QAAQ,GAAG;MACdC,GAAG,EAAE,EAAE;MACPC,QAAQ,EAAE,EAAE;MACZC,QAAQ,EAAE;IACZ,CAAC;EACH;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;EANE;IAAA;IAAA,OAOA,wCAAuC;MACrC,IAAI,CAAC,IAAI,CAACC,KAAK,EAAE;QACfC,oBAAW,CAACC,MAAM,CAACC,IAAI,CACrB,uFAAuF,CACxF;QAED,OAAO,iBAAQC,MAAM,CACnB,IAAIC,KAAK,CAAC,6EAA6E,CAAC,CACzF;MACH;MAEA,IAAOL,KAAK,GAAI,IAAI,CAAbA,KAAK;MAEZ,IAAI,CAACM,aAAa,GAAGC,UAAU,CAAC,YAAM;QACpCN,oBAAW,CAACC,MAAM,CAACC,IAAI,mGACsEX,sBAAsB,cAClH;QAEDQ,KAAK,CAACI,MAAM,CAAC,IAAIC,KAAK,CAAC,+CAA+C,CAAC,CAAC;MAC1E,CAAC,EAAEb,sBAAsB,GAAG,IAAI,CAAC;MAEjCS,oBAAW,CAACC,MAAM,CAACM,IAAI,CACrB,4FAA4F,CAC7F;MAED,OAAOR,KAAK,CAACS,OAAO;IACtB;;IAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EAPE;IAAA;IAAA,OAQA,qCAAmCC,WAAmB,EAAE;MAAA;MACtD;MACA,IAAOC,OAAO,GAAID,WAAW,CAAtBC,OAAO;MAEd,IAAI,CAAC,IAAI,CAACX,KAAK,EAAE;QACfC,oBAAW,CAACC,MAAM,CAACC,IAAI,CACrB,uFAAuF,CACxF;QAED;MACF;MAEA,IAAMS,eAAe,GAAG,CACtB;QAACC,UAAU,EAAE,kBAAkB;QAAEC,KAAK,EAAE;MAAK,CAAC,EAC9C;QAACD,UAAU,EAAE,uBAAuB;QAAEC,KAAK,EAAE;MAAU,CAAC,EACxD;QAACD,UAAU,EAAE,uBAAuB;QAAEC,KAAK,EAAE;MAAU,CAAC,CACzD;MAED,IAAIC,YAAY,GAAG,CAAC;MAEpBJ,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAEK,OAAO,CAAC,UAACC,cAAc,EAAK;QACnC;QACAL,eAAe,CAACI,OAAO,CAAC,UAACE,cAAc,EAAK;UAC1C,IAAID,cAAc,CAACE,UAAU,WAAID,cAAc,CAACL,UAAU,OAAI,EAAE;YAC9D,KAAI,CAACjB,QAAQ,CAACsB,cAAc,CAACJ,KAAK,CAAC,GAAGG,cAAc,CAACG,SAAS,CAC5DF,cAAc,CAACL,UAAU,CAACQ,MAAM,GAAG,CAAC,CACrC;YACDN,YAAY,IAAI,CAAC;UACnB;QACF,CAAC,CAAC;MACJ,CAAC,CAAC;MAEFO,YAAY,CAAC,IAAI,CAAChB,aAAa,CAAC;MAChC,IAAI,CAACA,aAAa,GAAGiB,SAAS;MAE9B,IAAIR,YAAY,KAAKH,eAAe,CAACS,MAAM,EAAE;QAC3CpB,oBAAW,CAACC,MAAM,CAACC,IAAI,8FACiE,wBACpFQ,OAAO,CACR,EACF;QACD,IAAI,CAACX,KAAK,CAACI,MAAM,CACf,IAAIC,KAAK,yDAAkD,wBAAeM,OAAO,CAAC,EAAG,CACtF;MACH,CAAC,MAAM;QACLV,oBAAW,CAACC,MAAM,CAACM,IAAI,6FACgE,IAAI,CAACZ,QAAQ,CAACC,GAAG,EACvG;QACD,IAAI,CAACG,KAAK,CAACwB,OAAO,EAAE;MACtB;IACF;;IAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EARE;IAAA;IAAA,OASA,sCAA6BC,OAAgB,EAAEC,cAAuB,EAAE;MACtE,IAAI,IAAI,CAAC1B,KAAK,EAAE;QACdC,oBAAW,CAACC,MAAM,CAACC,IAAI,CACrB,yEAAyE,CAC1E;QAED,OAAO,iBAAQqB,OAAO,EAAE;MAC1B;MAEA,IAAI,CAACxB,KAAK,GAAG,IAAI2B,aAAK,EAAE;MAExB,IAAMjB,WAAW,GAAG;QAClBkB,WAAW,EAAEC,gBAAI,CAACC,UAAU,CAACC,sBAAsB;QACnDC,OAAO,EAAEH,gBAAI,CAACI,YAAY;QAC1BC,GAAG,EAAEzC;MACP,CAAC;MAEDQ,oBAAW,CAACC,MAAM,CAACM,IAAI,CACrB,oFAAoF,CACrF;MAED,OAAO,IAAI,CAACb,WAAW,CACpBwC,QAAQ,CAAC;QACRzB,WAAW,EAAXA,WAAW;QACX;QACA0B,YAAY,EAAEX,OAAO,CAACY,OAAO;QAC7B;QACAC,OAAO,EAAEZ,cAAc,GAAG,EAAE,GAAGD,OAAO,CAACa,OAAO;QAC9CC,SAAS,EAAEd,OAAO,CAACe,EAAE;QACrBC,iBAAiB,EAAEhB,OAAO,CAACgB,iBAAiB;QAC5C;QACAC,SAAS,EAAEjB,OAAO,CAACkB,KAAK,CAACC,QAAQ,CAACC,YAAY,CAACC,YAAY;MAC7D,CAAC,CAAC,CACDC,IAAI,CAAC,gBAAwB;QAAA,IAAtBC,gBAAgB,QAAhBA,gBAAgB;QACtB,IAAIA,gBAAgB,EAAE;UACpBvB,OAAO,CAACwB,sBAAsB,CAACD,gBAAgB,CAAC;QAClD;MACF,CAAC,CAAC;IACN;;IAEA;AACF;AACA;AACA;AACA;AACA;AACA;EANE;IAAA;IAAA,OAOA,oBAAWvB,OAAgB,EAAE;MAC3BxB,oBAAW,CAACC,MAAM,CAACM,IAAI,CAAC,8CAA8C,CAAC;MAEvE,OAAO,IAAI,CAACb,WAAW,CAACwC,QAAQ,CAAC;QAC/BzB,WAAW,EAAE;UACXkB,WAAW,EAAEC,gBAAI,CAACC,UAAU,CAACoB,EAAE;UAC/BlB,OAAO,EAAEH,gBAAI,CAACI,YAAY;UAC1BC,GAAG,EAAEzC;QACP,CAAC;QACD;QACA2C,YAAY,EAAEX,OAAO,CAACY,OAAO;QAC7B;QACAC,OAAO,EAAEb,OAAO,CAACa,OAAO;QACxBC,SAAS,EAAEd,OAAO,CAACe,EAAE;QACrBC,iBAAiB,EAAEhB,OAAO,CAACgB,iBAAiB;QAC5C;QACAC,SAAS,EAAEjB,OAAO,CAACkB,KAAK,CAACC,QAAQ,CAACC,YAAY,CAACC,YAAY;MAC7D,CAAC,CAAC;IACJ;;IAEA;AACF;AACA;AACA;AACA;AACA;EALE;IAAA;IAAA;MAAA,6FAMA,iBAA4BrB,OAAgB;QAAA;QAAA;UAAA;YAAA;cAAA;cAAA,OAENA,OAAO,CAACkB,KAAK,CAACC,QAAQ,CAACC,YAAY,CAACM,qBAAqB,EAAE;YAAA;cAAzFA,qBAAqB;cAAA,KAEvBA,qBAAqB;gBAAA;gBAAA;cAAA;cACvBlD,oBAAW,CAACC,MAAM,CAACM,IAAI,CACrB,2FAA2F,CAC5F;cAAC,iCAEK,cAAc;YAAA;cAAA,IAIlBiB,OAAO,CAAC2B,MAAM,CAACC,YAAY,CAACC,mBAAmB;gBAAA;gBAAA;cAAA;cAClDrD,oBAAW,CAACC,MAAM,CAACM,IAAI,CACrB,qFAAqF,CACtF;cAAC,iCAEK,QAAQ;YAAA;cAAA,iCAGV,EAAE;YAAA;YAAA;cAAA;UAAA;QAAA;MAAA,CACV;MAAA;QAAA;MAAA;MAAA;IAAA;IAED;AACF;AACA;AACA;AACA;AACA;EALE;IAAA;IAAA;MAAA,yFAMA,kBAAgBiB,OAAO;QAAA;QAAA;UAAA;YAAA;cAAA;cAAA,OACI,IAAI,CAAC8B,aAAa,CAAC9B,OAAO,CAAC;YAAA;cAA9C+B,UAAU;cAAA,kCAET,CAAC,CAACA,UAAU;YAAA;YAAA;cAAA;UAAA;QAAA;MAAA,CACpB;MAAA;QAAA;MAAA;MAAA;IAAA;IAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EAhBE;IAAA;IAAA;MAAA,+FAiBA,kBAAsB/B,OAAgB,EAAEC,cAAwB;QAAA;QAAA;QAAA;UAAA;YAAA;cAAA;cAAA,OACrB,IAAI,CAAC6B,aAAa,CAAC9B,OAAO,CAAC;YAAA;cAA9DgC,0BAA0B;cAAA,KAE5BA,0BAA0B;gBAAA;gBAAA;cAAA;cAAA,kCACrB;gBACLC,cAAc,EAAEnC,SAAS;gBACzBkC,0BAA0B,EAA1BA;cACF,CAAC;YAAA;cAAA,kCAGI,IAAI,CAACE,4BAA4B,CAAClC,OAAO,EAAEC,cAAc,CAAC,CAC9DqB,IAAI,CAAC;gBAAA,OAAM,MAAI,CAACa,4BAA4B,EAAE;cAAA,EAAC,CAC/Cb,IAAI,CAAC;gBAAA,OAAM,MAAI,CAACc,UAAU,CAACpC,OAAO,CAAC;cAAA,EAAC,CACpCsB,IAAI,CAAC,YAAM;gBACV,MAAI,CAAC/C,KAAK,GAAGuB,SAAS;gBAEtBtB,oBAAW,CAACC,MAAM,CAACM,IAAI,CAAC,iEAAiE,CAAC;gBAE1F,OAAO;kBAACkD,cAAc,EAAE,MAAI,CAAC9D,QAAQ;kBAAE6D,0BAA0B,EAAElC;gBAAS,CAAC;cAC/E,CAAC,CAAC,CACDuC,KAAK,CAAC,UAACC,CAAC,EAAK;gBACZ;gBACA9D,oBAAW,CAACC,MAAM,CAACM,IAAI,kGACqEuD,CAAC,EAC5F;gBAEDC,gBAAO,CAACC,oBAAoB,CAACC,kBAAkB,CAACC,sBAAsB,EAAE;kBACtEC,cAAc,EAAE3C,OAAO,CAAC4C,aAAa;kBACrCC,QAAQ,EAAE7C,OAAO,CAAC8C,QAAQ,CAACC,KAAK,CAAC,GAAG,CAAC,CAACC,GAAG,EAAE;kBAC3CC,MAAM,EAAEX,CAAC,CAACY,OAAO;kBACjBC,KAAK,EAAEb,CAAC,CAACa;gBACX,CAAC,CAAC;gBAEF,OAAO;kBAAClB,cAAc,EAAEnC,SAAS;kBAAEkC,0BAA0B,EAAElC;gBAAS,CAAC;cAC3E,CAAC,CAAC;YAAA;YAAA;cAAA;UAAA;QAAA;MAAA,CACL;MAAA;QAAA;MAAA;MAAA;IAAA;EAAA;EAAA;AAAA;AAAA"}
|
|
1
|
+
{"version":3,"names":["TURN_DISCOVERY_TIMEOUT","TURN_DISCOVERY_SEQ","TurnDiscovery","roapRequest","turnInfo","url","username","password","defer","LoggerProxy","logger","warn","reject","Error","responseTimer","setTimeout","info","promise","roapMessage","headers","expectedHeaders","headerName","field","foundHeaders","forEach","receivedHeader","expectedHeader","startsWith","substring","length","clearTimeout","undefined","resolve","meeting","isReconnecting","Defer","messageType","ROAP","ROAP_TYPES","TURN_DISCOVERY_REQUEST","version","ROAP_VERSION","seq","sendRoap","locusSelfUrl","selfUrl","mediaId","meetingId","id","locusMediaRequest","ipVersion","MeetingUtil","getIpVersion","webex","then","mediaConnections","updateMediaConnections","OK","meetings","reachability","isAnyClusterReachable","config","experimental","enableTurnDiscovery","getSkipReason","skipReason","turnDiscoverySkippedReason","turnServerInfo","sendRoapTurnDiscoveryRequest","waitForTurnDiscoveryResponse","sendRoapOK","catch","e","Metrics","sendBehavioralMetric","BEHAVIORAL_METRICS","TURN_DISCOVERY_FAILURE","correlation_id","correlationId","locus_id","locusUrl","split","pop","reason","message","stack"],"sources":["turnDiscovery.ts"],"sourcesContent":["// @ts-ignore - Types not available for @webex/common\nimport {Defer} from '@webex/common';\n\nimport Metrics from '../metrics';\nimport BEHAVIORAL_METRICS from '../metrics/constants';\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport {ROAP} from '../constants';\n\nimport RoapRequest from './request';\nimport Meeting from '../meeting';\nimport MeetingUtil from '../meeting/util';\n\nconst TURN_DISCOVERY_TIMEOUT = 10; // in seconds\n\n// Roap spec says that seq should start from 1, but TURN discovery works fine with seq=0\n// and this is handy for us, because TURN discovery is always done before the first SDP exchange,\n// so we can do it with seq=0 or not do it at all and then we create the RoapMediaConnection\n// and do the SDP offer with seq=1\nconst TURN_DISCOVERY_SEQ = 0;\n\n/**\n * Handles the process of finding out TURN server information from Linus.\n * This is achieved by sending a TURN_DISCOVERY_REQUEST.\n */\nexport default class TurnDiscovery {\n private roapRequest: RoapRequest;\n\n private defer?: Defer; // used for waiting for the response\n\n private turnInfo: {\n url: string;\n username: string;\n password: string;\n };\n\n private responseTimer?: ReturnType<typeof setTimeout>;\n\n /**\n * Constructor\n *\n * @param {RoapRequest} roapRequest\n */\n constructor(roapRequest: RoapRequest) {\n this.roapRequest = roapRequest;\n this.turnInfo = {\n url: '',\n username: '',\n password: '',\n };\n }\n\n /**\n * waits for TURN_DISCOVERY_RESPONSE message to arrive\n *\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n private waitForTurnDiscoveryResponse() {\n if (!this.defer) {\n LoggerProxy.logger.warn(\n 'Roap:turnDiscovery#waitForTurnDiscoveryResponse --> TURN discovery is not in progress'\n );\n\n return Promise.reject(\n new Error('waitForTurnDiscoveryResponse() called before sendRoapTurnDiscoveryRequest()')\n );\n }\n\n const {defer} = this;\n\n this.responseTimer = setTimeout(() => {\n LoggerProxy.logger.warn(\n `Roap:turnDiscovery#waitForTurnDiscoveryResponse --> timeout! no response arrived within ${TURN_DISCOVERY_TIMEOUT} seconds`\n );\n\n defer.reject(new Error('Timed out waiting for TURN_DISCOVERY_RESPONSE'));\n }, TURN_DISCOVERY_TIMEOUT * 1000);\n\n LoggerProxy.logger.info(\n 'Roap:turnDiscovery#waitForTurnDiscoveryResponse --> waiting for TURN_DISCOVERY_RESPONSE...'\n );\n\n return defer.promise;\n }\n\n /**\n * handles TURN_DISCOVERY_RESPONSE roap message\n *\n * @param {Object} roapMessage\n * @returns {void}\n * @public\n * @memberof Roap\n */\n public handleTurnDiscoveryResponse(roapMessage: object) {\n // @ts-ignore - Fix missing type\n const {headers} = roapMessage;\n\n if (!this.defer) {\n LoggerProxy.logger.warn(\n 'Roap:turnDiscovery#handleTurnDiscoveryResponse --> unexpected TURN discovery response'\n );\n\n return;\n }\n\n const expectedHeaders = [\n {headerName: 'x-cisco-turn-url', field: 'url'},\n {headerName: 'x-cisco-turn-username', field: 'username'},\n {headerName: 'x-cisco-turn-password', field: 'password'},\n ];\n\n let foundHeaders = 0;\n\n headers?.forEach((receivedHeader) => {\n // check if it matches any of our expected headers\n expectedHeaders.forEach((expectedHeader) => {\n if (receivedHeader.startsWith(`${expectedHeader.headerName}=`)) {\n this.turnInfo[expectedHeader.field] = receivedHeader.substring(\n expectedHeader.headerName.length + 1\n );\n foundHeaders += 1;\n }\n });\n });\n\n clearTimeout(this.responseTimer);\n this.responseTimer = undefined;\n\n if (foundHeaders !== expectedHeaders.length) {\n LoggerProxy.logger.warn(\n `Roap:turnDiscovery#handleTurnDiscoveryResponse --> missing some headers, received: ${JSON.stringify(\n headers\n )}`\n );\n this.defer.reject(\n new Error(`TURN_DISCOVERY_RESPONSE missing some headers: ${JSON.stringify(headers)}`)\n );\n } else {\n LoggerProxy.logger.info(\n `Roap:turnDiscovery#handleTurnDiscoveryResponse --> received a valid response, url=${this.turnInfo.url}`\n );\n this.defer.resolve();\n }\n }\n\n /**\n * sends the TURN_DISCOVERY_REQUEST roap request\n *\n * @param {Meeting} meeting\n * @param {Boolean} isReconnecting\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n sendRoapTurnDiscoveryRequest(meeting: Meeting, isReconnecting: boolean) {\n if (this.defer) {\n LoggerProxy.logger.warn(\n 'Roap:turnDiscovery#sendRoapTurnDiscoveryRequest --> already in progress'\n );\n\n return Promise.resolve();\n }\n\n this.defer = new Defer();\n\n const roapMessage = {\n messageType: ROAP.ROAP_TYPES.TURN_DISCOVERY_REQUEST,\n version: ROAP.ROAP_VERSION,\n seq: TURN_DISCOVERY_SEQ,\n };\n\n LoggerProxy.logger.info(\n 'Roap:turnDiscovery#sendRoapTurnDiscoveryRequest --> sending TURN_DISCOVERY_REQUEST'\n );\n\n return this.roapRequest\n .sendRoap({\n roapMessage,\n // @ts-ignore - Fix missing type\n locusSelfUrl: meeting.selfUrl,\n // @ts-ignore - Fix missing type\n mediaId: isReconnecting ? '' : meeting.mediaId,\n meetingId: meeting.id,\n locusMediaRequest: meeting.locusMediaRequest,\n // @ts-ignore - because of meeting.webex\n ipVersion: MeetingUtil.getIpVersion(meeting.webex),\n })\n .then(({mediaConnections}) => {\n if (mediaConnections) {\n meeting.updateMediaConnections(mediaConnections);\n }\n });\n }\n\n /**\n * Sends the OK message that server expects to receive\n * after it sends us TURN_DISCOVERY_RESPONSE\n *\n * @param {Meeting} meeting\n * @returns {Promise}\n */\n sendRoapOK(meeting: Meeting) {\n LoggerProxy.logger.info('Roap:turnDiscovery#sendRoapOK --> sending OK');\n\n return this.roapRequest.sendRoap({\n roapMessage: {\n messageType: ROAP.ROAP_TYPES.OK,\n version: ROAP.ROAP_VERSION,\n seq: TURN_DISCOVERY_SEQ,\n },\n // @ts-ignore - fix type\n locusSelfUrl: meeting.selfUrl,\n // @ts-ignore - fix type\n mediaId: meeting.mediaId,\n meetingId: meeting.id,\n locusMediaRequest: meeting.locusMediaRequest,\n });\n }\n\n /**\n * Gets the reason why reachability is skipped.\n *\n * @param {Meeting} meeting\n * @returns {Promise<string>} Promise with empty string if reachability is not skipped or a reason if it is skipped\n */\n private async getSkipReason(meeting: Meeting): Promise<string> {\n // @ts-ignore - fix type\n const isAnyClusterReachable = await meeting.webex.meetings.reachability.isAnyClusterReachable();\n\n if (isAnyClusterReachable) {\n LoggerProxy.logger.info(\n 'Roap:turnDiscovery#getSkipReason --> reachability has not failed, skipping TURN discovery'\n );\n\n return 'reachability';\n }\n\n // @ts-ignore - fix type\n if (!meeting.config.experimental.enableTurnDiscovery) {\n LoggerProxy.logger.info(\n 'Roap:turnDiscovery#getSkipReason --> TURN discovery disabled in config, skipping it'\n );\n\n return 'config';\n }\n\n return '';\n }\n\n /**\n * Checks if TURN discovery is skipped.\n *\n * @param {Meeting} meeting\n * @returns {Boolean} true if TURN discovery is being skipped, false if it is being done\n */\n async isSkipped(meeting) {\n const skipReason = await this.getSkipReason(meeting);\n\n return !!skipReason;\n }\n\n /**\n * Retrieves TURN server information from the backend by doing\n * a roap message exchange:\n * client server\n * | -----TURN_DISCOVERY_REQUEST-----> |\n * | <----TURN_DISCOVERY_RESPONSE----- |\n * | --------------OK----------------> |\n *\n * This TURN discovery roap exchange is always done with seq=0.\n * The RoapMediaConnection SDP exchange always starts with seq=1,\n * so it works fine no matter if TURN discovery is done or not.\n *\n * @param {Meeting} meeting\n * @param {Boolean} isReconnecting should be set to true if this is a new\n * media connection just after a reconnection\n * @returns {Promise}\n */\n async doTurnDiscovery(meeting: Meeting, isReconnecting?: boolean) {\n const turnDiscoverySkippedReason = await this.getSkipReason(meeting);\n\n if (turnDiscoverySkippedReason) {\n return {\n turnServerInfo: undefined,\n turnDiscoverySkippedReason,\n };\n }\n\n return this.sendRoapTurnDiscoveryRequest(meeting, isReconnecting)\n .then(() => this.waitForTurnDiscoveryResponse())\n .then(() => this.sendRoapOK(meeting))\n .then(() => {\n this.defer = undefined;\n\n LoggerProxy.logger.info('Roap:turnDiscovery#doTurnDiscovery --> TURN discovery completed');\n\n return {turnServerInfo: this.turnInfo, turnDiscoverySkippedReason: undefined};\n })\n .catch((e) => {\n // we catch any errors and resolve with no turn information so that the normal call join flow can continue without TURN\n LoggerProxy.logger.info(\n `Roap:turnDiscovery#doTurnDiscovery --> TURN discovery failed, continuing without TURN: ${e}`\n );\n\n Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.TURN_DISCOVERY_FAILURE, {\n correlation_id: meeting.correlationId,\n locus_id: meeting.locusUrl.split('/').pop(),\n reason: e.message,\n stack: e.stack,\n });\n\n return {turnServerInfo: undefined, turnDiscoverySkippedReason: undefined};\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -55,6 +55,18 @@ declare class UserInLobbyError extends WebexMeetingsError {
|
|
|
55
55
|
constructor();
|
|
56
56
|
}
|
|
57
57
|
export { UserInLobbyError };
|
|
58
|
+
/**
|
|
59
|
+
* @class SpaceIDDeprecatedError
|
|
60
|
+
* @classdesc Raised whenever the user passes Space ID as destination for create meeting.
|
|
61
|
+
* @extends WebexMeetingsError
|
|
62
|
+
* @property {number} code - 30105
|
|
63
|
+
* @property {string} message - Using the space ID as a destination is no longer supported. Please refer to the [migration guide](https://github.com/webex/webex-js-sdk/wiki/Migration-guide-for-USM-meeting) to migrate to use the meeting ID or SIP address.'
|
|
64
|
+
*/
|
|
65
|
+
declare class SpaceIDDeprecatedError extends WebexMeetingsError {
|
|
66
|
+
static CODE: number;
|
|
67
|
+
constructor();
|
|
68
|
+
}
|
|
69
|
+
export { SpaceIDDeprecatedError };
|
|
58
70
|
/**
|
|
59
71
|
* @class IceGatheringFailed
|
|
60
72
|
* @classdesc Raised whenever ice gathering fails.
|
|
@@ -278,7 +278,7 @@ export default class Meetings extends WebexPlugin {
|
|
|
278
278
|
private destroy;
|
|
279
279
|
/**
|
|
280
280
|
* Create a meeting.
|
|
281
|
-
* @param {string} destination - sipURL,
|
|
281
|
+
* @param {string} destination - sipURL, phonenumber, or locus object}
|
|
282
282
|
* @param {string} [type] - the optional specified type, such as locusId
|
|
283
283
|
* @param {Boolean} useRandomDelayForInfo - whether a random delay should be added to fetching meeting info
|
|
284
284
|
* @param {Object} infoExtraParams extra parameters to be provided when fetching meeting info
|
package/package.json
CHANGED
|
@@ -107,6 +107,27 @@ class UserInLobbyError extends WebexMeetingsError {
|
|
|
107
107
|
export {UserInLobbyError};
|
|
108
108
|
WebExMeetingsErrors[UserInLobbyError.CODE] = UserInLobbyError;
|
|
109
109
|
|
|
110
|
+
/**
|
|
111
|
+
* @class SpaceIDDeprecatedError
|
|
112
|
+
* @classdesc Raised whenever the user passes Space ID as destination for create meeting.
|
|
113
|
+
* @extends WebexMeetingsError
|
|
114
|
+
* @property {number} code - 30105
|
|
115
|
+
* @property {string} message - Using the space ID as a destination is no longer supported. Please refer to the [migration guide](https://github.com/webex/webex-js-sdk/wiki/Migration-guide-for-USM-meeting) to migrate to use the meeting ID or SIP address.'
|
|
116
|
+
*/
|
|
117
|
+
class SpaceIDDeprecatedError extends WebexMeetingsError {
|
|
118
|
+
static CODE = 30105;
|
|
119
|
+
|
|
120
|
+
constructor() {
|
|
121
|
+
super(
|
|
122
|
+
SpaceIDDeprecatedError.CODE,
|
|
123
|
+
'Using the space ID as a destination is no longer supported. Please refer to the [migration guide](https://github.com/webex/webex-js-sdk/wiki/Migration-guide-for-USM-meeting) to migrate to use the meeting ID or SIP address.'
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export {SpaceIDDeprecatedError};
|
|
129
|
+
WebExMeetingsErrors[SpaceIDDeprecatedError.CODE] = SpaceIDDeprecatedError;
|
|
130
|
+
|
|
110
131
|
/**
|
|
111
132
|
* @class IceGatheringFailed
|
|
112
133
|
* @classdesc Raised whenever ice gathering fails.
|
package/src/config.ts
CHANGED
|
@@ -86,8 +86,8 @@ export default {
|
|
|
86
86
|
installedOrgID: undefined,
|
|
87
87
|
experimental: {
|
|
88
88
|
enableMediaNegotiatedEvent: false,
|
|
89
|
-
enableUnifiedMeetings:
|
|
90
|
-
enableAdhocMeetings:
|
|
89
|
+
enableUnifiedMeetings: true,
|
|
90
|
+
enableAdhocMeetings: true,
|
|
91
91
|
enableTurnDiscovery: true,
|
|
92
92
|
},
|
|
93
93
|
degradationPreferences: {
|
package/src/constants.ts
CHANGED
|
@@ -1242,8 +1242,8 @@ export const DEFAULT_MEETING_INFO_REQUEST_BODY = {
|
|
|
1242
1242
|
/** the values for IP_VERSION are fixed and defined in Orpheus API */
|
|
1243
1243
|
export const IP_VERSION = {
|
|
1244
1244
|
unknown: 0,
|
|
1245
|
-
only_ipv4: 4,
|
|
1246
|
-
only_ipv6: 6,
|
|
1245
|
+
only_ipv4: 4, // we know we have ipv4, we don't know or we don't have ipv6
|
|
1246
|
+
only_ipv6: 6, // we know we have ipv6, we don't know or we don't have ipv4
|
|
1247
1247
|
ipv4_and_ipv6: 1,
|
|
1248
1248
|
} as const;
|
|
1249
1249
|
|
package/src/meeting/index.ts
CHANGED
|
@@ -4506,7 +4506,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4506
4506
|
payload: {
|
|
4507
4507
|
identifiers: {meetingLookupUrl: this.meetingInfo?.meetingLookupUrl},
|
|
4508
4508
|
},
|
|
4509
|
-
options: {meetingId: this.id, rawError: error
|
|
4509
|
+
options: {meetingId: this.id, rawError: error},
|
|
4510
4510
|
});
|
|
4511
4511
|
|
|
4512
4512
|
// TODO: change this to error codes and pre defined dictionary
|
|
@@ -4879,7 +4879,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4879
4879
|
payload: {
|
|
4880
4880
|
canProceed: false,
|
|
4881
4881
|
},
|
|
4882
|
-
options: {meetingId: this.id, rawError: error
|
|
4882
|
+
options: {meetingId: this.id, rawError: error},
|
|
4883
4883
|
});
|
|
4884
4884
|
} else if (
|
|
4885
4885
|
error instanceof Errors.SdpOfferHandlingError ||
|
|
@@ -4893,7 +4893,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4893
4893
|
payload: {
|
|
4894
4894
|
canProceed: false,
|
|
4895
4895
|
},
|
|
4896
|
-
options: {meetingId: this.id, rawError: error
|
|
4896
|
+
options: {meetingId: this.id, rawError: error},
|
|
4897
4897
|
});
|
|
4898
4898
|
} else if (error instanceof Errors.SdpError) {
|
|
4899
4899
|
// this covers also the case of Errors.IceGatheringError which extends Errors.SdpError
|
|
@@ -4905,7 +4905,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4905
4905
|
payload: {
|
|
4906
4906
|
canProceed: false,
|
|
4907
4907
|
},
|
|
4908
|
-
options: {meetingId: this.id, rawError: error
|
|
4908
|
+
options: {meetingId: this.id, rawError: error},
|
|
4909
4909
|
});
|
|
4910
4910
|
}
|
|
4911
4911
|
};
|
|
@@ -16,7 +16,7 @@ export type RoapRequest = {
|
|
|
16
16
|
reachability: any;
|
|
17
17
|
sequence?: any;
|
|
18
18
|
joinCookie: any; // any, because this is opaque to the client, we pass whatever object we got from one backend component (Orpheus) to the other (Locus)
|
|
19
|
-
ipVersion
|
|
19
|
+
ipVersion?: IP_VERSION;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
export type LocalMuteRequest = {
|
|
@@ -28,7 +28,6 @@ export type LocalMuteRequest = {
|
|
|
28
28
|
audioMuted?: boolean;
|
|
29
29
|
videoMuted?: boolean;
|
|
30
30
|
};
|
|
31
|
-
ipVersion: IP_VERSION;
|
|
32
31
|
};
|
|
33
32
|
|
|
34
33
|
export type Request = RoapRequest | LocalMuteRequest;
|
|
@@ -204,7 +203,7 @@ export class LocusMediaRequest extends WebexPlugin {
|
|
|
204
203
|
correlationId: this.config.correlationId,
|
|
205
204
|
clientMediaPreferences: {
|
|
206
205
|
preferTranscoding: this.config.preferTranscoding,
|
|
207
|
-
ipver: request.ipVersion,
|
|
206
|
+
ipver: request.type === 'RoapMessage' ? request.ipVersion : undefined,
|
|
208
207
|
},
|
|
209
208
|
};
|
|
210
209
|
|
package/src/meeting/request.ts
CHANGED
|
@@ -108,6 +108,7 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
108
108
|
sipUri: string;
|
|
109
109
|
deviceUrl: string;
|
|
110
110
|
locusUrl: string;
|
|
111
|
+
locusClusterUrl: string;
|
|
111
112
|
resourceId: string;
|
|
112
113
|
correlationId: string;
|
|
113
114
|
ensureConversation: boolean;
|
|
@@ -124,7 +125,7 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
124
125
|
locale?: string;
|
|
125
126
|
deviceCapabilities?: Array<string>;
|
|
126
127
|
liveAnnotationSupported: boolean;
|
|
127
|
-
ipVersion
|
|
128
|
+
ipVersion?: IP_VERSION;
|
|
128
129
|
}) {
|
|
129
130
|
const {
|
|
130
131
|
asResourceOccupant,
|
|
@@ -133,6 +134,7 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
133
134
|
permissionToken,
|
|
134
135
|
deviceUrl,
|
|
135
136
|
locusUrl,
|
|
137
|
+
locusClusterUrl,
|
|
136
138
|
resourceId,
|
|
137
139
|
correlationId,
|
|
138
140
|
ensureConversation,
|
|
@@ -214,10 +216,18 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
214
216
|
url = `${locusUrl}/${PARTICIPANT}`;
|
|
215
217
|
} else if (inviteeAddress || meetingNumber) {
|
|
216
218
|
try {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
219
|
+
let clusterUrl;
|
|
220
|
+
|
|
221
|
+
if (locusClusterUrl) {
|
|
222
|
+
clusterUrl = `https://${locusClusterUrl}/locus/api/v1`;
|
|
223
|
+
} else {
|
|
224
|
+
// @ts-ignore
|
|
225
|
+
await this.webex.internal.services.waitForCatalog('postauth');
|
|
226
|
+
// @ts-ignore
|
|
227
|
+
clusterUrl = this.webex.internal.services.get('locus');
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
url = `${clusterUrl}/${LOCI}/${CALL}`;
|
|
221
231
|
body.invitee = {
|
|
222
232
|
address: inviteeAddress || `wbxmn:${meetingNumber}`,
|
|
223
233
|
};
|
package/src/meeting/util.ts
CHANGED
|
@@ -13,7 +13,9 @@ import {
|
|
|
13
13
|
FULL_STATE,
|
|
14
14
|
SELF_POLICY,
|
|
15
15
|
EVENT_TRIGGERS,
|
|
16
|
+
IP_VERSION,
|
|
16
17
|
} from '../constants';
|
|
18
|
+
import BrowserDetection from '../common/browser-detection';
|
|
17
19
|
import IntentToJoinError from '../common/errors/intent-to-join';
|
|
18
20
|
import JoinMeetingError from '../common/errors/join-meeting';
|
|
19
21
|
import ParameterError from '../common/errors/parameter';
|
|
@@ -73,7 +75,6 @@ const MeetingUtil = {
|
|
|
73
75
|
audioMuted,
|
|
74
76
|
videoMuted,
|
|
75
77
|
},
|
|
76
|
-
ipVersion: meeting.getWebexObject().meetings.reachability.getIpVersion(),
|
|
77
78
|
})
|
|
78
79
|
.then((response) => {
|
|
79
80
|
// @ts-ignore
|
|
@@ -92,6 +93,38 @@ const MeetingUtil = {
|
|
|
92
93
|
|
|
93
94
|
isPinOrGuest: (err) => err?.body?.errorCode && INTENT_TO_JOIN.includes(err.body.errorCode),
|
|
94
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Returns the current state of knowledge about whether we are on an ipv4-only or ipv6-only or mixed (ipv4 and ipv6) network.
|
|
98
|
+
* The return value matches the possible values of "ipver" parameter used by the backend APIs.
|
|
99
|
+
*
|
|
100
|
+
* @param {Object} webex webex instance
|
|
101
|
+
* @returns {IP_VERSION|undefined} ipver value to be passed to the backend APIs or undefined if we should not pass any value to the backend
|
|
102
|
+
*/
|
|
103
|
+
getIpVersion(webex: any): IP_VERSION | undefined {
|
|
104
|
+
const {supportsIpV4, supportsIpV6} = webex.internal.device.ipNetworkDetector;
|
|
105
|
+
|
|
106
|
+
if (BrowserDetection().isBrowser('firefox')) {
|
|
107
|
+
// our ipv6 solution relies on FQDN ICE candidates, but Firefox doesn't support them,
|
|
108
|
+
// see https://bugzilla.mozilla.org/show_bug.cgi?id=1713128
|
|
109
|
+
// so for Firefox we don't want the backend to activate the "ipv6 feature"
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (supportsIpV4 && supportsIpV6) {
|
|
114
|
+
return IP_VERSION.ipv4_and_ipv6;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (supportsIpV4) {
|
|
118
|
+
return IP_VERSION.only_ipv4;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (supportsIpV6) {
|
|
122
|
+
return IP_VERSION.only_ipv6;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return IP_VERSION.unknown;
|
|
126
|
+
},
|
|
127
|
+
|
|
95
128
|
joinMeeting: (meeting, options) => {
|
|
96
129
|
if (!meeting) {
|
|
97
130
|
return Promise.reject(new ParameterError('You need a meeting object.'));
|
|
@@ -113,6 +146,7 @@ const MeetingUtil = {
|
|
|
113
146
|
meetingNumber: meeting.meetingNumber,
|
|
114
147
|
deviceUrl: meeting.deviceUrl,
|
|
115
148
|
locusUrl: meeting.locusUrl,
|
|
149
|
+
locusClusterUrl: meeting.meetingInfo?.locusClusterUrl,
|
|
116
150
|
correlationId: meeting.correlationId,
|
|
117
151
|
roapMessage: options.roapMessage,
|
|
118
152
|
permissionToken: meeting.permissionToken,
|
|
@@ -126,7 +160,7 @@ const MeetingUtil = {
|
|
|
126
160
|
locale: options.locale,
|
|
127
161
|
deviceCapabilities: options.deviceCapabilities,
|
|
128
162
|
liveAnnotationSupported: options.liveAnnotationSupported,
|
|
129
|
-
ipVersion: meeting.getWebexObject()
|
|
163
|
+
ipVersion: MeetingUtil.getIpVersion(meeting.getWebexObject()),
|
|
130
164
|
})
|
|
131
165
|
.then((res) => {
|
|
132
166
|
// @ts-ignore
|
package/src/meeting-info/util.ts
CHANGED
|
@@ -233,7 +233,7 @@ MeetingInfoUtil.generateOptions = async (from) => {
|
|
|
233
233
|
}
|
|
234
234
|
} else {
|
|
235
235
|
throw new ParameterError(
|
|
236
|
-
'MeetingInfo is fetched with meeting link,
|
|
236
|
+
'MeetingInfo is fetched with the meeting link, SIP URI, phone number, Hydra people ID, or a conversation URL.'
|
|
237
237
|
);
|
|
238
238
|
}
|
|
239
239
|
|
|
@@ -28,8 +28,11 @@ import {
|
|
|
28
28
|
} from '../constants';
|
|
29
29
|
import ParameterError from '../common/errors/parameter';
|
|
30
30
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
31
|
+
import {SpaceIDDeprecatedError} from '../common/errors/webex-errors';
|
|
31
32
|
|
|
32
33
|
const MeetingInfoUtil: any = {};
|
|
34
|
+
const meetingInfoError =
|
|
35
|
+
'MeetingInfo is fetched with the meeting link, SIP URI, phone number, Hydra people ID, or a conversation URL.';
|
|
33
36
|
|
|
34
37
|
MeetingInfoUtil.getParsedUrl = (link) => {
|
|
35
38
|
try {
|
|
@@ -191,27 +194,14 @@ MeetingInfoUtil.getDestinationType = async (from) => {
|
|
|
191
194
|
return Promise.resolve(options);
|
|
192
195
|
});
|
|
193
196
|
} else if (hydraId.room) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
await webex.internal.services.waitForCatalog('postauth');
|
|
197
|
-
|
|
198
|
-
const conversationUrl = webex.internal.conversation.getUrlFromClusterId({
|
|
199
|
-
cluster: hydraId.cluster,
|
|
200
|
-
id: hydraId.destination,
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
options.destination = conversationUrl;
|
|
204
|
-
} catch (e) {
|
|
205
|
-
LoggerProxy.logger.error(`Meeting-info:util#getDestinationType --> ${e}`);
|
|
206
|
-
throw e;
|
|
207
|
-
}
|
|
208
|
-
} else {
|
|
209
|
-
LoggerProxy.logger.warn(
|
|
210
|
-
"Meeting-info:util#getDestinationType --> ('MeetingInfo is fetched with meeting link, sip uri, phone number, hydra room id, hydra people id, or a conversation url."
|
|
211
|
-
);
|
|
212
|
-
throw new ParameterError(
|
|
213
|
-
'MeetingInfo is fetched with meeting link, sip uri, phone number, hydra room id, hydra people id, or a conversation url.'
|
|
197
|
+
LoggerProxy.logger.error(
|
|
198
|
+
`Meeting-info:util#getDestinationType --> Using the space ID as a destination is no longer supported. Please refer to the [migration guide](https://github.com/webex/webex-js-sdk/wiki/Migration-guide-for-USM-meeting) to migrate to use the meeting ID or SIP address.`
|
|
214
199
|
);
|
|
200
|
+
// Error code 30105 added as Space ID deprecated as of beta, Please refer migration guide.
|
|
201
|
+
throw new SpaceIDDeprecatedError();
|
|
202
|
+
} else {
|
|
203
|
+
LoggerProxy.logger.warn(`Meeting-info:util#getDestinationType --> ${meetingInfoError}`);
|
|
204
|
+
throw new ParameterError(`${meetingInfoError}`);
|
|
215
205
|
}
|
|
216
206
|
|
|
217
207
|
return Promise.resolve(options);
|
package/src/meetings/index.ts
CHANGED
|
@@ -60,6 +60,7 @@ import MeetingCollection from './collection';
|
|
|
60
60
|
import MeetingsUtil from './util';
|
|
61
61
|
import PermissionError from '../common/errors/permission';
|
|
62
62
|
import {INoiseReductionEffect, IVirtualBackgroundEffect} from './meetings.types';
|
|
63
|
+
import {SpaceIDDeprecatedError} from '../common/errors/webex-errors';
|
|
63
64
|
|
|
64
65
|
let mediaLogger;
|
|
65
66
|
|
|
@@ -886,6 +887,7 @@ export default class Meetings extends WebexPlugin {
|
|
|
886
887
|
'Meetings:index#uploadLogs --> Upload logs for meeting completed.',
|
|
887
888
|
uploadResult
|
|
888
889
|
);
|
|
890
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.UPLOAD_LOGS_SUCCESS, options);
|
|
889
891
|
Trigger.trigger(
|
|
890
892
|
this,
|
|
891
893
|
{
|
|
@@ -920,8 +922,7 @@ export default class Meetings extends WebexPlugin {
|
|
|
920
922
|
);
|
|
921
923
|
|
|
922
924
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.UPLOAD_LOGS_FAILURE, {
|
|
923
|
-
|
|
924
|
-
meetingId: options.meetingsId,
|
|
925
|
+
...options,
|
|
925
926
|
reason: uploadError.message,
|
|
926
927
|
stack: uploadError.stack,
|
|
927
928
|
code: uploadError.code,
|
|
@@ -1037,7 +1038,7 @@ export default class Meetings extends WebexPlugin {
|
|
|
1037
1038
|
|
|
1038
1039
|
/**
|
|
1039
1040
|
* Create a meeting.
|
|
1040
|
-
* @param {string} destination - sipURL,
|
|
1041
|
+
* @param {string} destination - sipURL, phonenumber, or locus object}
|
|
1041
1042
|
* @param {string} [type] - the optional specified type, such as locusId
|
|
1042
1043
|
* @param {Boolean} useRandomDelayForInfo - whether a random delay should be added to fetching meeting info
|
|
1043
1044
|
* @param {Object} infoExtraParams extra parameters to be provided when fetching meeting info
|
|
@@ -1064,9 +1065,12 @@ export default class Meetings extends WebexPlugin {
|
|
|
1064
1065
|
.fetchInfoOptions(destination, type)
|
|
1065
1066
|
// Catch a failure to fetch info options.
|
|
1066
1067
|
.catch((error) => {
|
|
1067
|
-
LoggerProxy.logger.
|
|
1068
|
-
`Meetings:index#create -->
|
|
1068
|
+
LoggerProxy.logger.error(
|
|
1069
|
+
`Meetings:index#create --> ERROR, unable to determine info options: ${error.message}`
|
|
1069
1070
|
);
|
|
1071
|
+
if (error instanceof SpaceIDDeprecatedError) {
|
|
1072
|
+
throw new SpaceIDDeprecatedError();
|
|
1073
|
+
}
|
|
1070
1074
|
})
|
|
1071
1075
|
.then((options: any = {}) => {
|
|
1072
1076
|
// Normalize the destination.
|
|
@@ -1284,7 +1288,7 @@ export default class Meetings extends WebexPlugin {
|
|
|
1284
1288
|
//
|
|
1285
1289
|
// Our job is to determine the appropriate one
|
|
1286
1290
|
// and its corresponding service so that developers
|
|
1287
|
-
// need only sipURL
|
|
1291
|
+
// need only sipURL to get a meeting
|
|
1288
1292
|
// and its ID, but have the option to use createWithType()
|
|
1289
1293
|
// and specify those types to get meetingInfo
|
|
1290
1294
|
}
|
package/src/metrics/constants.ts
CHANGED
|
@@ -40,6 +40,7 @@ const BEHAVIORAL_METRICS = {
|
|
|
40
40
|
PEERCONNECTION_FAILURE: 'js_sdk_peerConnection_failures',
|
|
41
41
|
INVALID_ICE_CANDIDATE: 'js_sdk_invalid_ice_candidate',
|
|
42
42
|
UPLOAD_LOGS_FAILURE: 'js_sdk_upload_logs_failure',
|
|
43
|
+
UPLOAD_LOGS_SUCCESS: 'js_sdk_upload_logs_success',
|
|
43
44
|
RECEIVE_TRANSCRIPTION_FAILURE: 'js_sdk_receive_transcription_failure',
|
|
44
45
|
FETCH_MEETING_INFO_V1_SUCCESS: 'js_sdk_fetch_meeting_info_v1_success',
|
|
45
46
|
FETCH_MEETING_INFO_V1_FAILURE: 'js_sdk_fetch_meeting_info_v1_failure',
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
import _ from 'lodash';
|
|
8
8
|
|
|
9
9
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
10
|
-
import
|
|
10
|
+
import MeetingUtil from '../meeting/util';
|
|
11
|
+
|
|
12
|
+
import {ICE_GATHERING_STATE, CONNECTION_STATE, REACHABILITY} from '../constants';
|
|
11
13
|
|
|
12
14
|
import ReachabilityRequest from './request';
|
|
13
15
|
|
|
@@ -71,7 +73,7 @@ export default class Reachability {
|
|
|
71
73
|
// Fetch clusters and measure latency
|
|
72
74
|
try {
|
|
73
75
|
const {clusters, joinCookie} = await this.reachabilityRequest.getClusters(
|
|
74
|
-
|
|
76
|
+
MeetingUtil.getIpVersion(this.webex)
|
|
75
77
|
);
|
|
76
78
|
|
|
77
79
|
// Perform Reachability Check
|
|
@@ -134,14 +136,6 @@ export default class Reachability {
|
|
|
134
136
|
return reachable;
|
|
135
137
|
}
|
|
136
138
|
|
|
137
|
-
/**
|
|
138
|
-
* Returns what we know about the IP version of the networks we're connected to.
|
|
139
|
-
* @returns {IP_VERSION}
|
|
140
|
-
*/
|
|
141
|
-
getIpVersion(): IP_VERSION {
|
|
142
|
-
return IP_VERSION.unknown;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
139
|
/**
|
|
146
140
|
* Generate peerConnection config settings
|
|
147
141
|
* @param {object} cluster
|
|
@@ -33,7 +33,7 @@ class ReachabilityRequest {
|
|
|
33
33
|
* @param {IP_VERSION} ipVersion information about current ip network we're on
|
|
34
34
|
* @returns {Promise}
|
|
35
35
|
*/
|
|
36
|
-
getClusters = (ipVersion
|
|
36
|
+
getClusters = (ipVersion?: IP_VERSION): Promise<{clusters: ClusterList; joinCookie: any}> =>
|
|
37
37
|
this.webex
|
|
38
38
|
.request({
|
|
39
39
|
method: HTTP_VERBS.GET,
|
|
@@ -443,17 +443,19 @@ export default class ReconnectionManager {
|
|
|
443
443
|
}
|
|
444
444
|
}
|
|
445
445
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
446
|
+
if (!this.webex.credentials.isUnverifiedGuest) {
|
|
447
|
+
try {
|
|
448
|
+
LoggerProxy.logger.info(
|
|
449
|
+
'ReconnectionManager:index#executeReconnection --> Updating meeting data from server.'
|
|
450
|
+
);
|
|
451
|
+
await this.webex.meetings.syncMeetings();
|
|
452
|
+
} catch (syncError) {
|
|
453
|
+
LoggerProxy.logger.info(
|
|
454
|
+
'ReconnectionManager:index#executeReconnection --> Unable to sync meetings, reconnecting.',
|
|
455
|
+
syncError
|
|
456
|
+
);
|
|
457
|
+
throw new NeedsRetryError(syncError);
|
|
458
|
+
}
|
|
457
459
|
}
|
|
458
460
|
|
|
459
461
|
// TODO: try to improve this logic as the reconnection manager saves the instance of deleted meeting object
|
package/src/roap/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ import LoggerProxy from '../common/logs/logger-proxy';
|
|
|
7
7
|
import RoapRequest from './request';
|
|
8
8
|
import TurnDiscovery from './turnDiscovery';
|
|
9
9
|
import Meeting from '../meeting';
|
|
10
|
+
import MeetingUtil from '../meeting/util';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Roap options
|
|
@@ -100,7 +101,6 @@ export default class Roap extends StatelessWebexPlugin {
|
|
|
100
101
|
mediaId: options.mediaId,
|
|
101
102
|
meetingId: meeting.id,
|
|
102
103
|
locusMediaRequest: meeting.locusMediaRequest,
|
|
103
|
-
ipVersion: meeting.webex.meetings.reachability.getIpVersion(),
|
|
104
104
|
})
|
|
105
105
|
.then(() => {
|
|
106
106
|
LoggerProxy.logger.log(`Roap:index#sendRoapOK --> ROAP OK sent with seq ${options.seq}`);
|
|
@@ -135,7 +135,6 @@ export default class Roap extends StatelessWebexPlugin {
|
|
|
135
135
|
mediaId: options.mediaId,
|
|
136
136
|
meetingId: meeting.id,
|
|
137
137
|
locusMediaRequest: meeting.locusMediaRequest,
|
|
138
|
-
ipVersion: meeting.webex.meetings.reachability.getIpVersion(),
|
|
139
138
|
});
|
|
140
139
|
}
|
|
141
140
|
|
|
@@ -165,7 +164,6 @@ export default class Roap extends StatelessWebexPlugin {
|
|
|
165
164
|
mediaId: options.mediaId,
|
|
166
165
|
meetingId: meeting.id,
|
|
167
166
|
locusMediaRequest: meeting.locusMediaRequest,
|
|
168
|
-
ipVersion: meeting.webex.meetings.reachability.getIpVersion(),
|
|
169
167
|
})
|
|
170
168
|
.then(() => {
|
|
171
169
|
LoggerProxy.logger.log(
|
|
@@ -204,7 +202,7 @@ export default class Roap extends StatelessWebexPlugin {
|
|
|
204
202
|
meetingId: meeting.id,
|
|
205
203
|
preferTranscoding: !meeting.isMultistream,
|
|
206
204
|
locusMediaRequest: meeting.locusMediaRequest,
|
|
207
|
-
ipVersion: meeting.webex
|
|
205
|
+
ipVersion: MeetingUtil.getIpVersion(meeting.webex),
|
|
208
206
|
})
|
|
209
207
|
.then(({locus, mediaConnections}) => {
|
|
210
208
|
if (mediaConnections) {
|
package/src/roap/request.ts
CHANGED
|
@@ -63,6 +63,7 @@ export default class RoapRequest extends StatelessWebexPlugin {
|
|
|
63
63
|
* @param {String} options.mediaId
|
|
64
64
|
* @param {String} options.correlationId
|
|
65
65
|
* @param {String} options.meetingId
|
|
66
|
+
* @param {IP_VERSION} options.ipVersion only required for offers
|
|
66
67
|
* @returns {Promise} returns the response/failure of the request
|
|
67
68
|
*/
|
|
68
69
|
async sendRoap(options: {
|
|
@@ -70,7 +71,7 @@ export default class RoapRequest extends StatelessWebexPlugin {
|
|
|
70
71
|
locusSelfUrl: string;
|
|
71
72
|
mediaId: string;
|
|
72
73
|
meetingId: string;
|
|
73
|
-
ipVersion
|
|
74
|
+
ipVersion?: IP_VERSION;
|
|
74
75
|
locusMediaRequest?: LocusMediaRequest;
|
|
75
76
|
}) {
|
|
76
77
|
const {roapMessage, locusSelfUrl, mediaId, meetingId, locusMediaRequest, ipVersion} = options;
|