@webex/plugin-meetings 3.0.0-next.25 → 3.0.0-next.27

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.
@@ -209,7 +209,7 @@ var Breakout = _webexCore.WebexPlugin.extend({
209
209
  sessionId: this.sessionId
210
210
  });
211
211
  },
212
- version: "3.0.0-next.25"
212
+ version: "3.0.0-next.27"
213
213
  });
214
214
  var _default = exports.default = Breakout;
215
215
  //# sourceMappingURL=breakout.js.map
@@ -1041,7 +1041,7 @@ var Breakouts = _webexCore.WebexPlugin.extend({
1041
1041
  this.trigger(_constants.BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN);
1042
1042
  }
1043
1043
  },
1044
- version: "3.0.0-next.25"
1044
+ version: "3.0.0-next.27"
1045
1045
  });
1046
1046
  var _default = exports.default = Breakouts;
1047
1047
  //# sourceMappingURL=index.js.map
@@ -373,7 +373,7 @@ var SimultaneousInterpretation = _webexCore.WebexPlugin.extend({
373
373
  throw error;
374
374
  });
375
375
  },
376
- version: "3.0.0-next.25"
376
+ version: "3.0.0-next.27"
377
377
  });
378
378
  var _default = exports.default = SimultaneousInterpretation;
379
379
  //# sourceMappingURL=index.js.map
@@ -18,7 +18,7 @@ var SILanguage = _webexCore.WebexPlugin.extend({
18
18
  languageCode: 'number',
19
19
  languageName: 'string'
20
20
  },
21
- version: "3.0.0-next.25"
21
+ version: "3.0.0-next.27"
22
22
  });
23
23
  var _default = exports.default = SILanguage;
24
24
  //# sourceMappingURL=siLanguage.js.map
