@wazo/sdk 0.37.16 → 0.37.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/wazo-sdk.js +5 -5
- package/esm/__tests__/api-client.test.js +9 -5
- package/esm/__tests__/web-rtc-client.test.js +69 -19
- 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 +69 -19
- package/esm/checker/checks/aor.js +9 -5
- package/esm/checker/checks/api.js +9 -5
- package/esm/checker/checks/index.js +69 -19
- package/esm/checker/checks/wazo-websocket.js +1 -1
- package/esm/checker/checks/webrtc-transport.js +69 -19
- package/esm/checker/checks/webrtc.js +69 -19
- 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 +77 -19
- 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 +77 -19
- package/esm/simple/Configuration.js +77 -19
- package/esm/simple/Directory.js +9 -5
- package/esm/simple/Phone.js +77 -19
- package/esm/simple/Websocket.js +1 -1
- package/esm/simple/index.js +77 -19
- package/esm/simple/room/LocalParticipant.js +77 -19
- package/esm/simple/room/Participant.js +77 -19
- package/esm/simple/room/RemoteParticipant.js +77 -19
- package/esm/simple/room/Room.js +77 -19
- package/esm/simple/room/SipRoom.js +77 -19
- package/esm/simple/room/Stream.js +77 -19
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +77 -19
- package/esm/simple/utils.js +77 -19
- package/esm/utils/__tests__/api-requester.test.js +1 -1
- package/esm/utils/api-requester.js +1 -1
- package/esm/web-rtc-client.js +69 -19
- package/esm/websocket-client.js +1 -1
- package/lib/__tests__/api-client.test.js +9 -5
- package/lib/__tests__/web-rtc-client.test.js +69 -19
- 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 +69 -19
- package/lib/checker/checks/aor.js +9 -5
- package/lib/checker/checks/api.js +9 -5
- package/lib/checker/checks/index.js +69 -19
- package/lib/checker/checks/wazo-websocket.js +1 -1
- package/lib/checker/checks/webrtc-transport.js +69 -19
- package/lib/checker/checks/webrtc.js +69 -19
- 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 +77 -19
- 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 +77 -19
- package/lib/simple/Configuration.js +77 -19
- package/lib/simple/Directory.js +9 -5
- package/lib/simple/Phone.js +77 -19
- package/lib/simple/Websocket.js +1 -1
- package/lib/simple/index.js +77 -19
- package/lib/simple/room/LocalParticipant.js +77 -19
- package/lib/simple/room/Participant.js +77 -19
- package/lib/simple/room/RemoteParticipant.js +77 -19
- package/lib/simple/room/Room.js +77 -19
- package/lib/simple/room/SipRoom.js +77 -19
- package/lib/simple/room/Stream.js +77 -19
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +77 -19
- package/lib/simple/utils.js +77 -19
- package/lib/utils/__tests__/api-requester.test.js +1 -1
- package/lib/utils/api-requester.js +1 -1
- package/lib/web-rtc-client.js +69 -19
- package/lib/websocket-client.js +1 -1
- package/package.json +2 -2
- 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 +60 -14
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
|
}
|
|
@@ -7281,25 +7310,33 @@ class WebRTCClient extends Emitter {
|
|
|
7281
7310
|
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
7282
7311
|
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
7283
7312
|
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
7313
|
+
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
7314
|
+
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
7284
7315
|
let audioBytesSent = 0;
|
|
7285
7316
|
let audioBytesReceived = 0;
|
|
7286
7317
|
let videoBytesSent = 0;
|
|
7287
7318
|
let videoBytesReceived = 0;
|
|
7319
|
+
let transportSent = 0;
|
|
7320
|
+
let transportReceived = 0;
|
|
7321
|
+
let packetsLost = 0;
|
|
7288
7322
|
|
|
7289
7323
|
stats.forEach(report => {
|
|
7290
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') {
|
|
7291
7328
|
audioBytesSent += report.bytesSent;
|
|
7292
7329
|
}
|
|
7293
7330
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7294
|
-
videoBytesSent += report.bytesSent;
|
|
7331
|
+
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7295
7332
|
}
|
|
7296
7333
|
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
7297
|
-
|
|
7334
|
+
packetsLost += report.packetsLost;
|
|
7298
7335
|
networkStats.packetsReceived = report.packetsReceived;
|
|
7299
|
-
audioBytesReceived += report.bytesReceived;
|
|
7336
|
+
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7300
7337
|
}
|
|
7301
7338
|
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
7302
|
-
videoBytesReceived += report.bytesReceived;
|
|
7339
|
+
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7303
7340
|
}
|
|
7304
7341
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7305
7342
|
if ('framesPerSecond' in report) {
|
|
@@ -7311,19 +7348,32 @@ class WebRTCClient extends Emitter {
|
|
|
7311
7348
|
}
|
|
7312
7349
|
}
|
|
7313
7350
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
7351
|
+
packetsLost += report.packetsLost;
|
|
7314
7352
|
networkStats.roundTripTime = report.roundTripTime;
|
|
7315
7353
|
networkStats.jitter = report.jitter;
|
|
7316
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;
|
|
7361
|
+
}
|
|
7317
7362
|
});
|
|
7318
7363
|
|
|
7364
|
+
networkStats.packetsLost = packetsLost;
|
|
7319
7365
|
networkStats.audioBytesSent = audioBytesSent;
|
|
7320
7366
|
networkStats.audioBytesReceived = audioBytesReceived;
|
|
7321
7367
|
networkStats.videoBytesSent = videoBytesSent;
|
|
7322
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);
|
|
7323
7375
|
|
|
7324
|
-
networkStats.bandwidth =
|
|
7325
|
-
+ (networkStats.videoBytesSent - lastVideoSent) + (networkStats.audioBytesReceived - lastAudioReceived)
|
|
7326
|
-
+ (networkStats.videoBytesReceived - lastVideoReceived);
|
|
7376
|
+
networkStats.bandwidth = bandwidth;
|
|
7327
7377
|
|
|
7328
7378
|
this.eventEmitter.emit(ON_NETWORK_STATS, session, networkStats, this.sessionNetworkStats[sessionId]);
|
|
7329
7379
|
this.sessionNetworkStats[sessionId].push(networkStats);
|
package/lib/websocket-client.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wazo/sdk",
|
|
3
|
-
"version": "0.37.
|
|
3
|
+
"version": "0.37.20",
|
|
4
4
|
"description": "Wazo's JavaScript Software Development Kit.",
|
|
5
5
|
"main": "dist/wazo-sdk.js",
|
|
6
6
|
"author": "Wazo (http://wazo.io)",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"events": "^3.3.0",
|
|
49
49
|
"fstream": "^1.0.12",
|
|
50
|
-
"getstats": "manuquentin/getStats#
|
|
50
|
+
"getstats": "manuquentin/getStats#fix_stats_mobile",
|
|
51
51
|
"globby": "^11.0.3",
|
|
52
52
|
"google-libphonenumber": "^3.2.18",
|
|
53
53
|
"js-base64": "^3.6.0",
|
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';
|
|
@@ -52,6 +52,7 @@ export const ON_MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
|
|
|
52
52
|
export const ON_NETWORK_STATS = 'onNetworkStats';
|
|
53
53
|
export const ON_CHAT = 'phone/ON_CHAT';
|
|
54
54
|
export const ON_SIGNAL = 'phone/ON_SIGNAL';
|
|
55
|
+
export const ON_DISCONNECTED = 'onDisconnected';
|
|
55
56
|
|
|
56
57
|
export const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
|
|
57
58
|
export const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
|
|
@@ -91,6 +92,7 @@ export const events = [
|
|
|
91
92
|
ON_CHAT,
|
|
92
93
|
ON_SIGNAL,
|
|
93
94
|
ON_NETWORK_STATS,
|
|
95
|
+
ON_DISCONNECTED,
|
|
94
96
|
];
|
|
95
97
|
|
|
96
98
|
const logger = IssueReporter.loggerFor('webrtc-phone');
|
|
@@ -1445,6 +1447,11 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
1445
1447
|
this.eventEmitter.emit(ON_UNREGISTERED);
|
|
1446
1448
|
});
|
|
1447
1449
|
|
|
1450
|
+
this.client.on(this.client.ON_DISCONNECTED, () => {
|
|
1451
|
+
logger.info('WebRTC disconnected');
|
|
1452
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
1453
|
+
});
|
|
1454
|
+
|
|
1448
1455
|
this.client.on(this.client.REGISTERED, () => {
|
|
1449
1456
|
logger.info('WebRTC registered', {
|
|
1450
1457
|
shouldSendReinvite: this.shouldSendReinvite,
|
package/src/domain/Recording.js
CHANGED
|
@@ -24,7 +24,7 @@ export default class Recording {
|
|
|
24
24
|
start: Date;
|
|
25
25
|
uuid: string;
|
|
26
26
|
|
|
27
|
-
static parseMany(recordings: RecordingResponse[]): Recording[] {
|
|
27
|
+
static parseMany(recordings: RecordingResponse[] = []): Recording[] {
|
|
28
28
|
return recordings.map(item => Recording.parse(item));
|
|
29
29
|
}
|
|
30
30
|
|
package/src/web-rtc-client.js
CHANGED
|
@@ -69,6 +69,7 @@ const ON_REINVITE = 'reinvite';
|
|
|
69
69
|
const ON_ERROR = 'onError';
|
|
70
70
|
const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
|
|
71
71
|
const ON_NETWORK_STATS = 'onNetworkStats';
|
|
72
|
+
const ON_DISCONNECTED = 'onDisconnected';
|
|
72
73
|
|
|
73
74
|
export const events = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
|
|
74
75
|
export const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
|
|
@@ -145,6 +146,7 @@ export default class WebRTCClient extends Emitter {
|
|
|
145
146
|
ON_ERROR: string;
|
|
146
147
|
ON_SCREEN_SHARING_REINVITE: string;
|
|
147
148
|
ON_NETWORK_STATS: string;
|
|
149
|
+
ON_DISCONNECTED: string;
|
|
148
150
|
|
|
149
151
|
static isAPrivateIp(ip: string): boolean {
|
|
150
152
|
const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
|
|
@@ -210,6 +212,7 @@ export default class WebRTCClient extends Emitter {
|
|
|
210
212
|
this.ON_ERROR = ON_ERROR;
|
|
211
213
|
this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
|
|
212
214
|
this.ON_NETWORK_STATS = ON_NETWORK_STATS;
|
|
215
|
+
this.ON_DISCONNECTED = ON_DISCONNECTED;
|
|
213
216
|
}
|
|
214
217
|
|
|
215
218
|
configureMedia(media: MediaConfig) {
|
|
@@ -811,7 +814,7 @@ export default class WebRTCClient extends Emitter {
|
|
|
811
814
|
// We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
|
|
812
815
|
const transceivers = pc.getTransceivers();
|
|
813
816
|
const transceiverIdx = lastIndexOf(transceivers, transceiver =>
|
|
814
|
-
transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
|
|
817
|
+
transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
|
|
815
818
|
|
|
816
819
|
videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
|
|
817
820
|
} else {
|
|
@@ -1057,10 +1060,13 @@ export default class WebRTCClient extends Emitter {
|
|
|
1057
1060
|
return null;
|
|
1058
1061
|
}
|
|
1059
1062
|
|
|
1060
|
-
// let's update the local value
|
|
1061
|
-
if (this.audio
|
|
1062
|
-
|
|
1063
|
-
|
|
1063
|
+
// let's update the local audio value
|
|
1064
|
+
if (this.audio) {
|
|
1065
|
+
this.audio = {
|
|
1066
|
+
deviceId: {
|
|
1067
|
+
exact: id,
|
|
1068
|
+
},
|
|
1069
|
+
};
|
|
1064
1070
|
}
|
|
1065
1071
|
|
|
1066
1072
|
if (session) {
|
|
@@ -1073,6 +1079,9 @@ export default class WebRTCClient extends Emitter {
|
|
|
1073
1079
|
const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
|
|
1074
1080
|
|
|
1075
1081
|
if (sender) {
|
|
1082
|
+
if (sender.track) {
|
|
1083
|
+
audioTrack.enabled = sender.track.enabled;
|
|
1084
|
+
}
|
|
1076
1085
|
sender.replaceTrack(audioTrack);
|
|
1077
1086
|
}
|
|
1078
1087
|
|
|
@@ -1097,7 +1106,7 @@ export default class WebRTCClient extends Emitter {
|
|
|
1097
1106
|
return null;
|
|
1098
1107
|
}
|
|
1099
1108
|
|
|
1100
|
-
// let's update the local value
|
|
1109
|
+
// let's update the local video value
|
|
1101
1110
|
if (this.video) {
|
|
1102
1111
|
this.video = {
|
|
1103
1112
|
deviceId: {
|
|
@@ -1132,12 +1141,21 @@ export default class WebRTCClient extends Emitter {
|
|
|
1132
1141
|
return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
|
|
1133
1142
|
const videoTrack = stream.getVideoTracks()[0];
|
|
1134
1143
|
let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
|
|
1144
|
+
let wasTrackEnabled = false;
|
|
1135
1145
|
if (!sender) {
|
|
1136
1146
|
sender = pc && pc.getSenders().find(s => !s.track);
|
|
1137
1147
|
}
|
|
1138
1148
|
|
|
1139
1149
|
if (sender) {
|
|
1140
|
-
|
|
1150
|
+
// No video track means video not enabled
|
|
1151
|
+
wasTrackEnabled = sender.track ? sender.track.enabled : false;
|
|
1152
|
+
videoTrack.enabled = wasTrackEnabled;
|
|
1153
|
+
|
|
1154
|
+
if (!wasTrackEnabled) {
|
|
1155
|
+
videoTrack.stop();
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
|
|
1141
1159
|
}
|
|
1142
1160
|
|
|
1143
1161
|
// let's update the local stream
|
|
@@ -1821,6 +1839,7 @@ export default class WebRTCClient extends Emitter {
|
|
|
1821
1839
|
|
|
1822
1840
|
this.updateRemoteStream(this.getSipSessionId(session));
|
|
1823
1841
|
|
|
1842
|
+
const pc = session.sessionDescriptionHandler.peerConnection;
|
|
1824
1843
|
const onTrack = (event: any) => {
|
|
1825
1844
|
const isAudioOnly = this._isAudioOnly(session);
|
|
1826
1845
|
const { kind, label, readyState, id, muted } = event.track;
|
|
@@ -1840,6 +1859,12 @@ export default class WebRTCClient extends Emitter {
|
|
|
1840
1859
|
|
|
1841
1860
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
1842
1861
|
|
|
1862
|
+
pc.oniceconnectionstatechange = () => {
|
|
1863
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
1864
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
1865
|
+
}
|
|
1866
|
+
};
|
|
1867
|
+
|
|
1843
1868
|
if (withEvent) {
|
|
1844
1869
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
1845
1870
|
}
|
|
@@ -2051,25 +2076,33 @@ export default class WebRTCClient extends Emitter {
|
|
|
2051
2076
|
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
2052
2077
|
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
2053
2078
|
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
2079
|
+
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
2080
|
+
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
2054
2081
|
let audioBytesSent = 0;
|
|
2055
2082
|
let audioBytesReceived = 0;
|
|
2056
2083
|
let videoBytesSent = 0;
|
|
2057
2084
|
let videoBytesReceived = 0;
|
|
2085
|
+
let transportSent = 0;
|
|
2086
|
+
let transportReceived = 0;
|
|
2087
|
+
let packetsLost = 0;
|
|
2058
2088
|
|
|
2059
2089
|
stats.forEach(report => {
|
|
2060
2090
|
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
2091
|
+
audioBytesSent += report.bytesSent + report.headerBytesSent;
|
|
2092
|
+
}
|
|
2093
|
+
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
2061
2094
|
audioBytesSent += report.bytesSent;
|
|
2062
2095
|
}
|
|
2063
2096
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
2064
|
-
videoBytesSent += report.bytesSent;
|
|
2097
|
+
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
2065
2098
|
}
|
|
2066
2099
|
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
2067
|
-
|
|
2100
|
+
packetsLost += report.packetsLost;
|
|
2068
2101
|
networkStats.packetsReceived = report.packetsReceived;
|
|
2069
|
-
audioBytesReceived += report.bytesReceived;
|
|
2102
|
+
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
2070
2103
|
}
|
|
2071
2104
|
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
2072
|
-
videoBytesReceived += report.bytesReceived;
|
|
2105
|
+
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
2073
2106
|
}
|
|
2074
2107
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
2075
2108
|
if ('framesPerSecond' in report) {
|
|
@@ -2081,19 +2114,32 @@ export default class WebRTCClient extends Emitter {
|
|
|
2081
2114
|
}
|
|
2082
2115
|
}
|
|
2083
2116
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
2117
|
+
packetsLost += report.packetsLost;
|
|
2084
2118
|
networkStats.roundTripTime = report.roundTripTime;
|
|
2085
2119
|
networkStats.jitter = report.jitter;
|
|
2086
2120
|
}
|
|
2121
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
2122
|
+
packetsLost += report.packetsLost;
|
|
2123
|
+
}
|
|
2124
|
+
if (report.type === 'transport') {
|
|
2125
|
+
transportSent += report.bytesSent;
|
|
2126
|
+
transportReceived += report.bytesReceived;
|
|
2127
|
+
}
|
|
2087
2128
|
});
|
|
2088
2129
|
|
|
2130
|
+
networkStats.packetsLost = packetsLost;
|
|
2089
2131
|
networkStats.audioBytesSent = audioBytesSent;
|
|
2090
2132
|
networkStats.audioBytesReceived = audioBytesReceived;
|
|
2091
2133
|
networkStats.videoBytesSent = videoBytesSent;
|
|
2092
2134
|
networkStats.videoBytesReceived = videoBytesReceived;
|
|
2135
|
+
networkStats.transportSent = transportSent;
|
|
2136
|
+
networkStats.transportReceived = transportReceived;
|
|
2137
|
+
|
|
2138
|
+
const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
|
|
2139
|
+
+ (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
|
|
2140
|
+
+ (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
|
|
2093
2141
|
|
|
2094
|
-
networkStats.bandwidth =
|
|
2095
|
-
+ (networkStats.videoBytesSent - lastVideoSent) + (networkStats.audioBytesReceived - lastAudioReceived)
|
|
2096
|
-
+ (networkStats.videoBytesReceived - lastVideoReceived);
|
|
2142
|
+
networkStats.bandwidth = bandwidth;
|
|
2097
2143
|
|
|
2098
2144
|
this.eventEmitter.emit(ON_NETWORK_STATS, session, networkStats, this.sessionNetworkStats[sessionId]);
|
|
2099
2145
|
this.sessionNetworkStats[sessionId].push(networkStats);
|