@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
|
@@ -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
|
|
package/esm/simple/Auth.js
CHANGED
|
@@ -1886,7 +1886,7 @@ class IssueReporter {
|
|
|
1886
1886
|
payload._retry = retry + 1;
|
|
1887
1887
|
}
|
|
1888
1888
|
|
|
1889
|
-
this._sendDebugToGrafana(
|
|
1889
|
+
this._sendDebugToGrafana(payload, retry + 1);
|
|
1890
1890
|
}, 5000 + retry * 1000);
|
|
1891
1891
|
});
|
|
1892
1892
|
}
|
|
@@ -2604,7 +2604,8 @@ class ExternalApp {
|
|
|
2604
2604
|
|
|
2605
2605
|
|
|
2606
2606
|
|
|
2607
|
-
|
|
2607
|
+
|
|
2608
|
+
|
|
2608
2609
|
|
|
2609
2610
|
|
|
2610
2611
|
class Meeting {
|
|
@@ -2616,6 +2617,7 @@ class Meeting {
|
|
|
2616
2617
|
|
|
2617
2618
|
|
|
2618
2619
|
|
|
2620
|
+
|
|
2619
2621
|
|
|
2620
2622
|
|
|
2621
2623
|
static parse(plain ) {
|
|
@@ -2627,6 +2629,7 @@ class Meeting {
|
|
|
2627
2629
|
port: plain.port,
|
|
2628
2630
|
uuid: plain.uuid,
|
|
2629
2631
|
number: plain.number,
|
|
2632
|
+
persistent: plain.persistent,
|
|
2630
2633
|
});
|
|
2631
2634
|
}
|
|
2632
2635
|
|
|
@@ -2634,7 +2637,7 @@ class Meeting {
|
|
|
2634
2637
|
return newFrom(meeting, Meeting);
|
|
2635
2638
|
}
|
|
2636
2639
|
|
|
2637
|
-
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
|
|
2640
|
+
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
|
|
2638
2641
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2639
2642
|
this.uri = uri;
|
|
2640
2643
|
this.name = name;
|
|
@@ -2642,6 +2645,7 @@ class Meeting {
|
|
|
2642
2645
|
this.port = port;
|
|
2643
2646
|
this.uuid = uuid;
|
|
2644
2647
|
this.number = number;
|
|
2648
|
+
this.persistent = persistent;
|
|
2645
2649
|
|
|
2646
2650
|
// Useful to compare instead of instanceof with minified code
|
|
2647
2651
|
this.type = 'Meeting';
|
|
@@ -3576,7 +3580,7 @@ class Recording {
|
|
|
3576
3580
|
|
|
3577
3581
|
|
|
3578
3582
|
|
|
3579
|
-
static parseMany(recordings
|
|
3583
|
+
static parseMany(recordings = []) {
|
|
3580
3584
|
return recordings.map(item => Recording.parse(item));
|
|
3581
3585
|
}
|
|
3582
3586
|
|
|
@@ -3702,7 +3706,7 @@ class CallLog {
|
|
|
3702
3706
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3703
3707
|
start: moment(plain.start).toDate(),
|
|
3704
3708
|
end: plain.end ? moment(plain.end).toDate() : null,
|
|
3705
|
-
recordings: Recording.parseMany(plain.recordings),
|
|
3709
|
+
recordings: Recording.parseMany(plain.recordings || []),
|
|
3706
3710
|
});
|
|
3707
3711
|
}
|
|
3708
3712
|
|
|
@@ -6283,6 +6287,7 @@ const ON_REINVITE$1 = 'reinvite';
|
|
|
6283
6287
|
const ON_ERROR = 'onError';
|
|
6284
6288
|
const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
|
|
6285
6289
|
const ON_NETWORK_STATS$1 = 'onNetworkStats';
|
|
6290
|
+
const ON_DISCONNECTED$1 = 'onDisconnected';
|
|
6286
6291
|
|
|
6287
6292
|
const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
|
|
6288
6293
|
const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
|
|
@@ -6359,6 +6364,7 @@ class WebRTCClient extends Emitter {
|
|
|
6359
6364
|
|
|
6360
6365
|
|
|
6361
6366
|
|
|
6367
|
+
|
|
6362
6368
|
|
|
6363
6369
|
static isAPrivateIp(ip ) {
|
|
6364
6370
|
const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
|
|
@@ -6424,6 +6430,7 @@ class WebRTCClient extends Emitter {
|
|
|
6424
6430
|
this.ON_ERROR = ON_ERROR;
|
|
6425
6431
|
this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
|
|
6426
6432
|
this.ON_NETWORK_STATS = ON_NETWORK_STATS$1;
|
|
6433
|
+
this.ON_DISCONNECTED = ON_DISCONNECTED$1;
|
|
6427
6434
|
}
|
|
6428
6435
|
|
|
6429
6436
|
configureMedia(media ) {
|
|
@@ -7025,7 +7032,7 @@ class WebRTCClient extends Emitter {
|
|
|
7025
7032
|
// We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
|
|
7026
7033
|
const transceivers = pc.getTransceivers();
|
|
7027
7034
|
const transceiverIdx = lastIndexOf(transceivers, transceiver =>
|
|
7028
|
-
transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
|
|
7035
|
+
transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
|
|
7029
7036
|
|
|
7030
7037
|
videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
|
|
7031
7038
|
} else {
|
|
@@ -7271,10 +7278,13 @@ class WebRTCClient extends Emitter {
|
|
|
7271
7278
|
return null;
|
|
7272
7279
|
}
|
|
7273
7280
|
|
|
7274
|
-
// let's update the local value
|
|
7275
|
-
if (this.audio
|
|
7276
|
-
|
|
7277
|
-
|
|
7281
|
+
// let's update the local audio value
|
|
7282
|
+
if (this.audio) {
|
|
7283
|
+
this.audio = {
|
|
7284
|
+
deviceId: {
|
|
7285
|
+
exact: id,
|
|
7286
|
+
},
|
|
7287
|
+
};
|
|
7278
7288
|
}
|
|
7279
7289
|
|
|
7280
7290
|
if (session) {
|
|
@@ -7287,6 +7297,9 @@ class WebRTCClient extends Emitter {
|
|
|
7287
7297
|
const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
|
|
7288
7298
|
|
|
7289
7299
|
if (sender) {
|
|
7300
|
+
if (sender.track) {
|
|
7301
|
+
audioTrack.enabled = sender.track.enabled;
|
|
7302
|
+
}
|
|
7290
7303
|
sender.replaceTrack(audioTrack);
|
|
7291
7304
|
}
|
|
7292
7305
|
|
|
@@ -7311,7 +7324,7 @@ class WebRTCClient extends Emitter {
|
|
|
7311
7324
|
return null;
|
|
7312
7325
|
}
|
|
7313
7326
|
|
|
7314
|
-
// let's update the local value
|
|
7327
|
+
// let's update the local video value
|
|
7315
7328
|
if (this.video) {
|
|
7316
7329
|
this.video = {
|
|
7317
7330
|
deviceId: {
|
|
@@ -7346,12 +7359,21 @@ class WebRTCClient extends Emitter {
|
|
|
7346
7359
|
return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
|
|
7347
7360
|
const videoTrack = stream.getVideoTracks()[0];
|
|
7348
7361
|
let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
|
|
7362
|
+
let wasTrackEnabled = false;
|
|
7349
7363
|
if (!sender) {
|
|
7350
7364
|
sender = pc && pc.getSenders().find(s => !s.track);
|
|
7351
7365
|
}
|
|
7352
7366
|
|
|
7353
7367
|
if (sender) {
|
|
7354
|
-
|
|
7368
|
+
// No video track means video not enabled
|
|
7369
|
+
wasTrackEnabled = sender.track ? sender.track.enabled : false;
|
|
7370
|
+
videoTrack.enabled = wasTrackEnabled;
|
|
7371
|
+
|
|
7372
|
+
if (!wasTrackEnabled) {
|
|
7373
|
+
videoTrack.stop();
|
|
7374
|
+
}
|
|
7375
|
+
|
|
7376
|
+
sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
|
|
7355
7377
|
}
|
|
7356
7378
|
|
|
7357
7379
|
// let's update the local stream
|
|
@@ -8035,6 +8057,7 @@ class WebRTCClient extends Emitter {
|
|
|
8035
8057
|
|
|
8036
8058
|
this.updateRemoteStream(this.getSipSessionId(session));
|
|
8037
8059
|
|
|
8060
|
+
const pc = session.sessionDescriptionHandler.peerConnection;
|
|
8038
8061
|
const onTrack = (event ) => {
|
|
8039
8062
|
const isAudioOnly = this._isAudioOnly(session);
|
|
8040
8063
|
const { kind, label, readyState, id, muted } = event.track;
|
|
@@ -8054,6 +8077,12 @@ class WebRTCClient extends Emitter {
|
|
|
8054
8077
|
|
|
8055
8078
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
8056
8079
|
|
|
8080
|
+
pc.oniceconnectionstatechange = () => {
|
|
8081
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
8082
|
+
this.eventEmitter.emit(ON_DISCONNECTED$1);
|
|
8083
|
+
}
|
|
8084
|
+
};
|
|
8085
|
+
|
|
8057
8086
|
if (withEvent) {
|
|
8058
8087
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
8059
8088
|
}
|
|
@@ -8249,24 +8278,89 @@ class WebRTCClient extends Emitter {
|
|
|
8249
8278
|
const session = this.getSipSession(sessionId);
|
|
8250
8279
|
|
|
8251
8280
|
const stats = session ? await this.getStats(session) : null;
|
|
8252
|
-
if (!stats) {
|
|
8281
|
+
if (!stats || !(sessionId in this.sessionNetworkStats)) {
|
|
8253
8282
|
return;
|
|
8254
8283
|
}
|
|
8255
8284
|
|
|
8256
|
-
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
|
|
8285
|
+
const networkStats = {
|
|
8286
|
+
audioBytesSent: 0,
|
|
8287
|
+
videoBytesSent: 0,
|
|
8288
|
+
videoBytesReceived: 0,
|
|
8289
|
+
audioBytesReceived: 0,
|
|
8290
|
+
};
|
|
8291
|
+
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
8292
|
+
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
8293
|
+
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
8294
|
+
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
8295
|
+
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
8296
|
+
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
8297
|
+
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
8298
|
+
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
8299
|
+
let audioBytesSent = 0;
|
|
8300
|
+
let audioBytesReceived = 0;
|
|
8301
|
+
let videoBytesSent = 0;
|
|
8302
|
+
let videoBytesReceived = 0;
|
|
8303
|
+
let transportSent = 0;
|
|
8304
|
+
let transportReceived = 0;
|
|
8305
|
+
let packetsLost = 0;
|
|
8264
8306
|
|
|
8265
|
-
|
|
8266
|
-
|
|
8307
|
+
stats.forEach(report => {
|
|
8308
|
+
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
8309
|
+
audioBytesSent += report.bytesSent + report.headerBytesSent;
|
|
8310
|
+
}
|
|
8311
|
+
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
8312
|
+
audioBytesSent += report.bytesSent;
|
|
8313
|
+
}
|
|
8314
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
8315
|
+
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
8316
|
+
}
|
|
8317
|
+
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
8318
|
+
packetsLost += report.packetsLost;
|
|
8319
|
+
networkStats.packetsReceived = report.packetsReceived;
|
|
8320
|
+
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
8321
|
+
}
|
|
8322
|
+
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
8323
|
+
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
8324
|
+
}
|
|
8325
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
8326
|
+
if ('framesPerSecond' in report) {
|
|
8327
|
+
networkStats.framesPerSecond = report.framesPerSecond;
|
|
8328
|
+
}
|
|
8329
|
+
if ('framerateMean' in report) {
|
|
8330
|
+
// framerateMean is only available in FF
|
|
8331
|
+
networkStats.framesPerSecond = Math.round(report.framerateMean);
|
|
8267
8332
|
}
|
|
8268
8333
|
}
|
|
8334
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
8335
|
+
packetsLost += report.packetsLost;
|
|
8336
|
+
networkStats.roundTripTime = report.roundTripTime;
|
|
8337
|
+
networkStats.jitter = report.jitter;
|
|
8338
|
+
}
|
|
8339
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
8340
|
+
packetsLost += report.packetsLost;
|
|
8341
|
+
}
|
|
8342
|
+
if (report.type === 'transport') {
|
|
8343
|
+
transportSent += report.bytesSent;
|
|
8344
|
+
transportReceived += report.bytesReceived;
|
|
8345
|
+
}
|
|
8269
8346
|
});
|
|
8347
|
+
|
|
8348
|
+
networkStats.packetsLost = packetsLost;
|
|
8349
|
+
networkStats.audioBytesSent = audioBytesSent;
|
|
8350
|
+
networkStats.audioBytesReceived = audioBytesReceived;
|
|
8351
|
+
networkStats.videoBytesSent = videoBytesSent;
|
|
8352
|
+
networkStats.videoBytesReceived = videoBytesReceived;
|
|
8353
|
+
networkStats.transportSent = transportSent;
|
|
8354
|
+
networkStats.transportReceived = transportReceived;
|
|
8355
|
+
|
|
8356
|
+
const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
|
|
8357
|
+
+ (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
|
|
8358
|
+
+ (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
|
|
8359
|
+
|
|
8360
|
+
networkStats.bandwidth = bandwidth;
|
|
8361
|
+
|
|
8362
|
+
this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
|
|
8363
|
+
this.sessionNetworkStats[sessionId].push(networkStats);
|
|
8270
8364
|
}
|
|
8271
8365
|
|
|
8272
8366
|
}
|
|
@@ -8312,6 +8406,7 @@ const ON_MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
|
|
|
8312
8406
|
const ON_NETWORK_STATS = 'onNetworkStats';
|
|
8313
8407
|
const ON_CHAT = 'phone/ON_CHAT';
|
|
8314
8408
|
const ON_SIGNAL = 'phone/ON_SIGNAL';
|
|
8409
|
+
const ON_DISCONNECTED = 'onDisconnected';
|
|
8315
8410
|
|
|
8316
8411
|
const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
|
|
8317
8412
|
const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
|
|
@@ -8351,6 +8446,7 @@ const events = [
|
|
|
8351
8446
|
ON_CHAT,
|
|
8352
8447
|
ON_SIGNAL,
|
|
8353
8448
|
ON_NETWORK_STATS,
|
|
8449
|
+
ON_DISCONNECTED,
|
|
8354
8450
|
];
|
|
8355
8451
|
|
|
8356
8452
|
const logger$8 = IssueReporter$1.loggerFor('webrtc-phone');
|
|
@@ -9703,6 +9799,11 @@ class WebRTCPhone extends Emitter {
|
|
|
9703
9799
|
this.eventEmitter.emit(ON_UNREGISTERED);
|
|
9704
9800
|
});
|
|
9705
9801
|
|
|
9802
|
+
this.client.on(this.client.ON_DISCONNECTED, () => {
|
|
9803
|
+
logger$8.info('WebRTC disconnected');
|
|
9804
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
9805
|
+
});
|
|
9806
|
+
|
|
9706
9807
|
this.client.on(this.client.REGISTERED, () => {
|
|
9707
9808
|
logger$8.info('WebRTC registered', {
|
|
9708
9809
|
shouldSendReinvite: this.shouldSendReinvite,
|
|
@@ -9959,6 +10060,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
|
|
|
9959
10060
|
ON_NETWORK_STATS: ON_NETWORK_STATS,
|
|
9960
10061
|
ON_CHAT: ON_CHAT,
|
|
9961
10062
|
ON_SIGNAL: ON_SIGNAL,
|
|
10063
|
+
ON_DISCONNECTED: ON_DISCONNECTED,
|
|
9962
10064
|
MESSAGE_TYPE_CHAT: MESSAGE_TYPE_CHAT,
|
|
9963
10065
|
MESSAGE_TYPE_SIGNAL: MESSAGE_TYPE_SIGNAL,
|
|
9964
10066
|
events: events,
|
|
@@ -1886,7 +1886,7 @@ class IssueReporter {
|
|
|
1886
1886
|
payload._retry = retry + 1;
|
|
1887
1887
|
}
|
|
1888
1888
|
|
|
1889
|
-
this._sendDebugToGrafana(
|
|
1889
|
+
this._sendDebugToGrafana(payload, retry + 1);
|
|
1890
1890
|
}, 5000 + retry * 1000);
|
|
1891
1891
|
});
|
|
1892
1892
|
}
|
|
@@ -2604,7 +2604,8 @@ class ExternalApp {
|
|
|
2604
2604
|
|
|
2605
2605
|
|
|
2606
2606
|
|
|
2607
|
-
|
|
2607
|
+
|
|
2608
|
+
|
|
2608
2609
|
|
|
2609
2610
|
|
|
2610
2611
|
class Meeting {
|
|
@@ -2616,6 +2617,7 @@ class Meeting {
|
|
|
2616
2617
|
|
|
2617
2618
|
|
|
2618
2619
|
|
|
2620
|
+
|
|
2619
2621
|
|
|
2620
2622
|
|
|
2621
2623
|
static parse(plain ) {
|
|
@@ -2627,6 +2629,7 @@ class Meeting {
|
|
|
2627
2629
|
port: plain.port,
|
|
2628
2630
|
uuid: plain.uuid,
|
|
2629
2631
|
number: plain.number,
|
|
2632
|
+
persistent: plain.persistent,
|
|
2630
2633
|
});
|
|
2631
2634
|
}
|
|
2632
2635
|
|
|
@@ -2634,7 +2637,7 @@ class Meeting {
|
|
|
2634
2637
|
return newFrom(meeting, Meeting);
|
|
2635
2638
|
}
|
|
2636
2639
|
|
|
2637
|
-
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
|
|
2640
|
+
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
|
|
2638
2641
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2639
2642
|
this.uri = uri;
|
|
2640
2643
|
this.name = name;
|
|
@@ -2642,6 +2645,7 @@ class Meeting {
|
|
|
2642
2645
|
this.port = port;
|
|
2643
2646
|
this.uuid = uuid;
|
|
2644
2647
|
this.number = number;
|
|
2648
|
+
this.persistent = persistent;
|
|
2645
2649
|
|
|
2646
2650
|
// Useful to compare instead of instanceof with minified code
|
|
2647
2651
|
this.type = 'Meeting';
|
|
@@ -3576,7 +3580,7 @@ class Recording {
|
|
|
3576
3580
|
|
|
3577
3581
|
|
|
3578
3582
|
|
|
3579
|
-
static parseMany(recordings
|
|
3583
|
+
static parseMany(recordings = []) {
|
|
3580
3584
|
return recordings.map(item => Recording.parse(item));
|
|
3581
3585
|
}
|
|
3582
3586
|
|
|
@@ -3702,7 +3706,7 @@ class CallLog {
|
|
|
3702
3706
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3703
3707
|
start: moment(plain.start).toDate(),
|
|
3704
3708
|
end: plain.end ? moment(plain.end).toDate() : null,
|
|
3705
|
-
recordings: Recording.parseMany(plain.recordings),
|
|
3709
|
+
recordings: Recording.parseMany(plain.recordings || []),
|
|
3706
3710
|
});
|
|
3707
3711
|
}
|
|
3708
3712
|
|
|
@@ -6283,6 +6287,7 @@ const ON_REINVITE$1 = 'reinvite';
|
|
|
6283
6287
|
const ON_ERROR = 'onError';
|
|
6284
6288
|
const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
|
|
6285
6289
|
const ON_NETWORK_STATS$1 = 'onNetworkStats';
|
|
6290
|
+
const ON_DISCONNECTED$1 = 'onDisconnected';
|
|
6286
6291
|
|
|
6287
6292
|
const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
|
|
6288
6293
|
const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
|
|
@@ -6359,6 +6364,7 @@ class WebRTCClient extends Emitter {
|
|
|
6359
6364
|
|
|
6360
6365
|
|
|
6361
6366
|
|
|
6367
|
+
|
|
6362
6368
|
|
|
6363
6369
|
static isAPrivateIp(ip ) {
|
|
6364
6370
|
const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
|
|
@@ -6424,6 +6430,7 @@ class WebRTCClient extends Emitter {
|
|
|
6424
6430
|
this.ON_ERROR = ON_ERROR;
|
|
6425
6431
|
this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
|
|
6426
6432
|
this.ON_NETWORK_STATS = ON_NETWORK_STATS$1;
|
|
6433
|
+
this.ON_DISCONNECTED = ON_DISCONNECTED$1;
|
|
6427
6434
|
}
|
|
6428
6435
|
|
|
6429
6436
|
configureMedia(media ) {
|
|
@@ -7025,7 +7032,7 @@ class WebRTCClient extends Emitter {
|
|
|
7025
7032
|
// We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
|
|
7026
7033
|
const transceivers = pc.getTransceivers();
|
|
7027
7034
|
const transceiverIdx = lastIndexOf(transceivers, transceiver =>
|
|
7028
|
-
transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
|
|
7035
|
+
transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
|
|
7029
7036
|
|
|
7030
7037
|
videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
|
|
7031
7038
|
} else {
|
|
@@ -7271,10 +7278,13 @@ class WebRTCClient extends Emitter {
|
|
|
7271
7278
|
return null;
|
|
7272
7279
|
}
|
|
7273
7280
|
|
|
7274
|
-
// let's update the local value
|
|
7275
|
-
if (this.audio
|
|
7276
|
-
|
|
7277
|
-
|
|
7281
|
+
// let's update the local audio value
|
|
7282
|
+
if (this.audio) {
|
|
7283
|
+
this.audio = {
|
|
7284
|
+
deviceId: {
|
|
7285
|
+
exact: id,
|
|
7286
|
+
},
|
|
7287
|
+
};
|
|
7278
7288
|
}
|
|
7279
7289
|
|
|
7280
7290
|
if (session) {
|
|
@@ -7287,6 +7297,9 @@ class WebRTCClient extends Emitter {
|
|
|
7287
7297
|
const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
|
|
7288
7298
|
|
|
7289
7299
|
if (sender) {
|
|
7300
|
+
if (sender.track) {
|
|
7301
|
+
audioTrack.enabled = sender.track.enabled;
|
|
7302
|
+
}
|
|
7290
7303
|
sender.replaceTrack(audioTrack);
|
|
7291
7304
|
}
|
|
7292
7305
|
|
|
@@ -7311,7 +7324,7 @@ class WebRTCClient extends Emitter {
|
|
|
7311
7324
|
return null;
|
|
7312
7325
|
}
|
|
7313
7326
|
|
|
7314
|
-
// let's update the local value
|
|
7327
|
+
// let's update the local video value
|
|
7315
7328
|
if (this.video) {
|
|
7316
7329
|
this.video = {
|
|
7317
7330
|
deviceId: {
|
|
@@ -7346,12 +7359,21 @@ class WebRTCClient extends Emitter {
|
|
|
7346
7359
|
return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
|
|
7347
7360
|
const videoTrack = stream.getVideoTracks()[0];
|
|
7348
7361
|
let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
|
|
7362
|
+
let wasTrackEnabled = false;
|
|
7349
7363
|
if (!sender) {
|
|
7350
7364
|
sender = pc && pc.getSenders().find(s => !s.track);
|
|
7351
7365
|
}
|
|
7352
7366
|
|
|
7353
7367
|
if (sender) {
|
|
7354
|
-
|
|
7368
|
+
// No video track means video not enabled
|
|
7369
|
+
wasTrackEnabled = sender.track ? sender.track.enabled : false;
|
|
7370
|
+
videoTrack.enabled = wasTrackEnabled;
|
|
7371
|
+
|
|
7372
|
+
if (!wasTrackEnabled) {
|
|
7373
|
+
videoTrack.stop();
|
|
7374
|
+
}
|
|
7375
|
+
|
|
7376
|
+
sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
|
|
7355
7377
|
}
|
|
7356
7378
|
|
|
7357
7379
|
// let's update the local stream
|
|
@@ -8035,6 +8057,7 @@ class WebRTCClient extends Emitter {
|
|
|
8035
8057
|
|
|
8036
8058
|
this.updateRemoteStream(this.getSipSessionId(session));
|
|
8037
8059
|
|
|
8060
|
+
const pc = session.sessionDescriptionHandler.peerConnection;
|
|
8038
8061
|
const onTrack = (event ) => {
|
|
8039
8062
|
const isAudioOnly = this._isAudioOnly(session);
|
|
8040
8063
|
const { kind, label, readyState, id, muted } = event.track;
|
|
@@ -8054,6 +8077,12 @@ class WebRTCClient extends Emitter {
|
|
|
8054
8077
|
|
|
8055
8078
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
8056
8079
|
|
|
8080
|
+
pc.oniceconnectionstatechange = () => {
|
|
8081
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
8082
|
+
this.eventEmitter.emit(ON_DISCONNECTED$1);
|
|
8083
|
+
}
|
|
8084
|
+
};
|
|
8085
|
+
|
|
8057
8086
|
if (withEvent) {
|
|
8058
8087
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
8059
8088
|
}
|
|
@@ -8249,24 +8278,89 @@ class WebRTCClient extends Emitter {
|
|
|
8249
8278
|
const session = this.getSipSession(sessionId);
|
|
8250
8279
|
|
|
8251
8280
|
const stats = session ? await this.getStats(session) : null;
|
|
8252
|
-
if (!stats) {
|
|
8281
|
+
if (!stats || !(sessionId in this.sessionNetworkStats)) {
|
|
8253
8282
|
return;
|
|
8254
8283
|
}
|
|
8255
8284
|
|
|
8256
|
-
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
|
|
8285
|
+
const networkStats = {
|
|
8286
|
+
audioBytesSent: 0,
|
|
8287
|
+
videoBytesSent: 0,
|
|
8288
|
+
videoBytesReceived: 0,
|
|
8289
|
+
audioBytesReceived: 0,
|
|
8290
|
+
};
|
|
8291
|
+
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
8292
|
+
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
8293
|
+
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
8294
|
+
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
8295
|
+
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
8296
|
+
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
8297
|
+
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
8298
|
+
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
8299
|
+
let audioBytesSent = 0;
|
|
8300
|
+
let audioBytesReceived = 0;
|
|
8301
|
+
let videoBytesSent = 0;
|
|
8302
|
+
let videoBytesReceived = 0;
|
|
8303
|
+
let transportSent = 0;
|
|
8304
|
+
let transportReceived = 0;
|
|
8305
|
+
let packetsLost = 0;
|
|
8264
8306
|
|
|
8265
|
-
|
|
8266
|
-
|
|
8307
|
+
stats.forEach(report => {
|
|
8308
|
+
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
8309
|
+
audioBytesSent += report.bytesSent + report.headerBytesSent;
|
|
8310
|
+
}
|
|
8311
|
+
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
8312
|
+
audioBytesSent += report.bytesSent;
|
|
8313
|
+
}
|
|
8314
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
8315
|
+
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
8316
|
+
}
|
|
8317
|
+
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
8318
|
+
packetsLost += report.packetsLost;
|
|
8319
|
+
networkStats.packetsReceived = report.packetsReceived;
|
|
8320
|
+
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
8321
|
+
}
|
|
8322
|
+
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
8323
|
+
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
8324
|
+
}
|
|
8325
|
+
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
8326
|
+
if ('framesPerSecond' in report) {
|
|
8327
|
+
networkStats.framesPerSecond = report.framesPerSecond;
|
|
8328
|
+
}
|
|
8329
|
+
if ('framerateMean' in report) {
|
|
8330
|
+
// framerateMean is only available in FF
|
|
8331
|
+
networkStats.framesPerSecond = Math.round(report.framerateMean);
|
|
8267
8332
|
}
|
|
8268
8333
|
}
|
|
8334
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
8335
|
+
packetsLost += report.packetsLost;
|
|
8336
|
+
networkStats.roundTripTime = report.roundTripTime;
|
|
8337
|
+
networkStats.jitter = report.jitter;
|
|
8338
|
+
}
|
|
8339
|
+
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
8340
|
+
packetsLost += report.packetsLost;
|
|
8341
|
+
}
|
|
8342
|
+
if (report.type === 'transport') {
|
|
8343
|
+
transportSent += report.bytesSent;
|
|
8344
|
+
transportReceived += report.bytesReceived;
|
|
8345
|
+
}
|
|
8269
8346
|
});
|
|
8347
|
+
|
|
8348
|
+
networkStats.packetsLost = packetsLost;
|
|
8349
|
+
networkStats.audioBytesSent = audioBytesSent;
|
|
8350
|
+
networkStats.audioBytesReceived = audioBytesReceived;
|
|
8351
|
+
networkStats.videoBytesSent = videoBytesSent;
|
|
8352
|
+
networkStats.videoBytesReceived = videoBytesReceived;
|
|
8353
|
+
networkStats.transportSent = transportSent;
|
|
8354
|
+
networkStats.transportReceived = transportReceived;
|
|
8355
|
+
|
|
8356
|
+
const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
|
|
8357
|
+
+ (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
|
|
8358
|
+
+ (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
|
|
8359
|
+
|
|
8360
|
+
networkStats.bandwidth = bandwidth;
|
|
8361
|
+
|
|
8362
|
+
this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
|
|
8363
|
+
this.sessionNetworkStats[sessionId].push(networkStats);
|
|
8270
8364
|
}
|
|
8271
8365
|
|
|
8272
8366
|
}
|
|
@@ -8312,6 +8406,7 @@ const ON_MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
|
|
|
8312
8406
|
const ON_NETWORK_STATS = 'onNetworkStats';
|
|
8313
8407
|
const ON_CHAT = 'phone/ON_CHAT';
|
|
8314
8408
|
const ON_SIGNAL = 'phone/ON_SIGNAL';
|
|
8409
|
+
const ON_DISCONNECTED = 'onDisconnected';
|
|
8315
8410
|
|
|
8316
8411
|
const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
|
|
8317
8412
|
const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
|
|
@@ -8351,6 +8446,7 @@ const events = [
|
|
|
8351
8446
|
ON_CHAT,
|
|
8352
8447
|
ON_SIGNAL,
|
|
8353
8448
|
ON_NETWORK_STATS,
|
|
8449
|
+
ON_DISCONNECTED,
|
|
8354
8450
|
];
|
|
8355
8451
|
|
|
8356
8452
|
const logger$8 = IssueReporter$1.loggerFor('webrtc-phone');
|
|
@@ -9703,6 +9799,11 @@ class WebRTCPhone extends Emitter {
|
|
|
9703
9799
|
this.eventEmitter.emit(ON_UNREGISTERED);
|
|
9704
9800
|
});
|
|
9705
9801
|
|
|
9802
|
+
this.client.on(this.client.ON_DISCONNECTED, () => {
|
|
9803
|
+
logger$8.info('WebRTC disconnected');
|
|
9804
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
9805
|
+
});
|
|
9806
|
+
|
|
9706
9807
|
this.client.on(this.client.REGISTERED, () => {
|
|
9707
9808
|
logger$8.info('WebRTC registered', {
|
|
9708
9809
|
shouldSendReinvite: this.shouldSendReinvite,
|
|
@@ -9959,6 +10060,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
|
|
|
9959
10060
|
ON_NETWORK_STATS: ON_NETWORK_STATS,
|
|
9960
10061
|
ON_CHAT: ON_CHAT,
|
|
9961
10062
|
ON_SIGNAL: ON_SIGNAL,
|
|
10063
|
+
ON_DISCONNECTED: ON_DISCONNECTED,
|
|
9962
10064
|
MESSAGE_TYPE_CHAT: MESSAGE_TYPE_CHAT,
|
|
9963
10065
|
MESSAGE_TYPE_SIGNAL: MESSAGE_TYPE_SIGNAL,
|
|
9964
10066
|
events: events,
|