@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/esm/checker/Checker.js
CHANGED
|
@@ -400,7 +400,7 @@ class IssueReporter {
|
|
|
400
400
|
payload._retry = retry + 1;
|
|
401
401
|
}
|
|
402
402
|
|
|
403
|
-
this._sendDebugToGrafana(
|
|
403
|
+
this._sendDebugToGrafana(payload, retry + 1);
|
|
404
404
|
}, 5000 + retry * 1000);
|
|
405
405
|
});
|
|
406
406
|
}
|
|
@@ -2603,7 +2603,8 @@ class ExternalApp {
|
|
|
2603
2603
|
|
|
2604
2604
|
|
|
2605
2605
|
|
|
2606
|
-
|
|
2606
|
+
|
|
2607
|
+
|
|
2607
2608
|
|
|
2608
2609
|
|
|
2609
2610
|
class Meeting {
|
|
@@ -2615,6 +2616,7 @@ class Meeting {
|
|
|
2615
2616
|
|
|
2616
2617
|
|
|
2617
2618
|
|
|
2619
|
+
|
|
2618
2620
|
|
|
2619
2621
|
|
|
2620
2622
|
static parse(plain ) {
|
|
@@ -2626,6 +2628,7 @@ class Meeting {
|
|
|
2626
2628
|
port: plain.port,
|
|
2627
2629
|
uuid: plain.uuid,
|
|
2628
2630
|
number: plain.number,
|
|
2631
|
+
persistent: plain.persistent,
|
|
2629
2632
|
});
|
|
2630
2633
|
}
|
|
2631
2634
|
|
|
@@ -2633,7 +2636,7 @@ class Meeting {
|
|
|
2633
2636
|
return newFrom(meeting, Meeting);
|
|
2634
2637
|
}
|
|
2635
2638
|
|
|
2636
|
-
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
|
|
2639
|
+
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
|
|
2637
2640
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2638
2641
|
this.uri = uri;
|
|
2639
2642
|
this.name = name;
|
|
@@ -2641,6 +2644,7 @@ class Meeting {
|
|
|
2641
2644
|
this.port = port;
|
|
2642
2645
|
this.uuid = uuid;
|
|
2643
2646
|
this.number = number;
|
|
2647
|
+
this.persistent = persistent;
|
|
2644
2648
|
|
|
2645
2649
|
// Useful to compare instead of instanceof with minified code
|
|
2646
2650
|
this.type = 'Meeting';
|
|
@@ -3230,7 +3234,7 @@ class Recording {
|
|
|
3230
3234
|
|
|
3231
3235
|
|
|
3232
3236
|
|
|
3233
|
-
static parseMany(recordings
|
|
3237
|
+
static parseMany(recordings = []) {
|
|
3234
3238
|
return recordings.map(item => Recording.parse(item));
|
|
3235
3239
|
}
|
|
3236
3240
|
|
|
@@ -3356,7 +3360,7 @@ class CallLog {
|
|
|
3356
3360
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3357
3361
|
start: moment(plain.start).toDate(),
|
|
3358
3362
|
end: plain.end ? moment(plain.end).toDate() : null,
|
|
3359
|
-
recordings: Recording.parseMany(plain.recordings),
|
|
3363
|
+
recordings: Recording.parseMany(plain.recordings || []),
|
|
3360
3364
|
});
|
|
3361
3365
|
}
|
|
3362
3366
|
|
|
@@ -5871,6 +5875,7 @@ const ON_REINVITE = 'reinvite';
|
|
|
5871
5875
|
const ON_ERROR = 'onError';
|
|
5872
5876
|
const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
|
|
5873
5877
|
const ON_NETWORK_STATS = 'onNetworkStats';
|
|
5878
|
+
const ON_DISCONNECTED = 'onDisconnected';
|
|
5874
5879
|
class CanceledCallError extends Error {}
|
|
5875
5880
|
|
|
5876
5881
|
const MAX_REGISTER_TRIES = 10;
|
|
@@ -5944,6 +5949,7 @@ class WebRTCClient extends Emitter {
|
|
|
5944
5949
|
|
|
5945
5950
|
|
|
5946
5951
|
|
|
5952
|
+
|
|
5947
5953
|
|
|
5948
5954
|
static isAPrivateIp(ip ) {
|
|
5949
5955
|
const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
|
|
@@ -6009,6 +6015,7 @@ class WebRTCClient extends Emitter {
|
|
|
6009
6015
|
this.ON_ERROR = ON_ERROR;
|
|
6010
6016
|
this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
|
|
6011
6017
|
this.ON_NETWORK_STATS = ON_NETWORK_STATS;
|
|
6018
|
+
this.ON_DISCONNECTED = ON_DISCONNECTED;
|
|
6012
6019
|
}
|
|
6013
6020
|
|
|
6014
6021
|
configureMedia(media ) {
|
|
@@ -6610,7 +6617,7 @@ class WebRTCClient extends Emitter {
|
|
|
6610
6617
|
// We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
|
|
6611
6618
|
const transceivers = pc.getTransceivers();
|
|
6612
6619
|
const transceiverIdx = lastIndexOf(transceivers, transceiver =>
|
|
6613
|
-
transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
|
|
6620
|
+
transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
|
|
6614
6621
|
|
|
6615
6622
|
videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
|
|
6616
6623
|
} else {
|
|
@@ -6856,10 +6863,13 @@ class WebRTCClient extends Emitter {
|
|
|
6856
6863
|
return null;
|
|
6857
6864
|
}
|
|
6858
6865
|
|
|
6859
|
-
// let's update the local value
|
|
6860
|
-
if (this.audio
|
|
6861
|
-
|
|
6862
|
-
|
|
6866
|
+
// let's update the local audio value
|
|
6867
|
+
if (this.audio) {
|
|
6868
|
+
this.audio = {
|
|
6869
|
+
deviceId: {
|
|
6870
|
+
exact: id,
|
|
6871
|
+
},
|
|
6872
|
+
};
|
|
6863
6873
|
}
|
|
6864
6874
|
|
|
6865
6875
|
if (session) {
|
|
@@ -6872,6 +6882,9 @@ class WebRTCClient extends Emitter {
|
|
|
6872
6882
|
const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
|
|
6873
6883
|
|
|
6874
6884
|
if (sender) {
|
|
6885
|
+
if (sender.track) {
|
|
6886
|
+
audioTrack.enabled = sender.track.enabled;
|
|
6887
|
+
}
|
|
6875
6888
|
sender.replaceTrack(audioTrack);
|
|
6876
6889
|
}
|
|
6877
6890
|
|
|
@@ -6896,7 +6909,7 @@ class WebRTCClient extends Emitter {
|
|
|
6896
6909
|
return null;
|
|
6897
6910
|
}
|
|
6898
6911
|
|
|
6899
|
-
// let's update the local value
|
|
6912
|
+
// let's update the local video value
|
|
6900
6913
|
if (this.video) {
|
|
6901
6914
|
this.video = {
|
|
6902
6915
|
deviceId: {
|
|
@@ -6931,12 +6944,21 @@ class WebRTCClient extends Emitter {
|
|
|
6931
6944
|
return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
|
|
6932
6945
|
const videoTrack = stream.getVideoTracks()[0];
|
|
6933
6946
|
let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
|
|
6947
|
+
let wasTrackEnabled = false;
|
|
6934
6948
|
if (!sender) {
|
|
6935
6949
|
sender = pc && pc.getSenders().find(s => !s.track);
|
|
6936
6950
|
}
|
|
6937
6951
|
|
|
6938
6952
|
if (sender) {
|
|
6939
|
-
|
|
6953
|
+
// No video track means video not enabled
|
|
6954
|
+
wasTrackEnabled = sender.track ? sender.track.enabled : false;
|
|
6955
|
+
videoTrack.enabled = wasTrackEnabled;
|
|
6956
|
+
|
|
6957
|
+
if (!wasTrackEnabled) {
|
|
6958
|
+
videoTrack.stop();
|
|
6959
|
+
}
|
|
6960
|
+
|
|
6961
|
+
sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
|
|
6940
6962
|
}
|
|
6941
6963
|
|
|
6942
6964
|
// let's update the local stream
|
|
@@ -7620,6 +7642,7 @@ class WebRTCClient extends Emitter {
|
|
|
7620
7642
|
|
|
7621
7643
|
this.updateRemoteStream(this.getSipSessionId(session));
|
|
7622
7644
|
|
|
7645
|
+
const pc = session.sessionDescriptionHandler.peerConnection;
|
|
7623
7646
|
const onTrack = (event ) => {
|
|
7624
7647
|
const isAudioOnly = this._isAudioOnly(session);
|
|
7625
7648
|
const { kind, label, readyState, id, muted } = event.track;
|
|
@@ -7639,6 +7662,12 @@ class WebRTCClient extends Emitter {
|
|
|
7639
7662
|
|
|
7640
7663
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
7641
7664
|
|
|
7665
|
+
pc.oniceconnectionstatechange = () => {
|
|
7666
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
7667
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
7668
|
+
}
|
|
7669
|
+
};
|
|
7670
|
+
|
|
7642
7671
|
if (withEvent) {
|
|
7643
7672
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
7644
7673
|
}
|
|
@@ -7834,24 +7863,89 @@ class WebRTCClient extends Emitter {
|
|
|
7834
7863
|
const session = this.getSipSession(sessionId);
|
|
7835
7864
|
|
|
7836
7865
|
const stats = session ? await this.getStats(session) : null;
|
|
7837
|
-
if (!stats) {
|
|
7866
|
+
if (!stats || !(sessionId in this.sessionNetworkStats)) {
|
|
7838
7867
|
return;
|
|
7839
7868
|
}
|
|
7840
7869
|
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
|
|
7870
|
+
const networkStats = {
|
|
7871
|
+
audioBytesSent: 0,
|
|
7872
|
+
videoBytesSent: 0,
|
|
7873
|
+
videoBytesReceived: 0,
|
|
7874
|
+
audioBytesReceived: 0,
|
|
7875
|
+
};
|
|
7876
|
+
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
7877
|
+
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
7878
|
+
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
7879
|
+
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
7880
|
+
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
7881
|
+
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
7882
|
+
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
7883
|
+
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
7884
|
+
let audioBytesSent = 0;
|
|
7885
|
+
let audioBytesReceived = 0;
|
|
7886
|
+
let videoBytesSent = 0;
|
|
7887
|
+
let videoBytesReceived = 0;
|
|
7888
|
+
let transportSent = 0;
|
|
7889
|
+
let transportReceived = 0;
|
|
7890
|
+
let packetsLost = 0;
|
|
7849
7891
|
|
|
7850
|
-
|
|
7851
|
-
|
|
7892
|
+
stats.forEach(report => {
|
|
7893
|
+
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
7894
|
+
audioBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7895
|
+
}
|
|
7896
|
+
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
7897
|
+
audioBytesSent += report.bytesSent;
|
|
7898
|
+
}
|
|
7899
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7900
|
+
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7901
|
+
}
|
|
7902
|
+
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
7903
|
+
packetsLost += report.packetsLost;
|
|
7904
|
+
networkStats.packetsReceived = report.packetsReceived;
|
|
7905
|
+
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7906
|
+
}
|
|
7907
|
+
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
7908
|
+
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7909
|
+
}
|
|
7910
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7911
|
+
if ('framesPerSecond' in report) {
|
|
7912
|
+
networkStats.framesPerSecond = report.framesPerSecond;
|
|
7852
7913
|
}
|
|
7914
|
+
if ('framerateMean' in report) {
|
|
7915
|
+
// framerateMean is only available in FF
|
|
7916
|
+
networkStats.framesPerSecond = Math.round(report.framerateMean);
|
|
7917
|
+
}
|
|
7918
|
+
}
|
|
7919
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
7920
|
+
packetsLost += report.packetsLost;
|
|
7921
|
+
networkStats.roundTripTime = report.roundTripTime;
|
|
7922
|
+
networkStats.jitter = report.jitter;
|
|
7923
|
+
}
|
|
7924
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
7925
|
+
packetsLost += report.packetsLost;
|
|
7926
|
+
}
|
|
7927
|
+
if (report.type === 'transport') {
|
|
7928
|
+
transportSent += report.bytesSent;
|
|
7929
|
+
transportReceived += report.bytesReceived;
|
|
7853
7930
|
}
|
|
7854
7931
|
});
|
|
7932
|
+
|
|
7933
|
+
networkStats.packetsLost = packetsLost;
|
|
7934
|
+
networkStats.audioBytesSent = audioBytesSent;
|
|
7935
|
+
networkStats.audioBytesReceived = audioBytesReceived;
|
|
7936
|
+
networkStats.videoBytesSent = videoBytesSent;
|
|
7937
|
+
networkStats.videoBytesReceived = videoBytesReceived;
|
|
7938
|
+
networkStats.transportSent = transportSent;
|
|
7939
|
+
networkStats.transportReceived = transportReceived;
|
|
7940
|
+
|
|
7941
|
+
const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
|
|
7942
|
+
+ (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
|
|
7943
|
+
+ (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
|
|
7944
|
+
|
|
7945
|
+
networkStats.bandwidth = bandwidth;
|
|
7946
|
+
|
|
7947
|
+
this.eventEmitter.emit(ON_NETWORK_STATS, session, networkStats, this.sessionNetworkStats[sessionId]);
|
|
7948
|
+
this.sessionNetworkStats[sessionId].push(networkStats);
|
|
7855
7949
|
}
|
|
7856
7950
|
|
|
7857
7951
|
}
|
|
@@ -382,7 +382,7 @@ class IssueReporter {
|
|
|
382
382
|
payload._retry = retry + 1;
|
|
383
383
|
}
|
|
384
384
|
|
|
385
|
-
this._sendDebugToGrafana(
|
|
385
|
+
this._sendDebugToGrafana(payload, retry + 1);
|
|
386
386
|
}, 5000 + retry * 1000);
|
|
387
387
|
});
|
|
388
388
|
}
|
|
@@ -2585,7 +2585,8 @@ class ExternalApp {
|
|
|
2585
2585
|
|
|
2586
2586
|
|
|
2587
2587
|
|
|
2588
|
-
|
|
2588
|
+
|
|
2589
|
+
|
|
2589
2590
|
|
|
2590
2591
|
|
|
2591
2592
|
class Meeting {
|
|
@@ -2597,6 +2598,7 @@ class Meeting {
|
|
|
2597
2598
|
|
|
2598
2599
|
|
|
2599
2600
|
|
|
2601
|
+
|
|
2600
2602
|
|
|
2601
2603
|
|
|
2602
2604
|
static parse(plain ) {
|
|
@@ -2608,6 +2610,7 @@ class Meeting {
|
|
|
2608
2610
|
port: plain.port,
|
|
2609
2611
|
uuid: plain.uuid,
|
|
2610
2612
|
number: plain.number,
|
|
2613
|
+
persistent: plain.persistent,
|
|
2611
2614
|
});
|
|
2612
2615
|
}
|
|
2613
2616
|
|
|
@@ -2615,7 +2618,7 @@ class Meeting {
|
|
|
2615
2618
|
return newFrom(meeting, Meeting);
|
|
2616
2619
|
}
|
|
2617
2620
|
|
|
2618
|
-
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
|
|
2621
|
+
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
|
|
2619
2622
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2620
2623
|
this.uri = uri;
|
|
2621
2624
|
this.name = name;
|
|
@@ -2623,6 +2626,7 @@ class Meeting {
|
|
|
2623
2626
|
this.port = port;
|
|
2624
2627
|
this.uuid = uuid;
|
|
2625
2628
|
this.number = number;
|
|
2629
|
+
this.persistent = persistent;
|
|
2626
2630
|
|
|
2627
2631
|
// Useful to compare instead of instanceof with minified code
|
|
2628
2632
|
this.type = 'Meeting';
|
|
@@ -3186,7 +3190,7 @@ class Recording {
|
|
|
3186
3190
|
|
|
3187
3191
|
|
|
3188
3192
|
|
|
3189
|
-
static parseMany(recordings
|
|
3193
|
+
static parseMany(recordings = []) {
|
|
3190
3194
|
return recordings.map(item => Recording.parse(item));
|
|
3191
3195
|
}
|
|
3192
3196
|
|
|
@@ -3312,7 +3316,7 @@ class CallLog {
|
|
|
3312
3316
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3313
3317
|
start: moment(plain.start).toDate(),
|
|
3314
3318
|
end: plain.end ? moment(plain.end).toDate() : null,
|
|
3315
|
-
recordings: Recording.parseMany(plain.recordings),
|
|
3319
|
+
recordings: Recording.parseMany(plain.recordings || []),
|
|
3316
3320
|
});
|
|
3317
3321
|
}
|
|
3318
3322
|
|
|
@@ -382,7 +382,7 @@ class IssueReporter {
|
|
|
382
382
|
payload._retry = retry + 1;
|
|
383
383
|
}
|
|
384
384
|
|
|
385
|
-
this._sendDebugToGrafana(
|
|
385
|
+
this._sendDebugToGrafana(payload, retry + 1);
|
|
386
386
|
}, 5000 + retry * 1000);
|
|
387
387
|
});
|
|
388
388
|
}
|
|
@@ -2585,7 +2585,8 @@ class ExternalApp {
|
|
|
2585
2585
|
|
|
2586
2586
|
|
|
2587
2587
|
|
|
2588
|
-
|
|
2588
|
+
|
|
2589
|
+
|
|
2589
2590
|
|
|
2590
2591
|
|
|
2591
2592
|
class Meeting {
|
|
@@ -2597,6 +2598,7 @@ class Meeting {
|
|
|
2597
2598
|
|
|
2598
2599
|
|
|
2599
2600
|
|
|
2601
|
+
|
|
2600
2602
|
|
|
2601
2603
|
|
|
2602
2604
|
static parse(plain ) {
|
|
@@ -2608,6 +2610,7 @@ class Meeting {
|
|
|
2608
2610
|
port: plain.port,
|
|
2609
2611
|
uuid: plain.uuid,
|
|
2610
2612
|
number: plain.number,
|
|
2613
|
+
persistent: plain.persistent,
|
|
2611
2614
|
});
|
|
2612
2615
|
}
|
|
2613
2616
|
|
|
@@ -2615,7 +2618,7 @@ class Meeting {
|
|
|
2615
2618
|
return newFrom(meeting, Meeting);
|
|
2616
2619
|
}
|
|
2617
2620
|
|
|
2618
|
-
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
|
|
2621
|
+
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
|
|
2619
2622
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2620
2623
|
this.uri = uri;
|
|
2621
2624
|
this.name = name;
|
|
@@ -2623,6 +2626,7 @@ class Meeting {
|
|
|
2623
2626
|
this.port = port;
|
|
2624
2627
|
this.uuid = uuid;
|
|
2625
2628
|
this.number = number;
|
|
2629
|
+
this.persistent = persistent;
|
|
2626
2630
|
|
|
2627
2631
|
// Useful to compare instead of instanceof with minified code
|
|
2628
2632
|
this.type = 'Meeting';
|
|
@@ -3186,7 +3190,7 @@ class Recording {
|
|
|
3186
3190
|
|
|
3187
3191
|
|
|
3188
3192
|
|
|
3189
|
-
static parseMany(recordings
|
|
3193
|
+
static parseMany(recordings = []) {
|
|
3190
3194
|
return recordings.map(item => Recording.parse(item));
|
|
3191
3195
|
}
|
|
3192
3196
|
|
|
@@ -3312,7 +3316,7 @@ class CallLog {
|
|
|
3312
3316
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3313
3317
|
start: moment(plain.start).toDate(),
|
|
3314
3318
|
end: plain.end ? moment(plain.end).toDate() : null,
|
|
3315
|
-
recordings: Recording.parseMany(plain.recordings),
|
|
3319
|
+
recordings: Recording.parseMany(plain.recordings || []),
|
|
3316
3320
|
});
|
|
3317
3321
|
}
|
|
3318
3322
|
|
|
@@ -400,7 +400,7 @@ class IssueReporter {
|
|
|
400
400
|
payload._retry = retry + 1;
|
|
401
401
|
}
|
|
402
402
|
|
|
403
|
-
this._sendDebugToGrafana(
|
|
403
|
+
this._sendDebugToGrafana(payload, retry + 1);
|
|
404
404
|
}, 5000 + retry * 1000);
|
|
405
405
|
});
|
|
406
406
|
}
|
|
@@ -2603,7 +2603,8 @@ class ExternalApp {
|
|
|
2603
2603
|
|
|
2604
2604
|
|
|
2605
2605
|
|
|
2606
|
-
|
|
2606
|
+
|
|
2607
|
+
|
|
2607
2608
|
|
|
2608
2609
|
|
|
2609
2610
|
class Meeting {
|
|
@@ -2615,6 +2616,7 @@ class Meeting {
|
|
|
2615
2616
|
|
|
2616
2617
|
|
|
2617
2618
|
|
|
2619
|
+
|
|
2618
2620
|
|
|
2619
2621
|
|
|
2620
2622
|
static parse(plain ) {
|
|
@@ -2626,6 +2628,7 @@ class Meeting {
|
|
|
2626
2628
|
port: plain.port,
|
|
2627
2629
|
uuid: plain.uuid,
|
|
2628
2630
|
number: plain.number,
|
|
2631
|
+
persistent: plain.persistent,
|
|
2629
2632
|
});
|
|
2630
2633
|
}
|
|
2631
2634
|
|
|
@@ -2633,7 +2636,7 @@ class Meeting {
|
|
|
2633
2636
|
return newFrom(meeting, Meeting);
|
|
2634
2637
|
}
|
|
2635
2638
|
|
|
2636
|
-
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
|
|
2639
|
+
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
|
|
2637
2640
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2638
2641
|
this.uri = uri;
|
|
2639
2642
|
this.name = name;
|
|
@@ -2641,6 +2644,7 @@ class Meeting {
|
|
|
2641
2644
|
this.port = port;
|
|
2642
2645
|
this.uuid = uuid;
|
|
2643
2646
|
this.number = number;
|
|
2647
|
+
this.persistent = persistent;
|
|
2644
2648
|
|
|
2645
2649
|
// Useful to compare instead of instanceof with minified code
|
|
2646
2650
|
this.type = 'Meeting';
|
|
@@ -3230,7 +3234,7 @@ class Recording {
|
|
|
3230
3234
|
|
|
3231
3235
|
|
|
3232
3236
|
|
|
3233
|
-
static parseMany(recordings
|
|
3237
|
+
static parseMany(recordings = []) {
|
|
3234
3238
|
return recordings.map(item => Recording.parse(item));
|
|
3235
3239
|
}
|
|
3236
3240
|
|
|
@@ -3356,7 +3360,7 @@ class CallLog {
|
|
|
3356
3360
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3357
3361
|
start: moment(plain.start).toDate(),
|
|
3358
3362
|
end: plain.end ? moment(plain.end).toDate() : null,
|
|
3359
|
-
recordings: Recording.parseMany(plain.recordings),
|
|
3363
|
+
recordings: Recording.parseMany(plain.recordings || []),
|
|
3360
3364
|
});
|
|
3361
3365
|
}
|
|
3362
3366
|
|
|
@@ -5871,6 +5875,7 @@ const ON_REINVITE = 'reinvite';
|
|
|
5871
5875
|
const ON_ERROR = 'onError';
|
|
5872
5876
|
const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
|
|
5873
5877
|
const ON_NETWORK_STATS = 'onNetworkStats';
|
|
5878
|
+
const ON_DISCONNECTED = 'onDisconnected';
|
|
5874
5879
|
class CanceledCallError extends Error {}
|
|
5875
5880
|
|
|
5876
5881
|
const MAX_REGISTER_TRIES = 10;
|
|
@@ -5944,6 +5949,7 @@ class WebRTCClient extends Emitter {
|
|
|
5944
5949
|
|
|
5945
5950
|
|
|
5946
5951
|
|
|
5952
|
+
|
|
5947
5953
|
|
|
5948
5954
|
static isAPrivateIp(ip ) {
|
|
5949
5955
|
const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
|
|
@@ -6009,6 +6015,7 @@ class WebRTCClient extends Emitter {
|
|
|
6009
6015
|
this.ON_ERROR = ON_ERROR;
|
|
6010
6016
|
this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
|
|
6011
6017
|
this.ON_NETWORK_STATS = ON_NETWORK_STATS;
|
|
6018
|
+
this.ON_DISCONNECTED = ON_DISCONNECTED;
|
|
6012
6019
|
}
|
|
6013
6020
|
|
|
6014
6021
|
configureMedia(media ) {
|
|
@@ -6610,7 +6617,7 @@ class WebRTCClient extends Emitter {
|
|
|
6610
6617
|
// We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
|
|
6611
6618
|
const transceivers = pc.getTransceivers();
|
|
6612
6619
|
const transceiverIdx = lastIndexOf(transceivers, transceiver =>
|
|
6613
|
-
transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
|
|
6620
|
+
transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
|
|
6614
6621
|
|
|
6615
6622
|
videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
|
|
6616
6623
|
} else {
|
|
@@ -6856,10 +6863,13 @@ class WebRTCClient extends Emitter {
|
|
|
6856
6863
|
return null;
|
|
6857
6864
|
}
|
|
6858
6865
|
|
|
6859
|
-
// let's update the local value
|
|
6860
|
-
if (this.audio
|
|
6861
|
-
|
|
6862
|
-
|
|
6866
|
+
// let's update the local audio value
|
|
6867
|
+
if (this.audio) {
|
|
6868
|
+
this.audio = {
|
|
6869
|
+
deviceId: {
|
|
6870
|
+
exact: id,
|
|
6871
|
+
},
|
|
6872
|
+
};
|
|
6863
6873
|
}
|
|
6864
6874
|
|
|
6865
6875
|
if (session) {
|
|
@@ -6872,6 +6882,9 @@ class WebRTCClient extends Emitter {
|
|
|
6872
6882
|
const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
|
|
6873
6883
|
|
|
6874
6884
|
if (sender) {
|
|
6885
|
+
if (sender.track) {
|
|
6886
|
+
audioTrack.enabled = sender.track.enabled;
|
|
6887
|
+
}
|
|
6875
6888
|
sender.replaceTrack(audioTrack);
|
|
6876
6889
|
}
|
|
6877
6890
|
|
|
@@ -6896,7 +6909,7 @@ class WebRTCClient extends Emitter {
|
|
|
6896
6909
|
return null;
|
|
6897
6910
|
}
|
|
6898
6911
|
|
|
6899
|
-
// let's update the local value
|
|
6912
|
+
// let's update the local video value
|
|
6900
6913
|
if (this.video) {
|
|
6901
6914
|
this.video = {
|
|
6902
6915
|
deviceId: {
|
|
@@ -6931,12 +6944,21 @@ class WebRTCClient extends Emitter {
|
|
|
6931
6944
|
return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
|
|
6932
6945
|
const videoTrack = stream.getVideoTracks()[0];
|
|
6933
6946
|
let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
|
|
6947
|
+
let wasTrackEnabled = false;
|
|
6934
6948
|
if (!sender) {
|
|
6935
6949
|
sender = pc && pc.getSenders().find(s => !s.track);
|
|
6936
6950
|
}
|
|
6937
6951
|
|
|
6938
6952
|
if (sender) {
|
|
6939
|
-
|
|
6953
|
+
// No video track means video not enabled
|
|
6954
|
+
wasTrackEnabled = sender.track ? sender.track.enabled : false;
|
|
6955
|
+
videoTrack.enabled = wasTrackEnabled;
|
|
6956
|
+
|
|
6957
|
+
if (!wasTrackEnabled) {
|
|
6958
|
+
videoTrack.stop();
|
|
6959
|
+
}
|
|
6960
|
+
|
|
6961
|
+
sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
|
|
6940
6962
|
}
|
|
6941
6963
|
|
|
6942
6964
|
// let's update the local stream
|
|
@@ -7620,6 +7642,7 @@ class WebRTCClient extends Emitter {
|
|
|
7620
7642
|
|
|
7621
7643
|
this.updateRemoteStream(this.getSipSessionId(session));
|
|
7622
7644
|
|
|
7645
|
+
const pc = session.sessionDescriptionHandler.peerConnection;
|
|
7623
7646
|
const onTrack = (event ) => {
|
|
7624
7647
|
const isAudioOnly = this._isAudioOnly(session);
|
|
7625
7648
|
const { kind, label, readyState, id, muted } = event.track;
|
|
@@ -7639,6 +7662,12 @@ class WebRTCClient extends Emitter {
|
|
|
7639
7662
|
|
|
7640
7663
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
7641
7664
|
|
|
7665
|
+
pc.oniceconnectionstatechange = () => {
|
|
7666
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
7667
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
7668
|
+
}
|
|
7669
|
+
};
|
|
7670
|
+
|
|
7642
7671
|
if (withEvent) {
|
|
7643
7672
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
7644
7673
|
}
|
|
@@ -7834,24 +7863,89 @@ class WebRTCClient extends Emitter {
|
|
|
7834
7863
|
const session = this.getSipSession(sessionId);
|
|
7835
7864
|
|
|
7836
7865
|
const stats = session ? await this.getStats(session) : null;
|
|
7837
|
-
if (!stats) {
|
|
7866
|
+
if (!stats || !(sessionId in this.sessionNetworkStats)) {
|
|
7838
7867
|
return;
|
|
7839
7868
|
}
|
|
7840
7869
|
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
|
|
7870
|
+
const networkStats = {
|
|
7871
|
+
audioBytesSent: 0,
|
|
7872
|
+
videoBytesSent: 0,
|
|
7873
|
+
videoBytesReceived: 0,
|
|
7874
|
+
audioBytesReceived: 0,
|
|
7875
|
+
};
|
|
7876
|
+
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
7877
|
+
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
7878
|
+
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
7879
|
+
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
7880
|
+
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
7881
|
+
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
7882
|
+
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
7883
|
+
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
7884
|
+
let audioBytesSent = 0;
|
|
7885
|
+
let audioBytesReceived = 0;
|
|
7886
|
+
let videoBytesSent = 0;
|
|
7887
|
+
let videoBytesReceived = 0;
|
|
7888
|
+
let transportSent = 0;
|
|
7889
|
+
let transportReceived = 0;
|
|
7890
|
+
let packetsLost = 0;
|
|
7849
7891
|
|
|
7850
|
-
|
|
7851
|
-
|
|
7892
|
+
stats.forEach(report => {
|
|
7893
|
+
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
7894
|
+
audioBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7895
|
+
}
|
|
7896
|
+
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
7897
|
+
audioBytesSent += report.bytesSent;
|
|
7898
|
+
}
|
|
7899
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7900
|
+
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7901
|
+
}
|
|
7902
|
+
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
7903
|
+
packetsLost += report.packetsLost;
|
|
7904
|
+
networkStats.packetsReceived = report.packetsReceived;
|
|
7905
|
+
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7906
|
+
}
|
|
7907
|
+
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
7908
|
+
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7909
|
+
}
|
|
7910
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7911
|
+
if ('framesPerSecond' in report) {
|
|
7912
|
+
networkStats.framesPerSecond = report.framesPerSecond;
|
|
7852
7913
|
}
|
|
7914
|
+
if ('framerateMean' in report) {
|
|
7915
|
+
// framerateMean is only available in FF
|
|
7916
|
+
networkStats.framesPerSecond = Math.round(report.framerateMean);
|
|
7917
|
+
}
|
|
7918
|
+
}
|
|
7919
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
7920
|
+
packetsLost += report.packetsLost;
|
|
7921
|
+
networkStats.roundTripTime = report.roundTripTime;
|
|
7922
|
+
networkStats.jitter = report.jitter;
|
|
7923
|
+
}
|
|
7924
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
7925
|
+
packetsLost += report.packetsLost;
|
|
7926
|
+
}
|
|
7927
|
+
if (report.type === 'transport') {
|
|
7928
|
+
transportSent += report.bytesSent;
|
|
7929
|
+
transportReceived += report.bytesReceived;
|
|
7853
7930
|
}
|
|
7854
7931
|
});
|
|
7932
|
+
|
|
7933
|
+
networkStats.packetsLost = packetsLost;
|
|
7934
|
+
networkStats.audioBytesSent = audioBytesSent;
|
|
7935
|
+
networkStats.audioBytesReceived = audioBytesReceived;
|
|
7936
|
+
networkStats.videoBytesSent = videoBytesSent;
|
|
7937
|
+
networkStats.videoBytesReceived = videoBytesReceived;
|
|
7938
|
+
networkStats.transportSent = transportSent;
|
|
7939
|
+
networkStats.transportReceived = transportReceived;
|
|
7940
|
+
|
|
7941
|
+
const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
|
|
7942
|
+
+ (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
|
|
7943
|
+
+ (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
|
|
7944
|
+
|
|
7945
|
+
networkStats.bandwidth = bandwidth;
|
|
7946
|
+
|
|
7947
|
+
this.eventEmitter.emit(ON_NETWORK_STATS, session, networkStats, this.sessionNetworkStats[sessionId]);
|
|
7948
|
+
this.sessionNetworkStats[sessionId].push(networkStats);
|
|
7855
7949
|
}
|
|
7856
7950
|
|
|
7857
7951
|
}
|