@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.
Files changed (114) hide show
  1. package/dist/wazo-sdk.js +5 -5
  2. package/esm/__tests__/api-client.test.js +9 -5
  3. package/esm/__tests__/web-rtc-client.test.js +69 -19
  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 +69 -19
  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 +69 -19
  20. package/esm/checker/checks/wazo-websocket.js +1 -1
  21. package/esm/checker/checks/webrtc-transport.js +69 -19
  22. package/esm/checker/checks/webrtc.js +69 -19
  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 +77 -19
  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 +77 -19
  38. package/esm/simple/Configuration.js +77 -19
  39. package/esm/simple/Directory.js +9 -5
  40. package/esm/simple/Phone.js +77 -19
  41. package/esm/simple/Websocket.js +1 -1
  42. package/esm/simple/index.js +77 -19
  43. package/esm/simple/room/LocalParticipant.js +77 -19
  44. package/esm/simple/room/Participant.js +77 -19
  45. package/esm/simple/room/RemoteParticipant.js +77 -19
  46. package/esm/simple/room/Room.js +77 -19
  47. package/esm/simple/room/SipRoom.js +77 -19
  48. package/esm/simple/room/Stream.js +77 -19
  49. package/esm/simple/room/__tests__/RemoteParticipant.test.js +77 -19
  50. package/esm/simple/utils.js +77 -19
  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 +69 -19
  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 +69 -19
  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 +69 -19
  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 +69 -19
  73. package/lib/checker/checks/wazo-websocket.js +1 -1
  74. package/lib/checker/checks/webrtc-transport.js +69 -19
  75. package/lib/checker/checks/webrtc.js +69 -19
  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 +77 -19
  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 +77 -19
  91. package/lib/simple/Configuration.js +77 -19
  92. package/lib/simple/Directory.js +9 -5
  93. package/lib/simple/Phone.js +77 -19
  94. package/lib/simple/Websocket.js +1 -1
  95. package/lib/simple/index.js +77 -19
  96. package/lib/simple/room/LocalParticipant.js +77 -19
  97. package/lib/simple/room/Participant.js +77 -19
  98. package/lib/simple/room/RemoteParticipant.js +77 -19
  99. package/lib/simple/room/Room.js +77 -19
  100. package/lib/simple/room/SipRoom.js +77 -19
  101. package/lib/simple/room/Stream.js +77 -19
  102. package/lib/simple/room/__tests__/RemoteParticipant.test.js +77 -19
  103. package/lib/simple/utils.js +77 -19
  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 +69 -19
  107. package/lib/websocket-client.js +1 -1
  108. package/package.json +2 -2
  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 +60 -14
@@ -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
  }
@@ -8277,25 +8306,33 @@ class WebRTCClient extends Emitter {
8277
8306
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8278
8307
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8279
8308
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8309
+ const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8310
+ const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8280
8311
  let audioBytesSent = 0;
8281
8312
  let audioBytesReceived = 0;
8282
8313
  let videoBytesSent = 0;
8283
8314
  let videoBytesReceived = 0;
8315
+ let transportSent = 0;
8316
+ let transportReceived = 0;
8317
+ let packetsLost = 0;
8284
8318
 
8285
8319
  stats.forEach(report => {
8286
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') {
8287
8324
  audioBytesSent += report.bytesSent;
8288
8325
  }
8289
8326
  if (report.type === 'outbound-rtp' && report.kind === 'video') {
8290
- videoBytesSent += report.bytesSent;
8327
+ videoBytesSent += report.bytesSent + report.headerBytesSent;
8291
8328
  }
8292
8329
  if (report.type === 'inbound-rtp' && report.kind === 'audio') {
8293
- networkStats.packetsLost = report.packetsLost;
8330
+ packetsLost += report.packetsLost;
8294
8331
  networkStats.packetsReceived = report.packetsReceived;
8295
- audioBytesReceived += report.bytesReceived;
8332
+ audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
8296
8333
  }
8297
8334
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
8298
- videoBytesReceived += report.bytesReceived;
8335
+ videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
8299
8336
  }
8300
8337
  if (report.type === 'outbound-rtp' && report.kind === 'video') {
8301
8338
  if ('framesPerSecond' in report) {
@@ -8307,19 +8344,32 @@ class WebRTCClient extends Emitter {
8307
8344
  }
8308
8345
  }
8309
8346
  if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
8347
+ packetsLost += report.packetsLost;
8310
8348
  networkStats.roundTripTime = report.roundTripTime;
8311
8349
  networkStats.jitter = report.jitter;
8312
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
+ }
8313
8358
  });
8314
8359
 
8360
+ networkStats.packetsLost = packetsLost;
8315
8361
  networkStats.audioBytesSent = audioBytesSent;
8316
8362
  networkStats.audioBytesReceived = audioBytesReceived;
8317
8363
  networkStats.videoBytesSent = videoBytesSent;
8318
8364
  networkStats.videoBytesReceived = videoBytesReceived;