@@ -0,0 +1,61 @@
1
+ export interface MediaConnectionAwaiterProps {
2
+ webrtcMediaConnection: any;
3
+ }
4
+ /**
5
+ * @class MediaConnectionAwaiter
6
+ */
7
+ export default class MediaConnectionAwaiter {
8
+ private webrtcMediaConnection;
9
+ private timer;
10
+ private defer;
11
+ private retried;
12
+ private onTimeoutCallback;
13
+ private connectionStateCallback;
14
+ private iceGatheringStateCallback;
15
+ /**
16
+ * @param {MediaConnectionAwaiterProps} mediaConnectionAwaiterProps
17
+ */
18
+ constructor({ webrtcMediaConnection }: MediaConnectionAwaiterProps);
19
+ /**
20
+ * Returns true if the connection is connected, false otherwise.
21
+ *
22
+ * @returns {boolean}
23
+ */
24
+ private isConnected;
25
+ /**
26
+ * Returns true if the ICE Gathering is completed, false otherwise.
27
+ *
28
+ * @returns {boolean}
29
+ */
30
+ private isIceGatheringCompleted;
31
+ /**
32
+ * Clears the callbacks.
33
+ *
34
+ * @returns {void}
35
+ */
36
+ private clearCallbacks;
37
+ /**
38
+ * Listener for connection state change.
39
+ *
40
+ * @returns {void}
41
+ */
42
+ connectionStateListenerCallback(): void;
43
+ /**
44
+ * Listener for ICE gathering state change.
45
+ *
46
+ * @returns {void}
47
+ */
48
+ iceGatheringStateListenerCallback(): void;
49
+ /**
50
+ * Function called when the timeout is reached.
51
+ *
52
+ * @returns {void}
53
+ */
54
+ onTimeout(): void;
55
+ /**
56
+ * Waits for the webrtc media connection to be connected.
57
+ *
58
+ * @returns {Promise}
59
+ */
60
+ waitForMediaConnectionConnected(): Promise<void>;
61
+ }
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+
3
+ var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
4
+ var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
5
+ _Object$defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+ var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
10
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));
11
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
12
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
13
+ var _common = require("@webex/common");
14
+ var _internalMediaCore = require("@webex/internal-media-core");
15
+ var _loggerProxy = _interopRequireDefault(require("../common/logs/logger-proxy"));
16
+ var _constants = require("../constants");
17
+ /**
18
+ * @class MediaConnectionAwaiter
19
+ */
20
+ var MediaConnectionAwaiter = exports.default = /*#__PURE__*/function () {
21
+ /**
22
+ * @param {MediaConnectionAwaiterProps} mediaConnectionAwaiterProps
23
+ */
24
+ function MediaConnectionAwaiter(_ref) {
25
+ var webrtcMediaConnection = _ref.webrtcMediaConnection;
26
+ (0, _classCallCheck2.default)(this, MediaConnectionAwaiter);
27
+ (0, _defineProperty2.default)(this, "webrtcMediaConnection", void 0);
28
+ (0, _defineProperty2.default)(this, "timer", void 0);
29
+ (0, _defineProperty2.default)(this, "defer", void 0);
30
+ (0, _defineProperty2.default)(this, "retried", void 0);
31
+ (0, _defineProperty2.default)(this, "onTimeoutCallback", void 0);
32
+ (0, _defineProperty2.default)(this, "connectionStateCallback", void 0);
33
+ (0, _defineProperty2.default)(this, "iceGatheringStateCallback", void 0);
34
+ this.webrtcMediaConnection = webrtcMediaConnection;
35
+ this.defer = new _common.Defer();
36
+ this.retried = false;
37
+ this.onTimeoutCallback = this.onTimeout.bind(this);
38
+ this.connectionStateCallback = this.connectionStateListenerCallback.bind(this);
39
+ this.iceGatheringStateCallback = this.iceGatheringStateListenerCallback.bind(this);
40
+ }
41
+
42
+ /**
43
+ * Returns true if the connection is connected, false otherwise.
44
+ *
45
+ * @returns {boolean}
46
+ */
47
+ (0, _createClass2.default)(MediaConnectionAwaiter, [{
48
+ key: "isConnected",
49
+ value: function isConnected() {
50
+ return this.webrtcMediaConnection.getConnectionState() === _internalMediaCore.ConnectionState.Connected;
51
+ }
52
+
53
+ /**
54
+ * Returns true if the ICE Gathering is completed, false otherwise.
55
+ *
56
+ * @returns {boolean}
57
+ */
58
+ }, {
59
+ key: "isIceGatheringCompleted",
60
+ value: function isIceGatheringCompleted() {
61
+ return this.webrtcMediaConnection.getIceGatheringState() === 'complete';
62
+ }
63
+
64
+ /**
65
+ * Clears the callbacks.
66
+ *
67
+ * @returns {void}
68
+ */
69
+ }, {
70
+ key: "clearCallbacks",
71
+ value: function clearCallbacks() {
72
+ this.webrtcMediaConnection.off(_internalMediaCore.Event.ICE_GATHERING_STATE_CHANGED, this.iceGatheringStateCallback);
73
+ this.webrtcMediaConnection.off(_internalMediaCore.Event.CONNECTION_STATE_CHANGED, this.connectionStateCallback);
74
+ }
75
+
76
+ /**
77
+ * Listener for connection state change.
78
+ *
79
+ * @returns {void}
80
+ */
81
+ }, {
82
+ key: "connectionStateListenerCallback",
83
+ value: function connectionStateListenerCallback() {
84
+ _loggerProxy.default.logger.log("Media:MediaConnectionAwaiter#connectionStateListenerCallback --> connection state: ".concat(this.webrtcMediaConnection.getConnectionState()));
85
+ if (!this.isConnected()) {
86
+ return;
87
+ }
88
+ clearTimeout(this.timer);
89
+ this.clearCallbacks();
90
+ this.defer.resolve();
91
+ }
92
+
93
+ /**
94
+ * Listener for ICE gathering state change.
95
+ *
96
+ * @returns {void}
97
+ */
98
+ }, {
99
+ key: "iceGatheringStateListenerCallback",
100
+ value: function iceGatheringStateListenerCallback() {
101
+ var iceGatheringState = this.webrtcMediaConnection.getIceGatheringState();
102
+ _loggerProxy.default.logger.log("Media:MediaConnectionAwaiter#iceGatheringStateListenerCallback --> ICE gathering state change -> ".concat(iceGatheringState));
103
+ if (!this.isIceGatheringCompleted()) {
104
+ return;
105
+ }
106
+ if (this.isConnected()) {
107
+ return;
108
+ }
109
+ clearTimeout(this.timer);
110
+ this.timer = setTimeout(this.onTimeoutCallback, _constants.ICE_AND_DTLS_CONNECTION_TIMEOUT);
111
+ }
112
+
113
+ /**
114
+ * Function called when the timeout is reached.
115
+ *
116
+ * @returns {void}
117
+ */
118
+ }, {
119
+ key: "onTimeout",
120
+ value: function onTimeout() {
121
+ if (this.isConnected()) {
122
+ this.clearCallbacks();
123
+ this.defer.resolve();
124
+ return;
125
+ }
126
+ if (!this.isIceGatheringCompleted()) {
127
+ if (!this.retried) {
128
+ _loggerProxy.default.logger.warn('Media:MediaConnectionAwaiter#onTimeout --> ICE gathering did not complete within the timeout for the first time, retrying once');
129
+
130
+ // retry once if ICE gathering is not completed
131
+ this.retried = true;
132
+ clearTimeout(this.timer);
133
+ this.timer = setTimeout(this.onTimeoutCallback, _constants.ICE_AND_DTLS_CONNECTION_TIMEOUT);
134
+ return;
135
+ }
136
+ _loggerProxy.default.logger.warn('Media:MediaConnectionAwaiter#onTimeout --> ICE gathering did not complete within the timeout for the second time, rejecting');
137
+ } else {
138
+ _loggerProxy.default.logger.warn('Media:MediaConnectionAwaiter#onTimeout --> ICE gathering completed, but connection state is not connected, rejecting');
139
+ }
140
+ this.clearCallbacks();
141
+ this.defer.reject();
142
+ }
143
+
144
+ /**
145
+ * Waits for the webrtc media connection to be connected.
146
+ *
147
+ * @returns {Promise}
148
+ */
149
+ }, {
150
+ key: "waitForMediaConnectionConnected",
151
+ value: function waitForMediaConnectionConnected() {
152
+ if (this.isConnected()) {
153
+ return _promise.default.resolve();
154
+ }
155
+ this.webrtcMediaConnection.on(_internalMediaCore.Event.CONNECTION_STATE_CHANGED, this.connectionStateCallback);
156
+ this.webrtcMediaConnection.on(_internalMediaCore.Event.ICE_GATHERING_STATE_CHANGED, this.iceGatheringStateCallback);
157
+ this.timer = setTimeout(this.onTimeoutCallback, _constants.ICE_AND_DTLS_CONNECTION_TIMEOUT);
158
+ return this.defer.promise;
159
+ }
160
+ }]);
161
+ return MediaConnectionAwaiter;
162
+ }();
163
+ //# sourceMappingURL=MediaConnectionAwaiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_common","require","_internalMediaCore","_loggerProxy","_interopRequireDefault","_constants","MediaConnectionAwaiter","exports","default","_ref","webrtcMediaConnection","_classCallCheck2","_defineProperty2","defer","Defer","retried","onTimeoutCallback","onTimeout","bind","connectionStateCallback","connectionStateListenerCallback","iceGatheringStateCallback","iceGatheringStateListenerCallback","_createClass2","key","value","isConnected","getConnectionState","ConnectionState","Connected","isIceGatheringCompleted","getIceGatheringState","clearCallbacks","off","Event","ICE_GATHERING_STATE_CHANGED","CONNECTION_STATE_CHANGED","LoggerProxy","logger","log","concat","clearTimeout","timer","resolve","iceGatheringState","setTimeout","ICE_AND_DTLS_CONNECTION_TIMEOUT","warn","reject","waitForMediaConnectionConnected","_promise","on","promise"],"sources":["MediaConnectionAwaiter.ts"],"sourcesContent":["import {Defer} from '@webex/common';\nimport {ConnectionState, Event} from '@webex/internal-media-core';\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport {ICE_AND_DTLS_CONNECTION_TIMEOUT} from '../constants';\n\nexport interface MediaConnectionAwaiterProps {\n webrtcMediaConnection: any;\n}\n\n/**\n * @class MediaConnectionAwaiter\n */\nexport default class MediaConnectionAwaiter {\n private webrtcMediaConnection: any;\n private timer: any;\n private defer: Defer;\n private retried: boolean;\n private onTimeoutCallback: () => void;\n private connectionStateCallback: () => void;\n private iceGatheringStateCallback: () => void;\n\n /**\n * @param {MediaConnectionAwaiterProps} mediaConnectionAwaiterProps\n */\n constructor({webrtcMediaConnection}: MediaConnectionAwaiterProps) {\n this.webrtcMediaConnection = webrtcMediaConnection;\n this.defer = new Defer();\n this.retried = false;\n this.onTimeoutCallback = this.onTimeout.bind(this);\n this.connectionStateCallback = this.connectionStateListenerCallback.bind(this);\n this.iceGatheringStateCallback = this.iceGatheringStateListenerCallback.bind(this);\n }\n\n /**\n * Returns true if the connection is connected, false otherwise.\n *\n * @returns {boolean}\n */\n private isConnected(): boolean {\n return this.webrtcMediaConnection.getConnectionState() === ConnectionState.Connected;\n }\n\n /**\n * Returns true if the ICE Gathering is completed, false otherwise.\n *\n * @returns {boolean}\n */\n private isIceGatheringCompleted(): boolean {\n return this.webrtcMediaConnection.getIceGatheringState() === 'complete';\n }\n\n /**\n * Clears the callbacks.\n *\n * @returns {void}\n */\n private clearCallbacks(): void {\n this.webrtcMediaConnection.off(\n Event.ICE_GATHERING_STATE_CHANGED,\n this.iceGatheringStateCallback\n );\n this.webrtcMediaConnection.off(Event.CONNECTION_STATE_CHANGED, this.connectionStateCallback);\n }\n\n /**\n * Listener for connection state change.\n *\n * @returns {void}\n */\n connectionStateListenerCallback(): void {\n LoggerProxy.logger.log(\n `Media:MediaConnectionAwaiter#connectionStateListenerCallback --> connection state: ${this.webrtcMediaConnection.getConnectionState()}`\n );\n\n if (!this.isConnected()) {\n return;\n }\n\n clearTimeout(this.timer);\n\n this.clearCallbacks();\n\n this.defer.resolve();\n }\n\n /**\n * Listener for ICE gathering state change.\n *\n * @returns {void}\n */\n iceGatheringStateListenerCallback(): void {\n const iceGatheringState = this.webrtcMediaConnection.getIceGatheringState();\n\n LoggerProxy.logger.log(\n `Media:MediaConnectionAwaiter#iceGatheringStateListenerCallback --> ICE gathering state change -> ${iceGatheringState}`\n );\n\n if (!this.isIceGatheringCompleted()) {\n return;\n }\n\n if (this.isConnected()) {\n return;\n }\n\n clearTimeout(this.timer);\n\n this.timer = setTimeout(this.onTimeoutCallback, ICE_AND_DTLS_CONNECTION_TIMEOUT);\n }\n\n /**\n * Function called when the timeout is reached.\n *\n * @returns {void}\n */\n onTimeout(): void {\n if (this.isConnected()) {\n this.clearCallbacks();\n\n this.defer.resolve();\n\n return;\n }\n\n if (!this.isIceGatheringCompleted()) {\n if (!this.retried) {\n LoggerProxy.logger.warn(\n 'Media:MediaConnectionAwaiter#onTimeout --> ICE gathering did not complete within the timeout for the first time, retrying once'\n );\n\n // retry once if ICE gathering is not completed\n this.retried = true;\n clearTimeout(this.timer);\n this.timer = setTimeout(this.onTimeoutCallback, ICE_AND_DTLS_CONNECTION_TIMEOUT);\n\n return;\n }\n\n LoggerProxy.logger.warn(\n 'Media:MediaConnectionAwaiter#onTimeout --> ICE gathering did not complete within the timeout for the second time, rejecting'\n );\n } else {\n LoggerProxy.logger.warn(\n 'Media:MediaConnectionAwaiter#onTimeout --> ICE gathering completed, but connection state is not connected, rejecting'\n );\n }\n\n this.clearCallbacks();\n\n this.defer.reject();\n }\n\n /**\n * Waits for the webrtc media connection to be connected.\n *\n * @returns {Promise}\n */\n waitForMediaConnectionConnected(): Promise<void> {\n if (this.isConnected()) {\n return Promise.resolve();\n }\n\n this.webrtcMediaConnection.on(Event.CONNECTION_STATE_CHANGED, this.connectionStateCallback);\n\n this.webrtcMediaConnection.on(\n Event.ICE_GATHERING_STATE_CHANGED,\n this.iceGatheringStateCallback\n );\n\n this.timer = setTimeout(this.onTimeoutCallback, ICE_AND_DTLS_CONNECTION_TIMEOUT);\n\n return this.defer.promise;\n }\n}\n"],"mappings":"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"}
@@ -7,15 +7,14 @@ _Object$defineProperty(exports, "__esModule", {
7
7
  });
8
8
  exports.default = void 0;
9
9
  var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator"));
10
- var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
11
10
  var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
12
11
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/asyncToGenerator"));
13
12
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));
14
13
  var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
