@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
package/lib/index.js
CHANGED
|
@@ -1562,6 +1562,9 @@ class Contact {
|
|
|
1562
1562
|
}
|
|
1563
1563
|
|
|
1564
1564
|
static parseMany(response ) {
|
|
1565
|
+
if (!response || !response.results) {
|
|
1566
|
+
return [];
|
|
1567
|
+
}
|
|
1565
1568
|
return response.results.map(r => Contact.parse(r, response.column_types));
|
|
1566
1569
|
}
|
|
1567
1570
|
|
|
@@ -2639,8 +2642,9 @@ class ExternalApp {
|
|
|
2639
2642
|
|
|
2640
2643
|
|
|
2641
2644
|
|
|
2642
|
-
|
|
2645
|
+
|
|
2643
2646
|
|
|
2647
|
+
|
|
2644
2648
|
|
|
2645
2649
|
|
|
2646
2650
|
class Meeting {
|
|
@@ -2651,9 +2655,10 @@ class Meeting {
|
|
|
2651
2655
|
|
|
2652
2656
|
|
|
2653
2657
|
|
|
2654
|
-
|
|
2658
|
+
|
|
2655
2659
|
|
|
2656
2660
|
|
|
2661
|
+
|
|
2657
2662
|
|
|
2658
2663
|
static parse(plain ) {
|
|
2659
2664
|
return new Meeting({
|
|
@@ -2663,12 +2668,16 @@ class Meeting {
|
|
|
2663
2668
|
ownerUuids: plain.owner_uuids,
|
|
2664
2669
|
port: plain.port,
|
|
2665
2670
|
uuid: plain.uuid,
|
|
2666
|
-
|
|
2671
|
+
extension: plain.exten,
|
|
2667
2672
|
persistent: plain.persistent,
|
|
2673
|
+
creationTime: moment__default['default'](plain.creation_time).toDate(),
|
|
2668
2674
|
});
|
|
2669
2675
|
}
|
|
2670
2676
|
|
|
2671
2677
|
static parseMany(items ) {
|
|
2678
|
+
if (!items) {
|
|
2679
|
+
return [];
|
|
2680
|
+
}
|
|
2672
2681
|
return items.map(plain => Meeting.parse(plain));
|
|
2673
2682
|
}
|
|
2674
2683
|
|
|
@@ -2683,8 +2692,9 @@ class Meeting {
|
|
|
2683
2692
|
ownerUuids,
|
|
2684
2693
|
port,
|
|
2685
2694
|
uri,
|
|
2686
|
-
|
|
2695
|
+
extension,
|
|
2687
2696
|
persistent,
|
|
2697
|
+
creationTime,
|
|
2688
2698
|
} = {}) {
|
|
2689
2699
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2690
2700
|
this.uri = uri;
|
|
@@ -2692,8 +2702,9 @@ class Meeting {
|
|
|
2692
2702
|
this.ownerUuids = ownerUuids;
|
|
2693
2703
|
this.port = port;
|
|
2694
2704
|
this.uuid = uuid;
|
|
2695
|
-
this.
|
|
2705
|
+
this.extension = extension;
|
|
2696
2706
|
this.persistent = persistent;
|
|
2707
|
+
this.creationTime = creationTime;
|
|
2697
2708
|
|
|
2698
2709
|
// Useful to compare instead of instanceof with minified code
|
|
2699
2710
|
this.type = 'Meeting';
|
|
@@ -2871,6 +2882,10 @@ class ChatMessage {
|
|
|
2871
2882
|
|
|
2872
2883
|
|
|
2873
2884
|
static parseMany(plain ) {
|
|
2885
|
+
if (!plain || !plain.items) {
|
|
2886
|
+
return [];
|
|
2887
|
+
}
|
|
2888
|
+
|
|
2874
2889
|
return plain.items.map(item => ChatMessage.parse(item));
|
|
2875
2890
|
}
|
|
2876
2891
|
|
|
@@ -2980,6 +2995,9 @@ class Voicemail {
|
|
|
2980
2995
|
}
|
|
2981
2996
|
|
|
2982
2997
|
static parseMany(plain ) {
|
|
2998
|
+
if (!plain) {
|
|
2999
|
+
return [];
|
|
3000
|
+
}
|
|
2983
3001
|
const plainUnread = plain.folders.filter(folder => folder.type === 'new')[0].messages;
|
|
2984
3002
|
const plainRead = plain.folders.filter(folder => folder.type === 'old')[0].messages;
|
|
2985
3003
|
|
|
@@ -3089,6 +3107,9 @@ class Call {
|
|
|
3089
3107
|
|
|
3090
3108
|
|
|
3091
3109
|
static parseMany(plain ) {
|
|
3110
|
+
if (!plain) {
|
|
3111
|
+
return [];
|
|
3112
|
+
}
|
|
3092
3113
|
return plain.map((plainCall ) => Call.parse(plainCall));
|
|
3093
3114
|
}
|
|
3094
3115
|
|
|
@@ -3632,6 +3653,9 @@ class Recording {
|
|
|
3632
3653
|
|
|
3633
3654
|
|
|
3634
3655
|
static parseMany(recordings = []) {
|
|
3656
|
+
if (!recordings) {
|
|
3657
|
+
return [];
|
|
3658
|
+
}
|
|
3635
3659
|
return recordings.map(item => Recording.parse(item));
|
|
3636
3660
|
}
|
|
3637
3661
|
|
|
@@ -3733,6 +3757,10 @@ class CallLog {
|
|
|
3733
3757
|
}
|
|
3734
3758
|
|
|
3735
3759
|
static parseMany(plain ) {
|
|
3760
|
+
if (!plain || !plain.items) {
|
|
3761
|
+
return [];
|
|
3762
|
+
}
|
|
3763
|
+
|
|
3736
3764
|
return plain.items.map(item => CallLog.parse(item));
|
|
3737
3765
|
}
|
|
3738
3766
|
|
|
@@ -4385,6 +4413,10 @@ class CTIPhone extends Emitter {
|
|
|
4385
4413
|
return false;
|
|
4386
4414
|
}
|
|
4387
4415
|
|
|
4416
|
+
hasAVideoTrack() {
|
|
4417
|
+
return false;
|
|
4418
|
+
}
|
|
4419
|
+
|
|
4388
4420
|
getLocalStreamForCall() {
|
|
4389
4421
|
return null;
|
|
4390
4422
|
}
|
|
@@ -4778,6 +4810,9 @@ class ChatRoom {
|
|
|
4778
4810
|
|
|
4779
4811
|
|
|
4780
4812
|
static parseMany(plain ) {
|
|
4813
|
+
if (!plain || !plain.items) {
|
|
4814
|
+
return [];
|
|
4815
|
+
}
|
|
4781
4816
|
return plain.items.map(item => ChatRoom.parse(item));
|
|
4782
4817
|
}
|
|
4783
4818
|
|
|
@@ -5501,10 +5536,6 @@ const getSrflxOrRelay = (candidates ) =>
|
|
|
5501
5536
|
candidates
|
|
5502
5537
|
.filter(candidate => candidate && (candidate.type === 'srflx' || candidate.type === 'relay'));
|
|
5503
5538
|
|
|
5504
|
-
const areCandidateValid = (candidates ) =>
|
|
5505
|
-
getSrflxOrRelay(candidates)
|
|
5506
|
-
.length > 0;
|
|
5507
|
-
|
|
5508
5539
|
const getVideoDirection = (sdp ) => {
|
|
5509
5540
|
const parsedSdp = sdpParser__default['default'].parse(sdp);
|
|
5510
5541
|
const videoMedia = parsedSdp.media.find(media => media.type === 'video');
|
|
@@ -5557,8 +5588,6 @@ const fixSdp = (sdp , candidates , forcePort = true)
|
|
|
5557
5588
|
/* global RTCSessionDescriptionInit, navigator */
|
|
5558
5589
|
|
|
5559
5590
|
const wazoLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-sdh') : console;
|
|
5560
|
-
const MAX_WAIT_FOR_ICE_TRIES = 20;
|
|
5561
|
-
const WAIT_FOR_ICE_TIMEOUT = 500;
|
|
5562
5591
|
|
|
5563
5592
|
// Customized mediaStreamFactory allowing to send screensharing stream directory when upgrading
|
|
5564
5593
|
const wazoMediaStreamFactory = (constraints ) => {
|
|
@@ -5748,38 +5777,6 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
5748
5777
|
this._peerConnection = undefined;
|
|
5749
5778
|
}
|
|
5750
5779
|
|
|
5751
|
-
async _waitForValidGatheredIce() {
|
|
5752
|
-
let tries = 0;
|
|
5753
|
-
|
|
5754
|
-
while (!areCandidateValid(this.gatheredCandidates) && tries < MAX_WAIT_FOR_ICE_TRIES) {
|
|
5755
|
-
wazoLogger.trace('SessionDescriptionHandler._waitForValidGatheredIce, waiting for ice', {
|
|
5756
|
-
tries,
|
|
5757
|
-
max: MAX_WAIT_FOR_ICE_TRIES,
|
|
5758
|
-
});
|
|
5759
|
-
|
|
5760
|
-
tries++;
|
|
5761
|
-
|
|
5762
|
-
// eslint-disable-next-line no-await-in-loop
|
|
5763
|
-
await new Promise(resolve => setTimeout(resolve, WAIT_FOR_ICE_TIMEOUT));
|
|
5764
|
-
}
|
|
5765
|
-
|
|
5766
|
-
if (tries >= MAX_WAIT_FOR_ICE_TRIES) {
|
|
5767
|
-
const errorMsg = 'No valid candidates found, can\'t answer the call';
|
|
5768
|
-
const error = new Error(errorMsg);
|
|
5769
|
-
wazoLogger.error(errorMsg, { tries, max: MAX_WAIT_FOR_ICE_TRIES });
|
|
5770
|
-
|
|
5771
|
-
// Emit an error, because sip.js catches the exception and switch to status Terminated.
|
|
5772
|
-
this.eventEmitter.emit('error', error);
|
|
5773
|
-
|
|
5774
|
-
wazoLogger.error('No valid candidates found', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
|
|
5775
|
-
}
|
|
5776
|
-
|
|
5777
|
-
// eslint-disable-next-line
|
|
5778
|
-
wazoLogger.trace('Found valid candidates', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
|
|
5779
|
-
|
|
5780
|
-
return this.getLocalSessionDescription();
|
|
5781
|
-
}
|
|
5782
|
-
|
|
5783
5780
|
// Overridden to send `inactive` in conference
|
|
5784
5781
|
updateDirection(options , isConference = false,
|
|
5785
5782
|
audioOnly = false) {
|
|
@@ -6547,7 +6544,7 @@ class WebRTCClient extends Emitter {
|
|
|
6547
6544
|
}
|
|
6548
6545
|
|
|
6549
6546
|
call(number , enableVideo , audioOnly = false, conference = false) {
|
|
6550
|
-
logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
|
|
6547
|
+
logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
|
|
6551
6548
|
const inviterOptions = {
|
|
6552
6549
|
sessionDescriptionHandlerOptionsReInvite: {
|
|
6553
6550
|
conference,
|
|
@@ -7623,6 +7620,7 @@ class WebRTCClient extends Emitter {
|
|
|
7623
7620
|
const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
|
|
7624
7621
|
const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
|
|
7625
7622
|
const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
|
|
7623
|
+
const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
|
|
7626
7624
|
|
|
7627
7625
|
logger$9.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
|
|
7628
7626
|
|
|
@@ -7630,7 +7628,8 @@ class WebRTCClient extends Emitter {
|
|
|
7630
7628
|
constraints: {
|
|
7631
7629
|
// Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
|
|
7632
7630
|
audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
|
|
7633
|
-
video: screenSharing ? (isDesktop
|
|
7631
|
+
video: screenSharing ? (isDesktop
|
|
7632
|
+
? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
|
|
7634
7633
|
: this._getVideoConstraints(enableVideo),
|
|
7635
7634
|
screen: screenSharing,
|
|
7636
7635
|
desktop: isDesktop,
|
|
@@ -7965,11 +7964,14 @@ class WebRTCClient extends Emitter {
|
|
|
7965
7964
|
|
|
7966
7965
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
7967
7966
|
|
|
7968
|
-
|
|
7969
|
-
|
|
7970
|
-
|
|
7971
|
-
|
|
7972
|
-
|
|
7967
|
+
if (pc) {
|
|
7968
|
+
pc.oniceconnectionstatechange = () => {
|
|
7969
|
+
logger$9.info('on ice connection state changed', { state: pc.iceConnectionState });
|
|
7970
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
7971
|
+
this.eventEmitter.emit(ON_DISCONNECTED$1);
|
|
7972
|
+
}
|
|
7973
|
+
};
|
|
7974
|
+
}
|
|
7973
7975
|
|
|
7974
7976
|
if (withEvent) {
|
|
7975
7977
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
@@ -8179,13 +8181,17 @@ class WebRTCClient extends Emitter {
|
|
|
8179
8181
|
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
8180
8182
|
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
8181
8183
|
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
8184
|
+
const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
|
|
8182
8185
|
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
8183
8186
|
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
8187
|
+
const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
|
|
8184
8188
|
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
8185
8189
|
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
8186
8190
|
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
8187
|
-
let audioBytesSent = 0;
|
|
8188
|
-
let audioBytesReceived = 0;
|
|
8191
|
+
let audioBytesSent = 0; // content + header
|
|
8192
|
+
let audioBytesReceived = 0; // content + header
|
|
8193
|
+
let audioContentSent = 0; // useful to detect blank call
|
|
8194
|
+
let audioContentReceived = 0;
|
|
8189
8195
|
let videoBytesSent = 0;
|
|
8190
8196
|
let videoBytesReceived = 0;
|
|
8191
8197
|
let transportSent = 0;
|
|
@@ -8194,25 +8200,27 @@ class WebRTCClient extends Emitter {
|
|
|
8194
8200
|
|
|
8195
8201
|
stats.forEach(report => {
|
|
8196
8202
|
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
8197
|
-
audioBytesSent += report.bytesSent + report.headerBytesSent;
|
|
8203
|
+
audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
8204
|
+
audioContentSent += Number(report.bytesSent);
|
|
8198
8205
|
}
|
|
8199
8206
|
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
8200
|
-
audioBytesSent += report.bytesSent;
|
|
8207
|
+
audioBytesSent += Number(report.bytesSent);
|
|
8201
8208
|
}
|
|
8202
8209
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
8203
|
-
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
8210
|
+
videoBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
8204
8211
|
}
|
|
8205
8212
|
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
8206
|
-
packetsLost += report.packetsLost;
|
|
8207
|
-
networkStats.packetsReceived = report.packetsReceived;
|
|
8208
|
-
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
8213
|
+
packetsLost += Number(report.packetsLost);
|
|
8214
|
+
networkStats.packetsReceived = Number(report.packetsReceived);
|
|
8215
|
+
audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
8216
|
+
audioContentReceived += Number(report.bytesReceived);
|
|
8209
8217
|
}
|
|
8210
8218
|
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
8211
|
-
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
8219
|
+
videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
8212
8220
|
}
|
|
8213
8221
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
8214
8222
|
if ('framesPerSecond' in report) {
|
|
8215
|
-
networkStats.framesPerSecond = report.framesPerSecond;
|
|
8223
|
+
networkStats.framesPerSecond = Number(report.framesPerSecond);
|
|
8216
8224
|
}
|
|
8217
8225
|
if ('framerateMean' in report) {
|
|
8218
8226
|
// framerateMean is only available in FF
|
|
@@ -8220,24 +8228,31 @@ class WebRTCClient extends Emitter {
|
|
|
8220
8228
|
}
|
|
8221
8229
|
}
|
|
8222
8230
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
8223
|
-
packetsLost += report.packetsLost;
|
|
8224
|
-
networkStats.roundTripTime = report.roundTripTime;
|
|
8225
|
-
networkStats.jitter = report.jitter;
|
|
8231
|
+
packetsLost += Number(report.packetsLost);
|
|
8232
|
+
networkStats.roundTripTime = Number(report.roundTripTime);
|
|
8233
|
+
networkStats.jitter = Number(report.jitter);
|
|
8226
8234
|
}
|
|
8227
8235
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
8228
|
-
packetsLost += report.packetsLost;
|
|
8236
|
+
packetsLost += Number(report.packetsLost);
|
|
8229
8237
|
}
|
|
8230
8238
|
if (report.type === 'transport') {
|
|
8231
|
-
transportSent += report.bytesSent;
|
|
8232
|
-
transportReceived += report.bytesReceived;
|
|
8239
|
+
transportSent += Number(report.bytesSent);
|
|
8240
|
+
transportReceived += Number(report.bytesReceived);
|
|
8233
8241
|
}
|
|
8234
8242
|
});
|
|
8235
8243
|
|
|
8236
8244
|
networkStats.packetsLost = packetsLost;
|
|
8245
|
+
|
|
8237
8246
|
networkStats.totalAudioBytesSent = audioBytesSent;
|
|
8238
8247
|
networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
|
|
8239
8248
|
networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
|
|
8240
8249
|
networkStats.audioBytesReceived = audioBytesReceived;
|
|
8250
|
+
|
|
8251
|
+
networkStats.totalAudioContentSent = audioContentSent;
|
|
8252
|
+
networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
|
|
8253
|
+
networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
|
|
8254
|
+
networkStats.audioContentReceived = audioContentReceived;
|
|
8255
|
+
|
|
8241
8256
|
networkStats.totalVideoBytesSent = videoBytesSent;
|
|
8242
8257
|
networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
|
|
8243
8258
|
networkStats.totalVideoBytesReceived = videoBytesReceived;
|
|
@@ -9342,6 +9357,7 @@ class WebRTCPhone extends Emitter {
|
|
|
9342
9357
|
constraints,
|
|
9343
9358
|
audioOnly,
|
|
9344
9359
|
conference,
|
|
9360
|
+
iceRestart,
|
|
9345
9361
|
});
|
|
9346
9362
|
|
|
9347
9363
|
if (!sipSession) {
|
|
@@ -9445,6 +9461,11 @@ class WebRTCPhone extends Emitter {
|
|
|
9445
9461
|
|
|
9446
9462
|
this.client.downgradeToAudio(sipSession);
|
|
9447
9463
|
|
|
9464
|
+
if (callSession) {
|
|
9465
|
+
callSession.cameraEnabled = false;
|
|
9466
|
+
this._updateCallSession(callSession);
|
|
9467
|
+
}
|
|
9468
|
+
|
|
9448
9469
|
if (withMessage) {
|
|
9449
9470
|
this._sendReinviteMessage(callSession, false);
|
|
9450
9471
|
}
|
|
@@ -9472,6 +9493,11 @@ class WebRTCPhone extends Emitter {
|
|
|
9472
9493
|
|
|
9473
9494
|
const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
|
|
9474
9495
|
|
|
9496
|
+
if (callSession) {
|
|
9497
|
+
callSession.cameraEnabled = true;
|
|
9498
|
+
this._updateCallSession(callSession);
|
|
9499
|
+
}
|
|
9500
|
+
|
|
9475
9501
|
// If no stream is returned, it means we have to reinvite
|
|
9476
9502
|
if (!newStream) {
|
|
9477
9503
|
return true;
|
|
@@ -9524,7 +9550,10 @@ class WebRTCPhone extends Emitter {
|
|
|
9524
9550
|
|
|
9525
9551
|
onCancel(message);
|
|
9526
9552
|
const elsewhere = message.data.indexOf('cause=26') !== -1 && message.data.indexOf('completed elsewhere') !== -1;
|
|
9527
|
-
|
|
9553
|
+
const callSession = this._createCallSession(sipSession);
|
|
9554
|
+
delete this.callSessions[callSession.getId()];
|
|
9555
|
+
|
|
9556
|
+
this.eventEmitter.emit(ON_CALL_CANCELED, callSession, elsewhere);
|
|
9528
9557
|
};
|
|
9529
9558
|
} else if (sipSession instanceof invitation.Invitation) {
|
|
9530
9559
|
console.warn('sipSession._onCancel not found, please update the wazo SDK accordingly');
|
|
@@ -9705,18 +9734,20 @@ class WebRTCPhone extends Emitter {
|
|
|
9705
9734
|
screenTrack,
|
|
9706
9735
|
});
|
|
9707
9736
|
|
|
9708
|
-
|
|
9709
|
-
|
|
9710
|
-
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
|
|
9737
|
+
if (screenTrack) {
|
|
9738
|
+
screenTrack.onended = () => {
|
|
9739
|
+
logger$7.info('WebRTC phone - on screenshare ended', {
|
|
9740
|
+
hadVideo,
|
|
9741
|
+
id: this.getSipSessionId(sipSession),
|
|
9742
|
+
screenTrack,
|
|
9743
|
+
});
|
|
9714
9744
|
|
|
9715
|
-
|
|
9716
|
-
|
|
9717
|
-
|
|
9718
|
-
|
|
9719
|
-
|
|
9745
|
+
this.eventEmitter.emit(
|
|
9746
|
+
ON_SHARE_SCREEN_ENDING,
|
|
9747
|
+
this._createCallSession(sipSession, callSession),
|
|
9748
|
+
);
|
|
9749
|
+
};
|
|
9750
|
+
}
|
|
9720
9751
|
|
|
9721
9752
|
this.currentScreenShare = {
|
|
9722
9753
|
stream: screenStream,
|
|
@@ -9736,7 +9767,7 @@ class WebRTCPhone extends Emitter {
|
|
|
9736
9767
|
}
|
|
9737
9768
|
|
|
9738
9769
|
_onCallAccepted(sipSession , cameraEnabled ) {
|
|
9739
|
-
logger$7.info('WebRTC phone -
|
|
9770
|
+
logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
|
|
9740
9771
|
|
|
9741
9772
|
const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
|
|
9742
9773
|
this.currentSipSession = sipSession;
|
|
@@ -10248,7 +10279,7 @@ class WebRTCPhone extends Emitter {
|
|
|
10248
10279
|
// @TODO: line is not used here
|
|
10249
10280
|
async makeCall(number , line , cameraEnabled ,
|
|
10250
10281
|
audioOnly = false, conference = false) {
|
|
10251
|
-
logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
|
|
10282
|
+
logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
|
|
10252
10283
|
if (!number) {
|
|
10253
10284
|
return Promise.resolve(null);
|
|
10254
10285
|
}
|
|
@@ -10609,9 +10640,13 @@ class WebRTCPhone extends Emitter {
|
|
|
10609
10640
|
if (this.shouldSendReinvite && this.currentSipSession
|
|
10610
10641
|
&& this.currentSipSession.state === sessionState.SessionState.Established) {
|
|
10611
10642
|
this.shouldSendReinvite = false;
|
|
10643
|
+
const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
|
|
10644
|
+
const isConference = pc ? pc.sfu : false;
|
|
10645
|
+
const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
|
|
10646
|
+
|
|
10612
10647
|
try {
|
|
10613
10648
|
// Send reinvite with iceRestart
|
|
10614
|
-
this.sendReinvite(this.currentCallSession, null,
|
|
10649
|
+
this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
|
|
10615
10650
|
} catch (e) {
|
|
10616
10651
|
logger$7.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
|
|
10617
10652
|
}
|
|
@@ -10695,6 +10730,15 @@ class WebRTCPhone extends Emitter {
|
|
|
10695
10730
|
return this.client.getSipSessionId(sipSession);
|
|
10696
10731
|
}
|
|
10697
10732
|
|
|
10733
|
+
_updateCallSession(callSession ) {
|
|
10734
|
+
const sipSession = this.findSipSession(callSession);
|
|
10735
|
+
const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
|
|
10736
|
+
|
|
10737
|
+
if (sipSessionId) {
|
|
10738
|
+
this.callSessions[sipSessionId] = callSession;
|
|
10739
|
+
}
|
|
10740
|
+
}
|
|
10741
|
+
|
|
10698
10742
|
_onMessage(message ) {
|
|
10699
10743
|
if (!message || message.method !== 'MESSAGE') {
|
|
10700
10744
|
return;
|
|
@@ -419,10 +419,6 @@ const getSrflxOrRelay = (candidates ) =>
|
|
|
419
419
|
candidates
|
|
420
420
|
.filter(candidate => candidate && (candidate.type === 'srflx' || candidate.type === 'relay'));
|
|
421
421
|
|
|
422
|
-
const areCandidateValid = (candidates ) =>
|
|
423
|
-
getSrflxOrRelay(candidates)
|
|
424
|
-
.length > 0;
|
|
425
|
-
|
|
426
422
|
const fixSdp = (sdp , candidates , forcePort = true) => {
|
|
427
423
|
const parsedSdp = sdpParser__default['default'].parse(sdp);
|
|
428
424
|
const mainCandidate = getSrflxOrRelay(candidates)[0];
|
|
@@ -454,8 +450,6 @@ const fixSdp = (sdp , candidates , forcePort = true)
|
|
|
454
450
|
/* global RTCSessionDescriptionInit, navigator */
|
|
455
451
|
|
|
456
452
|
const wazoLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-sdh') : console;
|
|
457
|
-
const MAX_WAIT_FOR_ICE_TRIES = 20;
|
|
458
|
-
const WAIT_FOR_ICE_TIMEOUT = 500;
|
|
459
453
|
|
|
460
454
|
// Customized mediaStreamFactory allowing to send screensharing stream directory when upgrading
|
|
461
455
|
const wazoMediaStreamFactory = (constraints ) => {
|
|
@@ -645,38 +639,6 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
645
639
|
this._peerConnection = undefined;
|
|
646
640
|
}
|
|
647
641
|
|
|
648
|
-
async _waitForValidGatheredIce() {
|
|
649
|
-
let tries = 0;
|
|
650
|
-
|
|
651
|
-
while (!areCandidateValid(this.gatheredCandidates) && tries < MAX_WAIT_FOR_ICE_TRIES) {
|
|
652
|
-
wazoLogger.trace('SessionDescriptionHandler._waitForValidGatheredIce, waiting for ice', {
|
|
653
|
-
tries,
|
|
654
|
-
max: MAX_WAIT_FOR_ICE_TRIES,
|
|
655
|
-
});
|
|
656
|
-
|
|
657
|
-
tries++;
|
|
658
|
-
|
|
659
|
-
// eslint-disable-next-line no-await-in-loop
|
|
660
|
-
await new Promise(resolve => setTimeout(resolve, WAIT_FOR_ICE_TIMEOUT));
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
if (tries >= MAX_WAIT_FOR_ICE_TRIES) {
|
|
664
|
-
const errorMsg = 'No valid candidates found, can\'t answer the call';
|
|
665
|
-
const error = new Error(errorMsg);
|
|
666
|
-
wazoLogger.error(errorMsg, { tries, max: MAX_WAIT_FOR_ICE_TRIES });
|
|
667
|
-
|
|
668
|
-
// Emit an error, because sip.js catches the exception and switch to status Terminated.
|
|
669
|
-
this.eventEmitter.emit('error', error);
|
|
670
|
-
|
|
671
|
-
wazoLogger.error('No valid candidates found', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
// eslint-disable-next-line
|
|
675
|
-
wazoLogger.trace('Found valid candidates', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
|
|
676
|
-
|
|
677
|
-
return this.getLocalSessionDescription();
|
|
678
|
-
}
|
|
679
|
-
|
|
680
642
|
// Overridden to send `inactive` in conference
|
|
681
643
|
updateDirection(options , isConference = false,
|
|
682
644
|
audioOnly = false) {
|
package/lib/service/CallApi.js
CHANGED
|
@@ -82,6 +82,9 @@ class Call {
|
|
|
82
82
|
|
|
83
83
|
|
|
84
84
|
static parseMany(plain ) {
|
|
85
|
+
if (!plain) {
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
85
88
|
return plain.map((plainCall ) => Call.parse(plainCall));
|
|
86
89
|
}
|
|
87
90
|
|
|
@@ -1040,6 +1043,9 @@ class Contact {
|
|
|
1040
1043
|
}
|
|
1041
1044
|
|
|
1042
1045
|
static parseMany(response ) {
|
|
1046
|
+
if (!response || !response.results) {
|
|
1047
|
+
return [];
|
|
1048
|
+
}
|
|
1043
1049
|
return response.results.map(r => Contact.parse(r, response.column_types));
|
|
1044
1050
|
}
|
|
1045
1051
|
|
|
@@ -1712,6 +1718,9 @@ class Recording {
|
|
|
1712
1718
|
|
|
1713
1719
|
|
|
1714
1720
|
static parseMany(recordings = []) {
|
|
1721
|
+
if (!recordings) {
|
|
1722
|
+
return [];
|
|
1723
|
+
}
|
|
1715
1724
|
return recordings.map(item => Recording.parse(item));
|
|
1716
1725
|
}
|
|
1717
1726
|
|
|
@@ -1813,6 +1822,10 @@ class CallLog {
|
|
|
1813
1822
|
}
|
|
1814
1823
|
|
|
1815
1824
|
static parseMany(plain ) {
|
|
1825
|
+
if (!plain || !plain.items) {
|
|
1826
|
+
return [];
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1816
1829
|
return plain.items.map(item => CallLog.parse(item));
|
|
1817
1830
|
}
|
|
1818
1831
|
|
|
@@ -3138,8 +3151,9 @@ class ExternalApp {
|
|
|
3138
3151
|
|
|
3139
3152
|
|
|
3140
3153
|
|
|
3141
|
-
|
|
3154
|
+
|
|
3142
3155
|
|
|
3156
|
+
|
|
3143
3157
|
|
|
3144
3158
|
|
|
3145
3159
|
class Meeting {
|
|
@@ -3150,9 +3164,10 @@ class Meeting {
|
|
|
3150
3164
|
|
|
3151
3165
|
|
|
3152
3166
|
|
|
3153
|
-
|
|
3167
|
+
|
|
3154
3168
|
|
|
3155
3169
|
|
|
3170
|
+
|
|
3156
3171
|
|
|
3157
3172
|
static parse(plain ) {
|
|
3158
3173
|
return new Meeting({
|
|
@@ -3162,12 +3177,16 @@ class Meeting {
|
|
|
3162
3177
|
ownerUuids: plain.owner_uuids,
|
|
3163
3178
|
port: plain.port,
|
|
3164
3179
|
uuid: plain.uuid,
|
|
3165
|
-
|
|
3180
|
+
extension: plain.exten,
|
|
3166
3181
|
persistent: plain.persistent,
|
|
3182
|
+
creationTime: moment__default['default'](plain.creation_time).toDate(),
|
|
3167
3183
|
});
|
|
3168
3184
|
}
|
|
3169
3185
|
|
|
3170
3186
|
static parseMany(items ) {
|
|
3187
|
+
if (!items) {
|
|
3188
|
+
return [];
|
|
3189
|
+
}
|
|
3171
3190
|
return items.map(plain => Meeting.parse(plain));
|
|
3172
3191
|
}
|
|
3173
3192
|
|
|
@@ -3182,8 +3201,9 @@ class Meeting {
|
|
|
3182
3201
|
ownerUuids,
|
|
3183
3202
|
port,
|
|
3184
3203
|
uri,
|
|
3185
|
-
|
|
3204
|
+
extension,
|
|
3186
3205
|
persistent,
|
|
3206
|
+
creationTime,
|
|
3187
3207
|
} = {}) {
|
|
3188
3208
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
3189
3209
|
this.uri = uri;
|
|
@@ -3191,8 +3211,9 @@ class Meeting {
|
|
|
3191
3211
|
this.ownerUuids = ownerUuids;
|
|
3192
3212
|
this.port = port;
|
|
3193
3213
|
this.uuid = uuid;
|
|
3194
|
-
this.
|
|
3214
|
+
this.extension = extension;
|
|
3195
3215
|
this.persistent = persistent;
|
|
3216
|
+
this.creationTime = creationTime;
|
|
3196
3217
|
|
|
3197
3218
|
// Useful to compare instead of instanceof with minified code
|
|
3198
3219
|
this.type = 'Meeting';
|
|
@@ -3327,6 +3348,10 @@ class ChatMessage {
|
|
|
3327
3348
|
|
|
3328
3349
|
|
|
3329
3350
|
static parseMany(plain ) {
|
|
3351
|
+
if (!plain || !plain.items) {
|
|
3352
|
+
return [];
|
|
3353
|
+
}
|
|
3354
|
+
|
|
3330
3355
|
return plain.items.map(item => ChatMessage.parse(item));
|
|
3331
3356
|
}
|
|
3332
3357
|
|
|
@@ -3436,6 +3461,9 @@ class Voicemail {
|
|
|
3436
3461
|
}
|
|
3437
3462
|
|
|
3438
3463
|
static parseMany(plain ) {
|
|
3464
|
+
if (!plain) {
|
|
3465
|
+
return [];
|
|
3466
|
+
}
|
|
3439
3467
|
const plainUnread = plain.folders.filter(folder => folder.type === 'new')[0].messages;
|
|
3440
3468
|
const plainRead = plain.folders.filter(folder => folder.type === 'old')[0].messages;
|
|
3441
3469
|
|
|
@@ -3826,6 +3854,9 @@ class ChatRoom {
|
|
|
3826
3854
|
|
|
3827
3855
|
|
|
3828
3856
|
static parseMany(plain ) {
|
|
3857
|
+
if (!plain || !plain.items) {
|
|
3858
|
+
return [];
|
|
3859
|
+
}
|
|
3829
3860
|
return plain.items.map(item => ChatRoom.parse(item));
|
|
3830
3861
|
}
|
|
3831
3862
|
|