@webex/plugin-meetings 1.145.0 → 1.147.0
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/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/constants.js +4 -2
- package/dist/constants.js.map +1 -1
- package/dist/media/index.js +16 -8
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/index.js +19 -2
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/util.js +2 -1
- package/dist/meeting/util.js.map +1 -1
- package/dist/members/index.js +63 -0
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +41 -0
- package/dist/members/request.js.map +1 -1
- package/dist/members/util.js +59 -0
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/index.js +0 -2
- package/dist/metrics/index.js.map +1 -1
- package/dist/peer-connection-manager/index.js +8 -7
- package/dist/peer-connection-manager/index.js.map +1 -1
- package/dist/reconnection-manager/index.js +2 -1
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/handler.js +7 -8
- package/dist/roap/handler.js.map +1 -1
- package/dist/roap/index.js +8 -3
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/state.js +2 -0
- package/dist/roap/state.js.map +1 -1
- package/package.json +5 -5
- package/src/config.js +1 -0
- package/src/constants.js +1 -0
- package/src/media/index.js +58 -10
- package/src/meeting/index.js +17 -2
- package/src/meeting/util.js +2 -1
- package/src/members/index.js +56 -0
- package/src/members/request.js +35 -0
- package/src/members/util.js +58 -1
- package/src/metrics/index.js +0 -2
- package/src/peer-connection-manager/index.js +13 -9
- package/src/reconnection-manager/index.js +2 -1
- package/src/roap/handler.js +7 -8
- package/src/roap/index.js +10 -3
- package/src/roap/state.js +2 -0
- package/test/unit/spec/meeting/index.js +16 -0
- package/test/unit/spec/members/index.js +192 -0
- package/test/unit/spec/members/request.js +101 -0
package/src/media/index.js
CHANGED
|
@@ -71,13 +71,23 @@ Media.setLocalTrack = (enabled, track) => {
|
|
|
71
71
|
* @param {string} meetingProperties.remoteQualityLevel LOW|MEDIUM|HIGH
|
|
72
72
|
* @returns {Promise}
|
|
73
73
|
*/
|
|
74
|
-
Media.reconnectMedia = (peerConnection, {
|
|
74
|
+
Media.reconnectMedia = (peerConnection, {
|
|
75
|
+
meetingId,
|
|
76
|
+
remoteQualityLevel,
|
|
77
|
+
enableRtx,
|
|
78
|
+
enableExtmap
|
|
79
|
+
}) => {
|
|
75
80
|
if (peerConnection.connectionState === PEER_CONNECTION_STATE.CLOSED ||
|
|
76
81
|
peerConnection.connectionState === PEER_CONNECTION_STATE.FAILED) {
|
|
77
82
|
return Promise.reject(new ReconnectionError('Reinitiate peerconnection'));
|
|
78
83
|
}
|
|
79
84
|
|
|
80
|
-
return PeerConnectionManager.createOffer(peerConnection, {
|
|
85
|
+
return PeerConnectionManager.createOffer(peerConnection, {
|
|
86
|
+
meetingId,
|
|
87
|
+
remoteQualityLevel,
|
|
88
|
+
enableRtx,
|
|
89
|
+
enableExtmap
|
|
90
|
+
});
|
|
81
91
|
};
|
|
82
92
|
|
|
83
93
|
/**
|
|
@@ -165,9 +175,18 @@ Media.checkTracks = (trackType, track, receiveTracks) => {
|
|
|
165
175
|
* @param {string} meetingProperties.remoteQualityLevel LOW|MEDIUM|HIGH
|
|
166
176
|
* @returns {Array} [peerConnection, ]
|
|
167
177
|
*/
|
|
168
|
-
Media.attachMedia = (mediaProperties, {
|
|
178
|
+
Media.attachMedia = (mediaProperties, {
|
|
179
|
+
meetingId,
|
|
180
|
+
remoteQualityLevel,
|
|
181
|
+
enableRtx,
|
|
182
|
+
enableExtmap
|
|
183
|
+
}) => {
|
|
169
184
|
const {
|
|
170
|
-
mediaDirection,
|
|
185
|
+
mediaDirection,
|
|
186
|
+
audioTrack,
|
|
187
|
+
videoTrack,
|
|
188
|
+
shareTrack,
|
|
189
|
+
peerConnection
|
|
171
190
|
} = mediaProperties;
|
|
172
191
|
|
|
173
192
|
let result = null;
|
|
@@ -188,7 +207,12 @@ Media.attachMedia = (mediaProperties, {meetingId, remoteQualityLevel, enableRtx}
|
|
|
188
207
|
LoggerProxy.logger.info(`Media:index#attachMedia --> onnegotiationneeded#PeerConnection: ${event}`);
|
|
189
208
|
};
|
|
190
209
|
|
|
191
|
-
return PeerConnectionManager.createOffer(peerConnection, {
|
|
210
|
+
return PeerConnectionManager.createOffer(peerConnection, {
|
|
211
|
+
meetingId,
|
|
212
|
+
remoteQualityLevel,
|
|
213
|
+
enableRtx,
|
|
214
|
+
enableExtmap
|
|
215
|
+
});
|
|
192
216
|
};
|
|
193
217
|
|
|
194
218
|
/**
|
|
@@ -199,9 +223,18 @@ Media.attachMedia = (mediaProperties, {meetingId, remoteQualityLevel, enableRtx}
|
|
|
199
223
|
* @param {string} meetingProperties.remoteQualityLevel LOW|MEDIUM|HIGH
|
|
200
224
|
* @returns {Promise}
|
|
201
225
|
*/
|
|
202
|
-
Media.updateMedia = (mediaProperties, {
|
|
226
|
+
Media.updateMedia = (mediaProperties, {
|
|
227
|
+
meetingId,
|
|
228
|
+
remoteQualityLevel,
|
|
229
|
+
enableRtx,
|
|
230
|
+
enableExtmap
|
|
231
|
+
}) => {
|
|
203
232
|
const {
|
|
204
|
-
mediaDirection,
|
|
233
|
+
mediaDirection,
|
|
234
|
+
audioTrack,
|
|
235
|
+
videoTrack,
|
|
236
|
+
shareTrack,
|
|
237
|
+
peerConnection
|
|
205
238
|
} = mediaProperties;
|
|
206
239
|
|
|
207
240
|
// update audio transceiver
|
|
@@ -231,7 +264,12 @@ Media.updateMedia = (mediaProperties, {meetingId, remoteQualityLevel, enableRtx}
|
|
|
231
264
|
LoggerProxy.logger.info(`Media:index#updateMedia --> onnegotiationneeded#PeerConnection: ${event}`);
|
|
232
265
|
};
|
|
233
266
|
|
|
234
|
-
return PeerConnectionManager.createOffer(peerConnection, {
|
|
267
|
+
return PeerConnectionManager.createOffer(peerConnection, {
|
|
268
|
+
meetingId,
|
|
269
|
+
remoteQualityLevel,
|
|
270
|
+
enableRtx,
|
|
271
|
+
enableExtmap
|
|
272
|
+
});
|
|
235
273
|
};
|
|
236
274
|
|
|
237
275
|
/**
|
|
@@ -269,10 +307,20 @@ Media.setTrackOnTransceiver = (transceiver, options) => {
|
|
|
269
307
|
* @param {Object} options see #Media.setTrackOnTransceiver
|
|
270
308
|
* @returns {Promise}
|
|
271
309
|
*/
|
|
272
|
-
Media.updateTransceiver = ({
|
|
310
|
+
Media.updateTransceiver = ({
|
|
311
|
+
meetingId,
|
|
312
|
+
remoteQualityLevel,
|
|
313
|
+
enableRtx,
|
|
314
|
+
enableExtmap
|
|
315
|
+
}, peerConnection, transceiver, options) => {
|
|
273
316
|
Media.setTrackOnTransceiver(transceiver, options);
|
|
274
317
|
|
|
275
|
-
return PeerConnectionManager.createOffer(peerConnection, {
|
|
318
|
+
return PeerConnectionManager.createOffer(peerConnection, {
|
|
319
|
+
meetingId,
|
|
320
|
+
remoteQualityLevel,
|
|
321
|
+
enableRtx,
|
|
322
|
+
enableExtmap
|
|
323
|
+
});
|
|
276
324
|
};
|
|
277
325
|
|
|
278
326
|
/**
|
package/src/meeting/index.js
CHANGED
|
@@ -1742,6 +1742,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1742
1742
|
* @param {Object} invitee
|
|
1743
1743
|
* @param {String} invitee.emailAddress
|
|
1744
1744
|
* @param {String} invitee.email
|
|
1745
|
+
* @param {String} invitee.phoneNumber
|
|
1745
1746
|
* @param {Boolean} [alertIfActive]
|
|
1746
1747
|
* @returns {Promise} see #members.addMember
|
|
1747
1748
|
* @public
|
|
@@ -1751,6 +1752,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1751
1752
|
return this.members.addMember(invitee, alertIfActive);
|
|
1752
1753
|
}
|
|
1753
1754
|
|
|
1755
|
+
/**
|
|
1756
|
+
* Cancel an outgoing phone call invitation made during a meeting
|
|
1757
|
+
* @param {Object} invitee
|
|
1758
|
+
* @param {String} invitee.phoneNumber
|
|
1759
|
+
* @returns {Promise} see #members.cancelPhoneInvite
|
|
1760
|
+
* @public
|
|
1761
|
+
* @memberof Meeting
|
|
1762
|
+
*/
|
|
1763
|
+
cancelPhoneInvite(invitee) {
|
|
1764
|
+
return this.members.cancelPhoneInvite(invitee);
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1754
1767
|
/**
|
|
1755
1768
|
* Admit the guest(s) to the call once they are waiting
|
|
1756
1769
|
* @param {Array} memberIds
|
|
@@ -3663,7 +3676,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3663
3676
|
.then(() => Media.attachMedia(this.mediaProperties, {
|
|
3664
3677
|
meetingId: this.id,
|
|
3665
3678
|
remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
|
|
3666
|
-
enableRtx: this.config.enableRtx
|
|
3679
|
+
enableRtx: this.config.enableRtx,
|
|
3680
|
+
enableExtmap: this.config.enableExtmap
|
|
3667
3681
|
})
|
|
3668
3682
|
.then((peerConnection) => this.getDevices().then((devices) => {
|
|
3669
3683
|
MeetingUtil.handleDeviceLogging(devices);
|
|
@@ -3937,7 +3951,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3937
3951
|
.then(() => Media.updateMedia(this.mediaProperties, {
|
|
3938
3952
|
meetingId: this.id,
|
|
3939
3953
|
remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
|
|
3940
|
-
enableRtx: this.config.enableRtx
|
|
3954
|
+
enableRtx: this.config.enableRtx,
|
|
3955
|
+
enableExtmap: this.config.enableExtmap
|
|
3941
3956
|
})
|
|
3942
3957
|
.then((peerConnection) => {
|
|
3943
3958
|
LoggerProxy.logger.info(`${LOG_HEADER} PeerConnection received from updateMedia, ${peerConnection}`);
|
package/src/meeting/util.js
CHANGED
|
@@ -302,7 +302,8 @@ MeetingUtil.updateTransceiver = (options, meetingOptions) => {
|
|
|
302
302
|
return Media.updateTransceiver({
|
|
303
303
|
meetingId: meetingOptions.meeting.id,
|
|
304
304
|
remoteQualityLevel: meetingOptions.mediaProperties.remoteQualityLevel,
|
|
305
|
-
enableRtx: meetingOptions.meeting.config.enableRtx
|
|
305
|
+
enableRtx: meetingOptions.meeting.config.enableRtx,
|
|
306
|
+
enableExtmap: meetingOptions.meeting.config.enableExtmap
|
|
306
307
|
}, peerConnection, transceiver,
|
|
307
308
|
{
|
|
308
309
|
track,
|
package/src/members/index.js
CHANGED
|
@@ -594,6 +594,27 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
594
594
|
return this.membersRequest.addMembers(options);
|
|
595
595
|
}
|
|
596
596
|
|
|
597
|
+
/**
|
|
598
|
+
* Cancels an outgoing PSTN call to the associated meeting
|
|
599
|
+
* @param {String} invitee
|
|
600
|
+
* @returns {Promise}
|
|
601
|
+
* @memberof Members
|
|
602
|
+
*/
|
|
603
|
+
cancelPhoneInvite(invitee) {
|
|
604
|
+
if (!this.locusUrl) {
|
|
605
|
+
return Promise.reject(new ParameterError('The associated locus url for this meeting object must be defined.'));
|
|
606
|
+
}
|
|
607
|
+
if (MembersUtil.isInvalidInvitee(invitee)) {
|
|
608
|
+
return Promise.reject(
|
|
609
|
+
new ParameterError('The invitee must be defined with a valid phoneNumber property.')
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
const options = MembersUtil.cancelPhoneInviteOptions(invitee, this.locusUrl);
|
|
613
|
+
|
|
614
|
+
|
|
615
|
+
return this.membersRequest.cancelPhoneInvite(options);
|
|
616
|
+
}
|
|
617
|
+
|
|
597
618
|
/**
|
|
598
619
|
* Admits waiting members (invited guests to meeting)
|
|
599
620
|
* @param {Array} memberIds
|
|
@@ -668,4 +689,39 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
668
689
|
|
|
669
690
|
return this.membersRequest.transferHostToMember(options);
|
|
670
691
|
}
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* Sends DTMF tones for the PSTN member of a meeting
|
|
696
|
+
* @param {String} tones a string of one or more DTMF tones to send
|
|
697
|
+
* @param {String} memberId member id
|
|
698
|
+
* @returns {Promise}
|
|
699
|
+
* @public
|
|
700
|
+
* @memberof Members
|
|
701
|
+
*/
|
|
702
|
+
sendDialPadKey(tones = '', memberId = '') {
|
|
703
|
+
if (!tones && tones !== 0) {
|
|
704
|
+
return Promise.reject(new ParameterError('DMTF tones must be passed in'));
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
const member = this.membersCollection.get(memberId);
|
|
708
|
+
|
|
709
|
+
if (!member) {
|
|
710
|
+
return Promise.reject(new ParameterError('there is no member associated with that Id'));
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
const {locusUrl} = this;
|
|
714
|
+
|
|
715
|
+
const deviceArray = member.participant.devices;
|
|
716
|
+
const device = deviceArray.find(({deviceType}) => deviceType === 'SIP');
|
|
717
|
+
const url = device?.url;
|
|
718
|
+
|
|
719
|
+
if (locusUrl && url) {
|
|
720
|
+
const options = MembersUtil.genderateSendDTMFOptions(url, tones, memberId, locusUrl);
|
|
721
|
+
|
|
722
|
+
return this.membersRequest.sendDialPadKey(options);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
return Promise.reject(new Error('Members:index#sendDialPadKey --> cannot send DTMF, meeting does not have a connection to the "locus" call control service.'));
|
|
726
|
+
}
|
|
671
727
|
}
|
package/src/members/request.js
CHANGED
|
@@ -73,4 +73,39 @@ export default class MembersRequest extends StatelessWebexPlugin {
|
|
|
73
73
|
|
|
74
74
|
return this.request(requestParams);
|
|
75
75
|
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Sends a request to the DTMF endpoint to send tones
|
|
79
|
+
* @param {Object} options
|
|
80
|
+
* @param {String} options.locusUrl
|
|
81
|
+
* @param {String} options.url device url SIP user
|
|
82
|
+
* @param {String} options.tones a string of one or more DTMF tones to send
|
|
83
|
+
* @param {String} options.memberId ID of PSTN user
|
|
84
|
+
* @returns {Promise}
|
|
85
|
+
*/
|
|
86
|
+
sendDialPadKey(options) {
|
|
87
|
+
if (!options || !options.locusUrl || !options.memberId || !options.url || !options.tones && options.tones !== 0) {
|
|
88
|
+
throw new ParameterError('memberId must be defined, the associated locus url, the device url and DTMF tones for this meeting object must be defined.');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const requestParams = MembersUtil.generateSendDTMFRequestParams(options);
|
|
92
|
+
|
|
93
|
+
return this.request(requestParams);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @param {Object} options with format of {invitee: string, locusUrl: string}
|
|
98
|
+
* @returns {Promise}
|
|
99
|
+
* @throws {Error} if the options are not valid and complete, must have invitee with emailAddress OR email AND locusUrl
|
|
100
|
+
* @memberof MembersRequest
|
|
101
|
+
*/
|
|
102
|
+
cancelPhoneInvite(options) {
|
|
103
|
+
if (!(options?.invitee?.phoneNumber || options?.locusUrl)) {
|
|
104
|
+
throw new ParameterError('invitee must be passed and the associated locus url for this meeting object must be defined.');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const requestParams = MembersUtil.generateCancelInviteRequestParams(options);
|
|
108
|
+
|
|
109
|
+
return this.request(requestParams);
|
|
110
|
+
}
|
|
76
111
|
}
|
package/src/members/util.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import uuid from 'uuid';
|
|
2
|
+
|
|
1
3
|
import {
|
|
2
4
|
HTTP_VERBS,
|
|
3
5
|
CONTROLS,
|
|
@@ -5,7 +7,9 @@ import {
|
|
|
5
7
|
LEAVE,
|
|
6
8
|
PARTICIPANT,
|
|
7
9
|
VALID_EMAIL_ADDRESS,
|
|
8
|
-
DIALER_REGEX
|
|
10
|
+
DIALER_REGEX,
|
|
11
|
+
SEND_DTMF_ENDPOINT,
|
|
12
|
+
_REMOVE_
|
|
9
13
|
} from '../constants';
|
|
10
14
|
|
|
11
15
|
const MembersUtil = {};
|
|
@@ -156,4 +160,57 @@ MembersUtil.getTransferHostToMemberRequestParams = (options) => {
|
|
|
156
160
|
};
|
|
157
161
|
};
|
|
158
162
|
|
|
163
|
+
MembersUtil.genderateSendDTMFOptions = (url, tones, memberId, locusUrl) => ({
|
|
164
|
+
url,
|
|
165
|
+
tones,
|
|
166
|
+
memberId,
|
|
167
|
+
locusUrl
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
MembersUtil.generateSendDTMFRequestParams = ({
|
|
171
|
+
url, tones, memberId, locusUrl
|
|
172
|
+
}) => {
|
|
173
|
+
const body = {
|
|
174
|
+
device: {
|
|
175
|
+
url
|
|
176
|
+
},
|
|
177
|
+
memberId,
|
|
178
|
+
dtmf: {
|
|
179
|
+
correlationId: uuid.v4(),
|
|
180
|
+
tones,
|
|
181
|
+
direction: 'transmit'
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
const uri = `${locusUrl}/${PARTICIPANT}/${memberId}/${SEND_DTMF_ENDPOINT}`;
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
method: HTTP_VERBS.POST,
|
|
188
|
+
uri,
|
|
189
|
+
body
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
MembersUtil.cancelPhoneInviteOptions = (invitee, locusUrl) => ({
|
|
194
|
+
invitee,
|
|
195
|
+
locusUrl
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
MembersUtil.generateCancelInviteRequestParams = (options) => {
|
|
199
|
+
const body = {
|
|
200
|
+
actionType: _REMOVE_,
|
|
201
|
+
invitees: [
|
|
202
|
+
{
|
|
203
|
+
address: options.invitee.phoneNumber
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
};
|
|
207
|
+
const requestParams = {
|
|
208
|
+
method: HTTP_VERBS.PUT,
|
|
209
|
+
uri: options.locusUrl,
|
|
210
|
+
body
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
return requestParams;
|
|
214
|
+
};
|
|
215
|
+
|
|
159
216
|
export default MembersUtil;
|
package/src/metrics/index.js
CHANGED
|
@@ -175,7 +175,6 @@ class Metrics {
|
|
|
175
175
|
eventId: uuid.v4(),
|
|
176
176
|
version: 1,
|
|
177
177
|
origin: {
|
|
178
|
-
buildType: 'prod',
|
|
179
178
|
name: 'endpoint',
|
|
180
179
|
networkType: 'unknown',
|
|
181
180
|
userAgent: this.userAgentToString(),
|
|
@@ -264,7 +263,6 @@ class Metrics {
|
|
|
264
263
|
origin: {
|
|
265
264
|
audioSetupDelay,
|
|
266
265
|
videoSetupDelay,
|
|
267
|
-
buildType: 'prod',
|
|
268
266
|
name: 'endpoint',
|
|
269
267
|
networkType: options.networkType || UNKNOWN,
|
|
270
268
|
userAgent: this.userAgentToString(),
|
|
@@ -186,7 +186,6 @@ pc.iceCandidate = (peerConnection, {remoteQualityLevel}) =>
|
|
|
186
186
|
const timeout = setTimeout(() => {
|
|
187
187
|
peerConnection.sdp = limitBandwidth(peerConnection.localDescription.sdp);
|
|
188
188
|
peerConnection.sdp = setMaxFs(peerConnection.sdp, remoteQualityLevel);
|
|
189
|
-
peerConnection.sdp = peerConnection.sdp.replace(/\na=extmap.*/g, '');
|
|
190
189
|
|
|
191
190
|
if (isSdpInvalid(peerConnection.sdp)) {
|
|
192
191
|
setTimeout(() => {
|
|
@@ -214,7 +213,6 @@ pc.iceCandidate = (peerConnection, {remoteQualityLevel}) =>
|
|
|
214
213
|
if (!evt.candidate && !peerConnection.sdp) {
|
|
215
214
|
peerConnection.sdp = limitBandwidth(peerConnection.localDescription.sdp);
|
|
216
215
|
peerConnection.sdp = setMaxFs(peerConnection.sdp, remoteQualityLevel);
|
|
217
|
-
peerConnection.sdp = peerConnection.sdp.replace(/\na=extmap.*/g, '');
|
|
218
216
|
|
|
219
217
|
if (evt.candidate === null && !isSdpInvalid(peerConnection.sdp)) {
|
|
220
218
|
clearTimeout(timeout);
|
|
@@ -292,9 +290,7 @@ pc.addStream = (peerConnection, stream) => {
|
|
|
292
290
|
*/
|
|
293
291
|
pc.setRemoteSessionDetails = (peerConnection, typeStr, remoteSdp, meetingId) => {
|
|
294
292
|
LoggerProxy.logger.log(`PeerConnectionManager:index#setRemoteSessionDetails --> Setting the remote description type: ${typeStr}State: ${peerConnection.signalingState}`);
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
sdp = sdp.replace(/\na=extmap.*/g, '');
|
|
293
|
+
const sdp = remoteSdp;
|
|
298
294
|
|
|
299
295
|
// making sure that the remoteDescription is only set when there is a answer for offer
|
|
300
296
|
// or there is a offer from the server
|
|
@@ -363,9 +359,15 @@ pc.setRemoteSessionDetails = (peerConnection, typeStr, remoteSdp, meetingId) =>
|
|
|
363
359
|
* @param {string} meetingProperties.meetingId
|
|
364
360
|
* @param {string} meetingProperties.remoteQualityLevel LOW|MEDIUM|HIGH
|
|
365
361
|
* @param {string} meetingProperties.enableRtx
|
|
362
|
+
* @param {string} meetingProperties.enableExtmap
|
|
366
363
|
* @returns {RTCPeerConnection}
|
|
367
364
|
*/
|
|
368
|
-
pc.createOffer = (peerConnection, {
|
|
365
|
+
pc.createOffer = (peerConnection, {
|
|
366
|
+
meetingId,
|
|
367
|
+
remoteQualityLevel,
|
|
368
|
+
enableRtx,
|
|
369
|
+
enableExtmap
|
|
370
|
+
}) => {
|
|
369
371
|
LoggerProxy.logger.log('PeerConnectionManager:index#createOffer --> creating a new offer');
|
|
370
372
|
|
|
371
373
|
return peerConnection
|
|
@@ -389,7 +391,11 @@ pc.createOffer = (peerConnection, {meetingId, remoteQualityLevel, enableRtx}) =>
|
|
|
389
391
|
if (!checkH264Support(peerConnection.sdp)) {
|
|
390
392
|
throw new MediaError('openH264 is downloading please Wait. Upload logs if not working on second try');
|
|
391
393
|
}
|
|
392
|
-
|
|
394
|
+
|
|
395
|
+
if (!enableExtmap) {
|
|
396
|
+
peerConnection.sdp = peerConnection.sdp.replace(/\na=extmap.*/g, '');
|
|
397
|
+
}
|
|
398
|
+
|
|
393
399
|
pc.setContentSlides(peerConnection);
|
|
394
400
|
|
|
395
401
|
Metrics.postEvent({
|
|
@@ -512,8 +518,6 @@ pc.createAnswer = (params, {meetingId, remoteQualityLevel}) => {
|
|
|
512
518
|
throw new MediaError('openH264 is downloading please Wait. Upload logs if not working on second try');
|
|
513
519
|
}
|
|
514
520
|
|
|
515
|
-
peerConnection.sdp = peerConnection.sdp.replace(/\na=extmap.*/g, '');
|
|
516
|
-
|
|
517
521
|
return peerConnection;
|
|
518
522
|
})
|
|
519
523
|
.catch((error) => {
|
|
@@ -459,7 +459,8 @@ export default class ReconnectionManager {
|
|
|
459
459
|
return Media.attachMedia(this.meeting.mediaProperties, {
|
|
460
460
|
meetingId: this.meeting.id,
|
|
461
461
|
remoteQualityLevel: this.meeting.mediaProperties.remoteQualityLevel,
|
|
462
|
-
enableRtx: this.meeting.config.enableRtx
|
|
462
|
+
enableRtx: this.meeting.config.enableRtx,
|
|
463
|
+
enableExtmap: this.meeting.config.enableExtmap
|
|
463
464
|
})
|
|
464
465
|
.then((peerConnection) => this.meeting.setRemoteStream(peerConnection))
|
|
465
466
|
.then(() => {
|
package/src/roap/handler.js
CHANGED
|
@@ -192,8 +192,10 @@ export default class RoapHandler extends StatelessWebexPlugin {
|
|
|
192
192
|
handleAction(session, action, meeting, correlationId) {
|
|
193
193
|
let signal;
|
|
194
194
|
|
|
195
|
+
|
|
195
196
|
switch (action.type) {
|
|
196
197
|
case ROAP.RECEIVE_ROAP_MSG:
|
|
198
|
+
LoggerProxy.logger.log(`Roap:handler#handleAction --> RECEIVE_ROAP_MSG event captured, reciving a roap message : ${JSON.stringify(action)}`);
|
|
197
199
|
if (compareWithLastRoapMessage(this.lastRoapMessage, action)) {
|
|
198
200
|
LoggerProxy.logger.warn(`Roap:handler#handleAction --> duplicate roap offer from server: ${action.msg.seq}`);
|
|
199
201
|
}
|
|
@@ -204,18 +206,15 @@ export default class RoapHandler extends StatelessWebexPlugin {
|
|
|
204
206
|
}
|
|
205
207
|
break;
|
|
206
208
|
case ROAP.SEND_ROAP_MSG:
|
|
209
|
+
LoggerProxy.logger.log(`Roap:handler#handleAction --> SEND_ROAP_MSG event captured, sending roap message ${JSON.stringify(action)}`);
|
|
210
|
+
|
|
207
211
|
action.local = true;
|
|
208
212
|
this.execute(signal, session, action, meeting, ROAP.TX_);
|
|
209
213
|
break;
|
|
210
214
|
case ROAP.SEND_ROAP_MSG_SUCCESS:
|
|
211
|
-
//
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
// NOTE: When server send back an answer via mercury the
|
|
215
|
-
// remote SDP is already saved sent and ok message is sent back
|
|
216
|
-
// We dont have to indicate the roapHandler about the RX_ANSWER via SEND_ROAP_MSG_SUCCESS
|
|
217
|
-
// RoapHandler.transition(signal, session, meeting);
|
|
218
|
-
}
|
|
215
|
+
// NOTE: When server send back an answer via mercury the
|
|
216
|
+
// remote SDP is already saved sent and ok message is sent back
|
|
217
|
+
// We dont have to indicate the roapHandler about the RX_ANSWER via SEND_ROAP_MSG_SUCCESS
|
|
219
218
|
break;
|
|
220
219
|
case ROAP.RECEIVE_CALL_LEAVE:
|
|
221
220
|
RoapCollection.deleteSession(correlationId);
|
package/src/roap/index.js
CHANGED
|
@@ -174,6 +174,12 @@ export default class Roap extends StatelessWebexPlugin {
|
|
|
174
174
|
seq: options.seq
|
|
175
175
|
};
|
|
176
176
|
|
|
177
|
+
this.roapHandler.submit({
|
|
178
|
+
type: ROAP.SEND_ROAP_MSG,
|
|
179
|
+
msg: roapMessage,
|
|
180
|
+
correlationId: options.correlationId
|
|
181
|
+
});
|
|
182
|
+
|
|
177
183
|
return this.roapRequest
|
|
178
184
|
.sendRoap({
|
|
179
185
|
roapMessage,
|
|
@@ -186,10 +192,11 @@ export default class Roap extends StatelessWebexPlugin {
|
|
|
186
192
|
})
|
|
187
193
|
.then(() => {
|
|
188
194
|
meeting.setRoapSeq(options.seq);
|
|
195
|
+
|
|
189
196
|
this.roapHandler.submit({
|
|
190
|
-
type: ROAP.
|
|
191
|
-
|
|
192
|
-
correlationId:
|
|
197
|
+
type: ROAP.SEND_ROAP_MSG_SUCCESS,
|
|
198
|
+
seq: roapMessage.seq,
|
|
199
|
+
correlationId: meeting.correlationId
|
|
193
200
|
});
|
|
194
201
|
});
|
|
195
202
|
}
|
package/src/roap/state.js
CHANGED
|
@@ -25,6 +25,8 @@ const shouldStep = (roap, meeting) => {
|
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
const handleTransition = (value, signal, meeting) => {
|
|
28
|
+
LoggerProxy.logger.log(`Roap:state#handleTransition --> current ${value} to ${signal}`);
|
|
29
|
+
|
|
28
30
|
switch (value) {
|
|
29
31
|
case ROAP.ROAP_STATE.INIT:
|
|
30
32
|
if (signal === ROAP.ROAP_SIGNAL.RX_OFFER) {
|
|
@@ -186,6 +186,22 @@ describe('plugin-meetings', () => {
|
|
|
186
186
|
assert.calledWith(meeting.members.addMember, uuid1, false);
|
|
187
187
|
});
|
|
188
188
|
});
|
|
189
|
+
describe('#cancelPhoneInvite', () => {
|
|
190
|
+
it('should have #invite', () => {
|
|
191
|
+
assert.exists(meeting.cancelPhoneInvite);
|
|
192
|
+
});
|
|
193
|
+
beforeEach(() => {
|
|
194
|
+
meeting.members.cancelPhoneInvite = sinon.stub().returns(Promise.resolve(test1));
|
|
195
|
+
});
|
|
196
|
+
it('should proxy members #cancelPhoneInvite and return a promise', async () => {
|
|
197
|
+
const cancel = meeting.cancelPhoneInvite(uuid1);
|
|
198
|
+
|
|
199
|
+
assert.exists(cancel.then);
|
|
200
|
+
await cancel;
|
|
201
|
+
assert.calledOnce(meeting.members.cancelPhoneInvite);
|
|
202
|
+
assert.calledWith(meeting.members.cancelPhoneInvite, uuid1);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
189
205
|
describe('#admit', () => {
|
|
190
206
|
it('should have #admit', () => {
|
|
191
207
|
assert.exists(meeting.admit);
|