@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.
Files changed (66) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/common/errors/webex-errors.js +25 -5
  4. package/dist/common/errors/webex-errors.js.map +1 -1
  5. package/dist/config.js +2 -2
  6. package/dist/config.js.map +1 -1
  7. package/dist/constants.js +2 -0
  8. package/dist/constants.js.map +1 -1
  9. package/dist/interpretation/index.js +1 -1
  10. package/dist/interpretation/siLanguage.js +1 -1
  11. package/dist/meeting/index.js +4 -8
  12. package/dist/meeting/index.js.map +1 -1
  13. package/dist/meeting/locusMediaRequest.js +1 -1
  14. package/dist/meeting/locusMediaRequest.js.map +1 -1
  15. package/dist/meeting/request.js +23 -13
  16. package/dist/meeting/request.js.map +1 -1
  17. package/dist/meeting/util.js +33 -3
  18. package/dist/meeting/util.js.map +1 -1
  19. package/dist/meeting-info/util.js +1 -1
  20. package/dist/meeting-info/util.js.map +1 -1
  21. package/dist/meeting-info/utilv2.js +16 -31
  22. package/dist/meeting-info/utilv2.js.map +1 -1
  23. package/dist/meetings/index.js +9 -6
  24. package/dist/meetings/index.js.map +1 -1
  25. package/dist/metrics/constants.js +1 -0
  26. package/dist/metrics/constants.js.map +1 -1
  27. package/dist/reachability/index.js +2 -11
  28. package/dist/reachability/index.js.map +1 -1
  29. package/dist/reachability/request.js.map +1 -1
  30. package/dist/reconnection-manager/index.js +26 -22
  31. package/dist/reconnection-manager/index.js.map +1 -1
  32. package/dist/roap/index.js +5 -7
  33. package/dist/roap/index.js.map +1 -1
  34. package/dist/roap/request.js +1 -0
  35. package/dist/roap/request.js.map +1 -1
  36. package/dist/roap/turnDiscovery.js +3 -4
  37. package/dist/roap/turnDiscovery.js.map +1 -1
  38. package/dist/types/common/errors/webex-errors.d.ts +12 -0
  39. package/dist/types/meetings/index.d.ts +1 -1
  40. package/package.json +1 -1
  41. package/src/common/errors/webex-errors.ts +21 -0
  42. package/src/config.ts +2 -2
  43. package/src/constants.ts +2 -2
  44. package/src/meeting/index.ts +4 -4
  45. package/src/meeting/locusMediaRequest.ts +2 -3
  46. package/src/meeting/request.ts +15 -5
  47. package/src/meeting/util.ts +36 -2
  48. package/src/meeting-info/util.ts +1 -1
  49. package/src/meeting-info/utilv2.ts +10 -20
  50. package/src/meetings/index.ts +10 -6
  51. package/src/metrics/constants.ts +1 -0
  52. package/src/reachability/index.ts +4 -10
  53. package/src/reachability/request.ts +1 -1
  54. package/src/reconnection-manager/index.ts +13 -11
  55. package/src/roap/index.ts +2 -4
  56. package/src/roap/request.ts +2 -1
  57. package/src/roap/turnDiscovery.ts +2 -3
  58. package/test/unit/spec/meeting/index.js +8 -6
  59. package/test/unit/spec/meeting/locusMediaRequest.ts +1 -2
  60. package/test/unit/spec/meeting/request.js +23 -0
  61. package/test/unit/spec/meeting/utils.js +73 -4
  62. package/test/unit/spec/meetings/index.js +66 -1
  63. package/test/unit/spec/reachability/index.ts +8 -8
  64. package/test/unit/spec/reconnection-manager/index.js +21 -0
  65. package/test/unit/spec/roap/index.ts +5 -1
  66. 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: meeting.webex.meetings.reachability.getIpVersion()
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":"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"}
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, spaceId, phonenumber, or locus object}
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/plugin-meetings",
3
- "version": "3.0.0-stream-classes.02",
3
+ "version": "3.0.0-stream-classes.4",
4
4
  "description": "",
5
5
  "license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
6
6
  "contributors": [
@@ -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: false,
90
- enableAdhocMeetings: false,
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
 
@@ -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, showToUser: true},
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, showToUser: true},
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, showToUser: true},
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, showToUser: true},
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: IP_VERSION;
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
 
@@ -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: IP_VERSION;
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
- // @ts-ignore
218
- await this.webex.internal.services.waitForCatalog('postauth');
219
- // @ts-ignore
220
- url = `${this.webex.internal.services.get('locus')}/${LOCI}/${CALL}`;
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
  };
@@ -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().meetings.reachability.getIpVersion(),
163
+ ipVersion: MeetingUtil.getIpVersion(meeting.getWebexObject()),
130
164
  })
131
165
  .then((res) => {
132
166
  // @ts-ignore
@@ -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, sip uri, phone number, hydra room id, hydra people id, or a conversation url.'
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
- options.type = _CONVERSATION_URL_;
195
- try {
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);
@@ -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
- // @ts-ignore - seems like typo
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, spaceId, phonenumber, or locus object}
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.info(
1068
- `Meetings:index#create --> INFO, unable to determine info options: ${error.message}`
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 or spaceID to get a meeting
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
  }
@@ -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 {ICE_GATHERING_STATE, CONNECTION_STATE, REACHABILITY, IP_VERSION} from '../constants';
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
- this.getIpVersion()
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: IP_VERSION): Promise<{clusters: ClusterList; joinCookie: any}> =>
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
- try {
447
- LoggerProxy.logger.info(
448
- 'ReconnectionManager:index#executeReconnection --> Updating meeting data from server.'
449
- );
450
- await this.webex.meetings.syncMeetings();
451
- } catch (syncError) {
452
- LoggerProxy.logger.info(
453
- 'ReconnectionManager:index#executeReconnection --> Unable to sync meetings, reconnecting.',
454
- syncError
455
- );
456
- throw new NeedsRetryError(syncError);
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.meetings.reachability.getIpVersion(),
205
+ ipVersion: MeetingUtil.getIpVersion(meeting.webex),
208
206
  })
209
207
  .then(({locus, mediaConnections}) => {
210
208
  if (mediaConnections) {
@@ -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: IP_VERSION;
74
+ ipVersion?: IP_VERSION;
74
75
  locusMediaRequest?: LocusMediaRequest;
75
76
  }) {
76
77
  const {roapMessage, locusSelfUrl, mediaId, meetingId, locusMediaRequest, ipVersion} = options;