@webex/plugin-meetings 2.38.0 → 2.38.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/meeting/muteState.js +13 -0
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/roap/index.js +16 -10
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/turnDiscovery.js +6 -4
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/package.json +18 -18
- package/src/meeting/muteState.ts +11 -0
- package/src/roap/index.ts +8 -8
- package/src/roap/turnDiscovery.ts +4 -4
- package/test/unit/spec/meeting/muteState.js +11 -0
- package/test/unit/spec/roap/index.ts +8 -4
- package/test/unit/spec/roap/turnDiscovery.ts +8 -4
|
@@ -286,6 +286,19 @@ var MuteState = /*#__PURE__*/function () {
|
|
|
286
286
|
return this.state.client.localMute || this.state.server.localMute || this.state.server.remoteMute;
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
+
/**
|
|
290
|
+
* Returns true if the user is locally muted
|
|
291
|
+
*
|
|
292
|
+
* @public
|
|
293
|
+
* @memberof MuteState
|
|
294
|
+
* @returns {Boolean}
|
|
295
|
+
*/
|
|
296
|
+
}, {
|
|
297
|
+
key: "isLocallyMuted",
|
|
298
|
+
value: function isLocallyMuted() {
|
|
299
|
+
return this.state.client.localMute || this.state.server.localMute;
|
|
300
|
+
}
|
|
301
|
+
|
|
289
302
|
/**
|
|
290
303
|
* Returns true if the user is muted as a result of the client request (and not remotely muted)
|
|
291
304
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["createMuteState","type","meeting","mediaDirection","AUDIO","sendAudio","VIDEO","sendVideo","LoggerProxy","logger","info","id","MuteState","ParameterError","state","client","localMute","server","remoteMute","remoteMuted","unmuteAllowed","syncToServerInProgress","pendingPromiseResolve","pendingPromiseReject","mute","reject","PermissionError","applyClientStateLocally","resolve","applyClientStateToServer","Media","setLocalTrack","mediaProperties","audioTrack","videoTrack","localMuteRequiresSync","remoteMuteRequiresSync","localMuteSyncPromise","sendLocalMuteRequestToServer","then","sendRemoteMuteRequestToServer","catch","e","audioMuted","audio","videoMuted","video","MeetingUtil","remoteUpdateAudioVideo","locus","locusInfo","onFullLocus","remoteUpdateError","warn","members","muteMember","selfId","muted","Error","isMuted","isSelf"],"sources":["muteState.ts"],"sourcesContent":["import LoggerProxy from '../common/logs/logger-proxy';\nimport ParameterError from '../common/errors/parameter';\nimport PermissionError from '../common/errors/permission';\nimport Media from '../media';\nimport MeetingUtil from './util';\nimport {AUDIO, VIDEO} from '../constants';\n\n/* Certain aspects of server interaction for video muting are not implemented as we currently don't support remote muting of video.\n If we ever need to support it, search for REMOTE_MUTE_VIDEO_MISSING_IMPLEMENTATION string to find the places that need updating\n*/\n\nconst createMuteState = (type, meeting, mediaDirection) => {\n if (type === AUDIO && !mediaDirection.sendAudio) {\n return null;\n }\n if (type === VIDEO && !mediaDirection.sendVideo) {\n return null;\n }\n\n LoggerProxy.logger.info(\n `Meeting:muteState#createMuteState --> ${type}: creating MuteState for meeting id ${meeting?.id}`\n );\n\n return new MuteState(type, meeting);\n};\n\n/** The purpose of this class is to manage the local and remote mute state and make sure that the server state always matches\n the last requested state by the client.\n\n More info about Locus muting API: https://sqbu-github.cisco.com/pages/WebExSquared/locus/guides/mute.html#\n*/\nclass MuteState {\n pendingPromiseReject: any;\n pendingPromiseResolve: any;\n state: any;\n type: any;\n\n /**\n * Constructor\n *\n * @param {String} type - audio or video\n * @param {Object} meeting - the meeting object (used for reading current remote mute status)\n */\n constructor(type: string, meeting: any) {\n if (type !== AUDIO && type !== VIDEO) {\n throw new ParameterError('Mute state is designed for handling audio or video only');\n }\n this.type = type;\n this.state = {\n client: {\n localMute: false,\n },\n server: {\n localMute: false,\n // initial values available only for audio (REMOTE_MUTE_VIDEO_MISSING_IMPLEMENTATION)\n remoteMute: type === AUDIO ? meeting.remoteMuted : false,\n unmuteAllowed: type === AUDIO ? meeting.unmuteAllowed : true,\n },\n syncToServerInProgress: false,\n };\n // these 2 hold the resolve, reject methods for the promise we returned to the client in last handleClientRequest() call\n this.pendingPromiseResolve = null;\n this.pendingPromiseReject = null;\n }\n\n /**\n * Handles mute/unmute request from the client/user. Returns a promise that's resolved once the server update is completed or\n * at the point that this request becomese superseded by another client request.\n *\n * The client doesn't have to wait for the returned promise to resolve before calling handleClientRequest() again. If\n * handleClientRequest() is called again before the previous one resolved, the MuteState class will make sure that eventually\n * the server state will match the last requested state from the client.\n *\n * @public\n * @memberof MuteState\n * @param {Object} [meeting] the meeting object\n * @param {Boolean} [mute] true for muting, false for unmuting request\n * @returns {Promise}\n */\n public handleClientRequest(meeting?: object, mute?: boolean) {\n LoggerProxy.logger.info(\n `Meeting:muteState#handleClientRequest --> ${this.type}: user requesting new mute state: ${mute}`\n );\n\n if (!mute && !this.state.server.unmuteAllowed) {\n return Promise.reject(\n new PermissionError('User is not allowed to unmute self (hard mute feature is being used)')\n );\n }\n\n // we don't check if we're already in the same state, because even if we were, we would still have to apply the mute state locally,\n // because the client may have changed the audio/vidoe tracks\n this.state.client.localMute = mute;\n this.applyClientStateLocally(meeting);\n\n return new Promise((resolve, reject) => {\n if (this.pendingPromiseResolve) {\n // resolve the last promise we returned to the client as the client has issued a new request that has superseded the previous one\n this.pendingPromiseResolve();\n }\n this.pendingPromiseResolve = resolve;\n this.pendingPromiseReject = reject;\n this.applyClientStateToServer(meeting);\n });\n }\n\n /**\n * Applies the current mute state to the local track (by enabling or disabling it accordingly)\n *\n * @public\n * @param {Object} [meeting] the meeting object\n * @memberof MuteState\n * @returns {void}\n */\n public applyClientStateLocally(meeting?: any) {\n Media.setLocalTrack(\n !this.state.client.localMute,\n this.type === AUDIO ? meeting.mediaProperties.audioTrack : meeting.mediaProperties.videoTrack\n );\n }\n\n /**\n * Updates the server local and remote mute values so that they match the current client desired state.\n *\n * @private\n * @param {Object} [meeting] the meeting object\n * @memberof MuteState\n * @returns {void}\n */\n private applyClientStateToServer(meeting?: object) {\n if (this.state.syncToServerInProgress) {\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: request to server in progress, we need to wait for it to complete`\n );\n\n return;\n }\n\n const localMuteRequiresSync = this.state.client.localMute !== this.state.server.localMute;\n const remoteMuteRequiresSync = !this.state.client.localMute && this.state.server.remoteMute;\n\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: localMuteRequiresSync: ${localMuteRequiresSync} (${this.state.client.localMute} ?= ${this.state.server.localMute})`\n );\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: remoteMuteRequiresSync: ${remoteMuteRequiresSync}`\n );\n\n if (!localMuteRequiresSync && !remoteMuteRequiresSync) {\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: client state already matching server state, nothing to do`\n );\n\n if (this.pendingPromiseResolve) {\n this.pendingPromiseResolve();\n }\n this.pendingPromiseResolve = null;\n this.pendingPromiseReject = null;\n\n return;\n }\n\n this.state.syncToServerInProgress = true;\n\n // first sync local mute with server\n const localMuteSyncPromise = localMuteRequiresSync\n ? this.sendLocalMuteRequestToServer(meeting)\n : Promise.resolve();\n\n localMuteSyncPromise\n .then(() =>\n // then follow it up with remote mute sync\n remoteMuteRequiresSync ? this.sendRemoteMuteRequestToServer(meeting) : Promise.resolve()\n )\n .then(() => {\n this.state.syncToServerInProgress = false;\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: sync with server completed`\n );\n\n // need to check if a new sync is required, because this.state.client may have changed while we were doing the current sync\n this.applyClientStateToServer(meeting);\n })\n .catch((e) => {\n this.state.syncToServerInProgress = false;\n\n if (this.pendingPromiseReject) {\n this.pendingPromiseReject(e);\n }\n this.pendingPromiseResolve = null;\n this.pendingPromiseReject = null;\n });\n }\n\n /**\n * Sets the local mute value in the server\n *\n * @private\n * @param {Object} [meeting] the meeting object\n * @memberof MuteState\n * @returns {Promise}\n */\n private sendLocalMuteRequestToServer(meeting?: any) {\n const audioMuted =\n this.type === AUDIO ? this.state.client.localMute : meeting.audio?.state.client.localMute;\n const videoMuted =\n this.type === VIDEO ? this.state.client.localMute : meeting.video?.state.client.localMute;\n\n LoggerProxy.logger.info(\n `Meeting:muteState#sendLocalMuteRequestToServer --> ${this.type}: sending local mute (audio=${audioMuted}, video=${videoMuted}) to server`\n );\n\n return MeetingUtil.remoteUpdateAudioVideo(audioMuted, videoMuted, meeting)\n .then((locus) => {\n LoggerProxy.logger.info(\n `Meeting:muteState#sendLocalMuteRequestToServer --> ${this.type}: local mute (audio=${audioMuted}, video=${videoMuted}) applied to server`\n );\n\n this.state.server.localMute = this.type === AUDIO ? audioMuted : videoMuted;\n\n meeting.locusInfo.onFullLocus(locus);\n\n return locus;\n })\n .catch((remoteUpdateError) => {\n LoggerProxy.logger.warn(\n `Meeting:muteState#sendLocalMuteRequestToServer --> ${this.type}: failed to apply local mute (audio=${audioMuted}, video=${videoMuted}) to server: ${remoteUpdateError}`\n );\n\n return Promise.reject(remoteUpdateError);\n });\n }\n\n /**\n * Sets the remote mute value in the server\n *\n * @private\n * @param {Object} [meeting] the meeting object\n * @memberof MuteState\n * @returns {Promise}\n */\n private sendRemoteMuteRequestToServer(meeting?: any) {\n if (this.type === AUDIO) {\n const remoteMute = this.state.client.localMute;\n\n LoggerProxy.logger.info(\n `Meeting:muteState#sendRemoteMuteRequestToServer --> ${this.type}: sending remote mute:${remoteMute} to server`\n );\n\n return meeting.members\n .muteMember(meeting.members.selfId, remoteMute)\n .then(() => {\n LoggerProxy.logger.info(\n `Meeting:muteState#sendRemoteMuteRequestToServer --> ${this.type}: remote mute:${remoteMute} applied to server`\n );\n\n this.state.server.remoteMute = remoteMute;\n })\n .catch((remoteUpdateError) => {\n LoggerProxy.logger.warn(\n `Meeting:muteState#sendRemoteMuteRequestToServer --> ${this.type}: failed to apply remote mute ${remoteMute} to server: ${remoteUpdateError}`\n );\n\n return Promise.reject(remoteUpdateError);\n });\n }\n\n // for now we don't need to support remote muting of video (REMOTE_MUTE_VIDEO_MISSING_IMPLEMENTATION)\n this.state.server.remoteMute = this.state.client.localMute;\n\n return Promise.resolve();\n }\n\n /**\n * This method should be called whenever the server remote mute state is changed\n *\n * @public\n * @memberof MuteState\n * @param {Boolean} [muted] true if user is remotely muted, false otherwise\n * @param {Boolean} [unmuteAllowed] indicates if user is allowed to unmute self (false when \"hard mute\" feature is used)\n * @returns {undefined}\n */\n public handleServerRemoteMuteUpdate(muted?: boolean, unmuteAllowed?: boolean) {\n LoggerProxy.logger.info(\n `Meeting:muteState#handleServerRemoteMuteUpdate --> ${this.type}: updating server remoteMute to (${muted})`\n );\n this.state.server.remoteMute = muted;\n this.state.server.unmuteAllowed = unmuteAllowed;\n }\n\n /**\n * This method should be called whenever we receive from the server a requirement to locally unmute\n *\n * @public\n * @memberof MuteState\n * @param {Object} [meeting] the meeting object\n * @returns {undefined}\n */\n public handleServerLocalUnmuteRequired(meeting?: object) {\n LoggerProxy.logger.info(\n `Meeting:muteState#handleServerLocalUnmuteRequired --> ${this.type}: localAudioUnmuteRequired received -> doing local unmute`\n );\n\n this.state.server.remoteMute = false;\n this.state.client.localMute = false;\n\n if (this.pendingPromiseReject) {\n this.pendingPromiseReject(\n new Error('Server requested local unmute - this overrides any client request in progress')\n );\n this.pendingPromiseResolve = null;\n this.pendingPromiseReject = null;\n }\n\n this.applyClientStateLocally(meeting);\n this.applyClientStateToServer(meeting);\n }\n\n /**\n * Returns true if the user is locally or remotely muted\n *\n * @public\n * @memberof MuteState\n * @returns {Boolean}\n */\n public isMuted() {\n return (\n this.state.client.localMute || this.state.server.localMute || this.state.server.remoteMute\n );\n }\n\n /**\n * Returns true if the user is muted as a result of the client request (and not remotely muted)\n *\n * @public\n * @memberof MuteState\n * @returns {Boolean}\n */\n public isSelf() {\n return this.state.client.localMute && !this.state.server.remoteMute;\n }\n\n // defined for backwards compatibility with the old AudioStateMachine/VideoStateMachine classes\n get muted() {\n return this.isMuted();\n }\n\n // defined for backwards compatibility with the old AudioStateMachine/VideoStateMachine classes\n get self() {\n return this.isSelf();\n }\n}\n\nexport default createMuteState;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["createMuteState","type","meeting","mediaDirection","AUDIO","sendAudio","VIDEO","sendVideo","LoggerProxy","logger","info","id","MuteState","ParameterError","state","client","localMute","server","remoteMute","remoteMuted","unmuteAllowed","syncToServerInProgress","pendingPromiseResolve","pendingPromiseReject","mute","reject","PermissionError","applyClientStateLocally","resolve","applyClientStateToServer","Media","setLocalTrack","mediaProperties","audioTrack","videoTrack","localMuteRequiresSync","remoteMuteRequiresSync","localMuteSyncPromise","sendLocalMuteRequestToServer","then","sendRemoteMuteRequestToServer","catch","e","audioMuted","audio","videoMuted","video","MeetingUtil","remoteUpdateAudioVideo","locus","locusInfo","onFullLocus","remoteUpdateError","warn","members","muteMember","selfId","muted","Error","isMuted","isSelf"],"sources":["muteState.ts"],"sourcesContent":["import LoggerProxy from '../common/logs/logger-proxy';\nimport ParameterError from '../common/errors/parameter';\nimport PermissionError from '../common/errors/permission';\nimport Media from '../media';\nimport MeetingUtil from './util';\nimport {AUDIO, VIDEO} from '../constants';\n\n/* Certain aspects of server interaction for video muting are not implemented as we currently don't support remote muting of video.\n If we ever need to support it, search for REMOTE_MUTE_VIDEO_MISSING_IMPLEMENTATION string to find the places that need updating\n*/\n\nconst createMuteState = (type, meeting, mediaDirection) => {\n if (type === AUDIO && !mediaDirection.sendAudio) {\n return null;\n }\n if (type === VIDEO && !mediaDirection.sendVideo) {\n return null;\n }\n\n LoggerProxy.logger.info(\n `Meeting:muteState#createMuteState --> ${type}: creating MuteState for meeting id ${meeting?.id}`\n );\n\n return new MuteState(type, meeting);\n};\n\n/** The purpose of this class is to manage the local and remote mute state and make sure that the server state always matches\n the last requested state by the client.\n\n More info about Locus muting API: https://sqbu-github.cisco.com/pages/WebExSquared/locus/guides/mute.html#\n*/\nclass MuteState {\n pendingPromiseReject: any;\n pendingPromiseResolve: any;\n state: any;\n type: any;\n\n /**\n * Constructor\n *\n * @param {String} type - audio or video\n * @param {Object} meeting - the meeting object (used for reading current remote mute status)\n */\n constructor(type: string, meeting: any) {\n if (type !== AUDIO && type !== VIDEO) {\n throw new ParameterError('Mute state is designed for handling audio or video only');\n }\n this.type = type;\n this.state = {\n client: {\n localMute: false,\n },\n server: {\n localMute: false,\n // initial values available only for audio (REMOTE_MUTE_VIDEO_MISSING_IMPLEMENTATION)\n remoteMute: type === AUDIO ? meeting.remoteMuted : false,\n unmuteAllowed: type === AUDIO ? meeting.unmuteAllowed : true,\n },\n syncToServerInProgress: false,\n };\n // these 2 hold the resolve, reject methods for the promise we returned to the client in last handleClientRequest() call\n this.pendingPromiseResolve = null;\n this.pendingPromiseReject = null;\n }\n\n /**\n * Handles mute/unmute request from the client/user. Returns a promise that's resolved once the server update is completed or\n * at the point that this request becomese superseded by another client request.\n *\n * The client doesn't have to wait for the returned promise to resolve before calling handleClientRequest() again. If\n * handleClientRequest() is called again before the previous one resolved, the MuteState class will make sure that eventually\n * the server state will match the last requested state from the client.\n *\n * @public\n * @memberof MuteState\n * @param {Object} [meeting] the meeting object\n * @param {Boolean} [mute] true for muting, false for unmuting request\n * @returns {Promise}\n */\n public handleClientRequest(meeting?: object, mute?: boolean) {\n LoggerProxy.logger.info(\n `Meeting:muteState#handleClientRequest --> ${this.type}: user requesting new mute state: ${mute}`\n );\n\n if (!mute && !this.state.server.unmuteAllowed) {\n return Promise.reject(\n new PermissionError('User is not allowed to unmute self (hard mute feature is being used)')\n );\n }\n\n // we don't check if we're already in the same state, because even if we were, we would still have to apply the mute state locally,\n // because the client may have changed the audio/vidoe tracks\n this.state.client.localMute = mute;\n this.applyClientStateLocally(meeting);\n\n return new Promise((resolve, reject) => {\n if (this.pendingPromiseResolve) {\n // resolve the last promise we returned to the client as the client has issued a new request that has superseded the previous one\n this.pendingPromiseResolve();\n }\n this.pendingPromiseResolve = resolve;\n this.pendingPromiseReject = reject;\n this.applyClientStateToServer(meeting);\n });\n }\n\n /**\n * Applies the current mute state to the local track (by enabling or disabling it accordingly)\n *\n * @public\n * @param {Object} [meeting] the meeting object\n * @memberof MuteState\n * @returns {void}\n */\n public applyClientStateLocally(meeting?: any) {\n Media.setLocalTrack(\n !this.state.client.localMute,\n this.type === AUDIO ? meeting.mediaProperties.audioTrack : meeting.mediaProperties.videoTrack\n );\n }\n\n /**\n * Updates the server local and remote mute values so that they match the current client desired state.\n *\n * @private\n * @param {Object} [meeting] the meeting object\n * @memberof MuteState\n * @returns {void}\n */\n private applyClientStateToServer(meeting?: object) {\n if (this.state.syncToServerInProgress) {\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: request to server in progress, we need to wait for it to complete`\n );\n\n return;\n }\n\n const localMuteRequiresSync = this.state.client.localMute !== this.state.server.localMute;\n const remoteMuteRequiresSync = !this.state.client.localMute && this.state.server.remoteMute;\n\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: localMuteRequiresSync: ${localMuteRequiresSync} (${this.state.client.localMute} ?= ${this.state.server.localMute})`\n );\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: remoteMuteRequiresSync: ${remoteMuteRequiresSync}`\n );\n\n if (!localMuteRequiresSync && !remoteMuteRequiresSync) {\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: client state already matching server state, nothing to do`\n );\n\n if (this.pendingPromiseResolve) {\n this.pendingPromiseResolve();\n }\n this.pendingPromiseResolve = null;\n this.pendingPromiseReject = null;\n\n return;\n }\n\n this.state.syncToServerInProgress = true;\n\n // first sync local mute with server\n const localMuteSyncPromise = localMuteRequiresSync\n ? this.sendLocalMuteRequestToServer(meeting)\n : Promise.resolve();\n\n localMuteSyncPromise\n .then(() =>\n // then follow it up with remote mute sync\n remoteMuteRequiresSync ? this.sendRemoteMuteRequestToServer(meeting) : Promise.resolve()\n )\n .then(() => {\n this.state.syncToServerInProgress = false;\n LoggerProxy.logger.info(\n `Meeting:muteState#applyClientStateToServer --> ${this.type}: sync with server completed`\n );\n\n // need to check if a new sync is required, because this.state.client may have changed while we were doing the current sync\n this.applyClientStateToServer(meeting);\n })\n .catch((e) => {\n this.state.syncToServerInProgress = false;\n\n if (this.pendingPromiseReject) {\n this.pendingPromiseReject(e);\n }\n this.pendingPromiseResolve = null;\n this.pendingPromiseReject = null;\n });\n }\n\n /**\n * Sets the local mute value in the server\n *\n * @private\n * @param {Object} [meeting] the meeting object\n * @memberof MuteState\n * @returns {Promise}\n */\n private sendLocalMuteRequestToServer(meeting?: any) {\n const audioMuted =\n this.type === AUDIO ? this.state.client.localMute : meeting.audio?.state.client.localMute;\n const videoMuted =\n this.type === VIDEO ? this.state.client.localMute : meeting.video?.state.client.localMute;\n\n LoggerProxy.logger.info(\n `Meeting:muteState#sendLocalMuteRequestToServer --> ${this.type}: sending local mute (audio=${audioMuted}, video=${videoMuted}) to server`\n );\n\n return MeetingUtil.remoteUpdateAudioVideo(audioMuted, videoMuted, meeting)\n .then((locus) => {\n LoggerProxy.logger.info(\n `Meeting:muteState#sendLocalMuteRequestToServer --> ${this.type}: local mute (audio=${audioMuted}, video=${videoMuted}) applied to server`\n );\n\n this.state.server.localMute = this.type === AUDIO ? audioMuted : videoMuted;\n\n meeting.locusInfo.onFullLocus(locus);\n\n return locus;\n })\n .catch((remoteUpdateError) => {\n LoggerProxy.logger.warn(\n `Meeting:muteState#sendLocalMuteRequestToServer --> ${this.type}: failed to apply local mute (audio=${audioMuted}, video=${videoMuted}) to server: ${remoteUpdateError}`\n );\n\n return Promise.reject(remoteUpdateError);\n });\n }\n\n /**\n * Sets the remote mute value in the server\n *\n * @private\n * @param {Object} [meeting] the meeting object\n * @memberof MuteState\n * @returns {Promise}\n */\n private sendRemoteMuteRequestToServer(meeting?: any) {\n if (this.type === AUDIO) {\n const remoteMute = this.state.client.localMute;\n\n LoggerProxy.logger.info(\n `Meeting:muteState#sendRemoteMuteRequestToServer --> ${this.type}: sending remote mute:${remoteMute} to server`\n );\n\n return meeting.members\n .muteMember(meeting.members.selfId, remoteMute)\n .then(() => {\n LoggerProxy.logger.info(\n `Meeting:muteState#sendRemoteMuteRequestToServer --> ${this.type}: remote mute:${remoteMute} applied to server`\n );\n\n this.state.server.remoteMute = remoteMute;\n })\n .catch((remoteUpdateError) => {\n LoggerProxy.logger.warn(\n `Meeting:muteState#sendRemoteMuteRequestToServer --> ${this.type}: failed to apply remote mute ${remoteMute} to server: ${remoteUpdateError}`\n );\n\n return Promise.reject(remoteUpdateError);\n });\n }\n\n // for now we don't need to support remote muting of video (REMOTE_MUTE_VIDEO_MISSING_IMPLEMENTATION)\n this.state.server.remoteMute = this.state.client.localMute;\n\n return Promise.resolve();\n }\n\n /**\n * This method should be called whenever the server remote mute state is changed\n *\n * @public\n * @memberof MuteState\n * @param {Boolean} [muted] true if user is remotely muted, false otherwise\n * @param {Boolean} [unmuteAllowed] indicates if user is allowed to unmute self (false when \"hard mute\" feature is used)\n * @returns {undefined}\n */\n public handleServerRemoteMuteUpdate(muted?: boolean, unmuteAllowed?: boolean) {\n LoggerProxy.logger.info(\n `Meeting:muteState#handleServerRemoteMuteUpdate --> ${this.type}: updating server remoteMute to (${muted})`\n );\n this.state.server.remoteMute = muted;\n this.state.server.unmuteAllowed = unmuteAllowed;\n }\n\n /**\n * This method should be called whenever we receive from the server a requirement to locally unmute\n *\n * @public\n * @memberof MuteState\n * @param {Object} [meeting] the meeting object\n * @returns {undefined}\n */\n public handleServerLocalUnmuteRequired(meeting?: object) {\n LoggerProxy.logger.info(\n `Meeting:muteState#handleServerLocalUnmuteRequired --> ${this.type}: localAudioUnmuteRequired received -> doing local unmute`\n );\n\n this.state.server.remoteMute = false;\n this.state.client.localMute = false;\n\n if (this.pendingPromiseReject) {\n this.pendingPromiseReject(\n new Error('Server requested local unmute - this overrides any client request in progress')\n );\n this.pendingPromiseResolve = null;\n this.pendingPromiseReject = null;\n }\n\n this.applyClientStateLocally(meeting);\n this.applyClientStateToServer(meeting);\n }\n\n /**\n * Returns true if the user is locally or remotely muted\n *\n * @public\n * @memberof MuteState\n * @returns {Boolean}\n */\n public isMuted() {\n return (\n this.state.client.localMute || this.state.server.localMute || this.state.server.remoteMute\n );\n }\n\n /**\n * Returns true if the user is locally muted\n *\n * @public\n * @memberof MuteState\n * @returns {Boolean}\n */\n public isLocallyMuted() {\n return this.state.client.localMute || this.state.server.localMute;\n }\n\n /**\n * Returns true if the user is muted as a result of the client request (and not remotely muted)\n *\n * @public\n * @memberof MuteState\n * @returns {Boolean}\n */\n public isSelf() {\n return this.state.client.localMute && !this.state.server.remoteMute;\n }\n\n // defined for backwards compatibility with the old AudioStateMachine/VideoStateMachine classes\n get muted() {\n return this.isMuted();\n }\n\n // defined for backwards compatibility with the old AudioStateMachine/VideoStateMachine classes\n get self() {\n return this.isSelf();\n }\n}\n\nexport default createMuteState;\n"],"mappings":"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"}
|
package/dist/roap/index.js
CHANGED
|
@@ -72,6 +72,7 @@ var Roap = /*#__PURE__*/function (_StatelessWebexPlugin) {
|
|
|
72
72
|
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "roapRequest", void 0);
|
|
73
73
|
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "turnDiscovery", void 0);
|
|
74
74
|
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "sendRoapCallRequest", function (options) {
|
|
75
|
+
var _meeting$audio, _meeting$video;
|
|
75
76
|
var meeting = options.meeting;
|
|
76
77
|
var roapMessage = {
|
|
77
78
|
messageType: _constants.ROAP.ROAP_TYPES.OFFER,
|
|
@@ -92,8 +93,8 @@ var Roap = /*#__PURE__*/function (_StatelessWebexPlugin) {
|
|
|
92
93
|
roapMessage: roapMessage,
|
|
93
94
|
// eslint-disable-next-line no-warning-comments
|
|
94
95
|
// TODO: check whats the need for video and audiomute
|
|
95
|
-
audioMuted:
|
|
96
|
-
videoMuted:
|
|
96
|
+
audioMuted: (_meeting$audio = meeting.audio) === null || _meeting$audio === void 0 ? void 0 : _meeting$audio.isLocallyMuted(),
|
|
97
|
+
videoMuted: (_meeting$video = meeting.video) === null || _meeting$video === void 0 ? void 0 : _meeting$video.isLocallyMuted()
|
|
97
98
|
}))
|
|
98
99
|
// mediaId: meeting.mediaId
|
|
99
100
|
}]
|
|
@@ -210,6 +211,7 @@ var Roap = /*#__PURE__*/function (_StatelessWebexPlugin) {
|
|
|
210
211
|
value: function sendRoapOK(options) {
|
|
211
212
|
var _this2 = this;
|
|
212
213
|
return _promise.default.resolve().then(function () {
|
|
214
|
+
var _meeting$audio2, _meeting$video2;
|
|
213
215
|
// @ts-ignore
|
|
214
216
|
var meeting = _this2.webex.meetings.meetingCollection.getByKey('correlationId', options.correlationId);
|
|
215
217
|
var roapMessage = {
|
|
@@ -223,8 +225,8 @@ var Roap = /*#__PURE__*/function (_StatelessWebexPlugin) {
|
|
|
223
225
|
locusSelfUrl: meeting.selfUrl,
|
|
224
226
|
mediaId: options.mediaId,
|
|
225
227
|
correlationId: options.correlationId,
|
|
226
|
-
audioMuted: meeting.
|
|
227
|
-
videoMuted: meeting.
|
|
228
|
+
audioMuted: (_meeting$audio2 = meeting.audio) === null || _meeting$audio2 === void 0 ? void 0 : _meeting$audio2.isLocallyMuted(),
|
|
229
|
+
videoMuted: (_meeting$video2 = meeting.video) === null || _meeting$video2 === void 0 ? void 0 : _meeting$video2.isLocallyMuted(),
|
|
228
230
|
meetingId: meeting.id
|
|
229
231
|
}).then(function () {
|
|
230
232
|
_this2.roapHandler.submit({
|
|
@@ -252,7 +254,9 @@ var Roap = /*#__PURE__*/function (_StatelessWebexPlugin) {
|
|
|
252
254
|
}, {
|
|
253
255
|
key: "sendRoapAnswer",
|
|
254
256
|
value: function sendRoapAnswer(options) {
|
|
255
|
-
var
|
|
257
|
+
var _meeting$audio3,
|
|
258
|
+
_meeting$video3,
|
|
259
|
+
_this3 = this;
|
|
256
260
|
// @ts-ignore
|
|
257
261
|
var meeting = this.webex.meetings.meetingCollection.getByKey('correlationId', options.correlationId);
|
|
258
262
|
var roapMessage = {
|
|
@@ -271,8 +275,8 @@ var Roap = /*#__PURE__*/function (_StatelessWebexPlugin) {
|
|
|
271
275
|
locusSelfUrl: meeting.selfUrl,
|
|
272
276
|
mediaId: options.mediaId,
|
|
273
277
|
correlationId: options.correlationId,
|
|
274
|
-
audioMuted:
|
|
275
|
-
videoMuted:
|
|
278
|
+
audioMuted: (_meeting$audio3 = meeting.audio) === null || _meeting$audio3 === void 0 ? void 0 : _meeting$audio3.isLocallyMuted(),
|
|
279
|
+
videoMuted: (_meeting$video3 = meeting.video) === null || _meeting$video3 === void 0 ? void 0 : _meeting$video3.isLocallyMuted(),
|
|
276
280
|
meetingId: meeting.id
|
|
277
281
|
}).then(function () {
|
|
278
282
|
meeting.setRoapSeq(options.seq);
|
|
@@ -315,7 +319,9 @@ var Roap = /*#__PURE__*/function (_StatelessWebexPlugin) {
|
|
|
315
319
|
}, {
|
|
316
320
|
key: "sendRoapMediaRequest",
|
|
317
321
|
value: function sendRoapMediaRequest(options) {
|
|
318
|
-
var
|
|
322
|
+
var _meeting$audio4,
|
|
323
|
+
_meeting$video4,
|
|
324
|
+
_this4 = this;
|
|
319
325
|
var meeting = options.meeting,
|
|
320
326
|
reconnect = options.reconnect;
|
|
321
327
|
var roapMessage = {
|
|
@@ -342,8 +348,8 @@ var Roap = /*#__PURE__*/function (_StatelessWebexPlugin) {
|
|
|
342
348
|
correlationId: meeting.correlationId,
|
|
343
349
|
locusSelfUrl: meeting.selfUrl,
|
|
344
350
|
mediaId: sendEmptyMediaId ? '' : meeting.mediaId,
|
|
345
|
-
audioMuted: meeting.
|
|
346
|
-
videoMuted: meeting.
|
|
351
|
+
audioMuted: (_meeting$audio4 = meeting.audio) === null || _meeting$audio4 === void 0 ? void 0 : _meeting$audio4.isLocallyMuted(),
|
|
352
|
+
videoMuted: (_meeting$video4 = meeting.video) === null || _meeting$video4 === void 0 ? void 0 : _meeting$video4.isLocallyMuted(),
|
|
347
353
|
meetingId: meeting.id
|
|
348
354
|
}).then(function (_ref) {
|
|
349
355
|
var locus = _ref.locus,
|
package/dist/roap/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Roap","attrs","options","meeting","roapMessage","messageType","ROAP","ROAP_TYPES","OFFER","sdps","sdp","version","ROAP_VERSION","seq","roapSeq","tieBreaker","roapHandler","submit","type","SEND_ROAP_MSG","msg","correlationId","roapBody","localMedias","localSdp","roapRequest","attachRechabilityData","audioMuted","isAudioMuted","videoMuted","isVideoMuted","MeetingUtil","joinMeetingOptions","then","locus","SEND_ROAP_MSG_SUCCESS","setRoapSeq","RoapHandler","sendRoapOK","bind","sendRoapAnswer","roapFinished","RoapRequest","lastRoapOffer","turnDiscovery","TurnDiscovery","data","message","LoggerProxy","logger","log","TURN_DISCOVERY_RESPONSE","handleTurnDiscoveryResponse","RECEIVE_ROAP_MSG","RECEIVE_CALL_LEAVE","resolve","webex","meetings","meetingCollection","getByKey","OK","sendRoap","locusSelfUrl","selfUrl","mediaId","meetingId","id","ANSWER","session","errorType","ERROR","reconnect","sendEmptyMediaId","config","experimental","enableTurnDiscovery","mediaConnections","updateMediaConnections","sequenceId","RoapCollection","onSessionSequenceFinish","mediaNegotiatedEvent","isBusy","processNextQueuedMediaUpdate","isReconnecting","doTurnDiscovery","StatelessWebexPlugin"],"sources":["index.ts"],"sourcesContent":["// @ts-ignore\nimport {StatelessWebexPlugin} from '@webex/webex-core';\n\nimport {ROAP} from '../constants';\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport MeetingUtil from '../meeting/util';\n\nimport RoapHandler from './handler';\nimport RoapRequest from './request';\nimport RoapCollection from './collection';\nimport TurnDiscovery from './turnDiscovery';\nimport Meeting from '../meeting';\n\n/**\n * Roap options\n * @typedef {Object} RoapOptions\n * @property {String} sdp\n * @property {Meeting} meeting\n * @property {Number} roapSeq\n * @property {Boolean} reconnect\n */\n\n/**\n * @typedef {Object} SeqOptions\n * @property {String} correlationId\n * @property {String} mediaId\n * @property {Number} seq\n */\n\n/**\n * @class Roap\n * @export\n * @private\n */\nexport default class Roap extends StatelessWebexPlugin {\n attrs: any;\n lastRoapOffer: any;\n options: any;\n roapHandler: any;\n roapRequest: any;\n turnDiscovery: any;\n\n /**\n *\n * @param {Object} attrs\n * @param {Object} options\n */\n constructor(attrs: any, options: any) {\n super({}, options);\n /**\n * @instance\n * @type {Object}\n * @private\n * @memberof Roap\n */\n this.attrs = attrs;\n /**\n * @instance\n * @type {Object}\n * @private\n * @memberof Roap\n */\n this.options = options;\n /**\n * The Roap Process State Handler\n * @instance\n * @type {RoapHandler}\n * @private\n * @memberof Roap\n */\n this.roapHandler = new RoapHandler(\n this.attrs,\n this.options,\n this.sendRoapOK.bind(this),\n this.sendRoapAnswer.bind(this),\n this.roapFinished.bind(this)\n );\n /**\n * The Roap Request Server Proxy Object\n * @instance\n * @type {RoapRequest}\n * @private\n * @memberof Roap\n */\n // @ts-ignore\n this.roapRequest = new RoapRequest({}, options);\n /**\n * The last roap offer sent to server and acked\n * @instance\n * @type {Object}\n * @private\n * @memberof Roap\n */\n this.lastRoapOffer = {};\n\n this.turnDiscovery = new TurnDiscovery(this.roapRequest);\n }\n\n /**\n * Starts listening to mercury events for Roap messages\n * @param {object} data event object\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n private roapEvent(data: any) {\n const msg = data.message;\n const {correlationId} = data;\n\n LoggerProxy.logger.log(\n `Roap:index#roapEvent --> Received Roap Message [${JSON.stringify(msg, null, 2)}]`\n );\n\n if (msg.messageType === ROAP.ROAP_TYPES.TURN_DISCOVERY_RESPONSE) {\n // turn discovery is not part of normal roap protocol and so we are not handling it\n // through the usual roap state machine\n this.turnDiscovery.handleTurnDiscoveryResponse(msg);\n } else {\n this.roapHandler.submit({\n type: ROAP.RECEIVE_ROAP_MSG,\n msg,\n correlationId,\n });\n }\n }\n\n /**\n *\n * @param {String} correlationId correlation id of a meeting\n * @param {Number} seq ROAP sequence number\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n private stop(correlationId: string, seq: number) {\n this.roapHandler.submit({\n type: ROAP.RECEIVE_CALL_LEAVE,\n seq,\n correlationId,\n });\n\n return Promise.resolve();\n }\n\n /**\n *\n * @param {SeqOptions} options\n * @returns {null}\n * @private\n * @memberof Roap\n */\n private sendRoapOK(options: any) {\n return Promise.resolve().then(() => {\n // @ts-ignore\n const meeting = this.webex.meetings.meetingCollection.getByKey(\n 'correlationId',\n options.correlationId\n );\n const roapMessage = {\n messageType: ROAP.ROAP_TYPES.OK,\n version: ROAP.ROAP_VERSION,\n seq: options.seq,\n };\n\n LoggerProxy.logger.log(`Roap:index#sendRoapOK --> ROAP OK sending with seq ${options.seq}`);\n\n return this.roapRequest\n .sendRoap({\n roapMessage,\n locusSelfUrl: meeting.selfUrl,\n mediaId: options.mediaId,\n correlationId: options.correlationId,\n audioMuted: meeting.isAudioMuted(),\n videoMuted: meeting.isVideoMuted(),\n meetingId: meeting.id,\n })\n .then(() => {\n this.roapHandler.submit({\n type: ROAP.SEND_ROAP_MSG,\n msg: roapMessage,\n correlationId: options.correlationId,\n });\n LoggerProxy.logger.log(`Roap:index#sendRoapOK --> ROAP OK sent with seq ${options.seq}`);\n meeting.setRoapSeq(options.seq);\n });\n });\n }\n\n // eslint-disable-next-line no-warning-comments\n // TODO: try to merge sendRoapOk and roapAnswer\n /**\n * Sends a ROAP answer...\n * @param {SeqOptions} options\n * @param {Boolean} options.audioMuted\n * @param {Boolean} options.videoMuted\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n private sendRoapAnswer(options: any) {\n // @ts-ignore\n const meeting = this.webex.meetings.meetingCollection.getByKey(\n 'correlationId',\n options.correlationId\n );\n const roapMessage = {\n messageType: ROAP.ROAP_TYPES.ANSWER,\n sdps: options.sdps,\n version: ROAP.ROAP_VERSION,\n seq: options.seq,\n };\n\n this.roapHandler.submit({\n type: ROAP.SEND_ROAP_MSG,\n msg: roapMessage,\n correlationId: options.correlationId,\n });\n\n return this.roapRequest\n .sendRoap({\n roapMessage,\n locusSelfUrl: meeting.selfUrl,\n mediaId: options.mediaId,\n correlationId: options.correlationId,\n audioMuted: options.audioMuted,\n videoMuted: options.videoMuted,\n meetingId: meeting.id,\n })\n .then(() => {\n meeting.setRoapSeq(options.seq);\n\n this.roapHandler.submit({\n type: ROAP.SEND_ROAP_MSG_SUCCESS,\n seq: roapMessage.seq,\n correlationId: meeting.correlationId,\n });\n });\n }\n\n /**\n * Sends a ROAP error...\n * @param {Object} session\n * @param {Object} locus\n * @param {String} errorType\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n private sendRoapError(session: any, locus: object, errorType: string) {\n const msg = {\n messageType: ROAP.ROAP_TYPES.ERROR,\n version: ROAP.ROAP_VERSION,\n errorType,\n seq: session.OFFER.seq,\n };\n\n return this.roapRequest.sendRoap(msg, locus);\n }\n\n /**\n * sends a roap media request\n * @param {RoapOptions} options\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n sendRoapMediaRequest(options: any) {\n const {meeting, reconnect} = options;\n const roapMessage = {\n messageType: ROAP.ROAP_TYPES.OFFER,\n sdps: [options.sdp],\n // sdps: [options.sdp],\n version: ROAP.ROAP_VERSION,\n seq:\n typeof options.roapSeq !== 'number' && Number.isNaN(parseFloat(options.roapSeq))\n ? 0\n : options.roapSeq + 1,\n tieBreaker: 4294967294, // Math.floor(Math.random() * (2 ** 32) - 1) // TODO: Handle the roap conflict scenario\n };\n\n this.roapHandler.submit({\n type: ROAP.SEND_ROAP_MSG,\n msg: roapMessage,\n correlationId: meeting.correlationId,\n });\n\n // When reconnecting, it's important that the first roap message being sent out has empty media id.\n // Normally this is the roap offer, but when TURN discovery is enabled,\n // then this is the TURN discovery request message\n const sendEmptyMediaId = reconnect && !meeting.config.experimental.enableTurnDiscovery;\n\n return this.roapRequest\n .sendRoap({\n roapMessage,\n correlationId: meeting.correlationId,\n locusSelfUrl: meeting.selfUrl,\n mediaId: sendEmptyMediaId ? '' : meeting.mediaId,\n audioMuted: meeting.isAudioMuted(),\n videoMuted: meeting.isVideoMuted(),\n meetingId: meeting.id,\n })\n .then(({locus, mediaConnections}) => {\n this.roapHandler.submit({\n type: ROAP.SEND_ROAP_MSG_SUCCESS,\n seq: roapMessage.seq,\n correlationId: meeting.correlationId,\n });\n meeting.setRoapSeq(roapMessage.seq);\n\n if (mediaConnections) {\n meeting.updateMediaConnections(mediaConnections);\n }\n\n // eslint-disable-next-line no-warning-comments\n // TODO: we need to attach peerconenction to locus not sure if we need to pass everything here\n return locus;\n // eslint-disable-next-line no-warning-comments\n // TODO: check where to update the sequence number\n });\n }\n\n /**\n * sends a roap media request\n * @param {RoapOptions} options\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n sendRoapCallRequest = (options: any) => {\n const {meeting} = options;\n const roapMessage = {\n messageType: ROAP.ROAP_TYPES.OFFER,\n sdps: [options.sdp],\n version: ROAP.ROAP_VERSION,\n seq:\n typeof options.roapSeq !== 'number' && Number.isNaN(parseFloat(options.roapSeq))\n ? 0\n : options.roapSeq + 1,\n tieBreaker: 4294967294, // Math.floor(Math.random() * (2 ** 32) - 1) // TODO: Handle the roap conflict scenario\n };\n\n this.roapHandler.submit({\n type: ROAP.SEND_ROAP_MSG,\n msg: roapMessage,\n correlationId: meeting.correlationId,\n });\n\n const roapBody = {\n localMedias: [\n {\n localSdp: JSON.stringify(\n this.roapRequest.attachRechabilityData({\n roapMessage,\n // eslint-disable-next-line no-warning-comments\n // TODO: check whats the need for video and audiomute\n audioMuted: !!meeting.isAudioMuted(),\n videoMuted: !!meeting.isVideoMuted(),\n })\n ),\n // mediaId: meeting.mediaId\n },\n ],\n };\n\n return MeetingUtil.joinMeetingOptions(meeting, {roapMessage: roapBody}).then((locus) => {\n this.roapHandler.submit({\n type: ROAP.SEND_ROAP_MSG_SUCCESS,\n seq: roapMessage.seq,\n correlationId: meeting.correlationId,\n });\n meeting.setRoapSeq(roapMessage.seq);\n\n // eslint-disable-next-line no-warning-comments\n // TODO: we need to attach peerconenction to locus not sure if we need to pass everything here\n return locus;\n // eslint-disable-next-line no-warning-comments\n // TODO: check where to update the sequence number\n });\n };\n\n /**\n * Called when the roap sequence is finished (completed successfully or failed)\n * @param {String} correlationId id of the meeting affected\n * @param {String} sequenceId the id of the finished sequence\n * @returns {undefined}\n * @private\n * @memberof Roap\n */\n private roapFinished(correlationId: string, sequenceId: string) {\n RoapCollection.onSessionSequenceFinish(correlationId, sequenceId);\n // @ts-ignore\n const meeting = this.webex.meetings.meetingCollection.getByKey('correlationId', correlationId);\n\n meeting.mediaNegotiatedEvent();\n if (!RoapCollection.isBusy(correlationId)) {\n meeting.processNextQueuedMediaUpdate();\n }\n }\n\n /**\n * Performs a TURN server discovery procedure, which involves exchanging\n * some roap messages with the server. This exchange has to be done before\n * any other roap messages are sent\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 doTurnDiscovery(meeting: Meeting, isReconnecting: boolean) {\n return this.turnDiscovery.doTurnDiscovery(meeting, isReconnecting);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["Roap","attrs","options","meeting","roapMessage","messageType","ROAP","ROAP_TYPES","OFFER","sdps","sdp","version","ROAP_VERSION","seq","roapSeq","tieBreaker","roapHandler","submit","type","SEND_ROAP_MSG","msg","correlationId","roapBody","localMedias","localSdp","roapRequest","attachRechabilityData","audioMuted","audio","isLocallyMuted","videoMuted","video","MeetingUtil","joinMeetingOptions","then","locus","SEND_ROAP_MSG_SUCCESS","setRoapSeq","RoapHandler","sendRoapOK","bind","sendRoapAnswer","roapFinished","RoapRequest","lastRoapOffer","turnDiscovery","TurnDiscovery","data","message","LoggerProxy","logger","log","TURN_DISCOVERY_RESPONSE","handleTurnDiscoveryResponse","RECEIVE_ROAP_MSG","RECEIVE_CALL_LEAVE","resolve","webex","meetings","meetingCollection","getByKey","OK","sendRoap","locusSelfUrl","selfUrl","mediaId","meetingId","id","ANSWER","session","errorType","ERROR","reconnect","sendEmptyMediaId","config","experimental","enableTurnDiscovery","mediaConnections","updateMediaConnections","sequenceId","RoapCollection","onSessionSequenceFinish","mediaNegotiatedEvent","isBusy","processNextQueuedMediaUpdate","isReconnecting","doTurnDiscovery","StatelessWebexPlugin"],"sources":["index.ts"],"sourcesContent":["// @ts-ignore\nimport {StatelessWebexPlugin} from '@webex/webex-core';\n\nimport {ROAP} from '../constants';\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport MeetingUtil from '../meeting/util';\n\nimport RoapHandler from './handler';\nimport RoapRequest from './request';\nimport RoapCollection from './collection';\nimport TurnDiscovery from './turnDiscovery';\nimport Meeting from '../meeting';\n\n/**\n * Roap options\n * @typedef {Object} RoapOptions\n * @property {String} sdp\n * @property {Meeting} meeting\n * @property {Number} roapSeq\n * @property {Boolean} reconnect\n */\n\n/**\n * @typedef {Object} SeqOptions\n * @property {String} correlationId\n * @property {String} mediaId\n * @property {Number} seq\n */\n\n/**\n * @class Roap\n * @export\n * @private\n */\nexport default class Roap extends StatelessWebexPlugin {\n attrs: any;\n lastRoapOffer: any;\n options: any;\n roapHandler: any;\n roapRequest: any;\n turnDiscovery: any;\n\n /**\n *\n * @param {Object} attrs\n * @param {Object} options\n */\n constructor(attrs: any, options: any) {\n super({}, options);\n /**\n * @instance\n * @type {Object}\n * @private\n * @memberof Roap\n */\n this.attrs = attrs;\n /**\n * @instance\n * @type {Object}\n * @private\n * @memberof Roap\n */\n this.options = options;\n /**\n * The Roap Process State Handler\n * @instance\n * @type {RoapHandler}\n * @private\n * @memberof Roap\n */\n this.roapHandler = new RoapHandler(\n this.attrs,\n this.options,\n this.sendRoapOK.bind(this),\n this.sendRoapAnswer.bind(this),\n this.roapFinished.bind(this)\n );\n /**\n * The Roap Request Server Proxy Object\n * @instance\n * @type {RoapRequest}\n * @private\n * @memberof Roap\n */\n // @ts-ignore\n this.roapRequest = new RoapRequest({}, options);\n /**\n * The last roap offer sent to server and acked\n * @instance\n * @type {Object}\n * @private\n * @memberof Roap\n */\n this.lastRoapOffer = {};\n\n this.turnDiscovery = new TurnDiscovery(this.roapRequest);\n }\n\n /**\n * Starts listening to mercury events for Roap messages\n * @param {object} data event object\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n private roapEvent(data: any) {\n const msg = data.message;\n const {correlationId} = data;\n\n LoggerProxy.logger.log(\n `Roap:index#roapEvent --> Received Roap Message [${JSON.stringify(msg, null, 2)}]`\n );\n\n if (msg.messageType === ROAP.ROAP_TYPES.TURN_DISCOVERY_RESPONSE) {\n // turn discovery is not part of normal roap protocol and so we are not handling it\n // through the usual roap state machine\n this.turnDiscovery.handleTurnDiscoveryResponse(msg);\n } else {\n this.roapHandler.submit({\n type: ROAP.RECEIVE_ROAP_MSG,\n msg,\n correlationId,\n });\n }\n }\n\n /**\n *\n * @param {String} correlationId correlation id of a meeting\n * @param {Number} seq ROAP sequence number\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n private stop(correlationId: string, seq: number) {\n this.roapHandler.submit({\n type: ROAP.RECEIVE_CALL_LEAVE,\n seq,\n correlationId,\n });\n\n return Promise.resolve();\n }\n\n /**\n *\n * @param {SeqOptions} options\n * @returns {null}\n * @private\n * @memberof Roap\n */\n private sendRoapOK(options: any) {\n return Promise.resolve().then(() => {\n // @ts-ignore\n const meeting = this.webex.meetings.meetingCollection.getByKey(\n 'correlationId',\n options.correlationId\n );\n const roapMessage = {\n messageType: ROAP.ROAP_TYPES.OK,\n version: ROAP.ROAP_VERSION,\n seq: options.seq,\n };\n\n LoggerProxy.logger.log(`Roap:index#sendRoapOK --> ROAP OK sending with seq ${options.seq}`);\n\n return this.roapRequest\n .sendRoap({\n roapMessage,\n locusSelfUrl: meeting.selfUrl,\n mediaId: options.mediaId,\n correlationId: options.correlationId,\n audioMuted: meeting.audio?.isLocallyMuted(),\n videoMuted: meeting.video?.isLocallyMuted(),\n meetingId: meeting.id,\n })\n .then(() => {\n this.roapHandler.submit({\n type: ROAP.SEND_ROAP_MSG,\n msg: roapMessage,\n correlationId: options.correlationId,\n });\n LoggerProxy.logger.log(`Roap:index#sendRoapOK --> ROAP OK sent with seq ${options.seq}`);\n meeting.setRoapSeq(options.seq);\n });\n });\n }\n\n // eslint-disable-next-line no-warning-comments\n // TODO: try to merge sendRoapOk and roapAnswer\n /**\n * Sends a ROAP answer...\n * @param {SeqOptions} options\n * @param {Boolean} options.audioMuted\n * @param {Boolean} options.videoMuted\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n private sendRoapAnswer(options: any) {\n // @ts-ignore\n const meeting = this.webex.meetings.meetingCollection.getByKey(\n 'correlationId',\n options.correlationId\n );\n const roapMessage = {\n messageType: ROAP.ROAP_TYPES.ANSWER,\n sdps: options.sdps,\n version: ROAP.ROAP_VERSION,\n seq: options.seq,\n };\n\n this.roapHandler.submit({\n type: ROAP.SEND_ROAP_MSG,\n msg: roapMessage,\n correlationId: options.correlationId,\n });\n\n return this.roapRequest\n .sendRoap({\n roapMessage,\n locusSelfUrl: meeting.selfUrl,\n mediaId: options.mediaId,\n correlationId: options.correlationId,\n audioMuted: meeting.audio?.isLocallyMuted(),\n videoMuted: meeting.video?.isLocallyMuted(),\n meetingId: meeting.id,\n })\n .then(() => {\n meeting.setRoapSeq(options.seq);\n\n this.roapHandler.submit({\n type: ROAP.SEND_ROAP_MSG_SUCCESS,\n seq: roapMessage.seq,\n correlationId: meeting.correlationId,\n });\n });\n }\n\n /**\n * Sends a ROAP error...\n * @param {Object} session\n * @param {Object} locus\n * @param {String} errorType\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n private sendRoapError(session: any, locus: object, errorType: string) {\n const msg = {\n messageType: ROAP.ROAP_TYPES.ERROR,\n version: ROAP.ROAP_VERSION,\n errorType,\n seq: session.OFFER.seq,\n };\n\n return this.roapRequest.sendRoap(msg, locus);\n }\n\n /**\n * sends a roap media request\n * @param {RoapOptions} options\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n sendRoapMediaRequest(options: any) {\n const {meeting, reconnect} = options;\n const roapMessage = {\n messageType: ROAP.ROAP_TYPES.OFFER,\n sdps: [options.sdp],\n // sdps: [options.sdp],\n version: ROAP.ROAP_VERSION,\n seq:\n typeof options.roapSeq !== 'number' && Number.isNaN(parseFloat(options.roapSeq))\n ? 0\n : options.roapSeq + 1,\n tieBreaker: 4294967294, // Math.floor(Math.random() * (2 ** 32) - 1) // TODO: Handle the roap conflict scenario\n };\n\n this.roapHandler.submit({\n type: ROAP.SEND_ROAP_MSG,\n msg: roapMessage,\n correlationId: meeting.correlationId,\n });\n\n // When reconnecting, it's important that the first roap message being sent out has empty media id.\n // Normally this is the roap offer, but when TURN discovery is enabled,\n // then this is the TURN discovery request message\n const sendEmptyMediaId = reconnect && !meeting.config.experimental.enableTurnDiscovery;\n\n return this.roapRequest\n .sendRoap({\n roapMessage,\n correlationId: meeting.correlationId,\n locusSelfUrl: meeting.selfUrl,\n mediaId: sendEmptyMediaId ? '' : meeting.mediaId,\n audioMuted: meeting.audio?.isLocallyMuted(),\n videoMuted: meeting.video?.isLocallyMuted(),\n meetingId: meeting.id,\n })\n .then(({locus, mediaConnections}) => {\n this.roapHandler.submit({\n type: ROAP.SEND_ROAP_MSG_SUCCESS,\n seq: roapMessage.seq,\n correlationId: meeting.correlationId,\n });\n meeting.setRoapSeq(roapMessage.seq);\n\n if (mediaConnections) {\n meeting.updateMediaConnections(mediaConnections);\n }\n\n // eslint-disable-next-line no-warning-comments\n // TODO: we need to attach peerconenction to locus not sure if we need to pass everything here\n return locus;\n // eslint-disable-next-line no-warning-comments\n // TODO: check where to update the sequence number\n });\n }\n\n /**\n * sends a roap media request\n * @param {RoapOptions} options\n * @returns {Promise}\n * @private\n * @memberof Roap\n */\n sendRoapCallRequest = (options: any) => {\n const {meeting} = options;\n const roapMessage = {\n messageType: ROAP.ROAP_TYPES.OFFER,\n sdps: [options.sdp],\n version: ROAP.ROAP_VERSION,\n seq:\n typeof options.roapSeq !== 'number' && Number.isNaN(parseFloat(options.roapSeq))\n ? 0\n : options.roapSeq + 1,\n tieBreaker: 4294967294, // Math.floor(Math.random() * (2 ** 32) - 1) // TODO: Handle the roap conflict scenario\n };\n\n this.roapHandler.submit({\n type: ROAP.SEND_ROAP_MSG,\n msg: roapMessage,\n correlationId: meeting.correlationId,\n });\n\n const roapBody = {\n localMedias: [\n {\n localSdp: JSON.stringify(\n this.roapRequest.attachRechabilityData({\n roapMessage,\n // eslint-disable-next-line no-warning-comments\n // TODO: check whats the need for video and audiomute\n audioMuted: meeting.audio?.isLocallyMuted(),\n videoMuted: meeting.video?.isLocallyMuted(),\n })\n ),\n // mediaId: meeting.mediaId\n },\n ],\n };\n\n return MeetingUtil.joinMeetingOptions(meeting, {roapMessage: roapBody}).then((locus) => {\n this.roapHandler.submit({\n type: ROAP.SEND_ROAP_MSG_SUCCESS,\n seq: roapMessage.seq,\n correlationId: meeting.correlationId,\n });\n meeting.setRoapSeq(roapMessage.seq);\n\n // eslint-disable-next-line no-warning-comments\n // TODO: we need to attach peerconenction to locus not sure if we need to pass everything here\n return locus;\n // eslint-disable-next-line no-warning-comments\n // TODO: check where to update the sequence number\n });\n };\n\n /**\n * Called when the roap sequence is finished (completed successfully or failed)\n * @param {String} correlationId id of the meeting affected\n * @param {String} sequenceId the id of the finished sequence\n * @returns {undefined}\n * @private\n * @memberof Roap\n */\n private roapFinished(correlationId: string, sequenceId: string) {\n RoapCollection.onSessionSequenceFinish(correlationId, sequenceId);\n // @ts-ignore\n const meeting = this.webex.meetings.meetingCollection.getByKey('correlationId', correlationId);\n\n meeting.mediaNegotiatedEvent();\n if (!RoapCollection.isBusy(correlationId)) {\n meeting.processNextQueuedMediaUpdate();\n }\n }\n\n /**\n * Performs a TURN server discovery procedure, which involves exchanging\n * some roap messages with the server. This exchange has to be done before\n * any other roap messages are sent\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 doTurnDiscovery(meeting: Meeting, isReconnecting: boolean) {\n return this.turnDiscovery.doTurnDiscovery(meeting, isReconnecting);\n }\n}\n"],"mappings":"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"}
|
|
@@ -130,6 +130,7 @@ var TurnDiscovery = /*#__PURE__*/function () {
|
|
|
130
130
|
}, {
|
|
131
131
|
key: "sendRoapTurnDiscoveryRequest",
|
|
132
132
|
value: function sendRoapTurnDiscoveryRequest(meeting, isReconnecting) {
|
|
133
|
+
var _meeting$audio, _meeting$video;
|
|
133
134
|
var seq = meeting.roapSeq + 1;
|
|
134
135
|
if (this.defer) {
|
|
135
136
|
_loggerProxy.default.logger.warn('Roap:turnDiscovery#sendRoapTurnDiscoveryRequest --> already in progress');
|
|
@@ -149,8 +150,8 @@ var TurnDiscovery = /*#__PURE__*/function () {
|
|
|
149
150
|
locusSelfUrl: meeting.selfUrl,
|
|
150
151
|
// @ts-ignore - Fix missing type
|
|
151
152
|
mediaId: isReconnecting ? '' : meeting.mediaId,
|
|
152
|
-
audioMuted: meeting.
|
|
153
|
-
videoMuted: meeting.
|
|
153
|
+
audioMuted: (_meeting$audio = meeting.audio) === null || _meeting$audio === void 0 ? void 0 : _meeting$audio.isLocallyMuted(),
|
|
154
|
+
videoMuted: (_meeting$video = meeting.video) === null || _meeting$video === void 0 ? void 0 : _meeting$video.isLocallyMuted(),
|
|
154
155
|
meetingId: meeting.id
|
|
155
156
|
}).then(function (_ref) {
|
|
156
157
|
var mediaConnections = _ref.mediaConnections;
|
|
@@ -171,6 +172,7 @@ var TurnDiscovery = /*#__PURE__*/function () {
|
|
|
171
172
|
}, {
|
|
172
173
|
key: "sendRoapOK",
|
|
173
174
|
value: function sendRoapOK(meeting) {
|
|
175
|
+
var _meeting$audio2, _meeting$video2;
|
|
174
176
|
_loggerProxy.default.logger.info('Roap:turnDiscovery#sendRoapOK --> sending OK');
|
|
175
177
|
return this.roapRequest.sendRoap({
|
|
176
178
|
roapMessage: {
|
|
@@ -183,8 +185,8 @@ var TurnDiscovery = /*#__PURE__*/function () {
|
|
|
183
185
|
// @ts-ignore - fix type
|
|
184
186
|
mediaId: meeting.mediaId,
|
|
185
187
|
correlationId: meeting.correlationId,
|
|
186
|
-
audioMuted: meeting.
|
|
187
|
-
videoMuted: meeting.
|
|
188
|
+
audioMuted: (_meeting$audio2 = meeting.audio) === null || _meeting$audio2 === void 0 ? void 0 : _meeting$audio2.isLocallyMuted(),
|
|
189
|
+
videoMuted: (_meeting$video2 = meeting.video) === null || _meeting$video2 === void 0 ? void 0 : _meeting$video2.isLocallyMuted(),
|
|
188
190
|
meetingId: meeting.id
|
|
189
191
|
});
|
|
190
192
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TURN_DISCOVERY_TIMEOUT","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","seq","roapSeq","Defer","messageType","ROAP","ROAP_TYPES","TURN_DISCOVERY_REQUEST","version","ROAP_VERSION","sendRoap","correlationId","locusSelfUrl","selfUrl","mediaId","audioMuted","isAudioMuted","videoMuted","isVideoMuted","meetingId","id","then","mediaConnections","setRoapSeq","updateMediaConnections","OK","isAnyClusterReachable","webex","meetings","reachability","turnServerInfo","turnDiscoverySkippedReason","config","experimental","enableTurnDiscovery","sendRoapTurnDiscoveryRequest","waitForTurnDiscoveryResponse","sendRoapOK","catch","e","Metrics","sendBehavioralMetric","BEHAVIORAL_METRICS","TURN_DISCOVERY_FAILURE","correlation_id","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/**\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 private sendRoapTurnDiscoveryRequest(meeting: Meeting, isReconnecting: boolean) {\n const seq = meeting.roapSeq + 1;\n\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,\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 correlationId: meeting.correlationId,\n // @ts-ignore - Fix missing type\n locusSelfUrl: meeting.selfUrl,\n // @ts-ignore - Fix missing type\n mediaId: isReconnecting ? '' : meeting.mediaId,\n audioMuted: meeting.isAudioMuted(),\n videoMuted: meeting.isVideoMuted(),\n meetingId: meeting.id,\n })\n .then(({mediaConnections}) => {\n meeting.setRoapSeq(seq);\n\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: meeting.roapSeq,\n },\n // @ts-ignore - fix type\n locusSelfUrl: meeting.selfUrl,\n // @ts-ignore - fix type\n mediaId: meeting.mediaId,\n correlationId: meeting.correlationId,\n audioMuted: meeting.isAudioMuted(),\n videoMuted: meeting.isVideoMuted(),\n meetingId: meeting.id,\n });\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 * @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 doTurnDiscovery(meeting: Meeting, isReconnecting?: boolean) {\n // @ts-ignore - fix type\n const isAnyClusterReachable = meeting.webex.meetings.reachability.isAnyClusterReachable();\n\n if (isAnyClusterReachable) {\n LoggerProxy.logger.info(\n 'Roap:turnDiscovery#doTurnDiscovery --> reachability has not failed, skipping TURN discovery'\n );\n\n return Promise.resolve({\n turnServerInfo: undefined,\n turnDiscoverySkippedReason: 'reachability',\n });\n }\n\n // @ts-ignore - fix type\n if (!meeting.config.experimental.enableTurnDiscovery) {\n LoggerProxy.logger.info(\n 'Roap:turnDiscovery#doTurnDiscovery --> TURN discovery disabled in config, skipping it'\n );\n\n return Promise.resolve({turnServerInfo: undefined, turnDiscoverySkippedReason: 'config'});\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 Promise.resolve({turnServerInfo: undefined, turnDiscoverySkippedReason: undefined});\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["TURN_DISCOVERY_TIMEOUT","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","seq","roapSeq","Defer","messageType","ROAP","ROAP_TYPES","TURN_DISCOVERY_REQUEST","version","ROAP_VERSION","sendRoap","correlationId","locusSelfUrl","selfUrl","mediaId","audioMuted","audio","isLocallyMuted","videoMuted","video","meetingId","id","then","mediaConnections","setRoapSeq","updateMediaConnections","OK","isAnyClusterReachable","webex","meetings","reachability","turnServerInfo","turnDiscoverySkippedReason","config","experimental","enableTurnDiscovery","sendRoapTurnDiscoveryRequest","waitForTurnDiscoveryResponse","sendRoapOK","catch","e","Metrics","sendBehavioralMetric","BEHAVIORAL_METRICS","TURN_DISCOVERY_FAILURE","correlation_id","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/**\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 private sendRoapTurnDiscoveryRequest(meeting: Meeting, isReconnecting: boolean) {\n const seq = meeting.roapSeq + 1;\n\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,\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 correlationId: meeting.correlationId,\n // @ts-ignore - Fix missing type\n locusSelfUrl: meeting.selfUrl,\n // @ts-ignore - Fix missing type\n mediaId: isReconnecting ? '' : meeting.mediaId,\n audioMuted: meeting.audio?.isLocallyMuted(),\n videoMuted: meeting.video?.isLocallyMuted(),\n meetingId: meeting.id,\n })\n .then(({mediaConnections}) => {\n meeting.setRoapSeq(seq);\n\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: meeting.roapSeq,\n },\n // @ts-ignore - fix type\n locusSelfUrl: meeting.selfUrl,\n // @ts-ignore - fix type\n mediaId: meeting.mediaId,\n correlationId: meeting.correlationId,\n audioMuted: meeting.audio?.isLocallyMuted(),\n videoMuted: meeting.video?.isLocallyMuted(),\n meetingId: meeting.id,\n });\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 * @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 doTurnDiscovery(meeting: Meeting, isReconnecting?: boolean) {\n // @ts-ignore - fix type\n const isAnyClusterReachable = meeting.webex.meetings.reachability.isAnyClusterReachable();\n\n if (isAnyClusterReachable) {\n LoggerProxy.logger.info(\n 'Roap:turnDiscovery#doTurnDiscovery --> reachability has not failed, skipping TURN discovery'\n );\n\n return Promise.resolve({\n turnServerInfo: undefined,\n turnDiscoverySkippedReason: 'reachability',\n });\n }\n\n // @ts-ignore - fix type\n if (!meeting.config.experimental.enableTurnDiscovery) {\n LoggerProxy.logger.info(\n 'Roap:turnDiscovery#doTurnDiscovery --> TURN discovery disabled in config, skipping it'\n );\n\n return Promise.resolve({turnServerInfo: undefined, turnDiscoverySkippedReason: 'config'});\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 Promise.resolve({turnServerInfo: undefined, turnDiscoverySkippedReason: undefined});\n });\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/plugin-meetings",
|
|
3
|
-
"version": "2.38.
|
|
3
|
+
"version": "2.38.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
|
|
6
6
|
"contributors": [
|
|
@@ -29,15 +29,15 @@
|
|
|
29
29
|
]
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
|
-
"build": "yarn run tsc --declaration true --declarationDir ./types"
|
|
32
|
+
"build": "yarn run -T tsc --declaration true --declarationDir ./types"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@webex/plugin-meetings": "2.38.
|
|
36
|
-
"@webex/test-helper-chai": "2.38.
|
|
37
|
-
"@webex/test-helper-mocha": "2.38.
|
|
38
|
-
"@webex/test-helper-mock-webex": "2.38.
|
|
39
|
-
"@webex/test-helper-retry": "2.38.
|
|
40
|
-
"@webex/test-helper-test-users": "2.38.
|
|
35
|
+
"@webex/plugin-meetings": "2.38.1",
|
|
36
|
+
"@webex/test-helper-chai": "2.38.1",
|
|
37
|
+
"@webex/test-helper-mocha": "2.38.1",
|
|
38
|
+
"@webex/test-helper-mock-webex": "2.38.1",
|
|
39
|
+
"@webex/test-helper-retry": "2.38.1",
|
|
40
|
+
"@webex/test-helper-test-users": "2.38.1",
|
|
41
41
|
"chai": "^4.3.4",
|
|
42
42
|
"chai-as-promised": "^7.1.1",
|
|
43
43
|
"jsdom-global": "3.0.2",
|
|
@@ -45,18 +45,18 @@
|
|
|
45
45
|
"typescript": "^4.7.4"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@webex/common": "2.38.
|
|
48
|
+
"@webex/common": "2.38.1",
|
|
49
49
|
"@webex/internal-media-core": "0.0.7-beta",
|
|
50
|
-
"@webex/internal-plugin-conversation": "2.38.
|
|
51
|
-
"@webex/internal-plugin-device": "2.38.
|
|
52
|
-
"@webex/internal-plugin-mercury": "2.38.
|
|
53
|
-
"@webex/internal-plugin-metrics": "2.38.
|
|
54
|
-
"@webex/internal-plugin-support": "2.38.
|
|
55
|
-
"@webex/internal-plugin-user": "2.38.
|
|
56
|
-
"@webex/plugin-people": "2.38.
|
|
57
|
-
"@webex/plugin-rooms": "2.38.
|
|
50
|
+
"@webex/internal-plugin-conversation": "2.38.1",
|
|
51
|
+
"@webex/internal-plugin-device": "2.38.1",
|
|
52
|
+
"@webex/internal-plugin-mercury": "2.38.1",
|
|
53
|
+
"@webex/internal-plugin-metrics": "2.38.1",
|
|
54
|
+
"@webex/internal-plugin-support": "2.38.1",
|
|
55
|
+
"@webex/internal-plugin-user": "2.38.1",
|
|
56
|
+
"@webex/plugin-people": "2.38.1",
|
|
57
|
+
"@webex/plugin-rooms": "2.38.1",
|
|
58
58
|
"@webex/ts-sdp": "1.0.1",
|
|
59
|
-
"@webex/webex-core": "2.38.
|
|
59
|
+
"@webex/webex-core": "2.38.1",
|
|
60
60
|
"bowser": "^2.11.0",
|
|
61
61
|
"btoa": "^1.2.1",
|
|
62
62
|
"dotenv": "^4.0.0",
|
package/src/meeting/muteState.ts
CHANGED
|
@@ -329,6 +329,17 @@ class MuteState {
|
|
|
329
329
|
);
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
+
/**
|
|
333
|
+
* Returns true if the user is locally muted
|
|
334
|
+
*
|
|
335
|
+
* @public
|
|
336
|
+
* @memberof MuteState
|
|
337
|
+
* @returns {Boolean}
|
|
338
|
+
*/
|
|
339
|
+
public isLocallyMuted() {
|
|
340
|
+
return this.state.client.localMute || this.state.server.localMute;
|
|
341
|
+
}
|
|
342
|
+
|
|
332
343
|
/**
|
|
333
344
|
* Returns true if the user is muted as a result of the client request (and not remotely muted)
|
|
334
345
|
*
|
package/src/roap/index.ts
CHANGED
|
@@ -170,8 +170,8 @@ export default class Roap extends StatelessWebexPlugin {
|
|
|
170
170
|
locusSelfUrl: meeting.selfUrl,
|
|
171
171
|
mediaId: options.mediaId,
|
|
172
172
|
correlationId: options.correlationId,
|
|
173
|
-
audioMuted: meeting.
|
|
174
|
-
videoMuted: meeting.
|
|
173
|
+
audioMuted: meeting.audio?.isLocallyMuted(),
|
|
174
|
+
videoMuted: meeting.video?.isLocallyMuted(),
|
|
175
175
|
meetingId: meeting.id,
|
|
176
176
|
})
|
|
177
177
|
.then(() => {
|
|
@@ -222,8 +222,8 @@ export default class Roap extends StatelessWebexPlugin {
|
|
|
222
222
|
locusSelfUrl: meeting.selfUrl,
|
|
223
223
|
mediaId: options.mediaId,
|
|
224
224
|
correlationId: options.correlationId,
|
|
225
|
-
audioMuted:
|
|
226
|
-
videoMuted:
|
|
225
|
+
audioMuted: meeting.audio?.isLocallyMuted(),
|
|
226
|
+
videoMuted: meeting.video?.isLocallyMuted(),
|
|
227
227
|
meetingId: meeting.id,
|
|
228
228
|
})
|
|
229
229
|
.then(() => {
|
|
@@ -295,8 +295,8 @@ export default class Roap extends StatelessWebexPlugin {
|
|
|
295
295
|
correlationId: meeting.correlationId,
|
|
296
296
|
locusSelfUrl: meeting.selfUrl,
|
|
297
297
|
mediaId: sendEmptyMediaId ? '' : meeting.mediaId,
|
|
298
|
-
audioMuted: meeting.
|
|
299
|
-
videoMuted: meeting.
|
|
298
|
+
audioMuted: meeting.audio?.isLocallyMuted(),
|
|
299
|
+
videoMuted: meeting.video?.isLocallyMuted(),
|
|
300
300
|
meetingId: meeting.id,
|
|
301
301
|
})
|
|
302
302
|
.then(({locus, mediaConnections}) => {
|
|
@@ -353,8 +353,8 @@ export default class Roap extends StatelessWebexPlugin {
|
|
|
353
353
|
roapMessage,
|
|
354
354
|
// eslint-disable-next-line no-warning-comments
|
|
355
355
|
// TODO: check whats the need for video and audiomute
|
|
356
|
-
audioMuted:
|
|
357
|
-
videoMuted:
|
|
356
|
+
audioMuted: meeting.audio?.isLocallyMuted(),
|
|
357
|
+
videoMuted: meeting.video?.isLocallyMuted(),
|
|
358
358
|
})
|
|
359
359
|
),
|
|
360
360
|
// mediaId: meeting.mediaId
|
|
@@ -177,8 +177,8 @@ export default class TurnDiscovery {
|
|
|
177
177
|
locusSelfUrl: meeting.selfUrl,
|
|
178
178
|
// @ts-ignore - Fix missing type
|
|
179
179
|
mediaId: isReconnecting ? '' : meeting.mediaId,
|
|
180
|
-
audioMuted: meeting.
|
|
181
|
-
videoMuted: meeting.
|
|
180
|
+
audioMuted: meeting.audio?.isLocallyMuted(),
|
|
181
|
+
videoMuted: meeting.video?.isLocallyMuted(),
|
|
182
182
|
meetingId: meeting.id,
|
|
183
183
|
})
|
|
184
184
|
.then(({mediaConnections}) => {
|
|
@@ -211,8 +211,8 @@ export default class TurnDiscovery {
|
|
|
211
211
|
// @ts-ignore - fix type
|
|
212
212
|
mediaId: meeting.mediaId,
|
|
213
213
|
correlationId: meeting.correlationId,
|
|
214
|
-
audioMuted: meeting.
|
|
215
|
-
videoMuted: meeting.
|
|
214
|
+
audioMuted: meeting.audio?.isLocallyMuted(),
|
|
215
|
+
videoMuted: meeting.video?.isLocallyMuted(),
|
|
216
216
|
meetingId: meeting.id,
|
|
217
217
|
});
|
|
218
218
|
}
|
|
@@ -161,6 +161,17 @@ describe('plugin-meetings', () => {
|
|
|
161
161
|
assert.isFalse(audio.isSelf());
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
+
describe('#isLocallyMuted()', () => {
|
|
165
|
+
it('does not consider remote mute status for audio', async () => {
|
|
166
|
+
// simulate being already remote muted
|
|
167
|
+
meeting.remoteMuted = true;
|
|
168
|
+
// create a new MuteState intance
|
|
169
|
+
audio = createMuteState(AUDIO, meeting, {sendAudio: true});
|
|
170
|
+
|
|
171
|
+
assert.isFalse(audio.isLocallyMuted());
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
164
175
|
describe('#handleClientRequest', () => {
|
|
165
176
|
it('disables/enables the local audio track when audio is muted/unmuted', async () => {
|
|
166
177
|
// mute
|
|
@@ -47,8 +47,12 @@ describe('Roap', () => {
|
|
|
47
47
|
correlationId: 'correlation id',
|
|
48
48
|
selfUrl: 'self url',
|
|
49
49
|
mediaId: 'media id',
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
audio:{
|
|
51
|
+
isLocallyMuted: () => true,
|
|
52
|
+
},
|
|
53
|
+
video:{
|
|
54
|
+
isLocallyMuted: () => false,
|
|
55
|
+
},
|
|
52
56
|
setRoapSeq: sinon.stub(),
|
|
53
57
|
config: {experimental: {enableTurnDiscovery: false}},
|
|
54
58
|
};
|
|
@@ -99,8 +103,8 @@ describe('Roap', () => {
|
|
|
99
103
|
correlationId: meeting.correlationId,
|
|
100
104
|
locusSelfUrl: meeting.selfUrl,
|
|
101
105
|
mediaId: expectEmptyMediaId ? '' : meeting.mediaId,
|
|
102
|
-
audioMuted: meeting.
|
|
103
|
-
videoMuted: meeting.
|
|
106
|
+
audioMuted: meeting.audio?.isLocallyMuted(),
|
|
107
|
+
videoMuted: meeting.video?.isLocallyMuted(),
|
|
104
108
|
meetingId: meeting.id,
|
|
105
109
|
});
|
|
106
110
|
|
|
@@ -40,8 +40,12 @@ describe('TurnDiscovery', () => {
|
|
|
40
40
|
mediaId: 'fake media id',
|
|
41
41
|
locusUrl: `https://locus-a.wbx2.com/locus/api/v1/loci/${FAKE_LOCUS_ID}`,
|
|
42
42
|
roapSeq: -1,
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
audio:{
|
|
44
|
+
isLocallyMuted: () => true,
|
|
45
|
+
},
|
|
46
|
+
video:{
|
|
47
|
+
isLocallyMuted: () => false,
|
|
48
|
+
},
|
|
45
49
|
setRoapSeq: sinon.fake((newSeq) => {
|
|
46
50
|
testMeeting.roapSeq = newSeq;
|
|
47
51
|
}),
|
|
@@ -72,8 +76,8 @@ describe('TurnDiscovery', () => {
|
|
|
72
76
|
correlationId: testMeeting.correlationId,
|
|
73
77
|
locusSelfUrl: testMeeting.selfUrl,
|
|
74
78
|
mediaId: expectedMediaId,
|
|
75
|
-
audioMuted: testMeeting.
|
|
76
|
-
videoMuted: testMeeting.
|
|
79
|
+
audioMuted: testMeeting.audio?.isLocallyMuted(),
|
|
80
|
+
videoMuted: testMeeting.video?.isLocallyMuted(),
|
|
77
81
|
meetingId: testMeeting.id,
|
|
78
82
|
});
|
|
79
83
|
|