8365
+ networkStats.transportSent = transportSent;
8366
+ networkStats.transportReceived = transportReceived;
8319
8367
 
8320
- networkStats.bandwidth = (networkStats.audioBytesSent - lastAudioSent)
8321
- + (networkStats.videoBytesSent - lastVideoSent) + (networkStats.audioBytesReceived - lastAudioReceived)
8322
- + (networkStats.videoBytesReceived - lastVideoReceived);
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;
8323
8373
 
8324
8374
  this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8325
8375
  this.sessionNetworkStats[sessionId].push(networkStats);
@@ -8368,6 +8418,7 @@ const ON_MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
8368
8418
  const ON_NETWORK_STATS = 'onNetworkStats';
8369
8419
  const ON_CHAT = 'phone/ON_CHAT';
8370
8420
  const ON_SIGNAL = 'phone/ON_SIGNAL';
8421
+ const ON_DISCONNECTED = 'onDisconnected';
8371
8422
 
8372
8423
  const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
8373
8424
  const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
@@ -8407,6 +8458,7 @@ const events = [
8407
8458
  ON_CHAT,
8408
8459
  ON_SIGNAL,
8409
8460
  ON_NETWORK_STATS,
8461
+ ON_DISCONNECTED,
8410
8462
  ];
8411
8463
 
8412
8464
  const logger$8 = IssueReporter$1.loggerFor('webrtc-phone');
@@ -9759,6 +9811,11 @@ class WebRTCPhone extends Emitter {
9759
9811
  this.eventEmitter.emit(ON_UNREGISTERED);
9760
9812
  });
9761
9813
 
9814
+ this.client.on(this.client.ON_DISCONNECTED, () => {
9815
+ logger$8.info('WebRTC disconnected');
9816
+ this.eventEmitter.emit(ON_DISCONNECTED);
9817
+ });
9818
+
9762
9819
  this.client.on(this.client.REGISTERED, () => {
9763
9820
  logger$8.info('WebRTC registered', {
9764
9821
  shouldSendReinvite: this.shouldSendReinvite,
@@ -10015,6 +10072,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10015
10072
  ON_NETWORK_STATS: ON_NETWORK_STATS,
10016
10073
  ON_CHAT: ON_CHAT,
10017
10074
  ON_SIGNAL: ON_SIGNAL,
10075
+ ON_DISCONNECTED: ON_DISCONNECTED,
10018
10076
  MESSAGE_TYPE_CHAT: MESSAGE_TYPE_CHAT,
10019
10077
  MESSAGE_TYPE_SIGNAL: MESSAGE_TYPE_SIGNAL,
10020
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
  }
@@ -8275,25 +8304,33 @@ class WebRTCClient extends Emitter {
8275
8304
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8276
8305
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8277
8306
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8307
+ const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8308
+ const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8278
8309
  let audioBytesSent = 0;
8279
8310
  let audioBytesReceived = 0;
8280
8311
  let videoBytesSent = 0;
8281
8312
  let videoBytesReceived = 0;
8313
+ let transportSent = 0;
8314
+ let transportReceived = 0;
8315
+ let packetsLost = 0;
8282
8316
 
8283
8317
  stats.forEach(report => {
8284
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') {
8285
8322
  audioBytesSent += report.bytesSent;
8286
8323
  }
8287
8324
  if (report.type === 'outbound-rtp' && report.kind === 'video') {
8288
- videoBytesSent += report.bytesSent;
8325
+ videoBytesSent += report.bytesSent + report.headerBytesSent;
8289
8326
  }
8290
8327
  if (report.type === 'inbound-rtp' && report.kind === 'audio') {
8291
- networkStats.packetsLost = report.packetsLost;
8328
+ packetsLost += report.packetsLost;
8292
8329
  networkStats.packetsReceived = report.packetsReceived;
8293
- audioBytesReceived += report.bytesReceived;
8330
+ audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
8294
8331
  }
8295
8332
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
8296
- videoBytesReceived += report.bytesReceived;
8333
+ videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
8297
8334
  }
8298
8335
  if (report.type === 'outbound-rtp' && report.kind === 'video') {
8299
8336
  if ('framesPerSecond' in report) {
@@ -8305,19 +8342,32 @@ class WebRTCClient extends Emitter {
8305
8342
  }
8306
8343
  }
8307
8344
  if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
8345
+ packetsLost += report.packetsLost;
8308
8346
  networkStats.roundTripTime = report.roundTripTime;
8309
8347
  networkStats.jitter = report.jitter;
8310
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
+ }
8311
8356
  });
8312
8357
 
8358
+ networkStats.packetsLost = packetsLost;
8313
8359
  networkStats.audioBytesSent = audioBytesSent;
8314
8360
  networkStats.audioBytesReceived = audioBytesReceived;
8315
8361
  networkStats.videoBytesSent = videoBytesSent;
8316
8362
  networkStats.videoBytesReceived = videoBytesReceived;
8363
+ networkStats.transportSent = transportSent;
8364
+ networkStats.transportReceived = transportReceived;
8317
8365
 
8318
- networkStats.bandwidth = (networkStats.audioBytesSent - lastAudioSent)
8319
- + (networkStats.videoBytesSent - lastVideoSent) + (networkStats.audioBytesReceived - lastAudioReceived)
8320
- + (networkStats.videoBytesReceived - lastVideoReceived);
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;
8321
8371
 
8322
8372
  this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8323
8373
  this.sessionNetworkStats[sessionId].push(networkStats);
@@ -8366,6 +8416,7 @@ const ON_MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
8366
8416
  const ON_NETWORK_STATS = 'onNetworkStats';
8367
8417
  const ON_CHAT = 'phone/ON_CHAT';
8368
8418
  const ON_SIGNAL = 'phone/ON_SIGNAL';
8419
+ const ON_DISCONNECTED = 'onDisconnected';
8369
8420
 
8370
8421
  const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
8371
8422
  const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
@@ -8405,6 +8456,7 @@ const events = [
8405
8456
  ON_CHAT,
8406
8457
  ON_SIGNAL,
8407
8458
  ON_NETWORK_STATS,
8459
+ ON_DISCONNECTED,
8408
8460
  ];
8409
8461
 
8410
8462
  const logger$8 = IssueReporter$1.loggerFor('webrtc-phone');
@@ -9757,6 +9809,11 @@ class WebRTCPhone extends Emitter {
9757
9809
  this.eventEmitter.emit(ON_UNREGISTERED);
9758
9810
  });
9759
9811
 
9812
+ this.client.on(this.client.ON_DISCONNECTED, () => {
9813
+ logger$8.info('WebRTC disconnected');
9814
+ this.eventEmitter.emit(ON_DISCONNECTED);
9815
+ });
9816
+
9760
9817
  this.client.on(this.client.REGISTERED, () => {
9761
9818
  logger$8.info('WebRTC registered', {
9762
9819
  shouldSendReinvite: this.shouldSendReinvite,
@@ -10013,6 +10070,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10013
10070
  ON_NETWORK_STATS: ON_NETWORK_STATS,
10014
10071
  ON_CHAT: ON_CHAT,
10015
10072
  ON_SIGNAL: ON_SIGNAL,
10073
+ ON_DISCONNECTED: ON_DISCONNECTED,
10016
10074
  MESSAGE_TYPE_CHAT: MESSAGE_TYPE_CHAT,
10017
10075
  MESSAGE_TYPE_SIGNAL: MESSAGE_TYPE_SIGNAL,
10018
10076
  events: events,
@@ -388,7 +388,7 @@ class IssueReporter {
388
388
  payload._retry = retry + 1;
389
389
  }
390
390
 
391
- this._sendDebugToGrafana(body, retry + 1);
391
+ this._sendDebugToGrafana(payload, retry + 1);
392
392
  }, 5000 + retry * 1000);
393
393
  });
394
394
  }
