@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.
Files changed (114) hide show
  1. package/dist/wazo-sdk.js +3 -3
  2. package/esm/__tests__/api-client.test.js +9 -5
  3. package/esm/__tests__/web-rtc-client.test.js +117 -23
  4. package/esm/api/agentd.js +1 -1
  5. package/esm/api/amid.js +1 -1
  6. package/esm/api/application.js +1 -1
  7. package/esm/api/auth.js +1 -1
  8. package/esm/api/call-logd.js +3 -3
  9. package/esm/api/calld.js +1 -1
  10. package/esm/api/chatd.js +1 -1
  11. package/esm/api/confd.js +7 -3
  12. package/esm/api/ctid-ng.js +1 -1
  13. package/esm/api/dird.js +1 -1
  14. package/esm/api/webhookd.js +1 -1
  15. package/esm/api-client.js +9 -5
  16. package/esm/checker/Checker.js +117 -23
  17. package/esm/checker/checks/aor.js +9 -5
  18. package/esm/checker/checks/api.js +9 -5
  19. package/esm/checker/checks/index.js +117 -23
  20. package/esm/checker/checks/wazo-websocket.js +1 -1
  21. package/esm/checker/checks/webrtc-transport.js +117 -23
  22. package/esm/checker/checks/webrtc.js +117 -23
  23. package/esm/domain/AdHocAPIConference.js +9 -5
  24. package/esm/domain/CallLog.js +2 -2
  25. package/esm/domain/Features.js +9 -5
  26. package/esm/domain/Meeting.js +6 -2
  27. package/esm/domain/Phone/CTIPhone.js +9 -5
  28. package/esm/domain/Phone/WebRTCPhone.js +9 -2
  29. package/esm/domain/Recording.js +1 -1
  30. package/esm/domain/__tests__/CallLog.test.js +2 -2
  31. package/esm/index.js +125 -23
  32. package/esm/lib/WazoSessionDescriptionHandler.js +1 -1
  33. package/esm/service/CallApi.js +9 -5
  34. package/esm/service/IssueReporter.js +1 -1
  35. package/esm/service/__tests__/IssueReporter.test.js +1 -1
  36. package/esm/service/getApiClient.js +9 -5
  37. package/esm/simple/Auth.js +125 -23
  38. package/esm/simple/Configuration.js +125 -23
  39. package/esm/simple/Directory.js +9 -5
  40. package/esm/simple/Phone.js +125 -23
  41. package/esm/simple/Websocket.js +1 -1
  42. package/esm/simple/index.js +125 -23
  43. package/esm/simple/room/LocalParticipant.js +125 -23
  44. package/esm/simple/room/Participant.js +125 -23
  45. package/esm/simple/room/RemoteParticipant.js +125 -23
  46. package/esm/simple/room/Room.js +125 -23
  47. package/esm/simple/room/SipRoom.js +125 -23
  48. package/esm/simple/room/Stream.js +125 -23
  49. package/esm/simple/room/__tests__/RemoteParticipant.test.js +125 -23
  50. package/esm/simple/utils.js +125 -23
  51. package/esm/utils/__tests__/api-requester.test.js +1 -1
  52. package/esm/utils/api-requester.js +1 -1
  53. package/esm/web-rtc-client.js +117 -23
  54. package/esm/websocket-client.js +1 -1
  55. package/lib/__tests__/api-client.test.js +9 -5
  56. package/lib/__tests__/web-rtc-client.test.js +117 -23
  57. package/lib/api/agentd.js +1 -1
  58. package/lib/api/amid.js +1 -1
  59. package/lib/api/application.js +1 -1
  60. package/lib/api/auth.js +1 -1
  61. package/lib/api/call-logd.js +3 -3
  62. package/lib/api/calld.js +1 -1
  63. package/lib/api/chatd.js +1 -1
  64. package/lib/api/confd.js +7 -3
  65. package/lib/api/ctid-ng.js +1 -1
  66. package/lib/api/dird.js +1 -1
  67. package/lib/api/webhookd.js +1 -1
  68. package/lib/api-client.js +9 -5
  69. package/lib/checker/Checker.js +117 -23
  70. package/lib/checker/checks/aor.js +9 -5
  71. package/lib/checker/checks/api.js +9 -5
  72. package/lib/checker/checks/index.js +117 -23
  73. package/lib/checker/checks/wazo-websocket.js +1 -1
  74. package/lib/checker/checks/webrtc-transport.js +117 -23
  75. package/lib/checker/checks/webrtc.js +117 -23
  76. package/lib/domain/AdHocAPIConference.js +9 -5
  77. package/lib/domain/CallLog.js +2 -2
  78. package/lib/domain/Features.js +9 -5
  79. package/lib/domain/Meeting.js +6 -2
  80. package/lib/domain/Phone/CTIPhone.js +9 -5
  81. package/lib/domain/Phone/WebRTCPhone.js +9 -1
  82. package/lib/domain/Recording.js +1 -1
  83. package/lib/domain/__tests__/CallLog.test.js +2 -2
  84. package/lib/index.js +125 -23
  85. package/lib/lib/WazoSessionDescriptionHandler.js +1 -1
  86. package/lib/service/CallApi.js +9 -5
  87. package/lib/service/IssueReporter.js +1 -1
  88. package/lib/service/__tests__/IssueReporter.test.js +1 -1
  89. package/lib/service/getApiClient.js +9 -5
  90. package/lib/simple/Auth.js +125 -23
  91. package/lib/simple/Configuration.js +125 -23
  92. package/lib/simple/Directory.js +9 -5
  93. package/lib/simple/Phone.js +125 -23
  94. package/lib/simple/Websocket.js +1 -1
  95. package/lib/simple/index.js +125 -23
  96. package/lib/simple/room/LocalParticipant.js +125 -23
  97. package/lib/simple/room/Participant.js +125 -23
  98. package/lib/simple/room/RemoteParticipant.js +125 -23
  99. package/lib/simple/room/Room.js +125 -23
  100. package/lib/simple/room/SipRoom.js +125 -23
  101. package/lib/simple/room/Stream.js +125 -23
  102. package/lib/simple/room/__tests__/RemoteParticipant.test.js +125 -23
  103. package/lib/simple/utils.js +125 -23
  104. package/lib/utils/__tests__/api-requester.test.js +1 -1
  105. package/lib/utils/api-requester.js +1 -1
  106. package/lib/web-rtc-client.js +117 -23
  107. package/lib/websocket-client.js +1 -1
  108. package/package.json +1 -1
  109. package/src/domain/CallLog.js +1 -1
  110. package/src/domain/Meeting.js +6 -2
  111. package/src/domain/Phone/WebRTCPhone.js +7 -0
  112. package/src/domain/Recording.js +1 -1
  113. package/src/service/IssueReporter.js +1 -1
  114. package/src/web-rtc-client.js +108 -18
