@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
@@ -411,7 +411,7 @@ class IssueReporter {
411
411
  payload._retry = retry + 1;
412
412
  }
413
413
 
414
- this._sendDebugToGrafana(body, retry + 1);
414
+ this._sendDebugToGrafana(payload, retry + 1);
415
415
  }, 5000 + retry * 1000);
416
416
  });
417
417
  }
@@ -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
 
@@ -6557,6 +6561,7 @@ const ON_REINVITE$1 = 'reinvite';
6557
6561
  const ON_ERROR = 'onError';
6558
6562
  const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
6559
6563
  const ON_NETWORK_STATS$1 = 'onNetworkStats';
6564
+ const ON_DISCONNECTED$1 = 'onDisconnected';
6560
6565
 
6561
6566
  const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
6562
6567
  const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
@@ -6633,6 +6638,7 @@ class WebRTCClient extends Emitter {
6633
6638
 
6634
6639
 
6635
6640
 
6641
+
6636
6642
 
6637
6643
  static isAPrivateIp(ip ) {
6638
6644
  const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
@@ -6698,6 +6704,7 @@ class WebRTCClient extends Emitter {
6698
6704
  this.ON_ERROR = ON_ERROR;
6699
6705
  this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
6700
6706
  this.ON_NETWORK_STATS = ON_NETWORK_STATS$1;
6707
+ this.ON_DISCONNECTED = ON_DISCONNECTED$1;
6701
6708
  }
6702
6709
 
6703
6710
  configureMedia(media ) {
@@ -7299,7 +7306,7 @@ class WebRTCClient extends Emitter {
7299
7306
  // We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
7300
7307
  const transceivers = pc.getTransceivers();
7301
7308
  const transceiverIdx = lastIndexOf(transceivers, transceiver =>
7302
- transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
7309
+ transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
7303
7310
 
7304
7311
  videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
7305
7312
  } else {
@@ -7545,10 +7552,13 @@ class WebRTCClient extends Emitter {
7545
7552
  return null;
7546
7553
  }
7547
7554
 
7548
- // let's update the local value
7549
- if (this.audio && this.audio.deviceId) {
7550
- // $FlowFixMe
7551
- this.audio.deviceId.exact = id;
7555
+ // let's update the local audio value
7556
+ if (this.audio) {
7557
+ this.audio = {
7558
+ deviceId: {
7559
+ exact: id,
7560
+ },
7561
+ };
7552
7562
  }
7553
7563
 
7554
7564
  if (session) {
@@ -7561,6 +7571,9 @@ class WebRTCClient extends Emitter {
7561
7571
  const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
7562
7572
 
7563
7573
  if (sender) {
7574
+ if (sender.track) {
7575
+ audioTrack.enabled = sender.track.enabled;
7576
+ }
7564
7577
  sender.replaceTrack(audioTrack);
7565
7578
  }
7566
7579
 
@@ -7585,7 +7598,7 @@ class WebRTCClient extends Emitter {
7585
7598
  return null;
7586
7599
  }
7587
7600
 
7588
- // let's update the local value
7601
+ // let's update the local video value
7589
7602
  if (this.video) {
7590
7603
  this.video = {
7591
7604
  deviceId: {
@@ -7620,12 +7633,21 @@ class WebRTCClient extends Emitter {
7620
7633
  return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
7621
7634
  const videoTrack = stream.getVideoTracks()[0];
7622
7635
  let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
7636
+ let wasTrackEnabled = false;
7623
7637
  if (!sender) {
7624
7638
  sender = pc && pc.getSenders().find(s => !s.track);
7625
7639
  }
7626
7640
 
7627
7641
  if (sender) {
7628
- sender.replaceTrack(videoTrack);
7642
+ // No video track means video not enabled
7643
+ wasTrackEnabled = sender.track ? sender.track.enabled : false;
7644
+ videoTrack.enabled = wasTrackEnabled;
7645
+
7646
+ if (!wasTrackEnabled) {
7647
+ videoTrack.stop();
7648
+ }
7649
+
7650
+ sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
7629
7651
  }
7630
7652
 
7631
7653
  // let's update the local stream
@@ -8309,6 +8331,7 @@ class WebRTCClient extends Emitter {
8309
8331
 
8310
8332
  this.updateRemoteStream(this.getSipSessionId(session));
8311
8333
 
8334
+ const pc = session.sessionDescriptionHandler.peerConnection;
8312
8335
  const onTrack = (event ) => {
8313
8336
  const isAudioOnly = this._isAudioOnly(session);
8314
8337
  const { kind, label, readyState, id, muted } = event.track;
@@ -8328,6 +8351,12 @@ class WebRTCClient extends Emitter {
8328
8351
 
8329
8352
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
8330
8353
 
8354
+ pc.oniceconnectionstatechange = () => {
8355
+ if (pc.iceConnectionState === 'disconnected') {
8356
+ this.eventEmitter.emit(ON_DISCONNECTED$1);
8357
+ }
8358
+ };
8359
+
8331
8360
  if (withEvent) {
8332
8361
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
8333
8362
  }
@@ -8539,25 +8568,33 @@ class WebRTCClient extends Emitter {
8539
8568
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8540
8569
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8541
8570
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8571
+ const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8572
+ const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8542
8573
  let audioBytesSent = 0;
8543
8574
  let audioBytesReceived = 0;
8544
8575
  let videoBytesSent = 0;
8545
8576
  let videoBytesReceived = 0;
8577
+ let transportSent = 0;
8578
+ let transportReceived = 0;
8579
+ let packetsLost = 0;
8546
8580
 
8547
8581
  stats.forEach(report => {
8548
8582
  if (report.type === 'outbound-rtp' && report.kind === 'audio') {
8583
+ audioBytesSent += report.bytesSent + report.headerBytesSent;
8584
+ }
8585
+ if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
8549
8586
  audioBytesSent += report.bytesSent;
8550
8587
  }
8551
8588
  if (report.type === 'outbound-rtp' && report.kind === 'video') {
8552
- videoBytesSent += report.bytesSent;
8589
+ videoBytesSent += report.bytesSent + report.headerBytesSent;
8553
8590
  }
8554
8591
  if (report.type === 'inbound-rtp' && report.kind === 'audio') {
8555
- networkStats.packetsLost = report.packetsLost;
8592
+ packetsLost += report.packetsLost;
8556
8593
  networkStats.packetsReceived = report.packetsReceived;
8557
- audioBytesReceived += report.bytesReceived;
8594
+ audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
8558
8595
  }
8559
8596
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
8560
- videoBytesReceived += report.bytesReceived;
8597
+ videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
8561
8598
  }
8562
8599
  if (report.type === 'outbound-rtp' && report.kind === 'video') {
8563
8600
  if ('framesPerSecond' in report) {
@@ -8569,19 +8606,32 @@ class WebRTCClient extends Emitter {
8569
8606
  }
8570
8607
  }
8571
8608
  if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
8609
+ packetsLost += report.packetsLost;
8572
8610
  networkStats.roundTripTime = report.roundTripTime;
8573
8611
  networkStats.jitter = report.jitter;
8574
8612
  }
8613
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
8614
+ packetsLost += report.packetsLost;
8615
+ }
8616
+ if (report.type === 'transport') {
8617
+ transportSent += report.bytesSent;
8618
+ transportReceived += report.bytesReceived;
8619
+ }
8575
8620
  });
8576
8621
 
8622
+ networkStats.packetsLost = packetsLost;
8577
8623
  networkStats.audioBytesSent = audioBytesSent;
8578
8624
  networkStats.audioBytesReceived = audioBytesReceived;
8579
8625
  networkStats.videoBytesSent = videoBytesSent;
8580
8626
  networkStats.videoBytesReceived = videoBytesReceived;
8627
+ networkStats.transportSent = transportSent;
8628
+ networkStats.transportReceived = transportReceived;
8581
8629
 
8582
- networkStats.bandwidth = (networkStats.audioBytesSent - lastAudioSent)
8583
- + (networkStats.videoBytesSent - lastVideoSent) + (networkStats.audioBytesReceived - lastAudioReceived)
8584
- + (networkStats.videoBytesReceived - lastVideoReceived);
8630
+ const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
8631
+ + (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
8632
+ + (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
8633
+
8634
+ networkStats.bandwidth = bandwidth;
8585
8635
 
8586
8636
  this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8587
8637
  this.sessionNetworkStats[sessionId].push(networkStats);
@@ -8630,6 +8680,7 @@ const ON_MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
8630
8680
  const ON_NETWORK_STATS = 'onNetworkStats';
8631
8681
  const ON_CHAT = 'phone/ON_CHAT';
8632
8682
  const ON_SIGNAL = 'phone/ON_SIGNAL';
8683
+ const ON_DISCONNECTED = 'onDisconnected';
8633
8684
 
8634
8685
  const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
8635
8686
  const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
@@ -8669,6 +8720,7 @@ const events = [
8669
8720
  ON_CHAT,
8670
8721
  ON_SIGNAL,
8671
8722
  ON_NETWORK_STATS,
8723
+ ON_DISCONNECTED,
8672
8724
  ];
8673
8725
 
8674
8726
  const logger$7 = IssueReporter$1.loggerFor('webrtc-phone');
@@ -10021,6 +10073,11 @@ class WebRTCPhone extends Emitter {
10021
10073
  this.eventEmitter.emit(ON_UNREGISTERED);
10022
10074
  });
10023
10075
 
10076
+ this.client.on(this.client.ON_DISCONNECTED, () => {
10077
+ logger$7.info('WebRTC disconnected');
10078
+ this.eventEmitter.emit(ON_DISCONNECTED);
10079
+ });
10080
+
10024
10081
  this.client.on(this.client.REGISTERED, () => {
10025
10082
  logger$7.info('WebRTC registered', {
10026
10083
  shouldSendReinvite: this.shouldSendReinvite,
@@ -10277,6 +10334,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10277
10334
  ON_NETWORK_STATS: ON_NETWORK_STATS,
10278
10335
  ON_CHAT: ON_CHAT,
10279
10336
  ON_SIGNAL: ON_SIGNAL,
10337
+ ON_DISCONNECTED: ON_DISCONNECTED,
10280
10338
  MESSAGE_TYPE_CHAT: MESSAGE_TYPE_CHAT,
10281
10339
  MESSAGE_TYPE_SIGNAL: MESSAGE_TYPE_SIGNAL,
10282
10340
  events: events,
@@ -413,7 +413,7 @@ class IssueReporter {
413
413
  payload._retry = retry + 1;
414
414
  }
415
415
 
416
- this._sendDebugToGrafana(body, retry + 1);
416
+ this._sendDebugToGrafana(payload, retry + 1);
417
417
  }, 5000 + retry * 1000);
418
418
  });
419
419
  }
@@ -2616,7 +2616,8 @@ class ExternalApp {
2616
2616
 
2617
2617
 
2618
2618
 
2619
-
2619
+
2620
+
2620
2621
 
2621
2622
 
2622
2623
  class Meeting {
@@ -2628,6 +2629,7 @@ class Meeting {
2628
2629
 
2629
2630
 
2630
2631
 
2632
+
2631
2633
 
2632
2634
 
2633
2635
  static parse(plain ) {
@@ -2639,6 +2641,7 @@ class Meeting {
2639
2641
  port: plain.port,
2640
2642
  uuid: plain.uuid,
2641
2643
  number: plain.number,
2644
+ persistent: plain.persistent,
2642
2645
  });
2643
2646
  }
2644
2647
 
@@ -2646,7 +2649,7 @@ class Meeting {
2646
2649
  return newFrom(meeting, Meeting);
2647
2650
  }
2648
2651
 
2649
- constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
2652
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
2650
2653
  this.guestSipAuthorization = guestSipAuthorization;
2651
2654
  this.uri = uri;
2652
2655
  this.name = name;
@@ -2654,6 +2657,7 @@ class Meeting {
2654
2657
  this.port = port;
2655
2658
  this.uuid = uuid;
2656
2659
  this.number = number;
2660
+ this.persistent = persistent;
2657
2661
 
2658
2662
  // Useful to compare instead of instanceof with minified code
2659
2663
  this.type = 'Meeting';
@@ -3588,7 +3592,7 @@ class Recording {
3588
3592
 
3589
3593
 
3590
3594
 
3591
- static parseMany(recordings ) {
3595
+ static parseMany(recordings = []) {
3592
3596
  return recordings.map(item => Recording.parse(item));
3593
3597
  }
3594
3598
 
@@ -3714,7 +3718,7 @@ class CallLog {
3714
3718
  duration: (plain.duration || 0) * 1000, // duration is in seconds
3715
3719
  start: moment__default['default'](plain.start).toDate(),
3716
3720
  end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3717
- recordings: Recording.parseMany(plain.recordings),
3721
+ recordings: Recording.parseMany(plain.recordings || []),
3718
3722
  });
3719
3723
  }
3720
3724
 
@@ -6559,6 +6563,7 @@ const ON_REINVITE$1 = 'reinvite';
6559
6563
  const ON_ERROR = 'onError';
6560
6564
  const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
6561
6565
  const ON_NETWORK_STATS$1 = 'onNetworkStats';
6566
+ const ON_DISCONNECTED$1 = 'onDisconnected';
6562
6567
 
6563
6568
  const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
6564
6569
  const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
@@ -6635,6 +6640,7 @@ class WebRTCClient extends Emitter {
6635
6640
 
6636
6641
 
6637
6642
 
6643
+
6638
6644
 
6639
6645
  static isAPrivateIp(ip ) {
6640
6646
  const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
@@ -6700,6 +6706,7 @@ class WebRTCClient extends Emitter {
6700
6706
  this.ON_ERROR = ON_ERROR;
6701
6707
  this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
6702
6708
  this.ON_NETWORK_STATS = ON_NETWORK_STATS$1;
6709
+ this.ON_DISCONNECTED = ON_DISCONNECTED$1;
6703
6710
  }
6704
6711
 
6705
6712
  configureMedia(media ) {
@@ -7301,7 +7308,7 @@ class WebRTCClient extends Emitter {
7301
7308
  // We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
7302
7309
  const transceivers = pc.getTransceivers();
7303
7310
  const transceiverIdx = lastIndexOf(transceivers, transceiver =>
7304
- transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
7311
+ transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
7305
7312
 
7306
7313
  videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
7307
7314
  } else {
@@ -7547,10 +7554,13 @@ class WebRTCClient extends Emitter {
7547
7554
  return null;
7548
7555
  }
7549
7556
 
7550
- // let's update the local value
7551
- if (this.audio && this.audio.deviceId) {
7552
- // $FlowFixMe
7553
- this.audio.deviceId.exact = id;
7557
+ // let's update the local audio value
7558
+ if (this.audio) {
7559
+ this.audio = {
7560
+ deviceId: {
7561
+ exact: id,
7562
+ },
7563
+ };
7554
7564
  }
7555
7565
 
7556
7566
  if (session) {
@@ -7563,6 +7573,9 @@ class WebRTCClient extends Emitter {
7563
7573
  const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
7564
7574
 
7565
7575
  if (sender) {
7576
+ if (sender.track) {
7577
+ audioTrack.enabled = sender.track.enabled;
7578
+ }
7566
7579
  sender.replaceTrack(audioTrack);
7567
7580
  }
7568
7581
 
@@ -7587,7 +7600,7 @@ class WebRTCClient extends Emitter {
7587
7600
  return null;
7588
7601
  }
7589
7602
 
7590
- // let's update the local value
7603
+ // let's update the local video value
7591
7604
  if (this.video) {
7592
7605
  this.video = {
7593
7606
  deviceId: {
@@ -7622,12 +7635,21 @@ class WebRTCClient extends Emitter {
7622
7635
  return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
7623
7636
  const videoTrack = stream.getVideoTracks()[0];
7624
7637
  let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
7638
+ let wasTrackEnabled = false;
7625
7639
  if (!sender) {
7626
7640
  sender = pc && pc.getSenders().find(s => !s.track);
7627
7641
  }
7628
7642
 
7629
7643
  if (sender) {
7630
- sender.replaceTrack(videoTrack);
7644
+ // No video track means video not enabled
7645
+ wasTrackEnabled = sender.track ? sender.track.enabled : false;
7646
+ videoTrack.enabled = wasTrackEnabled;
7647
+
7648
+ if (!wasTrackEnabled) {
7649
+ videoTrack.stop();
7650
+ }
7651
+
7652
+ sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
7631
7653
  }
7632
7654
 
7633
7655
  // let's update the local stream
@@ -8311,6 +8333,7 @@ class WebRTCClient extends Emitter {
8311
8333
 
8312
8334
  this.updateRemoteStream(this.getSipSessionId(session));
8313
8335
 
8336
+ const pc = session.sessionDescriptionHandler.peerConnection;
8314
8337
  const onTrack = (event ) => {
8315
8338
  const isAudioOnly = this._isAudioOnly(session);
8316
8339
  const { kind, label, readyState, id, muted } = event.track;
@@ -8330,6 +8353,12 @@ class WebRTCClient extends Emitter {
8330
8353
 
8331
8354
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
8332
8355
 
8356
+ pc.oniceconnectionstatechange = () => {
8357
+ if (pc.iceConnectionState === 'disconnected') {
8358
+ this.eventEmitter.emit(ON_DISCONNECTED$1);
8359
+ }
8360
+ };
8361
+
8333
8362
  if (withEvent) {
8334
8363
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
8335
8364
  }
@@ -8541,25 +8570,33 @@ class WebRTCClient extends Emitter {
8541
8570
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8542
8571
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8543
8572
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8573
+ const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8574
+ const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8544
8575
  let audioBytesSent = 0;
8545
8576
  let audioBytesReceived = 0;
8546
8577
  let videoBytesSent = 0;
8547
8578
  let videoBytesReceived = 0;
8579
+ let transportSent = 0;
8580
+ let transportReceived = 0;
8581
+ let packetsLost = 0;
8548
8582
 
8549
8583
  stats.forEach(report => {
8550
8584
  if (report.type === 'outbound-rtp' && report.kind === 'audio') {
8585
+ audioBytesSent += report.bytesSent + report.headerBytesSent;
8586
+ }
8587
+ if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
8551
8588
  audioBytesSent += report.bytesSent;
8552
8589
  }
8553
8590
  if (report.type === 'outbound-rtp' && report.kind === 'video') {
8554
- videoBytesSent += report.bytesSent;
8591
+ videoBytesSent += report.bytesSent + report.headerBytesSent;
8555
8592
  }
8556
8593
  if (report.type === 'inbound-rtp' && report.kind === 'audio') {
8557
- networkStats.packetsLost = report.packetsLost;
8594
+ packetsLost += report.packetsLost;
8558
8595
  networkStats.packetsReceived = report.packetsReceived;
8559
- audioBytesReceived += report.bytesReceived;
8596
+ audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
8560
8597
  }
8561
8598
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
8562
- videoBytesReceived += report.bytesReceived;
8599
+ videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
8563
8600
  }
8564
8601
  if (report.type === 'outbound-rtp' && report.kind === 'video') {
8565
8602
  if ('framesPerSecond' in report) {
@@ -8571,19 +8608,32 @@ class WebRTCClient extends Emitter {
8571
8608
  }
8572
8609
  }
8573
8610
  if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
8611
+ packetsLost += report.packetsLost;
8574
8612
  networkStats.roundTripTime = report.roundTripTime;
8575
8613
  networkStats.jitter = report.jitter;
8576
8614
  }
8615
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
8616
+ packetsLost += report.packetsLost;
8617
+ }
8618
+ if (report.type === 'transport') {
8619
+ transportSent += report.bytesSent;
8620
+ transportReceived += report.bytesReceived;
8621
+ }
8577
8622
  });
8578
8623
 
8624
+ networkStats.packetsLost = packetsLost;
8579
8625
  networkStats.audioBytesSent = audioBytesSent;
8580
8626
  networkStats.audioBytesReceived = audioBytesReceived;
8581
8627
  networkStats.videoBytesSent = videoBytesSent;
8582
8628
  networkStats.videoBytesReceived = videoBytesReceived;
8629
+ networkStats.transportSent = transportSent;
8630
+ networkStats.transportReceived = transportReceived;
8583
8631
 
8584
- networkStats.bandwidth = (networkStats.audioBytesSent - lastAudioSent)
8585
- + (networkStats.videoBytesSent - lastVideoSent) + (networkStats.audioBytesReceived - lastAudioReceived)
8586
- + (networkStats.videoBytesReceived - lastVideoReceived);
8632
+ const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
8633
+ + (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
8634
+ + (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
8635
+
8636
+ networkStats.bandwidth = bandwidth;
8587
8637
 
8588
8638
  this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8589
8639
  this.sessionNetworkStats[sessionId].push(networkStats);
@@ -8632,6 +8682,7 @@ const ON_MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
8632
8682
  const ON_NETWORK_STATS = 'onNetworkStats';
8633
8683
  const ON_CHAT = 'phone/ON_CHAT';
8634
8684
  const ON_SIGNAL = 'phone/ON_SIGNAL';
8685
+ const ON_DISCONNECTED = 'onDisconnected';
8635
8686
 
8636
8687
  const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
8637
8688
  const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
@@ -8671,6 +8722,7 @@ const events = [
8671
8722
  ON_CHAT,
8672
8723
  ON_SIGNAL,
8673
8724
  ON_NETWORK_STATS,
8725
+ ON_DISCONNECTED,
8674
8726
  ];
8675
8727
 
8676
8728
  const logger$7 = IssueReporter$1.loggerFor('webrtc-phone');
@@ -10023,6 +10075,11 @@ class WebRTCPhone extends Emitter {
10023
10075
  this.eventEmitter.emit(ON_UNREGISTERED);
10024
10076
  });
10025
10077
 
10078
+ this.client.on(this.client.ON_DISCONNECTED, () => {
10079
+ logger$7.info('WebRTC disconnected');
10080
+ this.eventEmitter.emit(ON_DISCONNECTED);
10081
+ });
10082
+
10026
10083
  this.client.on(this.client.REGISTERED, () => {
10027
10084
  logger$7.info('WebRTC registered', {
10028
10085
  shouldSendReinvite: this.shouldSendReinvite,
@@ -10279,6 +10336,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10279
10336
  ON_NETWORK_STATS: ON_NETWORK_STATS,
10280
10337
  ON_CHAT: ON_CHAT,
10281
10338
  ON_SIGNAL: ON_SIGNAL,
10339
+ ON_DISCONNECTED: ON_DISCONNECTED,
10282
10340
  MESSAGE_TYPE_CHAT: MESSAGE_TYPE_CHAT,
10283
10341
  MESSAGE_TYPE_SIGNAL: MESSAGE_TYPE_SIGNAL,
10284
10342
  events: events,