15
14
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
16
- var _internalMediaCore = require("@webex/internal-media-core");
17
15
  var _constants = require("../constants");
18
16
  var _loggerProxy = _interopRequireDefault(require("../common/logs/logger-proxy"));
17
+ var _MediaConnectionAwaiter = _interopRequireDefault(require("./MediaConnectionAwaiter"));
19
18
  /**
20
19
  * @class MediaProperties
21
20
  */
@@ -198,29 +197,10 @@ var MediaProperties = exports.default = /*#__PURE__*/function () {
198
197
  }, {
199
198
  key: "waitForMediaConnectionConnected",
200
199
  value: function waitForMediaConnectionConnected() {
201
- var _this = this;
202
- var isConnected = function isConnected() {
203
- return _this.webrtcMediaConnection.getConnectionState() === _internalMediaCore.ConnectionState.Connected;
204
- };
205
- if (isConnected()) {
206
- return _promise.default.resolve();
207
- }
208
- return new _promise.default(function (resolve, reject) {
209
- var timer;
210
- var connectionStateListener = function connectionStateListener() {
211
- _loggerProxy.default.logger.log("Media:properties#waitForMediaConnectionConnected --> connection state: ".concat(_this.webrtcMediaConnection.getConnectionState()));
212
- if (isConnected()) {
213
- clearTimeout(timer);
214
- _this.webrtcMediaConnection.off(_internalMediaCore.Event.CONNECTION_STATE_CHANGED, connectionStateListener);
215
- resolve();
216
- }
217
- };
218
- timer = setTimeout(function () {
219
- _this.webrtcMediaConnection.off(_internalMediaCore.Event.CONNECTION_STATE_CHANGED, connectionStateListener);
220
- reject();
221
- }, _constants.ICE_AND_DTLS_CONNECTION_TIMEOUT);
222
- _this.webrtcMediaConnection.on(_internalMediaCore.Event.CONNECTION_STATE_CHANGED, connectionStateListener);
200
+ var mediaConnectionAwaiter = new _MediaConnectionAwaiter.default({
201
+ webrtcMediaConnection: this.webrtcMediaConnection
223
202
  });
203
+ return mediaConnectionAwaiter.waitForMediaConnectionConnected();
224
204
  }
225
205
 
226
206
  /**
@@ -1 +1 @@
1
- {"version":3,"names":["_internalMediaCore","require","_constants","_loggerProxy","_interopRequireDefault","MediaProperties","exports","default","_classCallCheck2","_defineProperty2","MEETINGS","webrtcMediaConnection","mediaDirection","receiveAudio","receiveVideo","receiveShare","sendAudio","sendVideo","sendShare","videoStream","audioStream","shareVideoStream","shareAudioStream","remoteShareStream","undefined","remoteAudioStream","remoteVideoStream","remoteQualityLevel","QUALITY_LEVELS","HIGH","mediaSettings","videoDeviceId","_createClass2","key","value","getVideoDeviceId","setMediaDirection","setMediaSettings","type","values","setMediaPeerConnection","mediaPeerConnection","setLocalVideoStream","setLocalAudioStream","setLocalShareVideoStream","setLocalShareAudioStream","setRemoteQualityLevel","setRemoteShareStream","setRemoteAudioStream","setRemoteVideoStream","setVideoDeviceId","deviceId","unsetPeerConnection","unsetRemoteMedia","unsetRemoteShareStream","unsetRemoteStreams","hasLocalShareStream","waitForMediaConnectionConnected","_this","isConnected","getConnectionState","ConnectionState","Connected","_promise","resolve","reject","timer","connectionStateListener","LoggerProxy","logger","log","concat","clearTimeout","off","Event","CONNECTION_STATE_CHANGED","setTimeout","ICE_AND_DTLS_CONNECTION_TIMEOUT","on","_getCurrentConnectionType","_asyncToGenerator2","_regenerator","mark","_callee","allStatsReports","statsResult","successfulCandidatePairs","foundConnectionType","candidatePairStates","wrap","_callee$","_context","prev","next","getStats","sent","forEach","report","push","t0","warn","filter","_report$state","state","toLowerCase","some","pair","localCandidate","find","id","localCandidateId","connectionType","relayProtocol","toUpperCase","_localCandidate$proto","protocol","candidateType","map","_stringify","abrupt","stop","getCurrentConnectionType","apply","arguments"],"sources":["properties.ts"],"sourcesContent":["import {ConnectionState, Event} from '@webex/internal-media-core';\n\nimport {\n LocalCameraStream,\n LocalMicrophoneStream,\n LocalDisplayStream,\n LocalSystemAudioStream,\n RemoteStream,\n} from '@webex/media-helpers';\n\nimport {MEETINGS, ICE_AND_DTLS_CONNECTION_TIMEOUT, QUALITY_LEVELS} from '../constants';\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nexport type MediaDirection = {\n sendAudio: boolean;\n sendVideo: boolean;\n sendShare: boolean;\n receiveAudio: boolean;\n receiveVideo: boolean;\n receiveShare: boolean;\n};\n\n/**\n * @class MediaProperties\n */\nexport default class MediaProperties {\n audioStream?: LocalMicrophoneStream;\n mediaDirection: MediaDirection;\n mediaSettings: any;\n webrtcMediaConnection: any;\n remoteAudioStream: RemoteStream;\n remoteQualityLevel: any;\n remoteShareStream: RemoteStream;\n remoteVideoStream: RemoteStream;\n shareVideoStream?: LocalDisplayStream;\n shareAudioStream?: LocalSystemAudioStream;\n videoDeviceId: any;\n videoStream?: LocalCameraStream;\n namespace = MEETINGS;\n\n /**\n * @param {Object} [options] -- to auto construct\n * @returns {MediaProperties}\n */\n constructor() {\n this.webrtcMediaConnection = null;\n this.mediaDirection = {\n receiveAudio: false,\n receiveVideo: false,\n receiveShare: false,\n sendAudio: false,\n sendVideo: false,\n sendShare: false,\n };\n this.videoStream = null;\n this.audioStream = null;\n this.shareVideoStream = null;\n this.shareAudioStream = null;\n this.remoteShareStream = undefined;\n this.remoteAudioStream = undefined;\n this.remoteVideoStream = undefined;\n this.remoteQualityLevel = QUALITY_LEVELS.HIGH;\n this.mediaSettings = {};\n this.videoDeviceId = null;\n }\n\n /**\n * Retrieves the preferred video input device\n * @returns {Object|null}\n */\n getVideoDeviceId() {\n return this.videoDeviceId || null;\n }\n\n setMediaDirection(mediaDirection) {\n this.mediaDirection = mediaDirection;\n }\n\n setMediaSettings(type, values) {\n this.mediaSettings[type] = values;\n }\n\n setMediaPeerConnection(mediaPeerConnection) {\n this.webrtcMediaConnection = mediaPeerConnection;\n }\n\n setLocalVideoStream(videoStream?: LocalCameraStream) {\n this.videoStream = videoStream;\n }\n\n setLocalAudioStream(audioStream?: LocalMicrophoneStream) {\n this.audioStream = audioStream;\n }\n\n setLocalShareVideoStream(shareVideoStream?: LocalDisplayStream) {\n this.shareVideoStream = shareVideoStream;\n }\n\n setLocalShareAudioStream(shareAudioStream?: LocalSystemAudioStream) {\n this.shareAudioStream = shareAudioStream;\n }\n\n setRemoteQualityLevel(remoteQualityLevel) {\n this.remoteQualityLevel = remoteQualityLevel;\n }\n\n setRemoteShareStream(remoteShareStream: RemoteStream) {\n this.remoteShareStream = remoteShareStream;\n }\n\n /**\n * Sets the remote audio stream\n * @param {RemoteStream} remoteAudioStream RemoteStream to save\n * @returns {void}\n */\n setRemoteAudioStream(remoteAudioStream: RemoteStream) {\n this.remoteAudioStream = remoteAudioStream;\n }\n\n /**\n * Sets the remote video stream\n * @param {RemoteStream} remoteVideoStream RemoteStream to save\n * @returns {void}\n */\n setRemoteVideoStream(remoteVideoStream: RemoteStream) {\n this.remoteVideoStream = remoteVideoStream;\n }\n\n /**\n * Stores the preferred video input device\n * @param {string} deviceId Preferred video input device\n * @returns {void}\n */\n setVideoDeviceId(deviceId: string) {\n this.videoDeviceId = deviceId;\n }\n\n unsetPeerConnection() {\n this.webrtcMediaConnection = null;\n }\n\n /**\n * Removes both remote audio and video from class instance\n * @returns {void}\n */\n unsetRemoteMedia() {\n this.remoteAudioStream = null;\n this.remoteVideoStream = null;\n }\n\n unsetRemoteShareStream() {\n this.remoteShareStream = null;\n }\n\n /**\n * Unsets all remote streams\n * @returns {void}\n */\n unsetRemoteStreams() {\n this.unsetRemoteMedia();\n this.unsetRemoteShareStream();\n }\n\n /**\n * Returns if we have at least one local share stream or not.\n * @returns {Boolean}\n */\n hasLocalShareStream() {\n return !!(this.shareAudioStream || this.shareVideoStream);\n }\n\n /**\n * Waits for the webrtc media connection to be connected.\n *\n * @returns {Promise<void>}\n */\n waitForMediaConnectionConnected(): Promise<void> {\n const isConnected = () =>\n this.webrtcMediaConnection.getConnectionState() === ConnectionState.Connected;\n\n if (isConnected()) {\n return Promise.resolve();\n }\n\n return new Promise<void>((resolve, reject) => {\n let timer;\n\n const connectionStateListener = () => {\n LoggerProxy.logger.log(\n `Media:properties#waitForMediaConnectionConnected --> connection state: ${this.webrtcMediaConnection.getConnectionState()}`\n );\n\n if (isConnected()) {\n clearTimeout(timer);\n this.webrtcMediaConnection.off(Event.CONNECTION_STATE_CHANGED, connectionStateListener);\n resolve();\n }\n };\n\n timer = setTimeout(() => {\n this.webrtcMediaConnection.off(Event.CONNECTION_STATE_CHANGED, connectionStateListener);\n reject();\n }, ICE_AND_DTLS_CONNECTION_TIMEOUT);\n\n this.webrtcMediaConnection.on(Event.CONNECTION_STATE_CHANGED, connectionStateListener);\n });\n }\n\n /**\n * Returns the type of a connection that has been established\n *\n * @returns {Promise<'UDP' | 'TCP' | 'TURN-TLS' | 'TURN-TCP' | 'TURN-UDP' | 'unknown'>}\n */\n async getCurrentConnectionType() {\n // we can only get the connection type after ICE connection has been established\n await this.waitForMediaConnectionConnected();\n\n const allStatsReports = [];\n\n try {\n const statsResult = await this.webrtcMediaConnection.getStats();\n statsResult.forEach((report) => allStatsReports.push(report));\n } catch (error) {\n LoggerProxy.logger.warn(\n `Media:properties#getCurrentConnectionType --> getStats() failed: ${error}`\n );\n }\n\n const successfulCandidatePairs = allStatsReports.filter(\n (report) => report.type === 'candidate-pair' && report.state?.toLowerCase() === 'succeeded'\n );\n\n let foundConnectionType = 'unknown';\n\n // all of the successful pairs should have the same connection type, so just return the type for the first one\n successfulCandidatePairs.some((pair) => {\n const localCandidate = allStatsReports.find(\n (report) => report.type === 'local-candidate' && report.id === pair.localCandidateId\n );\n\n if (localCandidate === undefined) {\n LoggerProxy.logger.warn(\n `Media:properties#getCurrentConnectionType --> failed to find local candidate \"${pair.localCandidateId}\" in getStats() results`\n );\n\n return false;\n }\n\n let connectionType;\n\n if (localCandidate.relayProtocol) {\n connectionType = `TURN-${localCandidate.relayProtocol.toUpperCase()}`;\n } else {\n connectionType = localCandidate.protocol?.toUpperCase(); // it will be UDP or TCP\n }\n\n if (connectionType) {\n foundConnectionType = connectionType;\n\n return true;\n }\n LoggerProxy.logger.warn(\n `Media:properties#getCurrentConnectionType --> missing localCandidate.protocol, candidateType=${localCandidate.candidateType}`\n );\n\n return false;\n });\n\n if (foundConnectionType === 'unknown') {\n const candidatePairStates = allStatsReports\n .filter((report) => report.type === 'candidate-pair')\n .map((report) => report.state);\n\n LoggerProxy.logger.warn(\n `Media:properties#getCurrentConnectionType --> all candidate pair states: ${JSON.stringify(\n candidatePairStates\n )}`\n );\n }\n\n return foundConnectionType;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"names":["_constants","require","_loggerProxy","_interopRequireDefault","_MediaConnectionAwaiter","MediaProperties","exports","default","_classCallCheck2","_defineProperty2","MEETINGS","webrtcMediaConnection","mediaDirection","receiveAudio","receiveVideo","receiveShare","sendAudio","sendVideo","sendShare","videoStream","audioStream","shareVideoStream","shareAudioStream","remoteShareStream","undefined","remoteAudioStream","remoteVideoStream","remoteQualityLevel","QUALITY_LEVELS","HIGH","mediaSettings","videoDeviceId","_createClass2","key","value","getVideoDeviceId","setMediaDirection","setMediaSettings","type","values","setMediaPeerConnection","mediaPeerConnection","setLocalVideoStream","setLocalAudioStream","setLocalShareVideoStream","setLocalShareAudioStream","setRemoteQualityLevel","setRemoteShareStream","setRemoteAudioStream","setRemoteVideoStream","setVideoDeviceId","deviceId","unsetPeerConnection","unsetRemoteMedia","unsetRemoteShareStream","unsetRemoteStreams","hasLocalShareStream","waitForMediaConnectionConnected","mediaConnectionAwaiter","MediaConnectionAwaiter","_getCurrentConnectionType","_asyncToGenerator2","_regenerator","mark","_callee","allStatsReports","statsResult","successfulCandidatePairs","foundConnectionType","candidatePairStates","wrap","_callee$","_context","prev","next","getStats","sent","forEach","report","push","t0","LoggerProxy","logger","warn","concat","filter","_report$state","state","toLowerCase","some","pair","localCandidate","find","id","localCandidateId","connectionType","relayProtocol","toUpperCase","_localCandidate$proto","protocol","candidateType","map","_stringify","abrupt","stop","getCurrentConnectionType","apply","arguments"],"sources":["properties.ts"],"sourcesContent":["import {\n LocalCameraStream,\n LocalMicrophoneStream,\n LocalDisplayStream,\n LocalSystemAudioStream,\n RemoteStream,\n} from '@webex/media-helpers';\n\nimport {MEETINGS, QUALITY_LEVELS} from '../constants';\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport MediaConnectionAwaiter from './MediaConnectionAwaiter';\n\nexport type MediaDirection = {\n sendAudio: boolean;\n sendVideo: boolean;\n sendShare: boolean;\n receiveAudio: boolean;\n receiveVideo: boolean;\n receiveShare: boolean;\n};\n\n/**\n * @class MediaProperties\n */\nexport default class MediaProperties {\n audioStream?: LocalMicrophoneStream;\n mediaDirection: MediaDirection;\n mediaSettings: any;\n webrtcMediaConnection: any;\n remoteAudioStream: RemoteStream;\n remoteQualityLevel: any;\n remoteShareStream: RemoteStream;\n remoteVideoStream: RemoteStream;\n shareVideoStream?: LocalDisplayStream;\n shareAudioStream?: LocalSystemAudioStream;\n videoDeviceId: any;\n videoStream?: LocalCameraStream;\n namespace = MEETINGS;\n\n /**\n * @param {Object} [options] -- to auto construct\n * @returns {MediaProperties}\n */\n constructor() {\n this.webrtcMediaConnection = null;\n this.mediaDirection = {\n receiveAudio: false,\n receiveVideo: false,\n receiveShare: false,\n sendAudio: false,\n sendVideo: false,\n sendShare: false,\n };\n this.videoStream = null;\n this.audioStream = null;\n this.shareVideoStream = null;\n this.shareAudioStream = null;\n this.remoteShareStream = undefined;\n this.remoteAudioStream = undefined;\n this.remoteVideoStream = undefined;\n this.remoteQualityLevel = QUALITY_LEVELS.HIGH;\n this.mediaSettings = {};\n this.videoDeviceId = null;\n }\n\n /**\n * Retrieves the preferred video input device\n * @returns {Object|null}\n */\n getVideoDeviceId() {\n return this.videoDeviceId || null;\n }\n\n setMediaDirection(mediaDirection) {\n this.mediaDirection = mediaDirection;\n }\n\n setMediaSettings(type, values) {\n this.mediaSettings[type] = values;\n }\n\n setMediaPeerConnection(mediaPeerConnection) {\n this.webrtcMediaConnection = mediaPeerConnection;\n }\n\n setLocalVideoStream(videoStream?: LocalCameraStream) {\n this.videoStream = videoStream;\n }\n\n setLocalAudioStream(audioStream?: LocalMicrophoneStream) {\n this.audioStream = audioStream;\n }\n\n setLocalShareVideoStream(shareVideoStream?: LocalDisplayStream) {\n this.shareVideoStream = shareVideoStream;\n }\n\n setLocalShareAudioStream(shareAudioStream?: LocalSystemAudioStream) {\n this.shareAudioStream = shareAudioStream;\n }\n\n setRemoteQualityLevel(remoteQualityLevel) {\n this.remoteQualityLevel = remoteQualityLevel;\n }\n\n setRemoteShareStream(remoteShareStream: RemoteStream) {\n this.remoteShareStream = remoteShareStream;\n }\n\n /**\n * Sets the remote audio stream\n * @param {RemoteStream} remoteAudioStream RemoteStream to save\n * @returns {void}\n */\n setRemoteAudioStream(remoteAudioStream: RemoteStream) {\n this.remoteAudioStream = remoteAudioStream;\n }\n\n /**\n * Sets the remote video stream\n * @param {RemoteStream} remoteVideoStream RemoteStream to save\n * @returns {void}\n */\n setRemoteVideoStream(remoteVideoStream: RemoteStream) {\n this.remoteVideoStream = remoteVideoStream;\n }\n\n /**\n * Stores the preferred video input device\n * @param {string} deviceId Preferred video input device\n * @returns {void}\n */\n setVideoDeviceId(deviceId: string) {\n this.videoDeviceId = deviceId;\n }\n\n unsetPeerConnection() {\n this.webrtcMediaConnection = null;\n }\n\n /**\n * Removes both remote audio and video from class instance\n * @returns {void}\n */\n unsetRemoteMedia() {\n this.remoteAudioStream = null;\n this.remoteVideoStream = null;\n }\n\n unsetRemoteShareStream() {\n this.remoteShareStream = null;\n }\n\n /**\n * Unsets all remote streams\n * @returns {void}\n */\n unsetRemoteStreams() {\n this.unsetRemoteMedia();\n this.unsetRemoteShareStream();\n }\n\n /**\n * Returns if we have at least one local share stream or not.\n * @returns {Boolean}\n */\n hasLocalShareStream() {\n return !!(this.shareAudioStream || this.shareVideoStream);\n }\n\n /**\n * Waits for the webrtc media connection to be connected.\n *\n * @returns {Promise<void>}\n */\n waitForMediaConnectionConnected(): Promise<void> {\n const mediaConnectionAwaiter = new MediaConnectionAwaiter({\n webrtcMediaConnection: this.webrtcMediaConnection,\n });\n\n return mediaConnectionAwaiter.waitForMediaConnectionConnected();\n }\n\n /**\n * Returns the type of a connection that has been established\n *\n * @returns {Promise<'UDP' | 'TCP' | 'TURN-TLS' | 'TURN-TCP' | 'TURN-UDP' | 'unknown'>}\n */\n async getCurrentConnectionType() {\n // we can only get the connection type after ICE connection has been established\n await this.waitForMediaConnectionConnected();\n\n const allStatsReports = [];\n\n try {\n const statsResult = await this.webrtcMediaConnection.getStats();\n statsResult.forEach((report) => allStatsReports.push(report));\n } catch (error) {\n LoggerProxy.logger.warn(\n `Media:properties#getCurrentConnectionType --> getStats() failed: ${error}`\n );\n }\n\n const successfulCandidatePairs = allStatsReports.filter(\n (report) => report.type === 'candidate-pair' && report.state?.toLowerCase() === 'succeeded'\n );\n\n let foundConnectionType = 'unknown';\n\n // all of the successful pairs should have the same connection type, so just return the type for the first one\n successfulCandidatePairs.some((pair) => {\n const localCandidate = allStatsReports.find(\n (report) => report.type === 'local-candidate' && report.id === pair.localCandidateId\n );\n\n if (localCandidate === undefined) {\n LoggerProxy.logger.warn(\n `Media:properties#getCurrentConnectionType --> failed to find local candidate \"${pair.localCandidateId}\" in getStats() results`\n );\n\n return false;\n }\n\n let connectionType;\n\n if (localCandidate.relayProtocol) {\n connectionType = `TURN-${localCandidate.relayProtocol.toUpperCase()}`;\n } else {\n connectionType = localCandidate.protocol?.toUpperCase(); // it will be UDP or TCP\n }\n\n if (connectionType) {\n foundConnectionType = connectionType;\n\n return true;\n }\n LoggerProxy.logger.warn(\n `Media:properties#getCurrentConnectionType --> missing localCandidate.protocol, candidateType=${localCandidate.candidateType}`\n );\n\n return false;\n });\n\n if (foundConnectionType === 'unknown') {\n const candidatePairStates = allStatsReports\n .filter((report) => report.type === 'candidate-pair')\n .map((report) => report.state);\n\n LoggerProxy.logger.warn(\n `Media:properties#getCurrentConnectionType --> all candidate pair states: ${JSON.stringify(\n candidatePairStates\n )}`\n );\n }\n\n return foundConnectionType;\n }\n}\n"],"mappings":"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"}
@@ -62,7 +62,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
62
62
  updateCanManageWebcast: function updateCanManageWebcast(canManageWebcast) {
63
63
  this.set('canManageWebcast', canManageWebcast);
64
64
  },
65
- version: "3.0.0-next.25"
65
+ version: "3.0.0-next.27"
66
66
  });
67
67
  var _default = exports.default = Webinar;
68
68
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -43,13 +43,13 @@
43
43
  "@webex/eslint-config-legacy": "0.0.0",
44
44
  "@webex/jest-config-legacy": "0.0.0",
45
45
  "@webex/legacy-tools": "0.0.0",
46
- "@webex/plugin-meetings": "3.0.0-next.25",
47
- "@webex/plugin-rooms": "3.0.0-next.15",
48
- "@webex/test-helper-chai": "3.0.0-next.13",
49
- "@webex/test-helper-mocha": "3.0.0-next.13",
50
- "@webex/test-helper-mock-webex": "3.0.0-next.13",
51
- "@webex/test-helper-retry": "3.0.0-next.13",
52
- "@webex/test-helper-test-users": "3.0.0-next.13",
46
+ "@webex/plugin-meetings": "3.0.0-next.27",
47
+ "@webex/plugin-rooms": "3.0.0-next.16",
48
+ "@webex/test-helper-chai": "3.0.0-next.14",
49
+ "@webex/test-helper-mocha": "3.0.0-next.14",
50
+ "@webex/test-helper-mock-webex": "3.0.0-next.14",
51
+ "@webex/test-helper-retry": "3.0.0-next.14",
52
+ "@webex/test-helper-test-users": "3.0.0-next.14",
53
53
  "chai": "^4.3.4",
54
54
  "chai-as-promised": "^7.1.1",
55
55
  "eslint": "^8.24.0",
@@ -61,20 +61,20 @@
61
61
  "typescript": "^4.7.4"
62
62
  },
63
63
  "dependencies": {
64
- "@webex/common": "3.0.0-next.13",
65
- "@webex/internal-media-core": "2.3.3",
66
- "@webex/internal-plugin-conversation": "3.0.0-next.15",
67
- "@webex/internal-plugin-device": "3.0.0-next.13",
68
- "@webex/internal-plugin-llm": "3.0.0-next.15",
69
- "@webex/internal-plugin-mercury": "3.0.0-next.15",
70
- "@webex/internal-plugin-metrics": "3.0.0-next.13",
71
- "@webex/internal-plugin-support": "3.0.0-next.15",
72
- "@webex/internal-plugin-user": "3.0.0-next.13",
73
- "@webex/internal-plugin-voicea": "3.0.0-next.25",
74
- "@webex/media-helpers": "3.0.1-next.14",
75
- "@webex/plugin-people": "3.0.0-next.15",
76
- "@webex/plugin-rooms": "3.0.0-next.15",
77
- "@webex/webex-core": "3.0.0-next.13",
64
+ "@webex/common": "3.0.0-next.14",
65
+ "@webex/internal-media-core": "2.4.0",
66
+ "@webex/internal-plugin-conversation": "3.0.0-next.16",
67
+ "@webex/internal-plugin-device": "3.0.0-next.14",
68
+ "@webex/internal-plugin-llm": "3.0.0-next.16",
69
+ "@webex/internal-plugin-mercury": "3.0.0-next.16",
70
+ "@webex/internal-plugin-metrics": "3.0.0-next.14",
71
+ "@webex/internal-plugin-support": "3.0.0-next.16",
72
+ "@webex/internal-plugin-user": "3.0.0-next.14",
73
+ "@webex/internal-plugin-voicea": "3.0.0-next.27",
74
+ "@webex/media-helpers": "3.0.1-next.16",
75
+ "@webex/plugin-people": "3.0.0-next.16",
76
+ "@webex/plugin-rooms": "3.0.0-next.16",
77
+ "@webex/webex-core": "3.0.0-next.14",
78
78
  "ampersand-collection": "^2.0.2",
79
79
  "bowser": "^2.11.0",
80
80
  "btoa": "^1.2.1",
@@ -91,5 +91,5 @@
91
91
  "//": [
92
92
  "TODO: upgrade jwt-decode when moving to node 18"
93
93
  ],
94
- "version": "3.0.0-next.25"
94
+ "version": "3.0.0-next.27"
95
95
  }
@@ -0,0 +1,174 @@
1
+ import {Defer} from '@webex/common';
2
+ import {ConnectionState, Event} from '@webex/internal-media-core';
3
+ import LoggerProxy from '../common/logs/logger-proxy';
4
+ import {ICE_AND_DTLS_CONNECTION_TIMEOUT} from '../constants';
5
+
6
+ export interface MediaConnectionAwaiterProps {
7
+ webrtcMediaConnection: any;
8
+ }
9
+
10
+ /**
11
+ * @class MediaConnectionAwaiter
12
+ */
13
+ export default class MediaConnectionAwaiter {
14
+ private webrtcMediaConnection: any;
15
+ private timer: any;
16
+ private defer: Defer;
17
+ private retried: boolean;
18
+ private onTimeoutCallback: () => void;
19
+ private connectionStateCallback: () => void;
20
+ private iceGatheringStateCallback: () => void;
21
+
22
+ /**
23
+ * @param {MediaConnectionAwaiterProps} mediaConnectionAwaiterProps
24
+ */
25
+ constructor({webrtcMediaConnection}: MediaConnectionAwaiterProps) {
26
+ this.webrtcMediaConnection = webrtcMediaConnection;
27
+ this.defer = new Defer();
28
+ this.retried = false;
29
+ this.onTimeoutCallback = this.onTimeout.bind(this);
30
+ this.connectionStateCallback = this.connectionStateListenerCallback.bind(this);
31
+ this.iceGatheringStateCallback = this.iceGatheringStateListenerCallback.bind(this);
32
+ }
33
+
34
+ /**
35
+ * Returns true if the connection is connected, false otherwise.
36
+ *
37
+ * @returns {boolean}
38
+ */
39
+ private isConnected(): boolean {
40
+ return this.webrtcMediaConnection.getConnectionState() === ConnectionState.Connected;
41
+ }
42
+
43
+ /**
44
+ * Returns true if the ICE Gathering is completed, false otherwise.
45
+ *
46
+ * @returns {boolean}
47
+ */
48
+ private isIceGatheringCompleted(): boolean {
49
+ return this.webrtcMediaConnection.getIceGatheringState() === 'complete';
50
+ }
51
+
52
+ /**
53
+ * Clears the callbacks.
54
+ *
55
+ * @returns {void}
56
+ */
57
+ private clearCallbacks(): void {
58
+ this.webrtcMediaConnection.off(
59
+ Event.ICE_GATHERING_STATE_CHANGED,
60
+ this.iceGatheringStateCallback
61
+ );
62
+ this.webrtcMediaConnection.off(Event.CONNECTION_STATE_CHANGED, this.connectionStateCallback);
63
+ }
64
+
65
+ /**
66
+ * Listener for connection state change.
67
+ *
68
+ * @returns {void}
69
+ */
70
+ connectionStateListenerCallback(): void {
71
+ LoggerProxy.logger.log(
72
+ `Media:MediaConnectionAwaiter#connectionStateListenerCallback --> connection state: ${this.webrtcMediaConnection.getConnectionState()}`
73
+ );
74
+
75
+ if (!this.isConnected()) {
76
+ return;
77
+ }
78
+
79
+ clearTimeout(this.timer);
80
+
81
+ this.clearCallbacks();
82
+
83
+ this.defer.resolve();
84
+ }
85
+
86
+ /**
87
+ * Listener for ICE gathering state change.
88
+ *
89
+ * @returns {void}
90
+ */
91
+ iceGatheringStateListenerCallback(): void {
92
+ const iceGatheringState = this.webrtcMediaConnection.getIceGatheringState();
93
+
94
+ LoggerProxy.logger.log(
95
+ `Media:MediaConnectionAwaiter#iceGatheringStateListenerCallback --> ICE gathering state change -> ${iceGatheringState}`
96
+ );
97
+
98
+ if (!this.isIceGatheringCompleted()) {
99
+ return;
100
+ }
101
+
102
+ if (this.isConnected()) {
103
+ return;
104
+ }
105
+
106
+ clearTimeout(this.timer);
107
+
108
+ this.timer = setTimeout(this.onTimeoutCallback, ICE_AND_DTLS_CONNECTION_TIMEOUT);
109
+ }
110
+
111
+ /**
112
+ * Function called when the timeout is reached.
113
+ *
114
+ * @returns {void}
115
+ */
116
+ onTimeout(): void {
117
+ if (this.isConnected()) {
118
+ this.clearCallbacks();
119
+
120
+ this.defer.resolve();
121
+
122
+ return;
123
+ }
124
+
125
+ if (!this.isIceGatheringCompleted()) {
126
+ if (!this.retried) {
127
+ LoggerProxy.logger.warn(
128
+ 'Media:MediaConnectionAwaiter#onTimeout --> ICE gathering did not complete within the timeout for the first time, retrying once'
129
+ );
130
+
131
+ // retry once if ICE gathering is not completed
132
+ this.retried = true;
133
+ clearTimeout(this.timer);
134
+ this.timer = setTimeout(this.onTimeoutCallback, ICE_AND_DTLS_CONNECTION_TIMEOUT);
135
+
136
+ return;
137
+ }
138
+
139
+ LoggerProxy.logger.warn(
140
+ 'Media:MediaConnectionAwaiter#onTimeout --> ICE gathering did not complete within the timeout for the second time, rejecting'
141
+ );
142
+ } else {
143
+ LoggerProxy.logger.warn(
144
+ 'Media:MediaConnectionAwaiter#onTimeout --> ICE gathering completed, but connection state is not connected, rejecting'
145
+ );
146
+ }
147
+
148
+ this.clearCallbacks();
149
+
150
+ this.defer.reject();
151
+ }
152
+
153
+ /**
154
+ * Waits for the webrtc media connection to be connected.
155
+ *
156
+ * @returns {Promise}
157
+ */
158
+ waitForMediaConnectionConnected(): Promise<void> {
159
+ if (this.isConnected()) {
160
+ return Promise.resolve();
161
+ }
162
+
163
+ this.webrtcMediaConnection.on(Event.CONNECTION_STATE_CHANGED, this.connectionStateCallback);
164
+
165
+ this.webrtcMediaConnection.on(
166
+ Event.ICE_GATHERING_STATE_CHANGED,
167
+ this.iceGatheringStateCallback
168
+ );
169
+
170
+ this.timer = setTimeout(this.onTimeoutCallback, ICE_AND_DTLS_CONNECTION_TIMEOUT);
171
+
172
+ return this.defer.promise;
173
+ }
174
+ }
@@ -1,5 +1,3 @@
1
- import {ConnectionState, Event} from '@webex/internal-media-core';
2
-
3
1
  import {
4
2
  LocalCameraStream,
5
3
  LocalMicrophoneStream,
@@ -8,8 +6,9 @@ import {
8
6
  RemoteStream,
9
7
  } from '@webex/media-helpers';
10
8
 
11
- import {MEETINGS, ICE_AND_DTLS_CONNECTION_TIMEOUT, QUALITY_LEVELS} from '../constants';
9
+ import {MEETINGS, QUALITY_LEVELS} from '../constants';
12
10
  import LoggerProxy from '../common/logs/logger-proxy';
11
+ import MediaConnectionAwaiter from './MediaConnectionAwaiter';
13
12
 
14
13
  export type MediaDirection = {
15
14
  sendAudio: boolean;
@@ -175,35 +174,11 @@ export default class MediaProperties {
175
174
  * @returns {Promise<void>}
176
175
  */
177
176
  waitForMediaConnectionConnected(): Promise<void> {
178
- const isConnected = () =>
179
- this.webrtcMediaConnection.getConnectionState() === ConnectionState.Connected;
180
-
181
- if (isConnected()) {
182
- return Promise.resolve();
183
- }
184
-
185
- return new Promise<void>((resolve, reject) => {
186
- let timer;
187
-
188
- const connectionStateListener = () => {
189
- LoggerProxy.logger.log(
190
- `Media:properties#waitForMediaConnectionConnected --> connection state: ${this.webrtcMediaConnection.getConnectionState()}`
191
- );
192
-
193
- if (isConnected()) {
194
- clearTimeout(timer);
195
- this.webrtcMediaConnection.off(Event.CONNECTION_STATE_CHANGED, connectionStateListener);
196
- resolve();
197
- }
198
- };
199
-
200
- timer = setTimeout(() => {
201
- this.webrtcMediaConnection.off(Event.CONNECTION_STATE_CHANGED, connectionStateListener);
202
- reject();
203
- }, ICE_AND_DTLS_CONNECTION_TIMEOUT);
204
-
205
- this.webrtcMediaConnection.on(Event.CONNECTION_STATE_CHANGED, connectionStateListener);
177
+ const mediaConnectionAwaiter = new MediaConnectionAwaiter({
178
+ webrtcMediaConnection: this.webrtcMediaConnection,
206
179
  });
180
+
181
+ return mediaConnectionAwaiter.waitForMediaConnectionConnected();
207
182
  }
208
183
 
209
184
  /**
@@ -0,0 +1,344 @@
1
+ import {assert} from '@webex/test-helper-chai';
2
+ import sinon from 'sinon';
3
+ import {ConnectionState, Event} from '@webex/internal-media-core';
4
+ import testUtils from '../../../utils/testUtils';
5
+ import {ICE_AND_DTLS_CONNECTION_TIMEOUT} from '@webex/plugin-meetings/src/constants';
6
+ import MediaConnectionAwaiter from '../../../../src/media/MediaConnectionAwaiter';
7
+
8
+ describe('MediaConnectionAwaiter', () => {
9
+ let mediaConnectionAwaiter;
10
+ let mockMC;
11
+ let clock;
12
+
13
+ beforeEach(() => {
14
+ clock = sinon.useFakeTimers();
15
+
16
+ mockMC = {
17
+ getStats: sinon.stub().resolves([]),
18
+ on: sinon.stub(),
19
+ off: sinon.stub(),
20
+ getConnectionState: sinon.stub().returns(ConnectionState.New),
21
+ getIceGatheringState: sinon.stub().returns('new'),
22
+ };
23
+
24
+ mediaConnectionAwaiter = new MediaConnectionAwaiter({
25
+ webrtcMediaConnection: mockMC,
26
+ });
27
+ });
28
+
29
+ afterEach(() => {
30
+ clock.restore();
31
+ sinon.restore();
32
+ });
33
+
34
+ describe('waitForMediaConnectionConnected', () => {
35
+ it('resolves immediately if connection state is connected', async () => {
36
+ mockMC.getConnectionState.returns(ConnectionState.Connected);
37
+
38
+ await mediaConnectionAwaiter.waitForMediaConnectionConnected();
39
+
40
+ assert.neverCalledWith(mockMC.on);
41
+ });
42
+
43
+ it('rejects after timeout if ice state is not connected', async () => {
44
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
45
+ mockMC.getIceGatheringState.returns('gathering');
46
+
47
+ let promiseResolved = false;
48
+ let promiseRejected = false;
49
+
50
+ mediaConnectionAwaiter
51
+ .waitForMediaConnectionConnected()
52
+ .then(() => {
53
+ promiseResolved = true;
54
+ })
55
+ .catch(() => {
56
+ promiseRejected = true;
57
+ });
58
+
59
+ await testUtils.flushPromises();
60
+ assert.equal(promiseResolved, false);
61
+ assert.equal(promiseRejected, false);
62
+
63
+ // check the right listener was registered
64
+ assert.calledTwice(mockMC.on);
65
+ assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
66
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_GATHERING_STATE_CHANGED);
67
+ const listener = mockMC.on.getCall(1).args[1];
68
+
69
+ mockMC.getIceGatheringState.returns('complete');
70
+ listener();
71
+
72
+ await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT);
73
+ await testUtils.flushPromises();
74
+
75
+ assert.equal(promiseResolved, false);
76
+ assert.equal(promiseRejected, true);
77
+
78
+ assert.calledTwice(mockMC.off);
79
+ });
80
+
81
+ it('resolves after timeout if connection state reach connected/completed', async () => {
82
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
83
+ mockMC.getIceGatheringState.returns('gathering');
84
+
85
+ let promiseResolved = false;
86
+ let promiseRejected = false;
87
+
88
+ mediaConnectionAwaiter
89
+ .waitForMediaConnectionConnected()
90
+ .then(() => {
91
+ promiseResolved = true;
92
+ })
93
+ .catch(() => {
94
+ promiseRejected = true;
95
+ });
96
+
97
+ await testUtils.flushPromises();
98
+ assert.equal(promiseResolved, false);
99
+ assert.equal(promiseRejected, false);
100
+
101
+ // check the right listener was registered
102
+ assert.calledTwice(mockMC.on);
103
+ assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
104
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_GATHERING_STATE_CHANGED);
105
+
106
+ mockMC.getConnectionState.returns(ConnectionState.Connected);
107
+
108
+ await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT);
109
+ await testUtils.flushPromises();
110
+
111
+ assert.equal(promiseResolved, true);
112
+ assert.equal(promiseRejected, false);
113
+
114
+ assert.calledTwice(mockMC.off);
115
+ });
116
+
117
+ it(`resolves when media connection reaches "connected" state`, async () => {
118
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
119
+ mockMC.getIceGatheringState.returns('gathering');
120
+
121
+ const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
122
+
123
+ let promiseResolved = false;
124
+ let promiseRejected = false;
125
+
126
+ mediaConnectionAwaiter
127
+ .waitForMediaConnectionConnected()
128
+ .then(() => {
129
+ promiseResolved = true;
130
+ })
131
+ .catch(() => {
132
+ promiseRejected = true;
133
+ });
134
+
135
+ await testUtils.flushPromises();
136
+ assert.equal(promiseResolved, false);
137
+ assert.equal(promiseRejected, false);
138
+
139
+ // check the right listener was registered
140
+ assert.calledTwice(mockMC.on);
141
+ assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
142
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_GATHERING_STATE_CHANGED);
143
+ const listener = mockMC.on.getCall(0).args[1];
144
+
145
+ // call the listener and pretend we are now connected
146
+ mockMC.getConnectionState.returns(ConnectionState.Connected);
147
+ listener();
148
+ await testUtils.flushPromises();
149
+
150
+ assert.equal(promiseResolved, true);
151
+ assert.equal(promiseRejected, false);
152
+
153
+ // check that listener was removed
154
+ assert.calledTwice(mockMC.off);
155
+
156
+ assert.calledOnce(clearTimeoutSpy);
157
+ });
158
+
159
+ it(`ice gathering state update to "gathering" state does not update timer`, async () => {
160
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
161
+ mockMC.getIceGatheringState.returns('new');
162
+
163
+ const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
164
+
165
+ let promiseResolved = false;
166
+ let promiseRejected = false;
167
+
168
+ mediaConnectionAwaiter
169
+ .waitForMediaConnectionConnected()
170
+ .then(() => {
171
+ promiseResolved = true;
172
+ })
173
+ .catch(() => {
174
+ promiseRejected = true;
175
+ });
176
+
177
+ await testUtils.flushPromises();
178
+ assert.equal(promiseResolved, false);
179
+ assert.equal(promiseRejected, false);
180
+
181
+ // check the right listener was registered
182
+ assert.calledTwice(mockMC.on);
183
+ assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
184
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_GATHERING_STATE_CHANGED);
185
+ const listener = mockMC.on.getCall(1).args[1];
186
+
187
+ // call the listener and pretend we are now connected
188
+ mockMC.getIceGatheringState.returns('gathering');
189
+ listener();
190
+
191
+ mockMC.getConnectionState.returns(ConnectionState.Connected);
192
+
193
+ await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT);
194
+ await testUtils.flushPromises();
195
+
196
+ assert.equal(promiseResolved, true);
197
+ assert.equal(promiseRejected, false);
198
+
199
+ // check that listener was removed
200
+ assert.calledTwice(mockMC.off);
201
+
202
+ assert.neverCalledWith(clearTimeoutSpy);
203
+ });
204
+
205
+ it(`ice gathering update to 'complete' state restarts the timer`, async () => {
206
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
207
+ mockMC.getIceGatheringState.returns('new');
208
+
209
+ const setTimeoutSpy = sinon.spy(clock, 'setTimeout');
210
+ const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
211
+
212
+ let promiseResolved = false;
213
+ let promiseRejected = false;
214
+
215
+ mediaConnectionAwaiter
216
+ .waitForMediaConnectionConnected()
217
+ .then(() => {
218
+ promiseResolved = true;
219
+ })
220
+ .catch(() => {
221
+ promiseRejected = true;
222
+ });
223
+
224
+ await testUtils.flushPromises();
225
+ assert.equal(promiseResolved, false);
226
+ assert.equal(promiseRejected, false);
227
+
228
+ assert.calledOnce(setTimeoutSpy);
229
+
230
+ // check the right listener was registered
231
+ assert.calledTwice(mockMC.on);
232
+ assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
233
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_GATHERING_STATE_CHANGED);
234
+ const listener = mockMC.on.getCall(1).args[1];
235
+
236
+ // call the listener and pretend we are now connected
237
+ mockMC.getIceGatheringState.returns('complete');
238
+ listener();
239
+
240
+ assert.calledOnce(clearTimeoutSpy);
241
+ assert.calledTwice(setTimeoutSpy);
242
+
243
+ mockMC.getConnectionState.returns(ConnectionState.Connected);
244
+
245
+ await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT);
246
+ await testUtils.flushPromises();
247
+
248
+ assert.equal(promiseResolved, true);
249
+ assert.equal(promiseRejected, false);
250
+
251
+ // check that listener was removed
252
+ assert.calledTwice(mockMC.off);
253
+ });
254
+
255
+ it(`reject with restart timer once if gathering state is not complete`, async () => {
256
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
257
+ mockMC.getIceGatheringState.returns('new');
258
+
259
+ const setTimeoutSpy = sinon.spy(clock, 'setTimeout');
260
+ const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
261
+
262
+ let promiseResolved = false;
263
+ let promiseRejected = false;
264
+
265
+ mediaConnectionAwaiter
266
+ .waitForMediaConnectionConnected()
267
+ .then(() => {
268
+ promiseResolved = true;
269
+ })
270
+ .catch(() => {
271
+ promiseRejected = true;
272
+ });
273
+
274
+ await testUtils.flushPromises();
275
+ assert.equal(promiseResolved, false);
276
+ assert.equal(promiseRejected, false);
277
+
278
+ // check the right listener was registered
279
+ assert.calledTwice(mockMC.on);
280
+ assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
281
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_GATHERING_STATE_CHANGED);
282
+
283
+ await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT * 2);
284
+ await testUtils.flushPromises();
285
+
286
+ assert.equal(promiseResolved, false);
287
+ assert.equal(promiseRejected, true);
288
+
289
+ // check that listener was removed
290
+ assert.calledTwice(mockMC.off);
291
+
292
+ assert.calledOnce(clearTimeoutSpy);
293
+ assert.calledTwice(setTimeoutSpy);
294
+ });
295
+
296
+ it(`resolves gathering and connection state complete right after`, async () => {
297
+ mockMC.getConnectionState.returns(ConnectionState.Connecting);
298
+ mockMC.getIceGatheringState.returns('new');
299
+
300
+ const setTimeoutSpy = sinon.spy(clock, 'setTimeout');
301
+ const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
302
+
303
+ let promiseResolved = false;
304
+ let promiseRejected = false;
305
+
306
+ mediaConnectionAwaiter
307
+ .waitForMediaConnectionConnected()
308
+ .then(() => {
309
+ promiseResolved = true;
310
+ })
311
+ .catch(() => {
312
+ promiseRejected = true;
313
+ });
314
+
315
+ await testUtils.flushPromises();
316
+ assert.equal(promiseResolved, false);
317
+ assert.equal(promiseRejected, false);
318
+
319
+ // check the right listener was registered
320
+ assert.calledTwice(mockMC.on);
321
+ assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
322
+ assert.equal(mockMC.on.getCall(1).args[0], Event.ICE_GATHERING_STATE_CHANGED);
323
+ const connectionStateListener = mockMC.on.getCall(0).args[1];
324
+ const iceGatheringListener = mockMC.on.getCall(1).args[1];
325
+
326
+ mockMC.getIceGatheringState.returns('complete');
327
+ iceGatheringListener();
328
+
329
+ mockMC.getConnectionState.returns(ConnectionState.Connected);
330
+ connectionStateListener();
331
+
332
+ await testUtils.flushPromises();
333
+
334
+ assert.equal(promiseResolved, true);
335
+ assert.equal(promiseRejected, false);
336
+
337
+ // check that listener was removed
338
+ assert.calledTwice(mockMC.off);
339
+
340
+ assert.calledTwice(clearTimeoutSpy);
341
+ assert.calledTwice(setTimeoutSpy);
342
+ });
343
+ });
344
+ });
@@ -1,11 +1,10 @@
1
1
  import {assert} from '@webex/test-helper-chai';
2
2
  import sinon from 'sinon';
3
- import {ConnectionState, Event} from '@webex/internal-media-core';
3
+ import {ConnectionState} from '@webex/internal-media-core';
4
4
  import MediaProperties from '@webex/plugin-meetings/src/media/properties';
5
- import MediaUtil from '@webex/plugin-meetings/src/media/util';
6
5
  import testUtils from '../../../utils/testUtils';
7
- import {ICE_AND_DTLS_CONNECTION_TIMEOUT} from '@webex/plugin-meetings/src/constants';
8
6
  import {Defer} from '@webex/common';
7
+ import MediaConnectionAwaiter from '../../../../src/media/MediaConnectionAwaiter';
9
8
 
10
9
  describe('MediaProperties', () => {
11
10
  let mediaProperties;
@@ -31,80 +30,27 @@ describe('MediaProperties', () => {
31
30
  sinon.restore();
32
31
  });
33
32
  describe('waitForMediaConnectionConnected', () => {
34
- it('resolves immediately if ice state is connected', async () => {
35
- await mediaProperties.waitForMediaConnectionConnected();
36
- });
37
- it('rejects after timeout if ice state does not reach connected/completed', async () => {
38
- mockMC.getConnectionState.returns(ConnectionState.Connecting);
39
-
40
- let promiseResolved = false;
41
- let promiseRejected = false;
42
-
43
- mediaProperties
44
- .waitForMediaConnectionConnected()
45
- .then(() => {
46
- promiseResolved = true;
47
- })
48
- .catch(() => {
49
- promiseRejected = true;
50
- });
51
-
52
- assert.equal(promiseResolved, false);
53
- assert.equal(promiseRejected, false);
54
-
55
- await clock.tickAsync(ICE_AND_DTLS_CONNECTION_TIMEOUT);
56
- await testUtils.flushPromises();
33
+ it('resolves if media connection is connected', async () => {
34
+ const waitForMediaConnectionConnectedResult = new Defer();
57
35
 
58
- assert.equal(promiseResolved, false);
59
- assert.equal(promiseRejected, true);
36
+ sinon
37
+ .stub(MediaConnectionAwaiter.prototype, 'waitForMediaConnectionConnected')
38
+ .returns(waitForMediaConnectionConnectedResult.promise);
60
39
 
61
- // check that listener was registered and removed
62
- assert.calledOnce(mockMC.on);
63
- assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
64
- const listener = mockMC.on.getCall(0).args[1];
40
+ waitForMediaConnectionConnectedResult.resolve();
65
41
 
66
- assert.calledOnce(mockMC.off);
67
- assert.calledWith(mockMC.off, Event.CONNECTION_STATE_CHANGED, listener);
42
+ await mediaProperties.waitForMediaConnectionConnected();
68
43
  });
44
+ it('rejects if media connection is not connected', async () => {
45
+ const waitForMediaConnectionConnectedResult = new Defer();
69
46
 
70
- it(`resolves when media connection reaches "connected" state`, async () => {
71
- mockMC.getConnectionState.returns(ConnectionState.Connecting);
72
-
73
- const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
74
-
75
- let promiseResolved = false;
76
- let promiseRejected = false;
77
-
78
- mediaProperties
79
- .waitForMediaConnectionConnected()
80
- .then(() => {
81
- promiseResolved = true;
82
- })
83
- .catch(() => {
84
- promiseRejected = true;
85
- });
86
-
87
- assert.equal(promiseResolved, false);
88
- assert.equal(promiseRejected, false);
89
-
90
- // check the right listener was registered
91
- assert.calledOnce(mockMC.on);
92
- assert.equal(mockMC.on.getCall(0).args[0], Event.CONNECTION_STATE_CHANGED);
93
- const listener = mockMC.on.getCall(0).args[1];
94
-
95
- // call the listener and pretend we are now connected
96
- mockMC.getConnectionState.returns(ConnectionState.Connected);
97
- listener();
98
- await testUtils.flushPromises();
99
-
100
- assert.equal(promiseResolved, true);
101
- assert.equal(promiseRejected, false);
47
+ sinon
48
+ .stub(MediaConnectionAwaiter.prototype, 'waitForMediaConnectionConnected')
49
+ .returns(waitForMediaConnectionConnectedResult.promise);
102
50
 
103
- // check that listener was removed
104
- assert.calledOnce(mockMC.off);
105
- assert.calledWith(mockMC.off, Event.CONNECTION_STATE_CHANGED, listener);
51
+ waitForMediaConnectionConnectedResult.reject();
106
52
 
107
- assert.calledOnce(clearTimeoutSpy);
53
+ await assert.isRejected(mediaProperties.waitForMediaConnectionConnected());
108
54
  });
109
55
  });
110
56