@wazo/sdk 0.37.22 → 0.37.26
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/wazo-sdk.js +5 -5
- package/esm/__tests__/api-client.test.js +37 -6
- package/esm/__tests__/web-rtc-client.test.js +78 -68
- package/esm/api/call-logd.js +7 -0
- package/esm/api/calld.js +10 -0
- package/esm/api/chatd.js +7 -0
- package/esm/api/confd.js +13 -5
- package/esm/api/ctid-ng.js +10 -0
- package/esm/api/dird.js +4 -1
- package/esm/api-client.js +37 -6
- package/esm/checker/Checker.js +78 -68
- package/esm/checker/checks/aor.js +37 -6
- package/esm/checker/checks/api.js +37 -6
- package/esm/checker/checks/index.js +78 -68
- package/esm/checker/checks/webrtc-transport.js +78 -68
- package/esm/checker/checks/webrtc.js +78 -68
- package/esm/domain/AdHocAPIConference.js +37 -6
- package/esm/domain/Call.js +3 -0
- package/esm/domain/CallLog.js +7 -0
- package/esm/domain/ChatMessage.js +4 -0
- package/esm/domain/ChatRoom.js +3 -0
- package/esm/domain/Contact.js +4 -1
- package/esm/domain/Features.js +37 -6
- package/esm/domain/Meeting.js +15 -5
- package/esm/domain/Phone/CTIPhone.js +41 -6
- package/esm/domain/Phone/WebRTCPhone.js +41 -15
- package/esm/domain/Recording.js +3 -0
- package/esm/domain/Voicemail.js +3 -0
- package/esm/domain/__tests__/Call.test.js +3 -0
- package/esm/domain/__tests__/CallLog.test.js +7 -0
- package/esm/domain/__tests__/Contact.test.js +4 -1
- package/esm/domain/__tests__/Meeting.test.js +144 -0
- package/esm/domain/__tests__/Voicemail.test.js +3 -0
- package/esm/index.js +122 -82
- package/esm/lib/WazoSessionDescriptionHandler.js +0 -38
- package/esm/service/CallApi.js +37 -6
- package/esm/service/getApiClient.js +37 -6
- package/esm/simple/Auth.js +122 -82
- package/esm/simple/Configuration.js +122 -82
- package/esm/simple/Directory.js +37 -6
- package/esm/simple/Phone.js +122 -82
- package/esm/simple/index.js +122 -82
- package/esm/simple/room/LocalParticipant.js +122 -82
- package/esm/simple/room/Participant.js +122 -82
- package/esm/simple/room/RemoteParticipant.js +122 -82
- package/esm/simple/room/Room.js +122 -82
- package/esm/simple/room/SipRoom.js +122 -82
- package/esm/simple/room/Stream.js +122 -82
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +122 -82
- package/esm/simple/utils.js +122 -82
- package/esm/types/WebSocketMessage.js +1 -1
- package/esm/web-rtc-client.js +78 -68
- package/lib/__tests__/api-client.test.js +37 -6
- package/lib/__tests__/web-rtc-client.test.js +78 -68
- package/lib/api/call-logd.js +7 -0
- package/lib/api/calld.js +10 -0
- package/lib/api/chatd.js +7 -0
- package/lib/api/confd.js +13 -5
- package/lib/api/ctid-ng.js +10 -0
- package/lib/api/dird.js +4 -1
- package/lib/api-client.js +37 -6
- package/lib/checker/Checker.js +78 -68
- package/lib/checker/checks/aor.js +37 -6
- package/lib/checker/checks/api.js +37 -6
- package/lib/checker/checks/index.js +78 -68
- package/lib/checker/checks/webrtc-transport.js +78 -68
- package/lib/checker/checks/webrtc.js +78 -68
- package/lib/domain/AdHocAPIConference.js +37 -6
- package/lib/domain/Call.js +3 -0
- package/lib/domain/CallLog.js +7 -0
- package/lib/domain/ChatMessage.js +4 -0
- package/lib/domain/ChatRoom.js +3 -0
- package/lib/domain/Contact.js +4 -1
- package/lib/domain/Features.js +37 -6
- package/lib/domain/Meeting.js +19 -5
- package/lib/domain/Phone/CTIPhone.js +41 -6
- package/lib/domain/Phone/WebRTCPhone.js +41 -15
- package/lib/domain/Recording.js +3 -0
- package/lib/domain/Voicemail.js +3 -0
- package/lib/domain/__tests__/Call.test.js +3 -0
- package/lib/domain/__tests__/CallLog.test.js +7 -0
- package/lib/domain/__tests__/Contact.test.js +4 -1
- package/lib/domain/__tests__/Meeting.test.js +150 -0
- package/lib/domain/__tests__/Voicemail.test.js +3 -0
- package/lib/index.js +122 -82
- package/lib/lib/WazoSessionDescriptionHandler.js +0 -38
- package/lib/service/CallApi.js +37 -6
- package/lib/service/getApiClient.js +37 -6
- package/lib/simple/Auth.js +122 -82
- package/lib/simple/Configuration.js +122 -82
- package/lib/simple/Directory.js +37 -6
- package/lib/simple/Phone.js +122 -82
- package/lib/simple/index.js +122 -82
- package/lib/simple/room/LocalParticipant.js +122 -82
- package/lib/simple/room/Participant.js +122 -82
- package/lib/simple/room/RemoteParticipant.js +122 -82
- package/lib/simple/room/Room.js +122 -82
- package/lib/simple/room/SipRoom.js +122 -82
- package/lib/simple/room/Stream.js +122 -82
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +122 -82
- package/lib/simple/utils.js +122 -82
- package/lib/types/WebSocketMessage.js +2 -0
- package/lib/web-rtc-client.js +78 -68
- package/package.json +1 -1
- package/src/domain/Call.js +3 -0
- package/src/domain/CallLog.js +4 -0
- package/src/domain/ChatMessage.js +4 -0
- package/src/domain/ChatRoom.js +3 -0
- package/src/domain/Contact.js +4 -1
- package/src/domain/Meeting.js +15 -5
- package/src/domain/Phone/CTIPhone.js +4 -0
- package/src/domain/Phone/Phone.js +2 -0
- package/src/domain/Phone/WebRTCPhone.js +41 -15
- package/src/domain/Recording.js +3 -0
- package/src/domain/Voicemail.js +3 -0
- package/src/domain/__tests__/Meeting.test.js +50 -0
- package/src/lib/WazoSessionDescriptionHandler.js +1 -35
- package/src/web-rtc-client.js +41 -24
|
@@ -724,10 +724,6 @@ const getSrflxOrRelay = (candidates ) =>
|
|
|
724
724
|
candidates
|
|
725
725
|
.filter(candidate => candidate && (candidate.type === 'srflx' || candidate.type === 'relay'));
|
|
726
726
|
|
|
727
|
-
const areCandidateValid = (candidates ) =>
|
|
728
|
-
getSrflxOrRelay(candidates)
|
|
729
|
-
.length > 0;
|
|
730
|
-
|
|
731
727
|
const getVideoDirection = (sdp ) => {
|
|
732
728
|
const parsedSdp = sdpParser.parse(sdp);
|
|
733
729
|
const videoMedia = parsedSdp.media.find(media => media.type === 'video');
|
|
@@ -780,8 +776,6 @@ const fixSdp = (sdp , candidates , forcePort = true)
|
|
|
780
776
|
/* global RTCSessionDescriptionInit, navigator */
|
|
781
777
|
|
|
782
778
|
const wazoLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-sdh') : console;
|
|
783
|
-
const MAX_WAIT_FOR_ICE_TRIES = 20;
|
|
784
|
-
const WAIT_FOR_ICE_TIMEOUT = 500;
|
|
785
779
|
|
|
786
780
|
// Customized mediaStreamFactory allowing to send screensharing stream directory when upgrading
|
|
787
781
|
const wazoMediaStreamFactory = (constraints ) => {
|
|
@@ -971,38 +965,6 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
971
965
|
this._peerConnection = undefined;
|
|
972
966
|
}
|
|
973
967
|
|
|
974
|
-
async _waitForValidGatheredIce() {
|
|
975
|
-
let tries = 0;
|
|
976
|
-
|
|
977
|
-
while (!areCandidateValid(this.gatheredCandidates) && tries < MAX_WAIT_FOR_ICE_TRIES) {
|
|
978
|
-
wazoLogger.trace('SessionDescriptionHandler._waitForValidGatheredIce, waiting for ice', {
|
|
979
|
-
tries,
|
|
980
|
-
max: MAX_WAIT_FOR_ICE_TRIES,
|
|
981
|
-
});
|
|
982
|
-
|
|
983
|
-
tries++;
|
|
984
|
-
|
|
985
|
-
// eslint-disable-next-line no-await-in-loop
|
|
986
|
-
await new Promise(resolve => setTimeout(resolve, WAIT_FOR_ICE_TIMEOUT));
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
if (tries >= MAX_WAIT_FOR_ICE_TRIES) {
|
|
990
|
-
const errorMsg = 'No valid candidates found, can\'t answer the call';
|
|
991
|
-
const error = new Error(errorMsg);
|
|
992
|
-
wazoLogger.error(errorMsg, { tries, max: MAX_WAIT_FOR_ICE_TRIES });
|
|
993
|
-
|
|
994
|
-
// Emit an error, because sip.js catches the exception and switch to status Terminated.
|
|
995
|
-
this.eventEmitter.emit('error', error);
|
|
996
|
-
|
|
997
|
-
wazoLogger.error('No valid candidates found', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
// eslint-disable-next-line
|
|
1001
|
-
wazoLogger.trace('Found valid candidates', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
|
|
1002
|
-
|
|
1003
|
-
return this.getLocalSessionDescription();
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
968
|
// Overridden to send `inactive` in conference
|
|
1007
969
|
updateDirection(options , isConference = false,
|
|
1008
970
|
audioOnly = false) {
|
|
@@ -2112,6 +2074,9 @@ class Contact {
|
|
|
2112
2074
|
}
|
|
2113
2075
|
|
|
2114
2076
|
static parseMany(response ) {
|
|
2077
|
+
if (!response || !response.results) {
|
|
2078
|
+
return [];
|
|
2079
|
+
}
|
|
2115
2080
|
return response.results.map(r => Contact.parse(r, response.column_types));
|
|
2116
2081
|
}
|
|
2117
2082
|
|
|
@@ -2482,7 +2447,7 @@ class Contact {
|
|
|
2482
2447
|
this[key] = old[key] || this[key];
|
|
2483
2448
|
});
|
|
2484
2449
|
|
|
2485
|
-
if (old.lineState
|
|
2450
|
+
if (old.lineState) {
|
|
2486
2451
|
this.lineState = old.lineState;
|
|
2487
2452
|
}
|
|
2488
2453
|
|
|
@@ -3189,8 +3154,9 @@ class ExternalApp {
|
|
|
3189
3154
|
|
|
3190
3155
|
|
|
3191
3156
|
|
|
3192
|
-
|
|
3157
|
+
|
|
3193
3158
|
|
|
3159
|
+
|
|
3194
3160
|
|
|
3195
3161
|
|
|
3196
3162
|
class Meeting {
|
|
@@ -3201,9 +3167,10 @@ class Meeting {
|
|
|
3201
3167
|
|
|
3202
3168
|
|
|
3203
3169
|
|
|
3204
|
-
|
|
3170
|
+
|
|
3205
3171
|
|
|
3206
3172
|
|
|
3173
|
+
|
|
3207
3174
|
|
|
3208
3175
|
static parse(plain ) {
|
|
3209
3176
|
return new Meeting({
|
|
@@ -3213,12 +3180,16 @@ class Meeting {
|
|
|
3213
3180
|
ownerUuids: plain.owner_uuids,
|
|
3214
3181
|
port: plain.port,
|
|
3215
3182
|
uuid: plain.uuid,
|
|
3216
|
-
|
|
3183
|
+
extension: plain.exten,
|
|
3217
3184
|
persistent: plain.persistent,
|
|
3185
|
+
creationTime: moment(plain.creation_time).toDate(),
|
|
3218
3186
|
});
|
|
3219
3187
|
}
|
|
3220
3188
|
|
|
3221
3189
|
static parseMany(items ) {
|
|
3190
|
+
if (!items) {
|
|
3191
|
+
return [];
|
|
3192
|
+
}
|
|
3222
3193
|
return items.map(plain => Meeting.parse(plain));
|
|
3223
3194
|
}
|
|
3224
3195
|
|
|
@@ -3233,8 +3204,9 @@ class Meeting {
|
|
|
3233
3204
|
ownerUuids,
|
|
3234
3205
|
port,
|
|
3235
3206
|
uri,
|
|
3236
|
-
|
|
3207
|
+
extension,
|
|
3237
3208
|
persistent,
|
|
3209
|
+
creationTime,
|
|
3238
3210
|
} = {}) {
|
|
3239
3211
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
3240
3212
|
this.uri = uri;
|
|
@@ -3242,8 +3214,9 @@ class Meeting {
|
|
|
3242
3214
|
this.ownerUuids = ownerUuids;
|
|
3243
3215
|
this.port = port;
|
|
3244
3216
|
this.uuid = uuid;
|
|
3245
|
-
this.
|
|
3217
|
+
this.extension = extension;
|
|
3246
3218
|
this.persistent = persistent;
|
|
3219
|
+
this.creationTime = creationTime;
|
|
3247
3220
|
|
|
3248
3221
|
// Useful to compare instead of instanceof with minified code
|
|
3249
3222
|
this.type = 'Meeting';
|
|
@@ -3421,6 +3394,10 @@ class ChatMessage {
|
|
|
3421
3394
|
|
|
3422
3395
|
|
|
3423
3396
|
static parseMany(plain ) {
|
|
3397
|
+
if (!plain || !plain.items) {
|
|
3398
|
+
return [];
|
|
3399
|
+
}
|
|
3400
|
+
|
|
3424
3401
|
return plain.items.map(item => ChatMessage.parse(item));
|
|
3425
3402
|
}
|
|
3426
3403
|
|
|
@@ -3530,6 +3507,9 @@ class Voicemail {
|
|
|
3530
3507
|
}
|
|
3531
3508
|
|
|
3532
3509
|
static parseMany(plain ) {
|
|
3510
|
+
if (!plain) {
|
|
3511
|
+
return [];
|
|
3512
|
+
}
|
|
3533
3513
|
const plainUnread = plain.folders.filter(folder => folder.type === 'new')[0].messages;
|
|
3534
3514
|
const plainRead = plain.folders.filter(folder => folder.type === 'old')[0].messages;
|
|
3535
3515
|
|
|
@@ -3639,6 +3619,9 @@ class Call {
|
|
|
3639
3619
|
|
|
3640
3620
|
|
|
3641
3621
|
static parseMany(plain ) {
|
|
3622
|
+
if (!plain) {
|
|
3623
|
+
return [];
|
|
3624
|
+
}
|
|
3642
3625
|
return plain.map((plainCall ) => Call.parse(plainCall));
|
|
3643
3626
|
}
|
|
3644
3627
|
|
|
@@ -3811,6 +3794,9 @@ class Recording {
|
|
|
3811
3794
|
|
|
3812
3795
|
|
|
3813
3796
|
static parseMany(recordings = []) {
|
|
3797
|
+
if (!recordings) {
|
|
3798
|
+
return [];
|
|
3799
|
+
}
|
|
3814
3800
|
return recordings.map(item => Recording.parse(item));
|
|
3815
3801
|
}
|
|
3816
3802
|
|
|
@@ -3912,6 +3898,10 @@ class CallLog {
|
|
|
3912
3898
|
}
|
|
3913
3899
|
|
|
3914
3900
|
static parseMany(plain ) {
|
|
3901
|
+
if (!plain || !plain.items) {
|
|
3902
|
+
return [];
|
|
3903
|
+
}
|
|
3904
|
+
|
|
3915
3905
|
return plain.items.map(item => CallLog.parse(item));
|
|
3916
3906
|
}
|
|
3917
3907
|
|
|
@@ -4484,6 +4474,9 @@ class ChatRoom {
|
|
|
4484
4474
|
|
|
4485
4475
|
|
|
4486
4476
|
static parseMany(plain ) {
|
|
4477
|
+
if (!plain || !plain.items) {
|
|
4478
|
+
return [];
|
|
4479
|
+
}
|
|
4487
4480
|
return plain.items.map(item => ChatRoom.parse(item));
|
|
4488
4481
|
}
|
|
4489
4482
|
|
|
@@ -5712,7 +5705,7 @@ class WebRTCClient extends Emitter {
|
|
|
5712
5705
|
}
|
|
5713
5706
|
|
|
5714
5707
|
call(number , enableVideo , audioOnly = false, conference = false) {
|
|
5715
|
-
logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
|
|
5708
|
+
logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
|
|
5716
5709
|
const inviterOptions = {
|
|
5717
5710
|
sessionDescriptionHandlerOptionsReInvite: {
|
|
5718
5711
|
conference,
|
|
@@ -6788,6 +6781,7 @@ class WebRTCClient extends Emitter {
|
|
|
6788
6781
|
const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
|
|
6789
6782
|
const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
|
|
6790
6783
|
const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
|
|
6784
|
+
const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
|
|
6791
6785
|
|
|
6792
6786
|
logger.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
|
|
6793
6787
|
|
|
@@ -6795,7 +6789,8 @@ class WebRTCClient extends Emitter {
|
|
|
6795
6789
|
constraints: {
|
|
6796
6790
|
// Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
|
|
6797
6791
|
audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
|
|
6798
|
-
video: screenSharing ? (isDesktop
|
|
6792
|
+
video: screenSharing ? (isDesktop
|
|
6793
|
+
? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
|
|
6799
6794
|
: this._getVideoConstraints(enableVideo),
|
|
6800
6795
|
screen: screenSharing,
|
|
6801
6796
|
desktop: isDesktop,
|
|
@@ -7130,12 +7125,14 @@ class WebRTCClient extends Emitter {
|
|
|
7130
7125
|
|
|
7131
7126
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
7132
7127
|
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7128
|
+
if (pc) {
|
|
7129
|
+
pc.oniceconnectionstatechange = () => {
|
|
7130
|
+
logger.info('on ice connection state changed', { state: pc.iceConnectionState });
|
|
7131
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
7132
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
7133
|
+
}
|
|
7134
|
+
};
|
|
7135
|
+
}
|
|
7139
7136
|
|
|
7140
7137
|
if (withEvent) {
|
|
7141
7138
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
@@ -7345,13 +7342,17 @@ class WebRTCClient extends Emitter {
|
|
|
7345
7342
|
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
7346
7343
|
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
7347
7344
|
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
7345
|
+
const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
|
|
7348
7346
|
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
7349
7347
|
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
7348
|
+
const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
|
|
7350
7349
|
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
7351
7350
|
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
7352
7351
|
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
7353
|
-
let audioBytesSent = 0;
|
|
7354
|
-
let audioBytesReceived = 0;
|
|
7352
|
+
let audioBytesSent = 0; // content + header
|
|
7353
|
+
let audioBytesReceived = 0; // content + header
|
|
7354
|
+
let audioContentSent = 0; // useful to detect blank call
|
|
7355
|
+
let audioContentReceived = 0;
|
|
7355
7356
|
let videoBytesSent = 0;
|
|
7356
7357
|
let videoBytesReceived = 0;
|
|
7357
7358
|
let transportSent = 0;
|
|
@@ -7360,25 +7361,27 @@ class WebRTCClient extends Emitter {
|
|
|
7360
7361
|
|
|
7361
7362
|
stats.forEach(report => {
|
|
7362
7363
|
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
7363
|
-
audioBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7364
|
+
audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
7365
|
+
audioContentSent += Number(report.bytesSent);
|
|
7364
7366
|
}
|
|
7365
7367
|
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
7366
|
-
audioBytesSent += report.bytesSent;
|
|
7368
|
+
audioBytesSent += Number(report.bytesSent);
|
|
7367
7369
|
}
|
|
7368
7370
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7369
|
-
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7371
|
+
videoBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
7370
7372
|
}
|
|
7371
7373
|
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
7372
|
-
packetsLost += report.packetsLost;
|
|
7373
|
-
networkStats.packetsReceived = report.packetsReceived;
|
|
7374
|
-
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7374
|
+
packetsLost += Number(report.packetsLost);
|
|
7375
|
+
networkStats.packetsReceived = Number(report.packetsReceived);
|
|
7376
|
+
audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
7377
|
+
audioContentReceived += Number(report.bytesReceived);
|
|
7375
7378
|
}
|
|
7376
7379
|
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
7377
|
-
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7380
|
+
videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
7378
7381
|
}
|
|
7379
7382
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7380
7383
|
if ('framesPerSecond' in report) {
|
|
7381
|
-
networkStats.framesPerSecond = report.framesPerSecond;
|
|
7384
|
+
networkStats.framesPerSecond = Number(report.framesPerSecond);
|
|
7382
7385
|
}
|
|
7383
7386
|
if ('framerateMean' in report) {
|
|
7384
7387
|
// framerateMean is only available in FF
|
|
@@ -7386,24 +7389,31 @@ class WebRTCClient extends Emitter {
|
|
|
7386
7389
|
}
|
|
7387
7390
|
}
|
|
7388
7391
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
7389
|
-
packetsLost += report.packetsLost;
|
|
7390
|
-
networkStats.roundTripTime = report.roundTripTime;
|
|
7391
|
-
networkStats.jitter = report.jitter;
|
|
7392
|
+
packetsLost += Number(report.packetsLost);
|
|
7393
|
+
networkStats.roundTripTime = Number(report.roundTripTime);
|
|
7394
|
+
networkStats.jitter = Number(report.jitter);
|
|
7392
7395
|
}
|
|
7393
7396
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
7394
|
-
packetsLost += report.packetsLost;
|
|
7397
|
+
packetsLost += Number(report.packetsLost);
|
|
7395
7398
|
}
|
|
7396
7399
|
if (report.type === 'transport') {
|
|
7397
|
-
transportSent += report.bytesSent;
|
|
7398
|
-
transportReceived += report.bytesReceived;
|
|
7400
|
+
transportSent += Number(report.bytesSent);
|
|
7401
|
+
transportReceived += Number(report.bytesReceived);
|
|
7399
7402
|
}
|
|
7400
7403
|
});
|
|
7401
7404
|
|
|
7402
7405
|
networkStats.packetsLost = packetsLost;
|
|
7406
|
+
|
|
7403
7407
|
networkStats.totalAudioBytesSent = audioBytesSent;
|
|
7404
7408
|
networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
|
|
7405
7409
|
networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
|
|
7406
7410
|
networkStats.audioBytesReceived = audioBytesReceived;
|
|
7411
|
+
|
|
7412
|
+
networkStats.totalAudioContentSent = audioContentSent;
|
|
7413
|
+
networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
|
|
7414
|
+
networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
|
|
7415
|
+
networkStats.audioContentReceived = audioContentReceived;
|
|
7416
|
+
|
|
7407
7417
|
networkStats.totalVideoBytesSent = videoBytesSent;
|
|
7408
7418
|
networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
|
|
7409
7419
|
networkStats.totalVideoBytesReceived = videoBytesReceived;
|
|
@@ -724,10 +724,6 @@ const getSrflxOrRelay = (candidates ) =>
|
|
|
724
724
|
candidates
|
|
725
725
|
.filter(candidate => candidate && (candidate.type === 'srflx' || candidate.type === 'relay'));
|
|
726
726
|
|
|
727
|
-
const areCandidateValid = (candidates ) =>
|
|
728
|
-
getSrflxOrRelay(candidates)
|
|
729
|
-
.length > 0;
|
|
730
|
-
|
|
731
727
|
const getVideoDirection = (sdp ) => {
|
|
732
728
|
const parsedSdp = sdpParser.parse(sdp);
|
|
733
729
|
const videoMedia = parsedSdp.media.find(media => media.type === 'video');
|
|
@@ -780,8 +776,6 @@ const fixSdp = (sdp , candidates , forcePort = true)
|
|
|
780
776
|
/* global RTCSessionDescriptionInit, navigator */
|
|
781
777
|
|
|
782
778
|
const wazoLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-sdh') : console;
|
|
783
|
-
const MAX_WAIT_FOR_ICE_TRIES = 20;
|
|
784
|
-
const WAIT_FOR_ICE_TIMEOUT = 500;
|
|
785
779
|
|
|
786
780
|
// Customized mediaStreamFactory allowing to send screensharing stream directory when upgrading
|
|
787
781
|
const wazoMediaStreamFactory = (constraints ) => {
|
|
@@ -971,38 +965,6 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
971
965
|
this._peerConnection = undefined;
|
|
972
966
|
}
|
|
973
967
|
|
|
974
|
-
async _waitForValidGatheredIce() {
|
|
975
|
-
let tries = 0;
|
|
976
|
-
|
|
977
|
-
while (!areCandidateValid(this.gatheredCandidates) && tries < MAX_WAIT_FOR_ICE_TRIES) {
|
|
978
|
-
wazoLogger.trace('SessionDescriptionHandler._waitForValidGatheredIce, waiting for ice', {
|
|
979
|
-
tries,
|
|
980
|
-
max: MAX_WAIT_FOR_ICE_TRIES,
|
|
981
|
-
});
|
|
982
|
-
|
|
983
|
-
tries++;
|
|
984
|
-
|
|
985
|
-
// eslint-disable-next-line no-await-in-loop
|
|
986
|
-
await new Promise(resolve => setTimeout(resolve, WAIT_FOR_ICE_TIMEOUT));
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
if (tries >= MAX_WAIT_FOR_ICE_TRIES) {
|
|
990
|
-
const errorMsg = 'No valid candidates found, can\'t answer the call';
|
|
991
|
-
const error = new Error(errorMsg);
|
|
992
|
-
wazoLogger.error(errorMsg, { tries, max: MAX_WAIT_FOR_ICE_TRIES });
|
|
993
|
-
|
|
994
|
-
// Emit an error, because sip.js catches the exception and switch to status Terminated.
|
|
995
|
-
this.eventEmitter.emit('error', error);
|
|
996
|
-
|
|
997
|
-
wazoLogger.error('No valid candidates found', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
// eslint-disable-next-line
|
|
1001
|
-
wazoLogger.trace('Found valid candidates', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
|
|
1002
|
-
|
|
1003
|
-
return this.getLocalSessionDescription();
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
968
|
// Overridden to send `inactive` in conference
|
|
1007
969
|
updateDirection(options , isConference = false,
|
|
1008
970
|
audioOnly = false) {
|
|
@@ -2112,6 +2074,9 @@ class Contact {
|
|
|
2112
2074
|
}
|
|
2113
2075
|
|
|
2114
2076
|
static parseMany(response ) {
|
|
2077
|
+
if (!response || !response.results) {
|
|
2078
|
+
return [];
|
|
2079
|
+
}
|
|
2115
2080
|
return response.results.map(r => Contact.parse(r, response.column_types));
|
|
2116
2081
|
}
|
|
2117
2082
|
|
|
@@ -2482,7 +2447,7 @@ class Contact {
|
|
|
2482
2447
|
this[key] = old[key] || this[key];
|
|
2483
2448
|
});
|
|
2484
2449
|
|
|
2485
|
-
if (old.lineState
|
|
2450
|
+
if (old.lineState) {
|
|
2486
2451
|
this.lineState = old.lineState;
|
|
2487
2452
|
}
|
|
2488
2453
|
|
|
@@ -3189,8 +3154,9 @@ class ExternalApp {
|
|
|
3189
3154
|
|
|
3190
3155
|
|
|
3191
3156
|
|
|
3192
|
-
|
|
3157
|
+
|
|
3193
3158
|
|
|
3159
|
+
|
|
3194
3160
|
|
|
3195
3161
|
|
|
3196
3162
|
class Meeting {
|
|
@@ -3201,9 +3167,10 @@ class Meeting {
|
|
|
3201
3167
|
|
|
3202
3168
|
|
|
3203
3169
|
|
|
3204
|
-
|
|
3170
|
+
|
|
3205
3171
|
|
|
3206
3172
|
|
|
3173
|
+
|
|
3207
3174
|
|
|
3208
3175
|
static parse(plain ) {
|
|
3209
3176
|
return new Meeting({
|
|
@@ -3213,12 +3180,16 @@ class Meeting {
|
|
|
3213
3180
|
ownerUuids: plain.owner_uuids,
|
|
3214
3181
|
port: plain.port,
|
|
3215
3182
|
uuid: plain.uuid,
|
|
3216
|
-
|
|
3183
|
+
extension: plain.exten,
|
|
3217
3184
|
persistent: plain.persistent,
|
|
3185
|
+
creationTime: moment(plain.creation_time).toDate(),
|
|
3218
3186
|
});
|
|
3219
3187
|
}
|
|
3220
3188
|
|
|
3221
3189
|
static parseMany(items ) {
|
|
3190
|
+
if (!items) {
|
|
3191
|
+
return [];
|
|
3192
|
+
}
|
|
3222
3193
|
return items.map(plain => Meeting.parse(plain));
|
|
3223
3194
|
}
|
|
3224
3195
|
|
|
@@ -3233,8 +3204,9 @@ class Meeting {
|
|
|
3233
3204
|
ownerUuids,
|
|
3234
3205
|
port,
|
|
3235
3206
|
uri,
|
|
3236
|
-
|
|
3207
|
+
extension,
|
|
3237
3208
|
persistent,
|
|
3209
|
+
creationTime,
|
|
3238
3210
|
} = {}) {
|
|
3239
3211
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
3240
3212
|
this.uri = uri;
|
|
@@ -3242,8 +3214,9 @@ class Meeting {
|
|
|
3242
3214
|
this.ownerUuids = ownerUuids;
|
|
3243
3215
|
this.port = port;
|
|
3244
3216
|
this.uuid = uuid;
|
|
3245
|
-
this.
|
|
3217
|
+
this.extension = extension;
|
|
3246
3218
|
this.persistent = persistent;
|
|
3219
|
+
this.creationTime = creationTime;
|
|
3247
3220
|
|
|
3248
3221
|
// Useful to compare instead of instanceof with minified code
|
|
3249
3222
|
this.type = 'Meeting';
|
|
@@ -3421,6 +3394,10 @@ class ChatMessage {
|
|
|
3421
3394
|
|
|
3422
3395
|
|
|
3423
3396
|
static parseMany(plain ) {
|
|
3397
|
+
if (!plain || !plain.items) {
|
|
3398
|
+
return [];
|
|
3399
|
+
}
|
|
3400
|
+
|
|
3424
3401
|
return plain.items.map(item => ChatMessage.parse(item));
|
|
3425
3402
|
}
|
|
3426
3403
|
|
|
@@ -3530,6 +3507,9 @@ class Voicemail {
|
|
|
3530
3507
|
}
|
|
3531
3508
|
|
|
3532
3509
|
static parseMany(plain ) {
|
|
3510
|
+
if (!plain) {
|
|
3511
|
+
return [];
|
|
3512
|
+
}
|
|
3533
3513
|
const plainUnread = plain.folders.filter(folder => folder.type === 'new')[0].messages;
|
|
3534
3514
|
const plainRead = plain.folders.filter(folder => folder.type === 'old')[0].messages;
|
|
3535
3515
|
|
|
@@ -3639,6 +3619,9 @@ class Call {
|
|
|
3639
3619
|
|
|
3640
3620
|
|
|
3641
3621
|
static parseMany(plain ) {
|
|
3622
|
+
if (!plain) {
|
|
3623
|
+
return [];
|
|
3624
|
+
}
|
|
3642
3625
|
return plain.map((plainCall ) => Call.parse(plainCall));
|
|
3643
3626
|
}
|
|
3644
3627
|
|
|
@@ -3811,6 +3794,9 @@ class Recording {
|
|
|
3811
3794
|
|
|
3812
3795
|
|
|
3813
3796
|
static parseMany(recordings = []) {
|
|
3797
|
+
if (!recordings) {
|
|
3798
|
+
return [];
|
|
3799
|
+
}
|
|
3814
3800
|
return recordings.map(item => Recording.parse(item));
|
|
3815
3801
|
}
|
|
3816
3802
|
|
|
@@ -3912,6 +3898,10 @@ class CallLog {
|
|
|
3912
3898
|
}
|
|
3913
3899
|
|
|
3914
3900
|
static parseMany(plain ) {
|
|
3901
|
+
if (!plain || !plain.items) {
|
|
3902
|
+
return [];
|
|
3903
|
+
}
|
|
3904
|
+
|
|
3915
3905
|
return plain.items.map(item => CallLog.parse(item));
|
|
3916
3906
|
}
|
|
3917
3907
|
|
|
@@ -4484,6 +4474,9 @@ class ChatRoom {
|
|
|
4484
4474
|
|
|
4485
4475
|
|
|
4486
4476
|
static parseMany(plain ) {
|
|
4477
|
+
if (!plain || !plain.items) {
|
|
4478
|
+
return [];
|
|
4479
|
+
}
|
|
4487
4480
|
return plain.items.map(item => ChatRoom.parse(item));
|
|
4488
4481
|
}
|
|
4489
4482
|
|
|
@@ -5712,7 +5705,7 @@ class WebRTCClient extends Emitter {
|
|
|
5712
5705
|
}
|
|
5713
5706
|
|
|
5714
5707
|
call(number , enableVideo , audioOnly = false, conference = false) {
|
|
5715
|
-
logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
|
|
5708
|
+
logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
|
|
5716
5709
|
const inviterOptions = {
|
|
5717
5710
|
sessionDescriptionHandlerOptionsReInvite: {
|
|
5718
5711
|
conference,
|
|
@@ -6788,6 +6781,7 @@ class WebRTCClient extends Emitter {
|
|
|
6788
6781
|
const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
|
|
6789
6782
|
const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
|
|
6790
6783
|
const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
|
|
6784
|
+
const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
|
|
6791
6785
|
|
|
6792
6786
|
logger.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
|
|
6793
6787
|
|
|
@@ -6795,7 +6789,8 @@ class WebRTCClient extends Emitter {
|
|
|
6795
6789
|
constraints: {
|
|
6796
6790
|
// Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
|
|
6797
6791
|
audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
|
|
6798
|
-
video: screenSharing ? (isDesktop
|
|
6792
|
+
video: screenSharing ? (isDesktop
|
|
6793
|
+
? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
|
|
6799
6794
|
: this._getVideoConstraints(enableVideo),
|
|
6800
6795
|
screen: screenSharing,
|
|
6801
6796
|
desktop: isDesktop,
|
|
@@ -7130,12 +7125,14 @@ class WebRTCClient extends Emitter {
|
|
|
7130
7125
|
|
|
7131
7126
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
7132
7127
|
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7128
|
+
if (pc) {
|
|
7129
|
+
pc.oniceconnectionstatechange = () => {
|
|
7130
|
+
logger.info('on ice connection state changed', { state: pc.iceConnectionState });
|
|
7131
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
7132
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
7133
|
+
}
|
|
7134
|
+
};
|
|
7135
|
+
}
|
|
7139
7136
|
|
|
7140
7137
|
if (withEvent) {
|
|
7141
7138
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
@@ -7345,13 +7342,17 @@ class WebRTCClient extends Emitter {
|
|
|
7345
7342
|
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
7346
7343
|
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
7347
7344
|
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
7345
|
+
const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
|
|
7348
7346
|
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
7349
7347
|
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
7348
|
+
const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
|
|
7350
7349
|
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
7351
7350
|
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
7352
7351
|
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
7353
|
-
let audioBytesSent = 0;
|
|
7354
|
-
let audioBytesReceived = 0;
|
|
7352
|
+
let audioBytesSent = 0; // content + header
|
|
7353
|
+
let audioBytesReceived = 0; // content + header
|
|
7354
|
+
let audioContentSent = 0; // useful to detect blank call
|
|
7355
|
+
let audioContentReceived = 0;
|
|
7355
7356
|
let videoBytesSent = 0;
|
|
7356
7357
|
let videoBytesReceived = 0;
|
|
7357
7358
|
let transportSent = 0;
|
|
@@ -7360,25 +7361,27 @@ class WebRTCClient extends Emitter {
|
|
|
7360
7361
|
|
|
7361
7362
|
stats.forEach(report => {
|
|
7362
7363
|
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
7363
|
-
audioBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7364
|
+
audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
7365
|
+
audioContentSent += Number(report.bytesSent);
|
|
7364
7366
|
}
|
|
7365
7367
|
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
7366
|
-
audioBytesSent += report.bytesSent;
|
|
7368
|
+
audioBytesSent += Number(report.bytesSent);
|
|
7367
7369
|
}
|
|
7368
7370
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7369
|
-
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7371
|
+
videoBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
7370
7372
|
}
|
|
7371
7373
|
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
7372
|
-
packetsLost += report.packetsLost;
|
|
7373
|
-
networkStats.packetsReceived = report.packetsReceived;
|
|
7374
|
-
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7374
|
+
packetsLost += Number(report.packetsLost);
|
|
7375
|
+
networkStats.packetsReceived = Number(report.packetsReceived);
|
|
7376
|
+
audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
7377
|
+
audioContentReceived += Number(report.bytesReceived);
|
|
7375
7378
|
}
|
|
7376
7379
|
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
7377
|
-
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7380
|
+
videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
7378
7381
|
}
|
|
7379
7382
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7380
7383
|
if ('framesPerSecond' in report) {
|
|
7381
|
-
networkStats.framesPerSecond = report.framesPerSecond;
|
|
7384
|
+
networkStats.framesPerSecond = Number(report.framesPerSecond);
|
|
7382
7385
|
}
|
|
7383
7386
|
if ('framerateMean' in report) {
|
|
7384
7387
|
// framerateMean is only available in FF
|
|
@@ -7386,24 +7389,31 @@ class WebRTCClient extends Emitter {
|
|
|
7386
7389
|
}
|
|
7387
7390
|
}
|
|
7388
7391
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
7389
|
-
packetsLost += report.packetsLost;
|
|
7390
|
-
networkStats.roundTripTime = report.roundTripTime;
|
|
7391
|
-
networkStats.jitter = report.jitter;
|
|
7392
|
+
packetsLost += Number(report.packetsLost);
|
|
7393
|
+
networkStats.roundTripTime = Number(report.roundTripTime);
|
|
7394
|
+
networkStats.jitter = Number(report.jitter);
|
|
7392
7395
|
}
|
|
7393
7396
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
7394
|
-
packetsLost += report.packetsLost;
|
|
7397
|
+
packetsLost += Number(report.packetsLost);
|
|
7395
7398
|
}
|
|
7396
7399
|
if (report.type === 'transport') {
|
|
7397
|
-
transportSent += report.bytesSent;
|
|
7398
|
-
transportReceived += report.bytesReceived;
|
|
7400
|
+
transportSent += Number(report.bytesSent);
|
|
7401
|
+
transportReceived += Number(report.bytesReceived);
|
|
7399
7402
|
}
|
|
7400
7403
|
});
|
|
7401
7404
|
|
|
7402
7405
|
networkStats.packetsLost = packetsLost;
|
|
7406
|
+
|
|
7403
7407
|
networkStats.totalAudioBytesSent = audioBytesSent;
|
|
7404
7408
|
networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
|
|
7405
7409
|
networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
|
|
7406
7410
|
networkStats.audioBytesReceived = audioBytesReceived;
|
|
7411
|
+
|
|
7412
|
+
networkStats.totalAudioContentSent = audioContentSent;
|
|
7413
|
+
networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
|
|
7414
|
+
networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
|
|
7415
|
+
networkStats.audioContentReceived = audioContentReceived;
|
|
7416
|
+
|
|
7407
7417
|
networkStats.totalVideoBytesSent = videoBytesSent;
|
|
7408
7418
|
networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
|
|
7409
7419
|
networkStats.totalVideoBytesReceived = videoBytesReceived;
|