@wazo/sdk 0.37.21 → 0.37.25
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 +36 -5
- package/esm/__tests__/web-rtc-client.test.js +77 -66
- 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 +3 -0
- package/esm/api-client.js +36 -5
- package/esm/checker/Checker.js +77 -66
- package/esm/checker/checks/aor.js +36 -5
- package/esm/checker/checks/api.js +36 -5
- package/esm/checker/checks/index.js +77 -66
- package/esm/checker/checks/webrtc-transport.js +77 -66
- package/esm/checker/checks/webrtc.js +77 -66
- package/esm/domain/AdHocAPIConference.js +36 -5
- 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 +3 -0
- package/esm/domain/Features.js +36 -5
- package/esm/domain/Meeting.js +15 -5
- package/esm/domain/Phone/CTIPhone.js +40 -5
- package/esm/domain/Phone/WebRTCPhone.js +45 -16
- 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 +3 -0
- package/esm/domain/__tests__/Meeting.test.js +144 -0
- package/esm/domain/__tests__/Voicemail.test.js +3 -0
- package/esm/index.js +125 -81
- package/esm/lib/WazoSessionDescriptionHandler.js +0 -38
- package/esm/service/CallApi.js +36 -5
- package/esm/service/getApiClient.js +36 -5
- package/esm/simple/Auth.js +125 -81
- package/esm/simple/Configuration.js +125 -81
- package/esm/simple/Directory.js +36 -5
- package/esm/simple/Phone.js +125 -81
- package/esm/simple/index.js +125 -81
- package/esm/simple/room/LocalParticipant.js +125 -81
- package/esm/simple/room/Participant.js +125 -81
- package/esm/simple/room/RemoteParticipant.js +125 -81
- package/esm/simple/room/Room.js +125 -81
- package/esm/simple/room/SipRoom.js +125 -81
- package/esm/simple/room/Stream.js +125 -81
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +125 -81
- package/esm/simple/utils.js +125 -81
- package/esm/types/WebSocketMessage.js +1 -1
- package/esm/web-rtc-client.js +77 -66
- package/lib/__tests__/api-client.test.js +36 -5
- package/lib/__tests__/web-rtc-client.test.js +77 -66
- 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 +3 -0
- package/lib/api-client.js +36 -5
- package/lib/checker/Checker.js +77 -66
- package/lib/checker/checks/aor.js +36 -5
- package/lib/checker/checks/api.js +36 -5
- package/lib/checker/checks/index.js +77 -66
- package/lib/checker/checks/webrtc-transport.js +77 -66
- package/lib/checker/checks/webrtc.js +77 -66
- package/lib/domain/AdHocAPIConference.js +36 -5
- 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 +3 -0
- package/lib/domain/Features.js +36 -5
- package/lib/domain/Meeting.js +19 -5
- package/lib/domain/Phone/CTIPhone.js +40 -5
- package/lib/domain/Phone/WebRTCPhone.js +45 -16
- 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 +3 -0
- package/lib/domain/__tests__/Meeting.test.js +150 -0
- package/lib/domain/__tests__/Voicemail.test.js +3 -0
- package/lib/index.js +125 -81
- package/lib/lib/WazoSessionDescriptionHandler.js +0 -38
- package/lib/service/CallApi.js +36 -5
- package/lib/service/getApiClient.js +36 -5
- package/lib/simple/Auth.js +125 -81
- package/lib/simple/Configuration.js +125 -81
- package/lib/simple/Directory.js +36 -5
- package/lib/simple/Phone.js +125 -81
- package/lib/simple/index.js +125 -81
- package/lib/simple/room/LocalParticipant.js +125 -81
- package/lib/simple/room/Participant.js +125 -81
- package/lib/simple/room/RemoteParticipant.js +125 -81
- package/lib/simple/room/Room.js +125 -81
- package/lib/simple/room/SipRoom.js +125 -81
- package/lib/simple/room/Stream.js +125 -81
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +125 -81
- package/lib/simple/utils.js +125 -81
- package/lib/types/WebSocketMessage.js +2 -0
- package/lib/web-rtc-client.js +77 -66
- 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 +3 -0
- 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 +45 -16
- 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 -23
|
@@ -1559,6 +1559,9 @@ class Contact {
|
|
|
1559
1559
|
}
|
|
1560
1560
|
|
|
1561
1561
|
static parseMany(response ) {
|
|
1562
|
+
if (!response || !response.results) {
|
|
1563
|
+
return [];
|
|
1564
|
+
}
|
|
1562
1565
|
return response.results.map(r => Contact.parse(r, response.column_types));
|
|
1563
1566
|
}
|
|
1564
1567
|
|
|
@@ -2636,8 +2639,9 @@ class ExternalApp {
|
|
|
2636
2639
|
|
|
2637
2640
|
|
|
2638
2641
|
|
|
2639
|
-
|
|
2642
|
+
|
|
2640
2643
|
|
|
2644
|
+
|
|
2641
2645
|
|
|
2642
2646
|
|
|
2643
2647
|
class Meeting {
|
|
@@ -2648,9 +2652,10 @@ class Meeting {
|
|
|
2648
2652
|
|
|
2649
2653
|
|
|
2650
2654
|
|
|
2651
|
-
|
|
2655
|
+
|
|
2652
2656
|
|
|
2653
2657
|
|
|
2658
|
+
|
|
2654
2659
|
|
|
2655
2660
|
static parse(plain ) {
|
|
2656
2661
|
return new Meeting({
|
|
@@ -2660,12 +2665,16 @@ class Meeting {
|
|
|
2660
2665
|
ownerUuids: plain.owner_uuids,
|
|
2661
2666
|
port: plain.port,
|
|
2662
2667
|
uuid: plain.uuid,
|
|
2663
|
-
|
|
2668
|
+
extension: plain.exten,
|
|
2664
2669
|
persistent: plain.persistent,
|
|
2670
|
+
creationTime: moment__default['default'](plain.creation_time).toDate(),
|
|
2665
2671
|
});
|
|
2666
2672
|
}
|
|
2667
2673
|
|
|
2668
2674
|
static parseMany(items ) {
|
|
2675
|
+
if (!items) {
|
|
2676
|
+
return [];
|
|
2677
|
+
}
|
|
2669
2678
|
return items.map(plain => Meeting.parse(plain));
|
|
2670
2679
|
}
|
|
2671
2680
|
|
|
@@ -2680,8 +2689,9 @@ class Meeting {
|
|
|
2680
2689
|
ownerUuids,
|
|
2681
2690
|
port,
|
|
2682
2691
|
uri,
|
|
2683
|
-
|
|
2692
|
+
extension,
|
|
2684
2693
|
persistent,
|
|
2694
|
+
creationTime,
|
|
2685
2695
|
} = {}) {
|
|
2686
2696
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2687
2697
|
this.uri = uri;
|
|
@@ -2689,8 +2699,9 @@ class Meeting {
|
|
|
2689
2699
|
this.ownerUuids = ownerUuids;
|
|
2690
2700
|
this.port = port;
|
|
2691
2701
|
this.uuid = uuid;
|
|
2692
|
-
this.
|
|
2702
|
+
this.extension = extension;
|
|
2693
2703
|
this.persistent = persistent;
|
|
2704
|
+
this.creationTime = creationTime;
|
|
2694
2705
|
|
|
2695
2706
|
// Useful to compare instead of instanceof with minified code
|
|
2696
2707
|
this.type = 'Meeting';
|
|
@@ -2868,6 +2879,10 @@ class ChatMessage {
|
|
|
2868
2879
|
|
|
2869
2880
|
|
|
2870
2881
|
static parseMany(plain ) {
|
|
2882
|
+
if (!plain || !plain.items) {
|
|
2883
|
+
return [];
|
|
2884
|
+
}
|
|
2885
|
+
|
|
2871
2886
|
return plain.items.map(item => ChatMessage.parse(item));
|
|
2872
2887
|
}
|
|
2873
2888
|
|
|
@@ -2977,6 +2992,9 @@ class Voicemail {
|
|
|
2977
2992
|
}
|
|
2978
2993
|
|
|
2979
2994
|
static parseMany(plain ) {
|
|
2995
|
+
if (!plain) {
|
|
2996
|
+
return [];
|
|
2997
|
+
}
|
|
2980
2998
|
const plainUnread = plain.folders.filter(folder => folder.type === 'new')[0].messages;
|
|
2981
2999
|
const plainRead = plain.folders.filter(folder => folder.type === 'old')[0].messages;
|
|
2982
3000
|
|
|
@@ -3086,6 +3104,9 @@ class Call {
|
|
|
3086
3104
|
|
|
3087
3105
|
|
|
3088
3106
|
static parseMany(plain ) {
|
|
3107
|
+
if (!plain) {
|
|
3108
|
+
return [];
|
|
3109
|
+
}
|
|
3089
3110
|
return plain.map((plainCall ) => Call.parse(plainCall));
|
|
3090
3111
|
}
|
|
3091
3112
|
|
|
@@ -3284,6 +3305,9 @@ class Recording {
|
|
|
3284
3305
|
|
|
3285
3306
|
|
|
3286
3307
|
static parseMany(recordings = []) {
|
|
3308
|
+
if (!recordings) {
|
|
3309
|
+
return [];
|
|
3310
|
+
}
|
|
3287
3311
|
return recordings.map(item => Recording.parse(item));
|
|
3288
3312
|
}
|
|
3289
3313
|
|
|
@@ -3385,6 +3409,10 @@ class CallLog {
|
|
|
3385
3409
|
}
|
|
3386
3410
|
|
|
3387
3411
|
static parseMany(plain ) {
|
|
3412
|
+
if (!plain || !plain.items) {
|
|
3413
|
+
return [];
|
|
3414
|
+
}
|
|
3415
|
+
|
|
3388
3416
|
return plain.items.map(item => CallLog.parse(item));
|
|
3389
3417
|
}
|
|
3390
3418
|
|
|
@@ -3957,6 +3985,9 @@ class ChatRoom {
|
|
|
3957
3985
|
|
|
3958
3986
|
|
|
3959
3987
|
static parseMany(plain ) {
|
|
3988
|
+
if (!plain || !plain.items) {
|
|
3989
|
+
return [];
|
|
3990
|
+
}
|
|
3960
3991
|
return plain.items.map(item => ChatRoom.parse(item));
|
|
3961
3992
|
}
|
|
3962
3993
|
|
|
@@ -5359,10 +5390,6 @@ const getSrflxOrRelay = (candidates ) =>
|
|
|
5359
5390
|
candidates
|
|
5360
5391
|
.filter(candidate => candidate && (candidate.type === 'srflx' || candidate.type === 'relay'));
|
|
5361
5392
|
|
|
5362
|
-
const areCandidateValid = (candidates ) =>
|
|
5363
|
-
getSrflxOrRelay(candidates)
|
|
5364
|
-
.length > 0;
|
|
5365
|
-
|
|
5366
5393
|
const getVideoDirection = (sdp ) => {
|
|
5367
5394
|
const parsedSdp = sdpParser__default['default'].parse(sdp);
|
|
5368
5395
|
const videoMedia = parsedSdp.media.find(media => media.type === 'video');
|
|
@@ -5415,8 +5442,6 @@ const fixSdp = (sdp , candidates , forcePort = true)
|
|
|
5415
5442
|
/* global RTCSessionDescriptionInit, navigator */
|
|
5416
5443
|
|
|
5417
5444
|
const wazoLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-sdh') : console;
|
|
5418
|
-
const MAX_WAIT_FOR_ICE_TRIES = 20;
|
|
5419
|
-
const WAIT_FOR_ICE_TIMEOUT = 500;
|
|
5420
5445
|
|
|
5421
5446
|
// Customized mediaStreamFactory allowing to send screensharing stream directory when upgrading
|
|
5422
5447
|
const wazoMediaStreamFactory = (constraints ) => {
|
|
@@ -5606,38 +5631,6 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
5606
5631
|
this._peerConnection = undefined;
|
|
5607
5632
|
}
|
|
5608
5633
|
|
|
5609
|
-
async _waitForValidGatheredIce() {
|
|
5610
|
-
let tries = 0;
|
|
5611
|
-
|
|
5612
|
-
while (!areCandidateValid(this.gatheredCandidates) && tries < MAX_WAIT_FOR_ICE_TRIES) {
|
|
5613
|
-
wazoLogger.trace('SessionDescriptionHandler._waitForValidGatheredIce, waiting for ice', {
|
|
5614
|
-
tries,
|
|
5615
|
-
max: MAX_WAIT_FOR_ICE_TRIES,
|
|
5616
|
-
});
|
|
5617
|
-
|
|
5618
|
-
tries++;
|
|
5619
|
-
|
|
5620
|
-
// eslint-disable-next-line no-await-in-loop
|
|
5621
|
-
await new Promise(resolve => setTimeout(resolve, WAIT_FOR_ICE_TIMEOUT));
|
|
5622
|
-
}
|
|
5623
|
-
|
|
5624
|
-
if (tries >= MAX_WAIT_FOR_ICE_TRIES) {
|
|
5625
|
-
const errorMsg = 'No valid candidates found, can\'t answer the call';
|
|
5626
|
-
const error = new Error(errorMsg);
|
|
5627
|
-
wazoLogger.error(errorMsg, { tries, max: MAX_WAIT_FOR_ICE_TRIES });
|
|
5628
|
-
|
|
5629
|
-
// Emit an error, because sip.js catches the exception and switch to status Terminated.
|
|
5630
|
-
this.eventEmitter.emit('error', error);
|
|
5631
|
-
|
|
5632
|
-
wazoLogger.error('No valid candidates found', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
|
|
5633
|
-
}
|
|
5634
|
-
|
|
5635
|
-
// eslint-disable-next-line
|
|
5636
|
-
wazoLogger.trace('Found valid candidates', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
|
|
5637
|
-
|
|
5638
|
-
return this.getLocalSessionDescription();
|
|
5639
|
-
}
|
|
5640
|
-
|
|
5641
5634
|
// Overridden to send `inactive` in conference
|
|
5642
5635
|
updateDirection(options , isConference = false,
|
|
5643
5636
|
audioOnly = false) {
|
|
@@ -6307,7 +6300,7 @@ class WebRTCClient extends Emitter {
|
|
|
6307
6300
|
}
|
|
6308
6301
|
|
|
6309
6302
|
call(number , enableVideo , audioOnly = false, conference = false) {
|
|
6310
|
-
logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
|
|
6303
|
+
logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
|
|
6311
6304
|
const inviterOptions = {
|
|
6312
6305
|
sessionDescriptionHandlerOptionsReInvite: {
|
|
6313
6306
|
conference,
|
|
@@ -7383,6 +7376,7 @@ class WebRTCClient extends Emitter {
|
|
|
7383
7376
|
const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
|
|
7384
7377
|
const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
|
|
7385
7378
|
const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
|
|
7379
|
+
const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
|
|
7386
7380
|
|
|
7387
7381
|
logger.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
|
|
7388
7382
|
|
|
@@ -7390,7 +7384,8 @@ class WebRTCClient extends Emitter {
|
|
|
7390
7384
|
constraints: {
|
|
7391
7385
|
// Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
|
|
7392
7386
|
audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
|
|
7393
|
-
video: screenSharing ? (isDesktop
|
|
7387
|
+
video: screenSharing ? (isDesktop
|
|
7388
|
+
? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
|
|
7394
7389
|
: this._getVideoConstraints(enableVideo),
|
|
7395
7390
|
screen: screenSharing,
|
|
7396
7391
|
desktop: isDesktop,
|
|
@@ -7725,11 +7720,14 @@ class WebRTCClient extends Emitter {
|
|
|
7725
7720
|
|
|
7726
7721
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
7727
7722
|
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7723
|
+
if (pc) {
|
|
7724
|
+
pc.oniceconnectionstatechange = () => {
|
|
7725
|
+
logger.info('on ice connection state changed', { state: pc.iceConnectionState });
|
|
7726
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
7727
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
7728
|
+
}
|
|
7729
|
+
};
|
|
7730
|
+
}
|
|
7733
7731
|
|
|
7734
7732
|
if (withEvent) {
|
|
7735
7733
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
@@ -7939,13 +7937,17 @@ class WebRTCClient extends Emitter {
|
|
|
7939
7937
|
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
7940
7938
|
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
7941
7939
|
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
7940
|
+
const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
|
|
7942
7941
|
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
7943
7942
|
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
7943
|
+
const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
|
|
7944
7944
|
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
7945
7945
|
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
7946
7946
|
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
7947
|
-
let audioBytesSent = 0;
|
|
7948
|
-
let audioBytesReceived = 0;
|
|
7947
|
+
let audioBytesSent = 0; // content + header
|
|
7948
|
+
let audioBytesReceived = 0; // content + header
|
|
7949
|
+
let audioContentSent = 0; // useful to detect blank call
|
|
7950
|
+
let audioContentReceived = 0;
|
|
7949
7951
|
let videoBytesSent = 0;
|
|
7950
7952
|
let videoBytesReceived = 0;
|
|
7951
7953
|
let transportSent = 0;
|
|
@@ -7954,25 +7956,27 @@ class WebRTCClient extends Emitter {
|
|
|
7954
7956
|
|
|
7955
7957
|
stats.forEach(report => {
|
|
7956
7958
|
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
7957
|
-
audioBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7959
|
+
audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
7960
|
+
audioContentSent += Number(report.bytesSent);
|
|
7958
7961
|
}
|
|
7959
7962
|
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
7960
|
-
audioBytesSent += report.bytesSent;
|
|
7963
|
+
audioBytesSent += Number(report.bytesSent);
|
|
7961
7964
|
}
|
|
7962
7965
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7963
|
-
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7966
|
+
videoBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
7964
7967
|
}
|
|
7965
7968
|
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
7966
|
-
packetsLost += report.packetsLost;
|
|
7967
|
-
networkStats.packetsReceived = report.packetsReceived;
|
|
7968
|
-
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7969
|
+
packetsLost += Number(report.packetsLost);
|
|
7970
|
+
networkStats.packetsReceived = Number(report.packetsReceived);
|
|
7971
|
+
audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
7972
|
+
audioContentReceived += Number(report.bytesReceived);
|
|
7969
7973
|
}
|
|
7970
7974
|
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
7971
|
-
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7975
|
+
videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
7972
7976
|
}
|
|
7973
7977
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7974
7978
|
if ('framesPerSecond' in report) {
|
|
7975
|
-
networkStats.framesPerSecond = report.framesPerSecond;
|
|
7979
|
+
networkStats.framesPerSecond = Number(report.framesPerSecond);
|
|
7976
7980
|
}
|
|
7977
7981
|
if ('framerateMean' in report) {
|
|
7978
7982
|
// framerateMean is only available in FF
|
|
@@ -7980,24 +7984,31 @@ class WebRTCClient extends Emitter {
|
|
|
7980
7984
|
}
|
|
7981
7985
|
}
|
|
7982
7986
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
7983
|
-
packetsLost += report.packetsLost;
|
|
7984
|
-
networkStats.roundTripTime = report.roundTripTime;
|
|
7985
|
-
networkStats.jitter = report.jitter;
|
|
7987
|
+
packetsLost += Number(report.packetsLost);
|
|
7988
|
+
networkStats.roundTripTime = Number(report.roundTripTime);
|
|
7989
|
+
networkStats.jitter = Number(report.jitter);
|
|
7986
7990
|
}
|
|
7987
7991
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
7988
|
-
packetsLost += report.packetsLost;
|
|
7992
|
+
packetsLost += Number(report.packetsLost);
|
|
7989
7993
|
}
|
|
7990
7994
|
if (report.type === 'transport') {
|
|
7991
|
-
transportSent += report.bytesSent;
|
|
7992
|
-
transportReceived += report.bytesReceived;
|
|
7995
|
+
transportSent += Number(report.bytesSent);
|
|
7996
|
+
transportReceived += Number(report.bytesReceived);
|
|
7993
7997
|
}
|
|
7994
7998
|
});
|
|
7995
7999
|
|
|
7996
8000
|
networkStats.packetsLost = packetsLost;
|
|
8001
|
+
|
|
7997
8002
|
networkStats.totalAudioBytesSent = audioBytesSent;
|
|
7998
8003
|
networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
|
|
7999
8004
|
networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
|
|
8000
8005
|
networkStats.audioBytesReceived = audioBytesReceived;
|
|
8006
|
+
|
|
8007
|
+
networkStats.totalAudioContentSent = audioContentSent;
|
|
8008
|
+
networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
|
|
8009
|
+
networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
|
|
8010
|
+
networkStats.audioContentReceived = audioContentReceived;
|
|
8011
|
+
|
|
8001
8012
|
networkStats.totalVideoBytesSent = videoBytesSent;
|
|
8002
8013
|
networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
|
|
8003
8014
|
networkStats.totalVideoBytesReceived = videoBytesReceived;
|
|
@@ -733,10 +733,6 @@ const getSrflxOrRelay = (candidates ) =>
|
|
|
733
733
|
candidates
|
|
734
734
|
.filter(candidate => candidate && (candidate.type === 'srflx' || candidate.type === 'relay'));
|
|
735
735
|
|
|
736
|
-
const areCandidateValid = (candidates ) =>
|
|
737
|
-
getSrflxOrRelay(candidates)
|
|
738
|
-
.length > 0;
|
|
739
|
-
|
|
740
736
|
const getVideoDirection = (sdp ) => {
|
|
741
737
|
const parsedSdp = sdpParser__default['default'].parse(sdp);
|
|
742
738
|
const videoMedia = parsedSdp.media.find(media => media.type === 'video');
|
|
@@ -789,8 +785,6 @@ const fixSdp = (sdp , candidates , forcePort = true)
|
|
|
789
785
|
/* global RTCSessionDescriptionInit, navigator */
|
|
790
786
|
|
|
791
787
|
const wazoLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-sdh') : console;
|
|
792
|
-
const MAX_WAIT_FOR_ICE_TRIES = 20;
|
|
793
|
-
const WAIT_FOR_ICE_TIMEOUT = 500;
|
|
794
788
|
|
|
795
789
|
// Customized mediaStreamFactory allowing to send screensharing stream directory when upgrading
|
|
796
790
|
const wazoMediaStreamFactory = (constraints ) => {
|
|
@@ -980,38 +974,6 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
980
974
|
this._peerConnection = undefined;
|
|
981
975
|
}
|
|
982
976
|
|
|
983
|
-
async _waitForValidGatheredIce() {
|
|
984
|
-
let tries = 0;
|
|
985
|
-
|
|
986
|
-
while (!areCandidateValid(this.gatheredCandidates) && tries < MAX_WAIT_FOR_ICE_TRIES) {
|
|
987
|
-
wazoLogger.trace('SessionDescriptionHandler._waitForValidGatheredIce, waiting for ice', {
|
|
988
|
-
tries,
|
|
989
|
-
max: MAX_WAIT_FOR_ICE_TRIES,
|
|
990
|
-
});
|
|
991
|
-
|
|
992
|
-
tries++;
|
|
993
|
-
|
|
994
|
-
// eslint-disable-next-line no-await-in-loop
|
|
995
|
-
await new Promise(resolve => setTimeout(resolve, WAIT_FOR_ICE_TIMEOUT));
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
if (tries >= MAX_WAIT_FOR_ICE_TRIES) {
|
|
999
|
-
const errorMsg = 'No valid candidates found, can\'t answer the call';
|
|
1000
|
-
const error = new Error(errorMsg);
|
|
1001
|
-
wazoLogger.error(errorMsg, { tries, max: MAX_WAIT_FOR_ICE_TRIES });
|
|
1002
|
-
|
|
1003
|
-
// Emit an error, because sip.js catches the exception and switch to status Terminated.
|
|
1004
|
-
this.eventEmitter.emit('error', error);
|
|
1005
|
-
|
|
1006
|
-
wazoLogger.error('No valid candidates found', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
// eslint-disable-next-line
|
|
1010
|
-
wazoLogger.trace('Found valid candidates', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
|
|
1011
|
-
|
|
1012
|
-
return this.getLocalSessionDescription();
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
977
|
// Overridden to send `inactive` in conference
|
|
1016
978
|
updateDirection(options , isConference = false,
|
|
1017
979
|
audioOnly = false) {
|
|
@@ -2121,6 +2083,9 @@ class Contact {
|
|
|
2121
2083
|
}
|
|
2122
2084
|
|
|
2123
2085
|
static parseMany(response ) {
|
|
2086
|
+
if (!response || !response.results) {
|
|
2087
|
+
return [];
|
|
2088
|
+
}
|
|
2124
2089
|
return response.results.map(r => Contact.parse(r, response.column_types));
|
|
2125
2090
|
}
|
|
2126
2091
|
|
|
@@ -3198,8 +3163,9 @@ class ExternalApp {
|
|
|
3198
3163
|
|
|
3199
3164
|
|
|
3200
3165
|
|
|
3201
|
-
|
|
3166
|
+
|
|
3202
3167
|
|
|
3168
|
+
|
|
3203
3169
|
|
|
3204
3170
|
|
|
3205
3171
|
class Meeting {
|
|
@@ -3210,9 +3176,10 @@ class Meeting {
|
|
|
3210
3176
|
|
|
3211
3177
|
|
|
3212
3178
|
|
|
3213
|
-
|
|
3179
|
+
|
|
3214
3180
|
|
|
3215
3181
|
|
|
3182
|
+
|
|
3216
3183
|
|
|
3217
3184
|
static parse(plain ) {
|
|
3218
3185
|
return new Meeting({
|
|
@@ -3222,12 +3189,16 @@ class Meeting {
|
|
|
3222
3189
|
ownerUuids: plain.owner_uuids,
|
|
3223
3190
|
port: plain.port,
|
|
3224
3191
|
uuid: plain.uuid,
|
|
3225
|
-
|
|
3192
|
+
extension: plain.exten,
|
|
3226
3193
|
persistent: plain.persistent,
|
|
3194
|
+
creationTime: moment__default['default'](plain.creation_time).toDate(),
|
|
3227
3195
|
});
|
|
3228
3196
|
}
|
|
3229
3197
|
|
|
3230
3198
|
static parseMany(items ) {
|
|
3199
|
+
if (!items) {
|
|
3200
|
+
return [];
|
|
3201
|
+
}
|
|
3231
3202
|
return items.map(plain => Meeting.parse(plain));
|
|
3232
3203
|
}
|
|
3233
3204
|
|
|
@@ -3242,8 +3213,9 @@ class Meeting {
|
|
|
3242
3213
|
ownerUuids,
|
|
3243
3214
|
port,
|
|
3244
3215
|
uri,
|
|
3245
|
-
|
|
3216
|
+
extension,
|
|
3246
3217
|
persistent,
|
|
3218
|
+
creationTime,
|
|
3247
3219
|
} = {}) {
|
|
3248
3220
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
3249
3221
|
this.uri = uri;
|
|
@@ -3251,8 +3223,9 @@ class Meeting {
|
|
|
3251
3223
|
this.ownerUuids = ownerUuids;
|
|
3252
3224
|
this.port = port;
|
|
3253
3225
|
this.uuid = uuid;
|
|
3254
|
-
this.
|
|
3226
|
+
this.extension = extension;
|
|
3255
3227
|
this.persistent = persistent;
|
|
3228
|
+
this.creationTime = creationTime;
|
|
3256
3229
|
|
|
3257
3230
|
// Useful to compare instead of instanceof with minified code
|
|
3258
3231
|
this.type = 'Meeting';
|
|
@@ -3430,6 +3403,10 @@ class ChatMessage {
|
|
|
3430
3403
|
|
|
3431
3404
|
|
|
3432
3405
|
static parseMany(plain ) {
|
|
3406
|
+
if (!plain || !plain.items) {
|
|
3407
|
+
return [];
|
|
3408
|
+
}
|
|
3409
|
+
|
|
3433
3410
|
return plain.items.map(item => ChatMessage.parse(item));
|
|
3434
3411
|
}
|
|
3435
3412
|
|
|
@@ -3539,6 +3516,9 @@ class Voicemail {
|
|
|
3539
3516
|
}
|
|
3540
3517
|
|
|
3541
3518
|
static parseMany(plain ) {
|
|
3519
|
+
if (!plain) {
|
|
3520
|
+
return [];
|
|
3521
|
+
}
|
|
3542
3522
|
const plainUnread = plain.folders.filter(folder => folder.type === 'new')[0].messages;
|
|
3543
3523
|
const plainRead = plain.folders.filter(folder => folder.type === 'old')[0].messages;
|
|
3544
3524
|
|
|
@@ -3648,6 +3628,9 @@ class Call {
|
|
|
3648
3628
|
|
|
3649
3629
|
|
|
3650
3630
|
static parseMany(plain ) {
|
|
3631
|
+
if (!plain) {
|
|
3632
|
+
return [];
|
|
3633
|
+
}
|
|
3651
3634
|
return plain.map((plainCall ) => Call.parse(plainCall));
|
|
3652
3635
|
}
|
|
3653
3636
|
|
|
@@ -3820,6 +3803,9 @@ class Recording {
|
|
|
3820
3803
|
|
|
3821
3804
|
|
|
3822
3805
|
static parseMany(recordings = []) {
|
|
3806
|
+
if (!recordings) {
|
|
3807
|
+
return [];
|
|
3808
|
+
}
|
|
3823
3809
|
return recordings.map(item => Recording.parse(item));
|
|
3824
3810
|
}
|
|
3825
3811
|
|
|
@@ -3921,6 +3907,10 @@ class CallLog {
|
|
|
3921
3907
|
}
|
|
3922
3908
|
|
|
3923
3909
|
static parseMany(plain ) {
|
|
3910
|
+
if (!plain || !plain.items) {
|
|
3911
|
+
return [];
|
|
3912
|
+
}
|
|
3913
|
+
|
|
3924
3914
|
return plain.items.map(item => CallLog.parse(item));
|
|
3925
3915
|
}
|
|
3926
3916
|
|
|
@@ -4493,6 +4483,9 @@ class ChatRoom {
|
|
|
4493
4483
|
|
|
4494
4484
|
|
|
4495
4485
|
static parseMany(plain ) {
|
|
4486
|
+
if (!plain || !plain.items) {
|
|
4487
|
+
return [];
|
|
4488
|
+
}
|
|
4496
4489
|
return plain.items.map(item => ChatRoom.parse(item));
|
|
4497
4490
|
}
|
|
4498
4491
|
|
|
@@ -5721,7 +5714,7 @@ class WebRTCClient extends Emitter {
|
|
|
5721
5714
|
}
|
|
5722
5715
|
|
|
5723
5716
|
call(number , enableVideo , audioOnly = false, conference = false) {
|
|
5724
|
-
logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
|
|
5717
|
+
logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
|
|
5725
5718
|
const inviterOptions = {
|
|
5726
5719
|
sessionDescriptionHandlerOptionsReInvite: {
|
|
5727
5720
|
conference,
|
|
@@ -6797,6 +6790,7 @@ class WebRTCClient extends Emitter {
|
|
|
6797
6790
|
const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
|
|
6798
6791
|
const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
|
|
6799
6792
|
const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
|
|
6793
|
+
const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
|
|
6800
6794
|
|
|
6801
6795
|
logger.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
|
|
6802
6796
|
|
|
@@ -6804,7 +6798,8 @@ class WebRTCClient extends Emitter {
|
|
|
6804
6798
|
constraints: {
|
|
6805
6799
|
// Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
|
|
6806
6800
|
audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
|
|
6807
|
-
video: screenSharing ? (isDesktop
|
|
6801
|
+
video: screenSharing ? (isDesktop
|
|
6802
|
+
? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
|
|
6808
6803
|
: this._getVideoConstraints(enableVideo),
|
|
6809
6804
|
screen: screenSharing,
|
|
6810
6805
|
desktop: isDesktop,
|
|
@@ -7139,11 +7134,14 @@ class WebRTCClient extends Emitter {
|
|
|
7139
7134
|
|
|
7140
7135
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
7141
7136
|
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7137
|
+
if (pc) {
|
|
7138
|
+
pc.oniceconnectionstatechange = () => {
|
|
7139
|
+
logger.info('on ice connection state changed', { state: pc.iceConnectionState });
|
|
7140
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
7141
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
7142
|
+
}
|
|
7143
|
+
};
|
|
7144
|
+
}
|
|
7147
7145
|
|
|
7148
7146
|
if (withEvent) {
|
|
7149
7147
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
@@ -7353,13 +7351,17 @@ class WebRTCClient extends Emitter {
|
|
|
7353
7351
|
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
7354
7352
|
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
7355
7353
|
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
7354
|
+
const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
|
|
7356
7355
|
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
7357
7356
|
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
7357
|
+
const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
|
|
7358
7358
|
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
7359
7359
|
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
7360
7360
|
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
7361
|
-
let audioBytesSent = 0;
|
|
7362
|
-
let audioBytesReceived = 0;
|
|
7361
|
+
let audioBytesSent = 0; // content + header
|
|
7362
|
+
let audioBytesReceived = 0; // content + header
|
|
7363
|
+
let audioContentSent = 0; // useful to detect blank call
|
|
7364
|
+
let audioContentReceived = 0;
|
|
7363
7365
|
let videoBytesSent = 0;
|
|
7364
7366
|
let videoBytesReceived = 0;
|
|
7365
7367
|
let transportSent = 0;
|
|
@@ -7368,25 +7370,27 @@ class WebRTCClient extends Emitter {
|
|
|
7368
7370
|
|
|
7369
7371
|
stats.forEach(report => {
|
|
7370
7372
|
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
7371
|
-
audioBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7373
|
+
audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
7374
|
+
audioContentSent += Number(report.bytesSent);
|
|
7372
7375
|
}
|
|
7373
7376
|
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
7374
|
-
audioBytesSent += report.bytesSent;
|
|
7377
|
+
audioBytesSent += Number(report.bytesSent);
|
|
7375
7378
|
}
|
|
7376
7379
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7377
|
-
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7380
|
+
videoBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
7378
7381
|
}
|
|
7379
7382
|
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
7380
|
-
packetsLost += report.packetsLost;
|
|
7381
|
-
networkStats.packetsReceived = report.packetsReceived;
|
|
7382
|
-
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7383
|
+
packetsLost += Number(report.packetsLost);
|
|
7384
|
+
networkStats.packetsReceived = Number(report.packetsReceived);
|
|
7385
|
+
audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
7386
|
+
audioContentReceived += Number(report.bytesReceived);
|
|
7383
7387
|
}
|
|
7384
7388
|
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
7385
|
-
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7389
|
+
videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
7386
7390
|
}
|
|
7387
7391
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7388
7392
|
if ('framesPerSecond' in report) {
|
|
7389
|
-
networkStats.framesPerSecond = report.framesPerSecond;
|
|
7393
|
+
networkStats.framesPerSecond = Number(report.framesPerSecond);
|
|
7390
7394
|
}
|
|
7391
7395
|
if ('framerateMean' in report) {
|
|
7392
7396
|
// framerateMean is only available in FF
|
|
@@ -7394,24 +7398,31 @@ class WebRTCClient extends Emitter {
|
|
|
7394
7398
|
}
|
|
7395
7399
|
}
|
|
7396
7400
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
7397
|
-
packetsLost += report.packetsLost;
|
|
7398
|
-
networkStats.roundTripTime = report.roundTripTime;
|
|
7399
|
-
networkStats.jitter = report.jitter;
|
|
7401
|
+
packetsLost += Number(report.packetsLost);
|
|
7402
|
+
networkStats.roundTripTime = Number(report.roundTripTime);
|
|
7403
|
+
networkStats.jitter = Number(report.jitter);
|
|
7400
7404
|
}
|
|
7401
7405
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
7402
|
-
packetsLost += report.packetsLost;
|
|
7406
|
+
packetsLost += Number(report.packetsLost);
|
|
7403
7407
|
}
|
|
7404
7408
|
if (report.type === 'transport') {
|
|
7405
|
-
transportSent += report.bytesSent;
|
|
7406
|
-
transportReceived += report.bytesReceived;
|
|
7409
|
+
transportSent += Number(report.bytesSent);
|
|
7410
|
+
transportReceived += Number(report.bytesReceived);
|
|
7407
7411
|
}
|
|
7408
7412
|
});
|
|
7409
7413
|
|
|
7410
7414
|
networkStats.packetsLost = packetsLost;
|
|
7415
|
+
|
|
7411
7416
|
networkStats.totalAudioBytesSent = audioBytesSent;
|
|
7412
7417
|
networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
|
|
7413
7418
|
networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
|
|
7414
7419
|
networkStats.audioBytesReceived = audioBytesReceived;
|
|
7420
|
+
|
|
7421
|
+
networkStats.totalAudioContentSent = audioContentSent;
|
|
7422
|
+
networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
|
|
7423
|
+
networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
|
|
7424
|
+
networkStats.audioContentReceived = audioContentReceived;
|
|
7425
|
+
|
|
7415
7426
|
networkStats.totalVideoBytesSent = videoBytesSent;
|
|
7416
7427
|
networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
|
|
7417
7428
|
networkStats.totalVideoBytesReceived = videoBytesReceived;
|