@@ -390,7 +390,7 @@ class IssueReporter {
390
390
  payload._retry = retry + 1;
391
391
  }
392
392
 
393
- this._sendDebugToGrafana(body, retry + 1);
393
+ this._sendDebugToGrafana(payload, retry + 1);
394
394
  }, 5000 + retry * 1000);
395
395
  });
396
396
  }
@@ -2593,7 +2593,8 @@ class ExternalApp {
2593
2593
 
2594
2594
 
2595
2595
 
2596
-
2596
+
2597
+
2597
2598
 
2598
2599
 
2599
2600
  class Meeting {
@@ -2605,6 +2606,7 @@ class Meeting {
2605
2606
 
2606
2607
 
2607
2608
 
2609
+
2608
2610
 
2609
2611
 
2610
2612
  static parse(plain ) {
@@ -2616,6 +2618,7 @@ class Meeting {
2616
2618
  port: plain.port,
2617
2619
  uuid: plain.uuid,
2618
2620
  number: plain.number,
2621
+ persistent: plain.persistent,
2619
2622
  });
2620
2623
  }
2621
2624
 
@@ -2623,7 +2626,7 @@ class Meeting {
2623
2626
  return newFrom(meeting, Meeting);
2624
2627
  }
2625
2628
 
2626
- constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
2629
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
2627
2630
  this.guestSipAuthorization = guestSipAuthorization;
2628
2631
  this.uri = uri;
2629
2632
  this.name = name;
@@ -2631,6 +2634,7 @@ class Meeting {
2631
2634
  this.port = port;
2632
2635
  this.uuid = uuid;
2633
2636
  this.number = number;
2637
+ this.persistent = persistent;
2634
2638
 
2635
2639
  // Useful to compare instead of instanceof with minified code
2636
2640
  this.type = 'Meeting';
@@ -3194,7 +3198,7 @@ class Recording {
3194
3198
 
3195
3199
 
3196
3200
 
3197
- static parseMany(recordings ) {
3201
+ static parseMany(recordings = []) {
3198
3202
  return recordings.map(item => Recording.parse(item));
3199
3203
  }
3200
3204
 
@@ -3320,7 +3324,7 @@ class CallLog {
3320
3324
  duration: (plain.duration || 0) * 1000, // duration is in seconds
3321
3325
  start: moment__default['default'](plain.start).toDate(),
3322
3326
  end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3323
- recordings: Recording.parseMany(plain.recordings),
3327
+ recordings: Recording.parseMany(plain.recordings || []),
3324
3328
  });
3325
3329
  }
3326
3330
 
@@ -1898,7 +1898,7 @@ class IssueReporter {
1898
1898
  payload._retry = retry + 1;
1899
1899
  }
1900
1900
 
1901
- this._sendDebugToGrafana(body, retry + 1);
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
 
@@ -6295,6 +6299,7 @@ const ON_REINVITE$1 = 'reinvite';
6295
6299
  const ON_ERROR = 'onError';
6296
6300
  const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
6297
6301
  const ON_NETWORK_STATS$1 = 'onNetworkStats';
6302
+ const ON_DISCONNECTED$1 = 'onDisconnected';
6298
6303
 
6299
6304
  const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
6300
6305
  const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
@@ -6371,6 +6376,7 @@ class WebRTCClient extends Emitter {
6371
6376
 
6372
6377
 
6373
6378
 
6379
+
6374
6380
 
6375
6381
  static isAPrivateIp(ip ) {
6376
6382
  const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
@@ -6436,6 +6442,7 @@ class WebRTCClient extends Emitter {
6436
6442
  this.ON_ERROR = ON_ERROR;
6437
6443
  this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
6438
6444
  this.ON_NETWORK_STATS = ON_NETWORK_STATS$1;
6445
+ this.ON_DISCONNECTED = ON_DISCONNECTED$1;
6439
6446
  }
6440
6447
 
6441
6448
  configureMedia(media ) {
@@ -7037,7 +7044,7 @@ class WebRTCClient extends Emitter {
7037
7044
  // We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
7038
7045
  const transceivers = pc.getTransceivers();
7039
7046
  const transceiverIdx = lastIndexOf(transceivers, transceiver =>
7040
- transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
7047
+ transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
7041
7048
 
7042
7049
  videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
7043
7050
  } else {
@@ -7283,10 +7290,13 @@ class WebRTCClient extends Emitter {
7283
7290
  return null;
7284
7291
  }
7285
7292
 
7286
- // let's update the local value
7287
- if (this.audio && this.audio.deviceId) {
7288
- // $FlowFixMe
7289
- this.audio.deviceId.exact = id;
7293
+ // let's update the local audio value
7294
+ if (this.audio) {
7295
+ this.audio = {
7296
+ deviceId: {
7297
+ exact: id,
7298
+ },
7299
+ };
7290
7300
  }
7291
7301
 
7292
7302
  if (session) {
@@ -7299,6 +7309,9 @@ class WebRTCClient extends Emitter {
7299
7309
  const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
7300
7310
 
7301
7311
  if (sender) {
7312
+ if (sender.track) {
7313
+ audioTrack.enabled = sender.track.enabled;
7314
+ }
7302
7315
  sender.replaceTrack(audioTrack);
7303
7316
  }
7304
7317
 
@@ -7323,7 +7336,7 @@ class WebRTCClient extends Emitter {
7323
7336
  return null;
7324
7337
  }
7325
7338
 
7326
- // let's update the local value
7339
+ // let's update the local video value
7327
7340
  if (this.video) {
7328
7341
  this.video = {
7329
7342
  deviceId: {
@@ -7358,12 +7371,21 @@ class WebRTCClient extends Emitter {
7358
7371
  return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
7359
7372
  const videoTrack = stream.getVideoTracks()[0];
7360
7373
  let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
7374
+ let wasTrackEnabled = false;
7361
7375
  if (!sender) {
7362
7376
  sender = pc && pc.getSenders().find(s => !s.track);
7363
7377
  }
7364
7378
 
7365
7379
  if (sender) {
7366
- sender.replaceTrack(videoTrack);
7380
+ // No video track means video not enabled
7381
+ wasTrackEnabled = sender.track ? sender.track.enabled : false;
7382
+ videoTrack.enabled = wasTrackEnabled;
7383
+
7384
+ if (!wasTrackEnabled) {
7385
+ videoTrack.stop();
7386
+ }
7387
+
7388
+ sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
7367
7389
  }
7368
7390
 
7369
7391
  // let's update the local stream
@@ -8047,6 +8069,7 @@ class WebRTCClient extends Emitter {
8047
8069
 
8048
8070
  this.updateRemoteStream(this.getSipSessionId(session));
8049
8071
 
8072
+ const pc = session.sessionDescriptionHandler.peerConnection;
8050
8073
  const onTrack = (event ) => {
8051
8074
  const isAudioOnly = this._isAudioOnly(session);
8052
8075
  const { kind, label, readyState, id, muted } = event.track;
@@ -8066,6 +8089,12 @@ class WebRTCClient extends Emitter {
8066
8089
 
8067
8090
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
8068
8091
 
8092
+ pc.oniceconnectionstatechange = () => {
8093
+ if (pc.iceConnectionState === 'disconnected') {
8094
+ this.eventEmitter.emit(ON_DISCONNECTED$1);
8095
+ }
8096
+ };
8097
+
8069
8098
  if (withEvent) {
8070
8099
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
8071
8100
  }
@@ -8261,24 +8290,89 @@ class WebRTCClient extends Emitter {
8261
8290
  const session = this.getSipSession(sessionId);
8262
8291
 
8263
8292
  const stats = session ? await this.getStats(session) : null;
8264
- if (!stats) {
8293
+ if (!stats || !(sessionId in this.sessionNetworkStats)) {
8265
8294
  return;
8266
8295
  }
8267
8296
 
8268
- stats.forEach(report => {
8269
- if (report.type === 'inbound-rtp') {
8270
- if (report.kind === 'audio') {
8271
- const networkStats = {
8272
- packetsLost: report.packetsLost,
8273
- packetsReceived: report.packetsReceived,
8274
- jitter: report.jitter,
8275
- };
8297
+ const networkStats = {
8298
+ audioBytesSent: 0,
8299
+ videoBytesSent: 0,
8300
+ videoBytesReceived: 0,
8301
+ audioBytesReceived: 0,
8302
+ };
8303
+ const nbStats = this.sessionNetworkStats[sessionId].length;
8304
+ const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
8305
+ const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
8306
+ const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8307
+ const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8308
+ const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8309
+ const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8310
+ const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8311
+ let audioBytesSent = 0;
8312
+ let audioBytesReceived = 0;
8313
+ let videoBytesSent = 0;
8314
+ let videoBytesReceived = 0;
8315
+ let transportSent = 0;
8316
+ let transportReceived = 0;
8317
+ let packetsLost = 0;
8276
8318
 
8277
- this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8278
- this.sessionNetworkStats[sessionId].push(networkStats);
8319
+ stats.forEach(report => {
8320
+ if (report.type === 'outbound-rtp' && report.kind === 'audio') {
8321
+ audioBytesSent += report.bytesSent + report.headerBytesSent;
8322
+ }
8323
+ if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
8324
+ audioBytesSent += report.bytesSent;
8325
+ }
8326
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
8327
+ videoBytesSent += report.bytesSent + report.headerBytesSent;
8328
+ }
8329
+ if (report.type === 'inbound-rtp' && report.kind === 'audio') {
8330
+ packetsLost += report.packetsLost;
8331
+ networkStats.packetsReceived = report.packetsReceived;
8332
+ audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
8333
+ }
8334
+ if (report.type === 'inbound-rtp' && report.kind === 'video') {
8335
+ videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
8336
+ }
8337
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
8338
+ if ('framesPerSecond' in report) {
8339
+ networkStats.framesPerSecond = report.framesPerSecond;
8340
+ }
8341
+ if ('framerateMean' in report) {
8342
+ // framerateMean is only available in FF
8343
+ networkStats.framesPerSecond = Math.round(report.framerateMean);
8279
8344
  }
8280
8345
  }
8346
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
8347
+ packetsLost += report.packetsLost;
8348
+ networkStats.roundTripTime = report.roundTripTime;
8349
+ networkStats.jitter = report.jitter;
8350
+ }
8351
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
8352
+ packetsLost += report.packetsLost;
8353
+ }
8354
+ if (report.type === 'transport') {
8355
+ transportSent += report.bytesSent;
8356
+ transportReceived += report.bytesReceived;
8357
+ }
8281
8358
  });
8359
+
8360
+ networkStats.packetsLost = packetsLost;
8361
+ networkStats.audioBytesSent = audioBytesSent;
8362
+ networkStats.audioBytesReceived = audioBytesReceived;
8363
+ networkStats.videoBytesSent = videoBytesSent;
8364
+ networkStats.videoBytesReceived = videoBytesReceived;
8365
+ networkStats.transportSent = transportSent;
8366
+ networkStats.transportReceived = transportReceived;
8367
+
8368
+ const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
8369
+ + (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
8370
+ + (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
8371
+
8372
+ networkStats.bandwidth = bandwidth;
8373
+
8374
+ this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8375
+ this.sessionNetworkStats[sessionId].push(networkStats);
8282
8376
  }
8283
8377
 
8284
8378
  }
@@ -8324,6 +8418,7 @@ const ON_MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
8324
8418
  const ON_NETWORK_STATS = 'onNetworkStats';
8325
8419
  const ON_CHAT = 'phone/ON_CHAT';
8326
8420
  const ON_SIGNAL = 'phone/ON_SIGNAL';
8421
+ const ON_DISCONNECTED = 'onDisconnected';
8327
8422
 
8328
8423
  const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
8329
8424
  const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
@@ -8363,6 +8458,7 @@ const events = [
8363
8458
  ON_CHAT,
8364
8459
  ON_SIGNAL,
8365
8460
  ON_NETWORK_STATS,
8461
+ ON_DISCONNECTED,
8366
8462
  ];
8367
8463
 
8368
8464
  const logger$8 = IssueReporter$1.loggerFor('webrtc-phone');
@@ -9715,6 +9811,11 @@ class WebRTCPhone extends Emitter {
9715
9811
  this.eventEmitter.emit(ON_UNREGISTERED);
9716
9812
  });
9717
9813
 
9814
+ this.client.on(this.client.ON_DISCONNECTED, () => {
9815
+ logger$8.info('WebRTC disconnected');
9816
+ this.eventEmitter.emit(ON_DISCONNECTED);
9817
+ });
9818
+
9718
9819
  this.client.on(this.client.REGISTERED, () => {
9719
9820
  logger$8.info('WebRTC registered', {
9720
9821
  shouldSendReinvite: this.shouldSendReinvite,
@@ -9971,6 +10072,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
9971
10072
  ON_NETWORK_STATS: ON_NETWORK_STATS,
9972
10073
  ON_CHAT: ON_CHAT,
9973
10074
  ON_SIGNAL: ON_SIGNAL,
10075
+ ON_DISCONNECTED: ON_DISCONNECTED,
9974
10076
  MESSAGE_TYPE_CHAT: MESSAGE_TYPE_CHAT,
9975
10077
  MESSAGE_TYPE_SIGNAL: MESSAGE_TYPE_SIGNAL,
9976
10078
  events: events,
@@ -1896,7 +1896,7 @@ class IssueReporter {
1896
1896
  payload._retry = retry + 1;
1897
1897
  }
1898
1898
 
1899
- this._sendDebugToGrafana(body, retry + 1);
1899
+ this._sendDebugToGrafana(payload, retry + 1);
1900
1900
  }, 5000 + retry * 1000);
1901
1901
  });
1902
1902
  }
@@ -2614,7 +2614,8 @@ class ExternalApp {
2614
2614
 
2615
2615
 
2616
2616
 
2617
-
2617
+
2618
+
2618
2619
 
2619
2620
 
2620
2621
  class Meeting {
@@ -2626,6 +2627,7 @@ class Meeting {
2626
2627
 
2627
2628
 
2628
2629
 
2630
+
2629
2631
 
2630
2632
 
2631
2633
  static parse(plain ) {
@@ -2637,6 +2639,7 @@ class Meeting {
2637
2639
  port: plain.port,
2638
2640
  uuid: plain.uuid,
2639
2641
  number: plain.number,
2642
+ persistent: plain.persistent,
2640
2643
  });
2641
2644
  }
2642
2645
 
@@ -2644,7 +2647,7 @@ class Meeting {
2644
2647
  return newFrom(meeting, Meeting);
2645
2648
  }
2646
2649
 
2647
- constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
2650
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
2648
2651
  this.guestSipAuthorization = guestSipAuthorization;
2649
2652
  this.uri = uri;
2650
2653
  this.name = name;
@@ -2652,6 +2655,7 @@ class Meeting {
2652
2655
  this.port = port;
2653
2656
  this.uuid = uuid;
2654
2657
  this.number = number;
2658
+ this.persistent = persistent;
2655
2659
 
2656
2660
  // Useful to compare instead of instanceof with minified code
2657
2661
  this.type = 'Meeting';
@@ -3586,7 +3590,7 @@ class Recording {
3586
3590
 
3587
3591
 
3588
3592
 
3589
- static parseMany(recordings ) {
3593
+ static parseMany(recordings = []) {
3590
3594
  return recordings.map(item => Recording.parse(item));
3591
3595
  }
3592
3596
 
@@ -3712,7 +3716,7 @@ class CallLog {
3712
3716
  duration: (plain.duration || 0) * 1000, // duration is in seconds
3713
3717
  start: moment__default['default'](plain.start).toDate(),
3714
3718
  end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3715
- recordings: Recording.parseMany(plain.recordings),
3719
+ recordings: Recording.parseMany(plain.recordings || []),
3716
3720
  });
3717
3721
  }
3718
3722
 
@@ -6293,6 +6297,7 @@ const ON_REINVITE$1 = 'reinvite';
6293
6297
  const ON_ERROR = 'onError';
6294
6298
  const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
6295
6299
  const ON_NETWORK_STATS$1 = 'onNetworkStats';
6300
+ const ON_DISCONNECTED$1 = 'onDisconnected';
6296
6301
 
6297
6302
  const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
6298
6303
  const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
@@ -6369,6 +6374,7 @@ class WebRTCClient extends Emitter {
6369
6374
 
6370
6375
 
6371
6376
 
6377
+
6372
6378
 
6373
6379
  static isAPrivateIp(ip ) {
6374
6380
  const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
@@ -6434,6 +6440,7 @@ class WebRTCClient extends Emitter {
6434
6440
  this.ON_ERROR = ON_ERROR;
6435
6441
  this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
6436
6442
  this.ON_NETWORK_STATS = ON_NETWORK_STATS$1;
6443
+ this.ON_DISCONNECTED = ON_DISCONNECTED$1;
6437
6444
  }
6438
6445
 
6439
6446
  configureMedia(media ) {
@@ -7035,7 +7042,7 @@ class WebRTCClient extends Emitter {
7035
7042
  // We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
7036
7043
  const transceivers = pc.getTransceivers();
7037
7044
  const transceiverIdx = lastIndexOf(transceivers, transceiver =>
7038
- transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
7045
+ transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
7039
7046
 
7040
7047
  videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
7041
7048
  } else {
@@ -7281,10 +7288,13 @@ class WebRTCClient extends Emitter {
7281
7288
  return null;
7282
7289
  }
7283
7290
 
7284
- // let's update the local value
7285
- if (this.audio && this.audio.deviceId) {
7286
- // $FlowFixMe
7287
- this.audio.deviceId.exact = id;
7291
+ // let's update the local audio value
7292
+ if (this.audio) {
7293
+ this.audio = {
7294
+ deviceId: {
7295
+ exact: id,
7296
+ },
7297
+ };
7288
7298
  }
7289
7299
 
7290
7300
  if (session) {
@@ -7297,6 +7307,9 @@ class WebRTCClient extends Emitter {
7297
7307
  const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
7298
7308
 
7299
7309
  if (sender) {
7310
+ if (sender.track) {
7311
+ audioTrack.enabled = sender.track.enabled;
7312
+ }
7300
7313
  sender.replaceTrack(audioTrack);
7301
7314
  }
7302
7315
 
@@ -7321,7 +7334,7 @@ class WebRTCClient extends Emitter {
7321
7334
  return null;
7322
7335
  }
7323
7336
 
7324
- // let's update the local value
7337
+ // let's update the local video value
7325
7338
  if (this.video) {
7326
7339
  this.video = {
7327
7340
  deviceId: {
@@ -7356,12 +7369,21 @@ class WebRTCClient extends Emitter {
7356
7369
  return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
7357
7370
  const videoTrack = stream.getVideoTracks()[0];
7358
7371
  let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
7372
+ let wasTrackEnabled = false;
7359
7373
  if (!sender) {
7360
7374
  sender = pc && pc.getSenders().find(s => !s.track);
7361
7375
  }
7362
7376
 
7363
7377
  if (sender) {
7364
- sender.replaceTrack(videoTrack);
7378
+ // No video track means video not enabled
7379
+ wasTrackEnabled = sender.track ? sender.track.enabled : false;
7380
+ videoTrack.enabled = wasTrackEnabled;
7381
+
7382
+ if (!wasTrackEnabled) {
7383
+ videoTrack.stop();
7384
+ }
7385
+
7386
+ sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
7365
7387
  }
7366
7388
 
7367
7389
  // let's update the local stream
@@ -8045,6 +8067,7 @@ class WebRTCClient extends Emitter {
8045
8067
 
8046
8068
  this.updateRemoteStream(this.getSipSessionId(session));
8047
8069
 
8070
+ const pc = session.sessionDescriptionHandler.peerConnection;
8048
8071
  const onTrack = (event ) => {
8049
8072
  const isAudioOnly = this._isAudioOnly(session);
8050
8073
  const { kind, label, readyState, id, muted } = event.track;
@@ -8064,6 +8087,12 @@ class WebRTCClient extends Emitter {
8064
8087
 
8065
8088
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
8066
8089
 
8090
+ pc.oniceconnectionstatechange = () => {
8091
+ if (pc.iceConnectionState === 'disconnected') {
8092
+ this.eventEmitter.emit(ON_DISCONNECTED$1);
8093
+ }
8094
+ };
8095
+
8067
8096
  if (withEvent) {
8068
8097
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
8069
8098
  }
@@ -8259,24 +8288,89 @@ class WebRTCClient extends Emitter {
8259
8288
  const session = this.getSipSession(sessionId);
8260
8289
 
8261
8290
  const stats = session ? await this.getStats(session) : null;
8262
- if (!stats) {
8291
+ if (!stats || !(sessionId in this.sessionNetworkStats)) {
8263
8292
  return;
8264
8293
  }
8265
8294
 
8266
- stats.forEach(report => {
8267
- if (report.type === 'inbound-rtp') {
8268
- if (report.kind === 'audio') {
8269
- const networkStats = {
8270
- packetsLost: report.packetsLost,
8271
- packetsReceived: report.packetsReceived,
8272
- jitter: report.jitter,
8273
- };
8295
+ const networkStats = {
8296
+ audioBytesSent: 0,
8297
+ videoBytesSent: 0,
8298
+ videoBytesReceived: 0,
8299
+ audioBytesReceived: 0,
8300
+ };
8301
+ const nbStats = this.sessionNetworkStats[sessionId].length;
8302
+ const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
8303
+ const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
8304
+ const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8305
+ const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8306
+ const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8307
+ const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8308
+ const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8309
+ let audioBytesSent = 0;
8310
+ let audioBytesReceived = 0;
8311
+ let videoBytesSent = 0;
8312
+ let videoBytesReceived = 0;
8313
+ let transportSent = 0;
8314
+ let transportReceived = 0;
8315
+ let packetsLost = 0;
8274
8316
 
8275
- this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8276
- this.sessionNetworkStats[sessionId].push(networkStats);
8317
+ stats.forEach(report => {
8318
+ if (report.type === 'outbound-rtp' && report.kind === 'audio') {
8319
+ audioBytesSent += report.bytesSent + report.headerBytesSent;
8320
+ }
8321
+ if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
8322
+ audioBytesSent += report.bytesSent;
8323
+ }
8324
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
8325
+ videoBytesSent += report.bytesSent + report.headerBytesSent;
8326
+ }
8327
+ if (report.type === 'inbound-rtp' && report.kind === 'audio') {
8328
+ packetsLost += report.packetsLost;
8329
+ networkStats.packetsReceived = report.packetsReceived;
8330
+ audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
8331
+ }
8332
+ if (report.type === 'inbound-rtp' && report.kind === 'video') {
8333
+ videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
8334
+ }
8335
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
8336
+ if ('framesPerSecond' in report) {
8337
+ networkStats.framesPerSecond = report.framesPerSecond;
8338
+ }
8339
+ if ('framerateMean' in report) {
8340
+ // framerateMean is only available in FF
8341
+ networkStats.framesPerSecond = Math.round(report.framerateMean);
8277
8342
  }
8278
8343
  }
8344
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
8345
+ packetsLost += report.packetsLost;
8346
+ networkStats.roundTripTime = report.roundTripTime;
8347
+ networkStats.jitter = report.jitter;
8348
+ }
8349
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
8350
+ packetsLost += report.packetsLost;
8351
+ }
8352
+ if (report.type === 'transport') {
8353
+ transportSent += report.bytesSent;
8354
+ transportReceived += report.bytesReceived;
8355
+ }
8279
8356
  });
8357
+
8358
+ networkStats.packetsLost = packetsLost;
8359
+ networkStats.audioBytesSent = audioBytesSent;
8360
+ networkStats.audioBytesReceived = audioBytesReceived;
8361
+ networkStats.videoBytesSent = videoBytesSent;
8362
+ networkStats.videoBytesReceived = videoBytesReceived;
8363
+ networkStats.transportSent = transportSent;
8364
+ networkStats.transportReceived = transportReceived;
8365
+
8366
+ const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
8367
+ + (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
8368
+ + (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
8369
+
8370
+ networkStats.bandwidth = bandwidth;
8371
+
8372
+ this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8373
+ this.sessionNetworkStats[sessionId].push(networkStats);
8280
8374
  }
8281
8375
 
8282
8376
  }
@@ -8322,6 +8416,7 @@ const ON_MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
8322
8416
  const ON_NETWORK_STATS = 'onNetworkStats';
8323
8417
  const ON_CHAT = 'phone/ON_CHAT';
8324
8418
  const ON_SIGNAL = 'phone/ON_SIGNAL';
8419
+ const ON_DISCONNECTED = 'onDisconnected';
8325
8420
 
8326
8421
  const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
8327
8422
  const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
@@ -8361,6 +8456,7 @@ const events = [
8361
8456
  ON_CHAT,
8362
8457
  ON_SIGNAL,
8363
8458
  ON_NETWORK_STATS,
8459
+ ON_DISCONNECTED,
8364
8460
  ];
8365
8461
 
8366
8462
  const logger$8 = IssueReporter$1.loggerFor('webrtc-phone');
@@ -9713,6 +9809,11 @@ class WebRTCPhone extends Emitter {
9713
9809
  this.eventEmitter.emit(ON_UNREGISTERED);
9714
9810
  });
9715
9811
 
9812
+ this.client.on(this.client.ON_DISCONNECTED, () => {
9813
+ logger$8.info('WebRTC disconnected');
9814
+ this.eventEmitter.emit(ON_DISCONNECTED);
9815
+ });
9816
+
9716
9817
  this.client.on(this.client.REGISTERED, () => {
9717
9818
  logger$8.info('WebRTC registered', {
9718
9819
  shouldSendReinvite: this.shouldSendReinvite,
@@ -9969,6 +10070,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
9969
10070
  ON_NETWORK_STATS: ON_NETWORK_STATS,
9970
10071
  ON_CHAT: ON_CHAT,
9971
10072
  ON_SIGNAL: ON_SIGNAL,
10073
+ ON_DISCONNECTED: ON_DISCONNECTED,
9972
10074
  MESSAGE_TYPE_CHAT: MESSAGE_TYPE_CHAT,
9973
10075
  MESSAGE_TYPE_SIGNAL: MESSAGE_TYPE_SIGNAL,
9974
10076
  events: events,