@wazo/sdk 0.37.15 → 0.37.19
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 +3 -3
- package/esm/__tests__/api-client.test.js +9 -5
- package/esm/__tests__/web-rtc-client.test.js +117 -23
- package/esm/api/agentd.js +1 -1
- package/esm/api/amid.js +1 -1
- package/esm/api/application.js +1 -1
- package/esm/api/auth.js +1 -1
- package/esm/api/call-logd.js +3 -3
- package/esm/api/calld.js +1 -1
- package/esm/api/chatd.js +1 -1
- package/esm/api/confd.js +7 -3
- package/esm/api/ctid-ng.js +1 -1
- package/esm/api/dird.js +1 -1
- package/esm/api/webhookd.js +1 -1
- package/esm/api-client.js +9 -5
- package/esm/checker/Checker.js +117 -23
- package/esm/checker/checks/aor.js +9 -5
- package/esm/checker/checks/api.js +9 -5
- package/esm/checker/checks/index.js +117 -23
- package/esm/checker/checks/wazo-websocket.js +1 -1
- package/esm/checker/checks/webrtc-transport.js +117 -23
- package/esm/checker/checks/webrtc.js +117 -23
- package/esm/domain/AdHocAPIConference.js +9 -5
- package/esm/domain/CallLog.js +2 -2
- package/esm/domain/Features.js +9 -5
- package/esm/domain/Meeting.js +6 -2
- package/esm/domain/Phone/CTIPhone.js +9 -5
- package/esm/domain/Phone/WebRTCPhone.js +9 -2
- package/esm/domain/Recording.js +1 -1
- package/esm/domain/__tests__/CallLog.test.js +2 -2
- package/esm/index.js +125 -23
- package/esm/lib/WazoSessionDescriptionHandler.js +1 -1
- package/esm/service/CallApi.js +9 -5
- package/esm/service/IssueReporter.js +1 -1
- package/esm/service/__tests__/IssueReporter.test.js +1 -1
- package/esm/service/getApiClient.js +9 -5
- package/esm/simple/Auth.js +125 -23
- package/esm/simple/Configuration.js +125 -23
- package/esm/simple/Directory.js +9 -5
- package/esm/simple/Phone.js +125 -23
- package/esm/simple/Websocket.js +1 -1
- package/esm/simple/index.js +125 -23
- package/esm/simple/room/LocalParticipant.js +125 -23
- package/esm/simple/room/Participant.js +125 -23
- package/esm/simple/room/RemoteParticipant.js +125 -23
- package/esm/simple/room/Room.js +125 -23
- package/esm/simple/room/SipRoom.js +125 -23
- package/esm/simple/room/Stream.js +125 -23
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +125 -23
- package/esm/simple/utils.js +125 -23
- package/esm/utils/__tests__/api-requester.test.js +1 -1
- package/esm/utils/api-requester.js +1 -1
- package/esm/web-rtc-client.js +117 -23
- package/esm/websocket-client.js +1 -1
- package/lib/__tests__/api-client.test.js +9 -5
- package/lib/__tests__/web-rtc-client.test.js +117 -23
- package/lib/api/agentd.js +1 -1
- package/lib/api/amid.js +1 -1
- package/lib/api/application.js +1 -1
- package/lib/api/auth.js +1 -1
- package/lib/api/call-logd.js +3 -3
- package/lib/api/calld.js +1 -1
- package/lib/api/chatd.js +1 -1
- package/lib/api/confd.js +7 -3
- package/lib/api/ctid-ng.js +1 -1
- package/lib/api/dird.js +1 -1
- package/lib/api/webhookd.js +1 -1
- package/lib/api-client.js +9 -5
- package/lib/checker/Checker.js +117 -23
- package/lib/checker/checks/aor.js +9 -5
- package/lib/checker/checks/api.js +9 -5
- package/lib/checker/checks/index.js +117 -23
- package/lib/checker/checks/wazo-websocket.js +1 -1
- package/lib/checker/checks/webrtc-transport.js +117 -23
- package/lib/checker/checks/webrtc.js +117 -23
- package/lib/domain/AdHocAPIConference.js +9 -5
- package/lib/domain/CallLog.js +2 -2
- package/lib/domain/Features.js +9 -5
- package/lib/domain/Meeting.js +6 -2
- package/lib/domain/Phone/CTIPhone.js +9 -5
- package/lib/domain/Phone/WebRTCPhone.js +9 -1
- package/lib/domain/Recording.js +1 -1
- package/lib/domain/__tests__/CallLog.test.js +2 -2
- package/lib/index.js +125 -23
- package/lib/lib/WazoSessionDescriptionHandler.js +1 -1
- package/lib/service/CallApi.js +9 -5
- package/lib/service/IssueReporter.js +1 -1
- package/lib/service/__tests__/IssueReporter.test.js +1 -1
- package/lib/service/getApiClient.js +9 -5
- package/lib/simple/Auth.js +125 -23
- package/lib/simple/Configuration.js +125 -23
- package/lib/simple/Directory.js +9 -5
- package/lib/simple/Phone.js +125 -23
- package/lib/simple/Websocket.js +1 -1
- package/lib/simple/index.js +125 -23
- package/lib/simple/room/LocalParticipant.js +125 -23
- package/lib/simple/room/Participant.js +125 -23
- package/lib/simple/room/RemoteParticipant.js +125 -23
- package/lib/simple/room/Room.js +125 -23
- package/lib/simple/room/SipRoom.js +125 -23
- package/lib/simple/room/Stream.js +125 -23
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +125 -23
- package/lib/simple/utils.js +125 -23
- package/lib/utils/__tests__/api-requester.test.js +1 -1
- package/lib/utils/api-requester.js +1 -1
- package/lib/web-rtc-client.js +117 -23
- package/lib/websocket-client.js +1 -1
- package/package.json +1 -1
- package/src/domain/CallLog.js +1 -1
- package/src/domain/Meeting.js +6 -2
- package/src/domain/Phone/WebRTCPhone.js +7 -0
- package/src/domain/Recording.js +1 -1
- package/src/service/IssueReporter.js +1 -1
- package/src/web-rtc-client.js +108 -18
package/lib/checker/Checker.js
CHANGED
|
@@ -410,7 +410,7 @@ class IssueReporter {
|
|
|
410
410
|
payload._retry = retry + 1;
|
|
411
411
|
}
|
|
412
412
|
|
|
413
|
-
this._sendDebugToGrafana(
|
|
413
|
+
this._sendDebugToGrafana(payload, retry + 1);
|
|
414
414
|
}, 5000 + retry * 1000);
|
|
415
415
|
});
|
|
416
416
|
}
|
|
@@ -2613,7 +2613,8 @@ class ExternalApp {
|
|
|
2613
2613
|
|
|
2614
2614
|
|
|
2615
2615
|
|
|
2616
|
-
|
|
2616
|
+
|
|
2617
|
+
|
|
2617
2618
|
|
|
2618
2619
|
|
|
2619
2620
|
class Meeting {
|
|
@@ -2625,6 +2626,7 @@ class Meeting {
|
|
|
2625
2626
|
|
|
2626
2627
|
|
|
2627
2628
|
|
|
2629
|
+
|
|
2628
2630
|
|
|
2629
2631
|
|
|
2630
2632
|
static parse(plain ) {
|
|
@@ -2636,6 +2638,7 @@ class Meeting {
|
|
|
2636
2638
|
port: plain.port,
|
|
2637
2639
|
uuid: plain.uuid,
|
|
2638
2640
|
number: plain.number,
|
|
2641
|
+
persistent: plain.persistent,
|
|
2639
2642
|
});
|
|
2640
2643
|
}
|
|
2641
2644
|
|
|
@@ -2643,7 +2646,7 @@ class Meeting {
|
|
|
2643
2646
|
return newFrom(meeting, Meeting);
|
|
2644
2647
|
}
|
|
2645
2648
|
|
|
2646
|
-
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
|
|
2649
|
+
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
|
|
2647
2650
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2648
2651
|
this.uri = uri;
|
|
2649
2652
|
this.name = name;
|
|
@@ -2651,6 +2654,7 @@ class Meeting {
|
|
|
2651
2654
|
this.port = port;
|
|
2652
2655
|
this.uuid = uuid;
|
|
2653
2656
|
this.number = number;
|
|
2657
|
+
this.persistent = persistent;
|
|
2654
2658
|
|
|
2655
2659
|
// Useful to compare instead of instanceof with minified code
|
|
2656
2660
|
this.type = 'Meeting';
|
|
@@ -3240,7 +3244,7 @@ class Recording {
|
|
|
3240
3244
|
|
|
3241
3245
|
|
|
3242
3246
|
|
|
3243
|
-
static parseMany(recordings
|
|
3247
|
+
static parseMany(recordings = []) {
|
|
3244
3248
|
return recordings.map(item => Recording.parse(item));
|
|
3245
3249
|
}
|
|
3246
3250
|
|
|
@@ -3366,7 +3370,7 @@ class CallLog {
|
|
|
3366
3370
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3367
3371
|
start: moment__default['default'](plain.start).toDate(),
|
|
3368
3372
|
end: plain.end ? moment__default['default'](plain.end).toDate() : null,
|
|
3369
|
-
recordings: Recording.parseMany(plain.recordings),
|
|
3373
|
+
recordings: Recording.parseMany(plain.recordings || []),
|
|
3370
3374
|
});
|
|
3371
3375
|
}
|
|
3372
3376
|
|
|
@@ -5881,6 +5885,7 @@ const ON_REINVITE = 'reinvite';
|
|
|
5881
5885
|
const ON_ERROR = 'onError';
|
|
5882
5886
|
const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
|
|
5883
5887
|
const ON_NETWORK_STATS = 'onNetworkStats';
|
|
5888
|
+
const ON_DISCONNECTED = 'onDisconnected';
|
|
5884
5889
|
class CanceledCallError extends Error {}
|
|
5885
5890
|
|
|
5886
5891
|
const MAX_REGISTER_TRIES = 10;
|
|
@@ -5954,6 +5959,7 @@ class WebRTCClient extends Emitter {
|
|
|
5954
5959
|
|
|
5955
5960
|
|
|
5956
5961
|
|
|
5962
|
+
|
|
5957
5963
|
|
|
5958
5964
|
static isAPrivateIp(ip ) {
|
|
5959
5965
|
const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
|
|
@@ -6019,6 +6025,7 @@ class WebRTCClient extends Emitter {
|
|
|
6019
6025
|
this.ON_ERROR = ON_ERROR;
|
|
6020
6026
|
this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
|
|
6021
6027
|
this.ON_NETWORK_STATS = ON_NETWORK_STATS;
|
|
6028
|
+
this.ON_DISCONNECTED = ON_DISCONNECTED;
|
|
6022
6029
|
}
|
|
6023
6030
|
|
|
6024
6031
|
configureMedia(media ) {
|
|
@@ -6620,7 +6627,7 @@ class WebRTCClient extends Emitter {
|
|
|
6620
6627
|
// We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
|
|
6621
6628
|
const transceivers = pc.getTransceivers();
|
|
6622
6629
|
const transceiverIdx = lastIndexOf(transceivers, transceiver =>
|
|
6623
|
-
transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
|
|
6630
|
+
transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
|
|
6624
6631
|
|
|
6625
6632
|
videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
|
|
6626
6633
|
} else {
|
|
@@ -6866,10 +6873,13 @@ class WebRTCClient extends Emitter {
|
|
|
6866
6873
|
return null;
|
|
6867
6874
|
}
|
|
6868
6875
|
|
|
6869
|
-
// let's update the local value
|
|
6870
|
-
if (this.audio
|
|
6871
|
-
|
|
6872
|
-
|
|
6876
|
+
// let's update the local audio value
|
|
6877
|
+
if (this.audio) {
|
|
6878
|
+
this.audio = {
|
|
6879
|
+
deviceId: {
|
|
6880
|
+
exact: id,
|
|
6881
|
+
},
|
|
6882
|
+
};
|
|
6873
6883
|
}
|
|
6874
6884
|
|
|
6875
6885
|
if (session) {
|
|
@@ -6882,6 +6892,9 @@ class WebRTCClient extends Emitter {
|
|
|
6882
6892
|
const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
|
|
6883
6893
|
|
|
6884
6894
|
if (sender) {
|
|
6895
|
+
if (sender.track) {
|
|
6896
|
+
audioTrack.enabled = sender.track.enabled;
|
|
6897
|
+
}
|
|
6885
6898
|
sender.replaceTrack(audioTrack);
|
|
6886
6899
|
}
|
|
6887
6900
|
|
|
@@ -6906,7 +6919,7 @@ class WebRTCClient extends Emitter {
|
|
|
6906
6919
|
return null;
|
|
6907
6920
|
}
|
|
6908
6921
|
|
|
6909
|
-
// let's update the local value
|
|
6922
|
+
// let's update the local video value
|
|
6910
6923
|
if (this.video) {
|
|
6911
6924
|
this.video = {
|
|
6912
6925
|
deviceId: {
|
|
@@ -6941,12 +6954,21 @@ class WebRTCClient extends Emitter {
|
|
|
6941
6954
|
return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
|
|
6942
6955
|
const videoTrack = stream.getVideoTracks()[0];
|
|
6943
6956
|
let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
|
|
6957
|
+
let wasTrackEnabled = false;
|
|
6944
6958
|
if (!sender) {
|
|
6945
6959
|
sender = pc && pc.getSenders().find(s => !s.track);
|
|
6946
6960
|
}
|
|
6947
6961
|
|
|
6948
6962
|
if (sender) {
|
|
6949
|
-
|
|
6963
|
+
// No video track means video not enabled
|
|
6964
|
+
wasTrackEnabled = sender.track ? sender.track.enabled : false;
|
|
6965
|
+
videoTrack.enabled = wasTrackEnabled;
|
|
6966
|
+
|
|
6967
|
+
if (!wasTrackEnabled) {
|
|
6968
|
+
videoTrack.stop();
|
|
6969
|
+
}
|
|
6970
|
+
|
|
6971
|
+
sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
|
|
6950
6972
|
}
|
|
6951
6973
|
|
|
6952
6974
|
// let's update the local stream
|
|
@@ -7630,6 +7652,7 @@ class WebRTCClient extends Emitter {
|
|
|
7630
7652
|
|
|
7631
7653
|
this.updateRemoteStream(this.getSipSessionId(session));
|
|
7632
7654
|
|
|
7655
|
+
const pc = session.sessionDescriptionHandler.peerConnection;
|
|
7633
7656
|
const onTrack = (event ) => {
|
|
7634
7657
|
const isAudioOnly = this._isAudioOnly(session);
|
|
7635
7658
|
const { kind, label, readyState, id, muted } = event.track;
|
|
@@ -7649,6 +7672,12 @@ class WebRTCClient extends Emitter {
|
|
|
7649
7672
|
|
|
7650
7673
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
7651
7674
|
|
|
7675
|
+
pc.oniceconnectionstatechange = () => {
|
|
7676
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
7677
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
7678
|
+
}
|
|
7679
|
+
};
|
|
7680
|
+
|
|
7652
7681
|
if (withEvent) {
|
|
7653
7682
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
7654
7683
|
}
|
|
@@ -7844,24 +7873,89 @@ class WebRTCClient extends Emitter {
|
|
|
7844
7873
|
const session = this.getSipSession(sessionId);
|
|
7845
7874
|
|
|
7846
7875
|
const stats = session ? await this.getStats(session) : null;
|
|
7847
|
-
if (!stats) {
|
|
7876
|
+
if (!stats || !(sessionId in this.sessionNetworkStats)) {
|
|
7848
7877
|
return;
|
|
7849
7878
|
}
|
|
7850
7879
|
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7880
|
+
const networkStats = {
|
|
7881
|
+
audioBytesSent: 0,
|
|
7882
|
+
videoBytesSent: 0,
|
|
7883
|
+
videoBytesReceived: 0,
|
|
7884
|
+
audioBytesReceived: 0,
|
|
7885
|
+
};
|
|
7886
|
+
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
7887
|
+
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
7888
|
+
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
7889
|
+
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
7890
|
+
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
7891
|
+
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
7892
|
+
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
7893
|
+
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
7894
|
+
let audioBytesSent = 0;
|
|
7895
|
+
let audioBytesReceived = 0;
|
|
7896
|
+
let videoBytesSent = 0;
|
|
7897
|
+
let videoBytesReceived = 0;
|
|
7898
|
+
let transportSent = 0;
|
|
7899
|
+
let transportReceived = 0;
|
|
7900
|
+
let packetsLost = 0;
|
|
7859
7901
|
|
|
7860
|
-
|
|
7861
|
-
|
|
7902
|
+
stats.forEach(report => {
|
|
7903
|
+
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
7904
|
+
audioBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7905
|
+
}
|
|
7906
|
+
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
7907
|
+
audioBytesSent += report.bytesSent;
|
|
7908
|
+
}
|
|
7909
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7910
|
+
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7911
|
+
}
|
|
7912
|
+
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
7913
|
+
packetsLost += report.packetsLost;
|
|
7914
|
+
networkStats.packetsReceived = report.packetsReceived;
|
|
7915
|
+
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7916
|
+
}
|
|
7917
|
+
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
7918
|
+
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7919
|
+
}
|
|
7920
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7921
|
+
if ('framesPerSecond' in report) {
|
|
7922
|
+
networkStats.framesPerSecond = report.framesPerSecond;
|
|
7862
7923
|
}
|
|
7924
|
+
if ('framerateMean' in report) {
|
|
7925
|
+
// framerateMean is only available in FF
|
|
7926
|
+
networkStats.framesPerSecond = Math.round(report.framerateMean);
|
|
7927
|
+
}
|
|
7928
|
+
}
|
|
7929
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
7930
|
+
packetsLost += report.packetsLost;
|
|
7931
|
+
networkStats.roundTripTime = report.roundTripTime;
|
|
7932
|
+
networkStats.jitter = report.jitter;
|
|
7933
|
+
}
|
|
7934
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
7935
|
+
packetsLost += report.packetsLost;
|
|
7936
|
+
}
|
|
7937
|
+
if (report.type === 'transport') {
|
|
7938
|
+
transportSent += report.bytesSent;
|
|
7939
|
+
transportReceived += report.bytesReceived;
|
|
7863
7940
|
}
|
|
7864
7941
|
});
|
|
7942
|
+
|
|
7943
|
+
networkStats.packetsLost = packetsLost;
|
|
7944
|
+
networkStats.audioBytesSent = audioBytesSent;
|
|
7945
|
+
networkStats.audioBytesReceived = audioBytesReceived;
|
|
7946
|
+
networkStats.videoBytesSent = videoBytesSent;
|
|
7947
|
+
networkStats.videoBytesReceived = videoBytesReceived;
|
|
7948
|
+
networkStats.transportSent = transportSent;
|
|
7949
|
+
networkStats.transportReceived = transportReceived;
|
|
7950
|
+
|
|
7951
|
+
const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
|
|
7952
|
+
+ (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
|
|
7953
|
+
+ (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
|
|
7954
|
+
|
|
7955
|
+
networkStats.bandwidth = bandwidth;
|
|
7956
|
+
|
|
7957
|
+
this.eventEmitter.emit(ON_NETWORK_STATS, session, networkStats, this.sessionNetworkStats[sessionId]);
|
|
7958
|
+
this.sessionNetworkStats[sessionId].push(networkStats);
|
|
7865
7959
|
}
|
|
7866
7960
|
|
|
7867
7961
|
}
|
|
@@ -388,7 +388,7 @@ class IssueReporter {
|
|
|
388
388
|
payload._retry = retry + 1;
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
-
this._sendDebugToGrafana(
|
|
391
|
+
this._sendDebugToGrafana(payload, retry + 1);
|
|
392
392
|
}, 5000 + retry * 1000);
|
|
393
393
|
});
|
|
394
394
|
}
|
|
@@ -2591,7 +2591,8 @@ class ExternalApp {
|
|
|
2591
2591
|
|
|
2592
2592
|
|
|
2593
2593
|
|
|
2594
|
-
|
|
2594
|
+
|
|
2595
|
+
|
|
2595
2596
|
|
|
2596
2597
|
|
|
2597
2598
|
class Meeting {
|
|
@@ -2603,6 +2604,7 @@ class Meeting {
|
|
|
2603
2604
|
|
|
2604
2605
|
|
|
2605
2606
|
|
|
2607
|
+
|
|
2606
2608
|
|
|
2607
2609
|
|
|
2608
2610
|
static parse(plain ) {
|
|
@@ -2614,6 +2616,7 @@ class Meeting {
|
|
|
2614
2616
|
port: plain.port,
|
|
2615
2617
|
uuid: plain.uuid,
|
|
2616
2618
|
number: plain.number,
|
|
2619
|
+
persistent: plain.persistent,
|
|
2617
2620
|
});
|
|
2618
2621
|
}
|
|
2619
2622
|
|
|
@@ -2621,7 +2624,7 @@ class Meeting {
|
|
|
2621
2624
|
return newFrom(meeting, Meeting);
|
|
2622
2625
|
}
|
|
2623
2626
|
|
|
2624
|
-
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
|
|
2627
|
+
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
|
|
2625
2628
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2626
2629
|
this.uri = uri;
|
|
2627
2630
|
this.name = name;
|
|
@@ -2629,6 +2632,7 @@ class Meeting {
|
|
|
2629
2632
|
this.port = port;
|
|
2630
2633
|
this.uuid = uuid;
|
|
2631
2634
|
this.number = number;
|
|
2635
|
+
this.persistent = persistent;
|
|
2632
2636
|
|
|
2633
2637
|
// Useful to compare instead of instanceof with minified code
|
|
2634
2638
|
this.type = 'Meeting';
|
|
@@ -3192,7 +3196,7 @@ class Recording {
|
|
|
3192
3196
|
|
|
3193
3197
|
|
|
3194
3198
|
|
|
3195
|
-
static parseMany(recordings
|
|
3199
|
+
static parseMany(recordings = []) {
|
|
3196
3200
|
return recordings.map(item => Recording.parse(item));
|
|
3197
3201
|
}
|
|
3198
3202
|
|
|
@@ -3318,7 +3322,7 @@ class CallLog {
|
|
|
3318
3322
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3319
3323
|
start: moment__default['default'](plain.start).toDate(),
|
|
3320
3324
|
end: plain.end ? moment__default['default'](plain.end).toDate() : null,
|
|
3321
|
-
recordings: Recording.parseMany(plain.recordings),
|
|
3325
|
+
recordings: Recording.parseMany(plain.recordings || []),
|
|
3322
3326
|
});
|
|
3323
3327
|
}
|
|
3324
3328
|
|
|
@@ -388,7 +388,7 @@ class IssueReporter {
|
|
|
388
388
|
payload._retry = retry + 1;
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
-
this._sendDebugToGrafana(
|
|
391
|
+
this._sendDebugToGrafana(payload, retry + 1);
|
|
392
392
|
}, 5000 + retry * 1000);
|
|
393
393
|
});
|
|
394
394
|
}
|
|
@@ -2591,7 +2591,8 @@ class ExternalApp {
|
|
|
2591
2591
|
|
|
2592
2592
|
|
|
2593
2593
|
|
|
2594
|
-
|
|
2594
|
+
|
|
2595
|
+
|
|
2595
2596
|
|
|
2596
2597
|
|
|
2597
2598
|
class Meeting {
|
|
@@ -2603,6 +2604,7 @@ class Meeting {
|
|
|
2603
2604
|
|
|
2604
2605
|
|
|
2605
2606
|
|
|
2607
|
+
|
|
2606
2608
|
|
|
2607
2609
|
|
|
2608
2610
|
static parse(plain ) {
|
|
@@ -2614,6 +2616,7 @@ class Meeting {
|
|
|
2614
2616
|
port: plain.port,
|
|
2615
2617
|
uuid: plain.uuid,
|
|
2616
2618
|
number: plain.number,
|
|
2619
|
+
persistent: plain.persistent,
|
|
2617
2620
|
});
|
|
2618
2621
|
}
|
|
2619
2622
|
|
|
@@ -2621,7 +2624,7 @@ class Meeting {
|
|
|
2621
2624
|
return newFrom(meeting, Meeting);
|
|
2622
2625
|
}
|
|
2623
2626
|
|
|
2624
|
-
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
|
|
2627
|
+
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
|
|
2625
2628
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2626
2629
|
this.uri = uri;
|
|
2627
2630
|
this.name = name;
|
|
@@ -2629,6 +2632,7 @@ class Meeting {
|
|
|
2629
2632
|
this.port = port;
|
|
2630
2633
|
this.uuid = uuid;
|
|
2631
2634
|
this.number = number;
|
|
2635
|
+
this.persistent = persistent;
|
|
2632
2636
|
|
|
2633
2637
|
// Useful to compare instead of instanceof with minified code
|
|
2634
2638
|
this.type = 'Meeting';
|
|
@@ -3192,7 +3196,7 @@ class Recording {
|
|
|
3192
3196
|
|
|
3193
3197
|
|
|
3194
3198
|
|
|
3195
|
-
static parseMany(recordings
|
|
3199
|
+
static parseMany(recordings = []) {
|
|
3196
3200
|
return recordings.map(item => Recording.parse(item));
|
|
3197
3201
|
}
|
|
3198
3202
|
|
|
@@ -3318,7 +3322,7 @@ class CallLog {
|
|
|
3318
3322
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3319
3323
|
start: moment__default['default'](plain.start).toDate(),
|
|
3320
3324
|
end: plain.end ? moment__default['default'](plain.end).toDate() : null,
|
|
3321
|
-
recordings: Recording.parseMany(plain.recordings),
|
|
3325
|
+
recordings: Recording.parseMany(plain.recordings || []),
|
|
3322
3326
|
});
|
|
3323
3327
|
}
|
|
3324
3328
|
|
|
@@ -410,7 +410,7 @@ class IssueReporter {
|
|
|
410
410
|
payload._retry = retry + 1;
|
|
411
411
|
}
|
|
412
412
|
|
|
413
|
-
this._sendDebugToGrafana(
|
|
413
|
+
this._sendDebugToGrafana(payload, retry + 1);
|
|
414
414
|
}, 5000 + retry * 1000);
|
|
415
415
|
});
|
|
416
416
|
}
|
|
@@ -2613,7 +2613,8 @@ class ExternalApp {
|
|
|
2613
2613
|
|
|
2614
2614
|
|
|
2615
2615
|
|
|
2616
|
-
|
|
2616
|
+
|
|
2617
|
+
|
|
2617
2618
|
|
|
2618
2619
|
|
|
2619
2620
|
class Meeting {
|
|
@@ -2625,6 +2626,7 @@ class Meeting {
|
|
|
2625
2626
|
|
|
2626
2627
|
|
|
2627
2628
|
|
|
2629
|
+
|
|
2628
2630
|
|
|
2629
2631
|
|
|
2630
2632
|
static parse(plain ) {
|
|
@@ -2636,6 +2638,7 @@ class Meeting {
|
|
|
2636
2638
|
port: plain.port,
|
|
2637
2639
|
uuid: plain.uuid,
|
|
2638
2640
|
number: plain.number,
|
|
2641
|
+
persistent: plain.persistent,
|
|
2639
2642
|
});
|
|
2640
2643
|
}
|
|
2641
2644
|
|
|
@@ -2643,7 +2646,7 @@ class Meeting {
|
|
|
2643
2646
|
return newFrom(meeting, Meeting);
|
|
2644
2647
|
}
|
|
2645
2648
|
|
|
2646
|
-
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
|
|
2649
|
+
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
|
|
2647
2650
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2648
2651
|
this.uri = uri;
|
|
2649
2652
|
this.name = name;
|
|
@@ -2651,6 +2654,7 @@ class Meeting {
|
|
|
2651
2654
|
this.port = port;
|
|
2652
2655
|
this.uuid = uuid;
|
|
2653
2656
|
this.number = number;
|
|
2657
|
+
this.persistent = persistent;
|
|
2654
2658
|
|
|
2655
2659
|
// Useful to compare instead of instanceof with minified code
|
|
2656
2660
|
this.type = 'Meeting';
|
|
@@ -3240,7 +3244,7 @@ class Recording {
|
|
|
3240
3244
|
|
|
3241
3245
|
|
|
3242
3246
|
|
|
3243
|
-
static parseMany(recordings
|
|
3247
|
+
static parseMany(recordings = []) {
|
|
3244
3248
|
return recordings.map(item => Recording.parse(item));
|
|
3245
3249
|
}
|
|
3246
3250
|
|
|
@@ -3366,7 +3370,7 @@ class CallLog {
|
|
|
3366
3370
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3367
3371
|
start: moment__default['default'](plain.start).toDate(),
|
|
3368
3372
|
end: plain.end ? moment__default['default'](plain.end).toDate() : null,
|
|
3369
|
-
recordings: Recording.parseMany(plain.recordings),
|
|
3373
|
+
recordings: Recording.parseMany(plain.recordings || []),
|
|
3370
3374
|
});
|
|
3371
3375
|
}
|
|
3372
3376
|
|
|
@@ -5881,6 +5885,7 @@ const ON_REINVITE = 'reinvite';
|
|
|
5881
5885
|
const ON_ERROR = 'onError';
|
|
5882
5886
|
const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
|
|
5883
5887
|
const ON_NETWORK_STATS = 'onNetworkStats';
|
|
5888
|
+
const ON_DISCONNECTED = 'onDisconnected';
|
|
5884
5889
|
class CanceledCallError extends Error {}
|
|
5885
5890
|
|
|
5886
5891
|
const MAX_REGISTER_TRIES = 10;
|
|
@@ -5954,6 +5959,7 @@ class WebRTCClient extends Emitter {
|
|
|
5954
5959
|
|
|
5955
5960
|
|
|
5956
5961
|
|
|
5962
|
+
|
|
5957
5963
|
|
|
5958
5964
|
static isAPrivateIp(ip ) {
|
|
5959
5965
|
const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
|
|
@@ -6019,6 +6025,7 @@ class WebRTCClient extends Emitter {
|
|
|
6019
6025
|
this.ON_ERROR = ON_ERROR;
|
|
6020
6026
|
this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
|
|
6021
6027
|
this.ON_NETWORK_STATS = ON_NETWORK_STATS;
|
|
6028
|
+
this.ON_DISCONNECTED = ON_DISCONNECTED;
|
|
6022
6029
|
}
|
|
6023
6030
|
|
|
6024
6031
|
configureMedia(media ) {
|
|
@@ -6620,7 +6627,7 @@ class WebRTCClient extends Emitter {
|
|
|
6620
6627
|
// We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
|
|
6621
6628
|
const transceivers = pc.getTransceivers();
|
|
6622
6629
|
const transceiverIdx = lastIndexOf(transceivers, transceiver =>
|
|
6623
|
-
transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
|
|
6630
|
+
transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
|
|
6624
6631
|
|
|
6625
6632
|
videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
|
|
6626
6633
|
} else {
|
|
@@ -6866,10 +6873,13 @@ class WebRTCClient extends Emitter {
|
|
|
6866
6873
|
return null;
|
|
6867
6874
|
}
|
|
6868
6875
|
|
|
6869
|
-
// let's update the local value
|
|
6870
|
-
if (this.audio
|
|
6871
|
-
|
|
6872
|
-
|
|
6876
|
+
// let's update the local audio value
|
|
6877
|
+
if (this.audio) {
|
|
6878
|
+
this.audio = {
|
|
6879
|
+
deviceId: {
|
|
6880
|
+
exact: id,
|
|
6881
|
+
},
|
|
6882
|
+
};
|
|
6873
6883
|
}
|
|
6874
6884
|
|
|
6875
6885
|
if (session) {
|
|
@@ -6882,6 +6892,9 @@ class WebRTCClient extends Emitter {
|
|
|
6882
6892
|
const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
|
|
6883
6893
|
|
|
6884
6894
|
if (sender) {
|
|
6895
|
+
if (sender.track) {
|
|
6896
|
+
audioTrack.enabled = sender.track.enabled;
|
|
6897
|
+
}
|
|
6885
6898
|
sender.replaceTrack(audioTrack);
|
|
6886
6899
|
}
|
|
6887
6900
|
|
|
@@ -6906,7 +6919,7 @@ class WebRTCClient extends Emitter {
|
|
|
6906
6919
|
return null;
|
|
6907
6920
|
}
|
|
6908
6921
|
|
|
6909
|
-
// let's update the local value
|
|
6922
|
+
// let's update the local video value
|
|
6910
6923
|
if (this.video) {
|
|
6911
6924
|
this.video = {
|
|
6912
6925
|
deviceId: {
|
|
@@ -6941,12 +6954,21 @@ class WebRTCClient extends Emitter {
|
|
|
6941
6954
|
return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
|
|
6942
6955
|
const videoTrack = stream.getVideoTracks()[0];
|
|
6943
6956
|
let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
|
|
6957
|
+
let wasTrackEnabled = false;
|
|
6944
6958
|
if (!sender) {
|
|
6945
6959
|
sender = pc && pc.getSenders().find(s => !s.track);
|
|
6946
6960
|
}
|
|
6947
6961
|
|
|
6948
6962
|
if (sender) {
|
|
6949
|
-
|
|
6963
|
+
// No video track means video not enabled
|
|
6964
|
+
wasTrackEnabled = sender.track ? sender.track.enabled : false;
|
|
6965
|
+
videoTrack.enabled = wasTrackEnabled;
|
|
6966
|
+
|
|
6967
|
+
if (!wasTrackEnabled) {
|
|
6968
|
+
videoTrack.stop();
|
|
6969
|
+
}
|
|
6970
|
+
|
|
6971
|
+
sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
|
|
6950
6972
|
}
|
|
6951
6973
|
|
|
6952
6974
|
// let's update the local stream
|
|
@@ -7630,6 +7652,7 @@ class WebRTCClient extends Emitter {
|
|
|
7630
7652
|
|
|
7631
7653
|
this.updateRemoteStream(this.getSipSessionId(session));
|
|
7632
7654
|
|
|
7655
|
+
const pc = session.sessionDescriptionHandler.peerConnection;
|
|
7633
7656
|
const onTrack = (event ) => {
|
|
7634
7657
|
const isAudioOnly = this._isAudioOnly(session);
|
|
7635
7658
|
const { kind, label, readyState, id, muted } = event.track;
|
|
@@ -7649,6 +7672,12 @@ class WebRTCClient extends Emitter {
|
|
|
7649
7672
|
|
|
7650
7673
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
7651
7674
|
|
|
7675
|
+
pc.oniceconnectionstatechange = () => {
|
|
7676
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
7677
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
7678
|
+
}
|
|
7679
|
+
};
|
|
7680
|
+
|
|
7652
7681
|
if (withEvent) {
|
|
7653
7682
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
7654
7683
|
}
|
|
@@ -7844,24 +7873,89 @@ class WebRTCClient extends Emitter {
|
|
|
7844
7873
|
const session = this.getSipSession(sessionId);
|
|
7845
7874
|
|
|
7846
7875
|
const stats = session ? await this.getStats(session) : null;
|
|
7847
|
-
if (!stats) {
|
|
7876
|
+
if (!stats || !(sessionId in this.sessionNetworkStats)) {
|
|
7848
7877
|
return;
|
|
7849
7878
|
}
|
|
7850
7879
|
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7880
|
+
const networkStats = {
|
|
7881
|
+
audioBytesSent: 0,
|
|
7882
|
+
videoBytesSent: 0,
|
|
7883
|
+
videoBytesReceived: 0,
|
|
7884
|
+
audioBytesReceived: 0,
|
|
7885
|
+
};
|
|
7886
|
+
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
7887
|
+
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
7888
|
+
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
7889
|
+
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
7890
|
+
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
7891
|
+
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
7892
|
+
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
7893
|
+
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
7894
|
+
let audioBytesSent = 0;
|
|
7895
|
+
let audioBytesReceived = 0;
|
|
7896
|
+
let videoBytesSent = 0;
|
|
7897
|
+
let videoBytesReceived = 0;
|
|
7898
|
+
let transportSent = 0;
|
|
7899
|
+
let transportReceived = 0;
|
|
7900
|
+
let packetsLost = 0;
|
|
7859
7901
|
|
|
7860
|
-
|
|
7861
|
-
|
|
7902
|
+
stats.forEach(report => {
|
|
7903
|
+
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
7904
|
+
audioBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7905
|
+
}
|
|
7906
|
+
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
7907
|
+
audioBytesSent += report.bytesSent;
|
|
7908
|
+
}
|
|
7909
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7910
|
+
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7911
|
+
}
|
|
7912
|
+
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
7913
|
+
packetsLost += report.packetsLost;
|
|
7914
|
+
networkStats.packetsReceived = report.packetsReceived;
|
|
7915
|
+
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7916
|
+
}
|
|
7917
|
+
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
7918
|
+
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7919
|
+
}
|
|
7920
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7921
|
+
if ('framesPerSecond' in report) {
|
|
7922
|
+
networkStats.framesPerSecond = report.framesPerSecond;
|
|
7862
7923
|
}
|
|
7924
|
+
if ('framerateMean' in report) {
|
|
7925
|
+
// framerateMean is only available in FF
|
|
7926
|
+
networkStats.framesPerSecond = Math.round(report.framerateMean);
|
|
7927
|
+
}
|
|
7928
|
+
}
|
|
7929
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
7930
|
+
packetsLost += report.packetsLost;
|
|
7931
|
+
networkStats.roundTripTime = report.roundTripTime;
|
|
7932
|
+
networkStats.jitter = report.jitter;
|
|
7933
|
+
}
|
|
7934
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
7935
|
+
packetsLost += report.packetsLost;
|
|
7936
|
+
}
|
|
7937
|
+
if (report.type === 'transport') {
|
|
7938
|
+
transportSent += report.bytesSent;
|
|
7939
|
+
transportReceived += report.bytesReceived;
|
|
7863
7940
|
}
|
|
7864
7941
|
});
|
|
7942
|
+
|
|
7943
|
+
networkStats.packetsLost = packetsLost;
|
|
7944
|
+
networkStats.audioBytesSent = audioBytesSent;
|
|
7945
|
+
networkStats.audioBytesReceived = audioBytesReceived;
|
|
7946
|
+
networkStats.videoBytesSent = videoBytesSent;
|
|
7947
|
+
networkStats.videoBytesReceived = videoBytesReceived;
|
|
7948
|
+
networkStats.transportSent = transportSent;
|
|
7949
|
+
networkStats.transportReceived = transportReceived;
|
|
7950
|
+
|
|
7951
|
+
const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
|
|
7952
|
+
+ (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
|
|
7953
|
+
+ (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
|
|
7954
|
+
|
|
7955
|
+
networkStats.bandwidth = bandwidth;
|
|
7956
|
+
|
|
7957
|
+
this.eventEmitter.emit(ON_NETWORK_STATS, session, networkStats, this.sessionNetworkStats[sessionId]);
|
|
7958
|
+
this.sessionNetworkStats[sessionId].push(networkStats);
|
|
7865
7959
|
}
|
|
7866
7960
|
|
|
7867
7961
|
}
|