@@ -2591,7 +2591,8 @@ class ExternalApp {
2591
2591
 
2592
2592
 
2593
2593
 
2594
-
2594
+
2595
+
2595
2596
 
2596
2597
 
2597
2598
  class Meeting {
@@ -2603,6 +2604,7 @@ class Meeting {
2603
2604
 
2604
2605
 
2605
2606
 
2607
+
2606
2608
 
2607
2609
 
2608
2610
  static parse(plain ) {
@@ -2614,6 +2616,7 @@ class Meeting {
2614
2616
  port: plain.port,
2615
2617
  uuid: plain.uuid,
2616
2618
  number: plain.number,
2619
+ persistent: plain.persistent,
2617
2620
  });
2618
2621
  }
2619
2622
 
@@ -2621,7 +2624,7 @@ class Meeting {
2621
2624
  return newFrom(meeting, Meeting);
2622
2625
  }
2623
2626
 
2624
- constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
2627
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
2625
2628
  this.guestSipAuthorization = guestSipAuthorization;
2626
2629
  this.uri = uri;
2627
2630
  this.name = name;
@@ -2629,6 +2632,7 @@ class Meeting {
2629
2632
  this.port = port;
2630
2633
  this.uuid = uuid;
2631
2634
  this.number = number;
2635
+ this.persistent = persistent;
2632
2636
 
2633
2637
  // Useful to compare instead of instanceof with minified code
2634
2638
  this.type = 'Meeting';
@@ -3192,7 +3196,7 @@ class Recording {
3192
3196
 
3193
3197
 
3194
3198
 
3195
- static parseMany(recordings ) {
3199
+ static parseMany(recordings = []) {
3196
3200
  return recordings.map(item => Recording.parse(item));
3197
3201
  }
3198
3202
 
@@ -3318,7 +3322,7 @@ class CallLog {
3318
3322
  duration: (plain.duration || 0) * 1000, // duration is in seconds
3319
3323
  start: moment__default['default'](plain.start).toDate(),
3320
3324
  end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3321
- recordings: Recording.parseMany(plain.recordings),
3325
+ recordings: Recording.parseMany(plain.recordings || []),
3322
3326
  });
3323
3327
  }
3324
3328