@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
@@ -702,7 +702,7 @@ class IssueReporter {
702
702
  payload._retry = retry + 1;
703
703
  }
704
704
 
705
- this._sendDebugToGrafana(body, retry + 1);
705
+ this._sendDebugToGrafana(payload, retry + 1);
706
706
  }, 5000 + retry * 1000);
707
707
  });
708
708
  }
@@ -2640,7 +2640,8 @@ class ExternalApp {
2640
2640
 
2641
2641
 
2642
2642
 
2643
-
2643
+
2644
+
2644
2645
 
2645
2646
 
2646
2647
  class Meeting {
@@ -2652,6 +2653,7 @@ class Meeting {
2652
2653
 
2653
2654
 
2654
2655
 
2656
+
2655
2657
 
2656
2658
 
2657
2659
  static parse(plain ) {
@@ -2663,6 +2665,7 @@ class Meeting {
2663
2665
  port: plain.port,
2664
2666
  uuid: plain.uuid,
2665
2667
  number: plain.number,
2668
+ persistent: plain.persistent,
2666
2669
  });
2667
2670
  }
2668
2671
 
@@ -2670,7 +2673,7 @@ class Meeting {
2670
2673
  return newFrom(meeting, Meeting);
2671
2674
  }
2672
2675
 
2673
- constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
2676
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
2674
2677
  this.guestSipAuthorization = guestSipAuthorization;
2675
2678
  this.uri = uri;
2676
2679
  this.name = name;
@@ -2678,6 +2681,7 @@ class Meeting {
2678
2681
  this.port = port;
2679
2682
  this.uuid = uuid;
2680
2683
  this.number = number;
2684
+ this.persistent = persistent;
2681
2685
 
2682
2686
  // Useful to compare instead of instanceof with minified code
2683
2687
  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,
@@ -702,7 +702,7 @@ class IssueReporter {
702
702
  payload._retry = retry + 1;
703
703
  }
704
704
 
705
- this._sendDebugToGrafana(body, retry + 1);
705
+ this._sendDebugToGrafana(payload, retry + 1);
706
706
  }, 5000 + retry * 1000);
707
707
  });
708
708
  }
@@ -2640,7 +2640,8 @@ class ExternalApp {
2640
2640
 
2641
2641
 
2642
2642
 
2643
-
2643
+
2644
+
2644
2645
 
2645
2646
 
2646
2647
  class Meeting {
@@ -2652,6 +2653,7 @@ class Meeting {
2652
2653
 
2653
2654
 
2654
2655
 
2656
+
2655
2657
 
2656
2658
 
2657
2659
  static parse(plain ) {
@@ -2663,6 +2665,7 @@ class Meeting {
2663
2665
  port: plain.port,
2664
2666
  uuid: plain.uuid,
2665
2667
  number: plain.number,
2668
+ persistent: plain.persistent,
2666
2669
  });
2667
2670
  }
2668
2671
 
@@ -2670,7 +2673,7 @@ class Meeting {
2670
2673
  return newFrom(meeting, Meeting);
2671
2674
  }
2672
2675
 
2673
- constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
2676
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
2674
2677
  this.guestSipAuthorization = guestSipAuthorization;
2675
2678
  this.uri = uri;
2676
2679
  this.name = name;
@@ -2678,6 +2681,7 @@ class Meeting {
2678
2681
  this.port = port;
2679
2682
  this.uuid = uuid;
2680
2683
  this.number = number;
2684
+ this.persistent = persistent;
2681
2685
 
2682
2686
  // Useful to compare instead of instanceof with minified code
2683
2687
  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,