@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/simple/utils.js
CHANGED
|
@@ -1898,7 +1898,7 @@ class IssueReporter {
|
|
|
1898
1898
|
payload._retry = retry + 1;
|
|
1899
1899
|
}
|
|
1900
1900
|
|
|
1901
|
-
this._sendDebugToGrafana(
|
|
1901
|
+
this._sendDebugToGrafana(payload, retry + 1);
|
|
1902
1902
|
}, 5000 + retry * 1000);
|
|
1903
1903
|
});
|
|
1904
1904
|
}
|
|
@@ -2616,7 +2616,8 @@ class ExternalApp {
|
|
|
2616
2616
|
|
|
2617
2617
|
|
|
2618
2618
|
|
|
2619
|
-
|
|
2619
|
+
|
|
2620
|
+
|
|
2620
2621
|
|
|
2621
2622
|
|
|
2622
2623
|
class Meeting {
|
|
@@ -2628,6 +2629,7 @@ class Meeting {
|
|
|
2628
2629
|
|
|
2629
2630
|
|
|
2630
2631
|
|
|
2632
|
+
|
|
2631
2633
|
|
|
2632
2634
|
|
|
2633
2635
|
static parse(plain ) {
|
|
@@ -2639,6 +2641,7 @@ class Meeting {
|
|
|
2639
2641
|
port: plain.port,
|
|
2640
2642
|
uuid: plain.uuid,
|
|
2641
2643
|
number: plain.number,
|
|
2644
|
+
persistent: plain.persistent,
|
|
2642
2645
|
});
|
|
2643
2646
|
}
|
|
2644
2647
|
|
|
@@ -2646,7 +2649,7 @@ class Meeting {
|
|
|
2646
2649
|
return newFrom(meeting, Meeting);
|
|
2647
2650
|
}
|
|
2648
2651
|
|
|
2649
|
-
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
|
|
2652
|
+
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
|
|
2650
2653
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2651
2654
|
this.uri = uri;
|
|
2652
2655
|
this.name = name;
|
|
@@ -2654,6 +2657,7 @@ class Meeting {
|
|
|
2654
2657
|
this.port = port;
|
|
2655
2658
|
this.uuid = uuid;
|
|
2656
2659
|
this.number = number;
|
|
2660
|
+
this.persistent = persistent;
|
|
2657
2661
|
|
|
2658
2662
|
// Useful to compare instead of instanceof with minified code
|
|
2659
2663
|
this.type = 'Meeting';
|
|
@@ -3588,7 +3592,7 @@ class Recording {
|
|
|
3588
3592
|
|
|
3589
3593
|
|
|
3590
3594
|
|
|
3591
|
-
static parseMany(recordings
|
|
3595
|
+
static parseMany(recordings = []) {
|
|
3592
3596
|
return recordings.map(item => Recording.parse(item));
|
|
3593
3597
|
}
|
|
3594
3598
|
|
|
@@ -3714,7 +3718,7 @@ class CallLog {
|
|
|
3714
3718
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3715
3719
|
start: moment__default['default'](plain.start).toDate(),
|
|
3716
3720
|
end: plain.end ? moment__default['default'](plain.end).toDate() : null,
|
|
3717
|
-
recordings: Recording.parseMany(plain.recordings),
|
|
3721
|
+
recordings: Recording.parseMany(plain.recordings || []),
|
|
3718
3722
|
});
|
|
3719
3723
|
}
|
|
3720
3724
|
|
|
@@ -6559,6 +6563,7 @@ const ON_REINVITE$1 = 'reinvite';
|
|
|
6559
6563
|
const ON_ERROR = 'onError';
|
|
6560
6564
|
const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
|
|
6561
6565
|
const ON_NETWORK_STATS$1 = 'onNetworkStats';
|
|
6566
|
+
const ON_DISCONNECTED$1 = 'onDisconnected';
|
|
6562
6567
|
|
|
6563
6568
|
const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
|
|
6564
6569
|
const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
|
|
@@ -6635,6 +6640,7 @@ class WebRTCClient extends Emitter {
|
|
|
6635
6640
|
|
|
6636
6641
|
|
|
6637
6642
|
|
|
6643
|
+
|
|
6638
6644
|
|
|
6639
6645
|
static isAPrivateIp(ip ) {
|
|
6640
6646
|
const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
|
|
@@ -6700,6 +6706,7 @@ class WebRTCClient extends Emitter {
|
|
|
6700
6706
|
this.ON_ERROR = ON_ERROR;
|
|
6701
6707
|
this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
|
|
6702
6708
|
this.ON_NETWORK_STATS = ON_NETWORK_STATS$1;
|
|
6709
|
+
this.ON_DISCONNECTED = ON_DISCONNECTED$1;
|
|
6703
6710
|
}
|
|
6704
6711
|
|
|
6705
6712
|
configureMedia(media ) {
|
|
@@ -7301,7 +7308,7 @@ class WebRTCClient extends Emitter {
|
|
|
7301
7308
|
// We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
|
|
7302
7309
|
const transceivers = pc.getTransceivers();
|
|
7303
7310
|
const transceiverIdx = lastIndexOf(transceivers, transceiver =>
|
|
7304
|
-
transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
|
|
7311
|
+
transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
|
|
7305
7312
|
|
|
7306
7313
|
videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
|
|
7307
7314
|
} else {
|
|
@@ -7547,10 +7554,13 @@ class WebRTCClient extends Emitter {
|
|
|
7547
7554
|
return null;
|
|
7548
7555
|
}
|
|
7549
7556
|
|
|
7550
|
-
// let's update the local value
|
|
7551
|
-
if (this.audio
|
|
7552
|
-
|
|
7553
|
-
|
|
7557
|
+
// let's update the local audio value
|
|
7558
|
+
if (this.audio) {
|
|
7559
|
+
this.audio = {
|
|
7560
|
+
deviceId: {
|
|
7561
|
+
exact: id,
|
|
7562
|
+
},
|
|
7563
|
+
};
|
|
7554
7564
|
}
|
|
7555
7565
|
|
|
7556
7566
|
if (session) {
|
|
@@ -7563,6 +7573,9 @@ class WebRTCClient extends Emitter {
|
|
|
7563
7573
|
const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
|
|
7564
7574
|
|
|
7565
7575
|
if (sender) {
|
|
7576
|
+
if (sender.track) {
|
|
7577
|
+
audioTrack.enabled = sender.track.enabled;
|
|
7578
|
+
}
|
|
7566
7579
|
sender.replaceTrack(audioTrack);
|
|
7567
7580
|
}
|
|
7568
7581
|
|
|
@@ -7587,7 +7600,7 @@ class WebRTCClient extends Emitter {
|
|
|
7587
7600
|
return null;
|
|
7588
7601
|
}
|
|
7589
7602
|
|
|
7590
|
-
// let's update the local value
|
|
7603
|
+
// let's update the local video value
|
|
7591
7604
|
if (this.video) {
|
|
7592
7605
|
this.video = {
|
|
7593
7606
|
deviceId: {
|
|
@@ -7622,12 +7635,21 @@ class WebRTCClient extends Emitter {
|
|
|
7622
7635
|
return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
|
|
7623
7636
|
const videoTrack = stream.getVideoTracks()[0];
|
|
7624
7637
|
let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
|
|
7638
|
+
let wasTrackEnabled = false;
|
|
7625
7639
|
if (!sender) {
|
|
7626
7640
|
sender = pc && pc.getSenders().find(s => !s.track);
|
|
7627
7641
|
}
|
|
7628
7642
|
|
|
7629
7643
|
if (sender) {
|
|
7630
|
-
|
|
7644
|
+
// No video track means video not enabled
|
|
7645
|
+
wasTrackEnabled = sender.track ? sender.track.enabled : false;
|
|
7646
|
+
videoTrack.enabled = wasTrackEnabled;
|
|
7647
|
+
|
|
7648
|
+
if (!wasTrackEnabled) {
|
|
7649
|
+
videoTrack.stop();
|
|
7650
|
+
}
|
|
7651
|
+
|
|
7652
|
+
sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
|
|
7631
7653
|
}
|
|
7632
7654
|
|
|
7633
7655
|
// let's update the local stream
|
|
@@ -8311,6 +8333,7 @@ class WebRTCClient extends Emitter {
|
|
|
8311
8333
|
|
|
8312
8334
|
this.updateRemoteStream(this.getSipSessionId(session));
|
|
8313
8335
|
|
|
8336
|
+
const pc = session.sessionDescriptionHandler.peerConnection;
|
|
8314
8337
|
const onTrack = (event ) => {
|
|
8315
8338
|
const isAudioOnly = this._isAudioOnly(session);
|
|
8316
8339
|
const { kind, label, readyState, id, muted } = event.track;
|
|
@@ -8330,6 +8353,12 @@ class WebRTCClient extends Emitter {
|
|
|
8330
8353
|
|
|
8331
8354
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
8332
8355
|
|
|
8356
|
+
pc.oniceconnectionstatechange = () => {
|
|
8357
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
8358
|
+
this.eventEmitter.emit(ON_DISCONNECTED$1);
|
|
8359
|
+
}
|
|
8360
|
+
};
|
|
8361
|
+
|
|
8333
8362
|
if (withEvent) {
|
|
8334
8363
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
8335
8364
|
}
|
|
@@ -8525,24 +8554,89 @@ class WebRTCClient extends Emitter {
|
|
|
8525
8554
|
const session = this.getSipSession(sessionId);
|
|
8526
8555
|
|
|
8527
8556
|
const stats = session ? await this.getStats(session) : null;
|
|
8528
|
-
if (!stats) {
|
|
8557
|
+
if (!stats || !(sessionId in this.sessionNetworkStats)) {
|
|
8529
8558
|
return;
|
|
8530
8559
|
}
|
|
8531
8560
|
|
|
8532
|
-
|
|
8533
|
-
|
|
8534
|
-
|
|
8535
|
-
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
|
|
8539
|
-
|
|
8561
|
+
const networkStats = {
|
|
8562
|
+
audioBytesSent: 0,
|
|
8563
|
+
videoBytesSent: 0,
|
|
8564
|
+
videoBytesReceived: 0,
|
|
8565
|
+
audioBytesReceived: 0,
|
|
8566
|
+
};
|
|
8567
|
+
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
8568
|
+
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
8569
|
+
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
8570
|
+
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
8571
|
+
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
8572
|
+
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
8573
|
+
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
8574
|
+
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
8575
|
+
let audioBytesSent = 0;
|
|
8576
|
+
let audioBytesReceived = 0;
|
|
8577
|
+
let videoBytesSent = 0;
|
|
8578
|
+
let videoBytesReceived = 0;
|
|
8579
|
+
let transportSent = 0;
|
|
8580
|
+
let transportReceived = 0;
|
|
8581
|
+
let packetsLost = 0;
|
|
8540
8582
|
|
|
8541
|
-
|
|
8542
|
-
|
|
8583
|
+
stats.forEach(report => {
|
|
8584
|
+
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
8585
|
+
audioBytesSent += report.bytesSent + report.headerBytesSent;
|
|
8586
|
+
}
|
|
8587
|
+
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
8588
|
+
audioBytesSent += report.bytesSent;
|
|
8589
|
+
}
|
|
8590
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
8591
|
+
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
8592
|
+
}
|
|
8593
|
+
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
8594
|
+
packetsLost += report.packetsLost;
|
|
8595
|
+
networkStats.packetsReceived = report.packetsReceived;
|
|
8596
|
+
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
8597
|
+
}
|
|
8598
|
+
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
8599
|
+
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
8600
|
+
}
|
|
8601
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
8602
|
+
if ('framesPerSecond' in report) {
|
|
8603
|
+
networkStats.framesPerSecond = report.framesPerSecond;
|
|
8604
|
+
}
|
|
8605
|
+
if ('framerateMean' in report) {
|
|
8606
|
+
// framerateMean is only available in FF
|
|
8607
|
+
networkStats.framesPerSecond = Math.round(report.framerateMean);
|
|
8543
8608
|
}
|
|
8544
8609
|
}
|
|
8610
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
8611
|
+
packetsLost += report.packetsLost;
|
|
8612
|
+
networkStats.roundTripTime = report.roundTripTime;
|
|
8613
|
+
networkStats.jitter = report.jitter;
|
|
8614
|
+
}
|
|
8615
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
8616
|
+
packetsLost += report.packetsLost;
|
|
8617
|
+
}
|
|
8618
|
+
if (report.type === 'transport') {
|
|
8619
|
+
transportSent += report.bytesSent;
|
|
8620
|
+
transportReceived += report.bytesReceived;
|
|
8621
|
+
}
|
|
8545
8622
|
});
|
|
8623
|
+
|
|
8624
|
+
networkStats.packetsLost = packetsLost;
|
|
8625
|
+
networkStats.audioBytesSent = audioBytesSent;
|
|
8626
|
+
networkStats.audioBytesReceived = audioBytesReceived;
|
|
8627
|
+
networkStats.videoBytesSent = videoBytesSent;
|
|
8628
|
+
networkStats.videoBytesReceived = videoBytesReceived;
|
|
8629
|
+
networkStats.transportSent = transportSent;
|
|
8630
|
+
networkStats.transportReceived = transportReceived;
|
|
8631
|
+
|
|
8632
|
+
const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
|
|
8633
|
+
+ (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
|
|
8634
|
+
+ (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
|
|
8635
|
+
|
|
8636
|
+
networkStats.bandwidth = bandwidth;
|
|
8637
|
+
|
|
8638
|
+
this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
|
|
8639
|
+
this.sessionNetworkStats[sessionId].push(networkStats);
|
|
8546
8640
|
}
|
|
8547
8641
|
|
|
8548
8642
|
}
|
|
@@ -8588,6 +8682,7 @@ const ON_MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
|
|
|
8588
8682
|
const ON_NETWORK_STATS = 'onNetworkStats';
|
|
8589
8683
|
const ON_CHAT = 'phone/ON_CHAT';
|
|
8590
8684
|
const ON_SIGNAL = 'phone/ON_SIGNAL';
|
|
8685
|
+
const ON_DISCONNECTED = 'onDisconnected';
|
|
8591
8686
|
|
|
8592
8687
|
const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
|
|
8593
8688
|
const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
|
|
@@ -8627,6 +8722,7 @@ const events = [
|
|
|
8627
8722
|
ON_CHAT,
|
|
8628
8723
|
ON_SIGNAL,
|
|
8629
8724
|
ON_NETWORK_STATS,
|
|
8725
|
+
ON_DISCONNECTED,
|
|
8630
8726
|
];
|
|
8631
8727
|
|
|
8632
8728
|
const logger$7 = IssueReporter$1.loggerFor('webrtc-phone');
|
|
@@ -9979,6 +10075,11 @@ class WebRTCPhone extends Emitter {
|
|
|
9979
10075
|
this.eventEmitter.emit(ON_UNREGISTERED);
|
|
9980
10076
|
});
|
|
9981
10077
|
|
|
10078
|
+
this.client.on(this.client.ON_DISCONNECTED, () => {
|
|
10079
|
+
logger$7.info('WebRTC disconnected');
|
|
10080
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
10081
|
+
});
|
|
10082
|
+
|
|
9982
10083
|
this.client.on(this.client.REGISTERED, () => {
|
|
9983
10084
|
logger$7.info('WebRTC registered', {
|
|
9984
10085
|
shouldSendReinvite: this.shouldSendReinvite,
|
|
@@ -10235,6 +10336,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
|
|
|
10235
10336
|
ON_NETWORK_STATS: ON_NETWORK_STATS,
|
|
10236
10337
|
ON_CHAT: ON_CHAT,
|
|
10237
10338
|
ON_SIGNAL: ON_SIGNAL,
|
|
10339
|
+
ON_DISCONNECTED: ON_DISCONNECTED,
|
|
10238
10340
|
MESSAGE_TYPE_CHAT: MESSAGE_TYPE_CHAT,
|
|
10239
10341
|
MESSAGE_TYPE_SIGNAL: MESSAGE_TYPE_SIGNAL,
|
|
10240
10342
|
events: events,
|
package/lib/web-rtc-client.js
CHANGED
|
@@ -675,7 +675,7 @@ class IssueReporter {
|
|
|
675
675
|
payload._retry = retry + 1;
|
|
676
676
|
}
|
|
677
677
|
|
|
678
|
-
this._sendDebugToGrafana(
|
|
678
|
+
this._sendDebugToGrafana(payload, retry + 1);
|
|
679
679
|
}, 5000 + retry * 1000);
|
|
680
680
|
});
|
|
681
681
|
}
|
|
@@ -3177,7 +3177,8 @@ class ExternalApp {
|
|
|
3177
3177
|
|
|
3178
3178
|
|
|
3179
3179
|
|
|
3180
|
-
|
|
3180
|
+
|
|
3181
|
+
|
|
3181
3182
|
|
|
3182
3183
|
|
|
3183
3184
|
class Meeting {
|
|
@@ -3189,6 +3190,7 @@ class Meeting {
|
|
|
3189
3190
|
|
|
3190
3191
|
|
|
3191
3192
|
|
|
3193
|
+
|
|
3192
3194
|
|
|
3193
3195
|
|
|
3194
3196
|
static parse(plain ) {
|
|
@@ -3200,6 +3202,7 @@ class Meeting {
|
|
|
3200
3202
|
port: plain.port,
|
|
3201
3203
|
uuid: plain.uuid,
|
|
3202
3204
|
number: plain.number,
|
|
3205
|
+
persistent: plain.persistent,
|
|
3203
3206
|
});
|
|
3204
3207
|
}
|
|
3205
3208
|
|
|
@@ -3207,7 +3210,7 @@ class Meeting {
|
|
|
3207
3210
|
return newFrom(meeting, Meeting);
|
|
3208
3211
|
}
|
|
3209
3212
|
|
|
3210
|
-
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
|
|
3213
|
+
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
|
|
3211
3214
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
3212
3215
|
this.uri = uri;
|
|
3213
3216
|
this.name = name;
|
|
@@ -3215,6 +3218,7 @@ class Meeting {
|
|
|
3215
3218
|
this.port = port;
|
|
3216
3219
|
this.uuid = uuid;
|
|
3217
3220
|
this.number = number;
|
|
3221
|
+
this.persistent = persistent;
|
|
3218
3222
|
|
|
3219
3223
|
// Useful to compare instead of instanceof with minified code
|
|
3220
3224
|
this.type = 'Meeting';
|
|
@@ -3778,7 +3782,7 @@ class Recording {
|
|
|
3778
3782
|
|
|
3779
3783
|
|
|
3780
3784
|
|
|
3781
|
-
static parseMany(recordings
|
|
3785
|
+
static parseMany(recordings = []) {
|
|
3782
3786
|
return recordings.map(item => Recording.parse(item));
|
|
3783
3787
|
}
|
|
3784
3788
|
|
|
@@ -3904,7 +3908,7 @@ class CallLog {
|
|
|
3904
3908
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3905
3909
|
start: moment__default['default'](plain.start).toDate(),
|
|
3906
3910
|
end: plain.end ? moment__default['default'](plain.end).toDate() : null,
|
|
3907
|
-
recordings: Recording.parseMany(plain.recordings),
|
|
3911
|
+
recordings: Recording.parseMany(plain.recordings || []),
|
|
3908
3912
|
});
|
|
3909
3913
|
}
|
|
3910
3914
|
|
|
@@ -5299,6 +5303,7 @@ const ON_REINVITE = 'reinvite';
|
|
|
5299
5303
|
const ON_ERROR = 'onError';
|
|
5300
5304
|
const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
|
|
5301
5305
|
const ON_NETWORK_STATS = 'onNetworkStats';
|
|
5306
|
+
const ON_DISCONNECTED = 'onDisconnected';
|
|
5302
5307
|
|
|
5303
5308
|
const events = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
|
|
5304
5309
|
const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
|
|
@@ -5375,6 +5380,7 @@ class WebRTCClient extends Emitter {
|
|
|
5375
5380
|
|
|
5376
5381
|
|
|
5377
5382
|
|
|
5383
|
+
|
|
5378
5384
|
|
|
5379
5385
|
static isAPrivateIp(ip ) {
|
|
5380
5386
|
const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
|
|
@@ -5440,6 +5446,7 @@ class WebRTCClient extends Emitter {
|
|
|
5440
5446
|
this.ON_ERROR = ON_ERROR;
|
|
5441
5447
|
this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
|
|
5442
5448
|
this.ON_NETWORK_STATS = ON_NETWORK_STATS;
|
|
5449
|
+
this.ON_DISCONNECTED = ON_DISCONNECTED;
|
|
5443
5450
|
}
|
|
5444
5451
|
|
|
5445
5452
|
configureMedia(media ) {
|
|
@@ -6041,7 +6048,7 @@ class WebRTCClient extends Emitter {
|
|
|
6041
6048
|
// We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
|
|
6042
6049
|
const transceivers = pc.getTransceivers();
|
|
6043
6050
|
const transceiverIdx = lastIndexOf(transceivers, transceiver =>
|
|
6044
|
-
transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
|
|
6051
|
+
transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
|
|
6045
6052
|
|
|
6046
6053
|
videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
|
|
6047
6054
|
} else {
|
|
@@ -6287,10 +6294,13 @@ class WebRTCClient extends Emitter {
|
|
|
6287
6294
|
return null;
|
|
6288
6295
|
}
|
|
6289
6296
|
|
|
6290
|
-
// let's update the local value
|
|
6291
|
-
if (this.audio
|
|
6292
|
-
|
|
6293
|
-
|
|
6297
|
+
// let's update the local audio value
|
|
6298
|
+
if (this.audio) {
|
|
6299
|
+
this.audio = {
|
|
6300
|
+
deviceId: {
|
|
6301
|
+
exact: id,
|
|
6302
|
+
},
|
|
6303
|
+
};
|
|
6294
6304
|
}
|
|
6295
6305
|
|
|
6296
6306
|
if (session) {
|
|
@@ -6303,6 +6313,9 @@ class WebRTCClient extends Emitter {
|
|
|
6303
6313
|
const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
|
|
6304
6314
|
|
|
6305
6315
|
if (sender) {
|
|
6316
|
+
if (sender.track) {
|
|
6317
|
+
audioTrack.enabled = sender.track.enabled;
|
|
6318
|
+
}
|
|
6306
6319
|
sender.replaceTrack(audioTrack);
|
|
6307
6320
|
}
|
|
6308
6321
|
|
|
@@ -6327,7 +6340,7 @@ class WebRTCClient extends Emitter {
|
|
|
6327
6340
|
return null;
|
|
6328
6341
|
}
|
|
6329
6342
|
|
|
6330
|
-
// let's update the local value
|
|
6343
|
+
// let's update the local video value
|
|
6331
6344
|
if (this.video) {
|
|
6332
6345
|
this.video = {
|
|
6333
6346
|
deviceId: {
|
|
@@ -6362,12 +6375,21 @@ class WebRTCClient extends Emitter {
|
|
|
6362
6375
|
return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
|
|
6363
6376
|
const videoTrack = stream.getVideoTracks()[0];
|
|
6364
6377
|
let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
|
|
6378
|
+
let wasTrackEnabled = false;
|
|
6365
6379
|
if (!sender) {
|
|
6366
6380
|
sender = pc && pc.getSenders().find(s => !s.track);
|
|
6367
6381
|
}
|
|
6368
6382
|
|
|
6369
6383
|
if (sender) {
|
|
6370
|
-
|
|
6384
|
+
// No video track means video not enabled
|
|
6385
|
+
wasTrackEnabled = sender.track ? sender.track.enabled : false;
|
|
6386
|
+
videoTrack.enabled = wasTrackEnabled;
|
|
6387
|
+
|
|
6388
|
+
if (!wasTrackEnabled) {
|
|
6389
|
+
videoTrack.stop();
|
|
6390
|
+
}
|
|
6391
|
+
|
|
6392
|
+
sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
|
|
6371
6393
|
}
|
|
6372
6394
|
|
|
6373
6395
|
// let's update the local stream
|
|
@@ -7051,6 +7073,7 @@ class WebRTCClient extends Emitter {
|
|
|
7051
7073
|
|
|
7052
7074
|
this.updateRemoteStream(this.getSipSessionId(session));
|
|
7053
7075
|
|
|
7076
|
+
const pc = session.sessionDescriptionHandler.peerConnection;
|
|
7054
7077
|
const onTrack = (event ) => {
|
|
7055
7078
|
const isAudioOnly = this._isAudioOnly(session);
|
|
7056
7079
|
const { kind, label, readyState, id, muted } = event.track;
|
|
@@ -7070,6 +7093,12 @@ class WebRTCClient extends Emitter {
|
|
|
7070
7093
|
|
|
7071
7094
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
7072
7095
|
|
|
7096
|
+
pc.oniceconnectionstatechange = () => {
|
|
7097
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
7098
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
7099
|
+
}
|
|
7100
|
+
};
|
|
7101
|
+
|
|
7073
7102
|
if (withEvent) {
|
|
7074
7103
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
7075
7104
|
}
|
|
@@ -7265,24 +7294,89 @@ class WebRTCClient extends Emitter {
|
|
|
7265
7294
|
const session = this.getSipSession(sessionId);
|
|
7266
7295
|
|
|
7267
7296
|
const stats = session ? await this.getStats(session) : null;
|
|
7268
|
-
if (!stats) {
|
|
7297
|
+
if (!stats || !(sessionId in this.sessionNetworkStats)) {
|
|
7269
7298
|
return;
|
|
7270
7299
|
}
|
|
7271
7300
|
|
|
7301
|
+
const networkStats = {
|
|
7302
|
+
audioBytesSent: 0,
|
|
7303
|
+
videoBytesSent: 0,
|
|
7304
|
+
videoBytesReceived: 0,
|
|
7305
|
+
audioBytesReceived: 0,
|
|
7306
|
+
};
|
|
7307
|
+
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
7308
|
+
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
7309
|
+
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
7310
|
+
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
7311
|
+
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
7312
|
+
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
7313
|
+
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
7314
|
+
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
7315
|
+
let audioBytesSent = 0;
|
|
7316
|
+
let audioBytesReceived = 0;
|
|
7317
|
+
let videoBytesSent = 0;
|
|
7318
|
+
let videoBytesReceived = 0;
|
|
7319
|
+
let transportSent = 0;
|
|
7320
|
+
let transportReceived = 0;
|
|
7321
|
+
let packetsLost = 0;
|
|
7322
|
+
|
|
7272
7323
|
stats.forEach(report => {
|
|
7273
|
-
if (report.type === '
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7324
|
+
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
7325
|
+
audioBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7326
|
+
}
|
|
7327
|
+
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
7328
|
+
audioBytesSent += report.bytesSent;
|
|
7329
|
+
}
|
|
7330
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7331
|
+
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7332
|
+
}
|
|
7333
|
+
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
7334
|
+
packetsLost += report.packetsLost;
|
|
7335
|
+
networkStats.packetsReceived = report.packetsReceived;
|
|
7336
|
+
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7337
|
+
}
|
|
7338
|
+
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
7339
|
+
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7340
|
+
}
|
|
7341
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7342
|
+
if ('framesPerSecond' in report) {
|
|
7343
|
+
networkStats.framesPerSecond = report.framesPerSecond;
|
|
7283
7344
|
}
|
|
7345
|
+
if ('framerateMean' in report) {
|
|
7346
|
+
// framerateMean is only available in FF
|
|
7347
|
+
networkStats.framesPerSecond = Math.round(report.framerateMean);
|
|
7348
|
+
}
|
|
7349
|
+
}
|
|
7350
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
7351
|
+
packetsLost += report.packetsLost;
|
|
7352
|
+
networkStats.roundTripTime = report.roundTripTime;
|
|
7353
|
+
networkStats.jitter = report.jitter;
|
|
7354
|
+
}
|
|
7355
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
7356
|
+
packetsLost += report.packetsLost;
|
|
7357
|
+
}
|
|
7358
|
+
if (report.type === 'transport') {
|
|
7359
|
+
transportSent += report.bytesSent;
|
|
7360
|
+
transportReceived += report.bytesReceived;
|
|
7284
7361
|
}
|
|
7285
7362
|
});
|
|
7363
|
+
|
|
7364
|
+
networkStats.packetsLost = packetsLost;
|
|
7365
|
+
networkStats.audioBytesSent = audioBytesSent;
|
|
7366
|
+
networkStats.audioBytesReceived = audioBytesReceived;
|
|
7367
|
+
networkStats.videoBytesSent = videoBytesSent;
|
|
7368
|
+
networkStats.videoBytesReceived = videoBytesReceived;
|
|
7369
|
+
networkStats.transportSent = transportSent;
|
|
7370
|
+
networkStats.transportReceived = transportReceived;
|
|
7371
|
+
|
|
7372
|
+
const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
|
|
7373
|
+
+ (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
|
|
7374
|
+
+ (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
|
|
7375
|
+
|
|
7376
|
+
networkStats.bandwidth = bandwidth;
|
|
7377
|
+
|
|
7378
|
+
this.eventEmitter.emit(ON_NETWORK_STATS, session, networkStats, this.sessionNetworkStats[sessionId]);
|
|
7379
|
+
this.sessionNetworkStats[sessionId].push(networkStats);
|
|
7286
7380
|
}
|
|
7287
7381
|
|
|
7288
7382
|
}
|
package/lib/websocket-client.js
CHANGED
package/package.json
CHANGED
package/src/domain/CallLog.js
CHANGED
|
@@ -108,7 +108,7 @@ export default class CallLog {
|
|
|
108
108
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
109
109
|
start: moment(plain.start).toDate(),
|
|
110
110
|
end: plain.end ? moment(plain.end).toDate() : null,
|
|
111
|
-
recordings: Recording.parseMany(plain.recordings),
|
|
111
|
+
recordings: Recording.parseMany(plain.recordings || []),
|
|
112
112
|
});
|
|
113
113
|
}
|
|
114
114
|
|
package/src/domain/Meeting.js
CHANGED
|
@@ -8,7 +8,8 @@ export type MeetingCreationResponse = {
|
|
|
8
8
|
owner_uuids: Array<string>,
|
|
9
9
|
port: string,
|
|
10
10
|
uuid: string,
|
|
11
|
-
number: string
|
|
11
|
+
number: string,
|
|
12
|
+
persistent: boolean,
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export default class Meeting {
|
|
@@ -20,6 +21,7 @@ export default class Meeting {
|
|
|
20
21
|
name: string;
|
|
21
22
|
port: string;
|
|
22
23
|
number: string;
|
|
24
|
+
persistent: boolean;
|
|
23
25
|
ownerUuids: Array<string>;
|
|
24
26
|
|
|
25
27
|
static parse(plain: MeetingCreationResponse): Meeting {
|
|
@@ -31,6 +33,7 @@ export default class Meeting {
|
|
|
31
33
|
port: plain.port,
|
|
32
34
|
uuid: plain.uuid,
|
|
33
35
|
number: plain.number,
|
|
36
|
+
persistent: plain.persistent,
|
|
34
37
|
});
|
|
35
38
|
}
|
|
36
39
|
|
|
@@ -38,7 +41,7 @@ export default class Meeting {
|
|
|
38
41
|
return newFrom(meeting, Meeting);
|
|
39
42
|
}
|
|
40
43
|
|
|
41
|
-
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number }: Object = {}) {
|
|
44
|
+
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent }: Object = {}) {
|
|
42
45
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
43
46
|
this.uri = uri;
|
|
44
47
|
this.name = name;
|
|
@@ -46,6 +49,7 @@ export default class Meeting {
|
|
|
46
49
|
this.port = port;
|
|
47
50
|
this.uuid = uuid;
|
|
48
51
|
this.number = number;
|
|
52
|
+
this.persistent = persistent;
|
|
49
53
|
|
|
50
54
|
// Useful to compare instead of instanceof with minified code
|
|
51
55
|
this.type = 'Meeting';
|