@wazo/sdk 0.37.15 → 0.37.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/dist/wazo-sdk.js +3 -3
  2. package/esm/__tests__/api-client.test.js +9 -5
  3. package/esm/__tests__/web-rtc-client.test.js +117 -23
  4. package/esm/api/agentd.js +1 -1
  5. package/esm/api/amid.js +1 -1
  6. package/esm/api/application.js +1 -1
  7. package/esm/api/auth.js +1 -1
  8. package/esm/api/call-logd.js +3 -3
  9. package/esm/api/calld.js +1 -1
  10. package/esm/api/chatd.js +1 -1
  11. package/esm/api/confd.js +7 -3
  12. package/esm/api/ctid-ng.js +1 -1
  13. package/esm/api/dird.js +1 -1
  14. package/esm/api/webhookd.js +1 -1
  15. package/esm/api-client.js +9 -5
  16. package/esm/checker/Checker.js +117 -23
  17. package/esm/checker/checks/aor.js +9 -5
  18. package/esm/checker/checks/api.js +9 -5
  19. package/esm/checker/checks/index.js +117 -23
  20. package/esm/checker/checks/wazo-websocket.js +1 -1
  21. package/esm/checker/checks/webrtc-transport.js +117 -23
  22. package/esm/checker/checks/webrtc.js +117 -23
  23. package/esm/domain/AdHocAPIConference.js +9 -5
  24. package/esm/domain/CallLog.js +2 -2
  25. package/esm/domain/Features.js +9 -5
  26. package/esm/domain/Meeting.js +6 -2
  27. package/esm/domain/Phone/CTIPhone.js +9 -5
  28. package/esm/domain/Phone/WebRTCPhone.js +9 -2
  29. package/esm/domain/Recording.js +1 -1
  30. package/esm/domain/__tests__/CallLog.test.js +2 -2
  31. package/esm/index.js +125 -23
  32. package/esm/lib/WazoSessionDescriptionHandler.js +1 -1
  33. package/esm/service/CallApi.js +9 -5
  34. package/esm/service/IssueReporter.js +1 -1
  35. package/esm/service/__tests__/IssueReporter.test.js +1 -1
  36. package/esm/service/getApiClient.js +9 -5
  37. package/esm/simple/Auth.js +125 -23
  38. package/esm/simple/Configuration.js +125 -23
  39. package/esm/simple/Directory.js +9 -5
  40. package/esm/simple/Phone.js +125 -23
  41. package/esm/simple/Websocket.js +1 -1
  42. package/esm/simple/index.js +125 -23
  43. package/esm/simple/room/LocalParticipant.js +125 -23
  44. package/esm/simple/room/Participant.js +125 -23
  45. package/esm/simple/room/RemoteParticipant.js +125 -23
  46. package/esm/simple/room/Room.js +125 -23
  47. package/esm/simple/room/SipRoom.js +125 -23
  48. package/esm/simple/room/Stream.js +125 -23
  49. package/esm/simple/room/__tests__/RemoteParticipant.test.js +125 -23
  50. package/esm/simple/utils.js +125 -23
  51. package/esm/utils/__tests__/api-requester.test.js +1 -1
  52. package/esm/utils/api-requester.js +1 -1
  53. package/esm/web-rtc-client.js +117 -23
  54. package/esm/websocket-client.js +1 -1
  55. package/lib/__tests__/api-client.test.js +9 -5
  56. package/lib/__tests__/web-rtc-client.test.js +117 -23
  57. package/lib/api/agentd.js +1 -1
  58. package/lib/api/amid.js +1 -1
  59. package/lib/api/application.js +1 -1
  60. package/lib/api/auth.js +1 -1
  61. package/lib/api/call-logd.js +3 -3
  62. package/lib/api/calld.js +1 -1
  63. package/lib/api/chatd.js +1 -1
  64. package/lib/api/confd.js +7 -3
  65. package/lib/api/ctid-ng.js +1 -1
  66. package/lib/api/dird.js +1 -1
  67. package/lib/api/webhookd.js +1 -1
  68. package/lib/api-client.js +9 -5
  69. package/lib/checker/Checker.js +117 -23
  70. package/lib/checker/checks/aor.js +9 -5
  71. package/lib/checker/checks/api.js +9 -5
  72. package/lib/checker/checks/index.js +117 -23
  73. package/lib/checker/checks/wazo-websocket.js +1 -1
  74. package/lib/checker/checks/webrtc-transport.js +117 -23
  75. package/lib/checker/checks/webrtc.js +117 -23
  76. package/lib/domain/AdHocAPIConference.js +9 -5
  77. package/lib/domain/CallLog.js +2 -2
  78. package/lib/domain/Features.js +9 -5
  79. package/lib/domain/Meeting.js +6 -2
  80. package/lib/domain/Phone/CTIPhone.js +9 -5
  81. package/lib/domain/Phone/WebRTCPhone.js +9 -1
  82. package/lib/domain/Recording.js +1 -1
  83. package/lib/domain/__tests__/CallLog.test.js +2 -2
  84. package/lib/index.js +125 -23
  85. package/lib/lib/WazoSessionDescriptionHandler.js +1 -1
  86. package/lib/service/CallApi.js +9 -5
  87. package/lib/service/IssueReporter.js +1 -1
  88. package/lib/service/__tests__/IssueReporter.test.js +1 -1
  89. package/lib/service/getApiClient.js +9 -5
  90. package/lib/simple/Auth.js +125 -23
  91. package/lib/simple/Configuration.js +125 -23
  92. package/lib/simple/Directory.js +9 -5
  93. package/lib/simple/Phone.js +125 -23
  94. package/lib/simple/Websocket.js +1 -1
  95. package/lib/simple/index.js +125 -23
  96. package/lib/simple/room/LocalParticipant.js +125 -23
  97. package/lib/simple/room/Participant.js +125 -23
  98. package/lib/simple/room/RemoteParticipant.js +125 -23
  99. package/lib/simple/room/Room.js +125 -23
  100. package/lib/simple/room/SipRoom.js +125 -23
  101. package/lib/simple/room/Stream.js +125 -23
  102. package/lib/simple/room/__tests__/RemoteParticipant.test.js +125 -23
  103. package/lib/simple/utils.js +125 -23
  104. package/lib/utils/__tests__/api-requester.test.js +1 -1
  105. package/lib/utils/api-requester.js +1 -1
  106. package/lib/web-rtc-client.js +117 -23
  107. package/lib/websocket-client.js +1 -1
  108. package/package.json +1 -1
  109. package/src/domain/CallLog.js +1 -1
  110. package/src/domain/Meeting.js +6 -2
  111. package/src/domain/Phone/WebRTCPhone.js +7 -0
  112. package/src/domain/Recording.js +1 -1
  113. package/src/service/IssueReporter.js +1 -1
  114. package/src/web-rtc-client.js +108 -18
@@ -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
  }
@@ -8525,24 +8554,89 @@ class WebRTCClient extends Emitter {
8525
8554
  const session = this.getSipSession(sessionId);
8526
8555
 
8527
8556
  const stats = session ? await this.getStats(session) : null;
8528
- if (!stats) {
8557
+ if (!stats || !(sessionId in this.sessionNetworkStats)) {
8529
8558
  return;
8530
8559
  }
8531
8560
 
8532
- stats.forEach(report => {
8533
- if (report.type === 'inbound-rtp') {
8534
- if (report.kind === 'audio') {
8535
- const networkStats = {
8536
- packetsLost: report.packetsLost,
8537
- packetsReceived: report.packetsReceived,
8538
- jitter: report.jitter,
8539
- };
8561
+ const networkStats = {
8562
+ audioBytesSent: 0,
8563
+ videoBytesSent: 0,
8564
+ videoBytesReceived: 0,
8565
+ audioBytesReceived: 0,
8566
+ };
8567
+ const nbStats = this.sessionNetworkStats[sessionId].length;
8568
+ const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
8569
+ const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
8570
+ const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8571
+ const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8572
+ const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8573
+ const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8574
+ const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8575
+ let audioBytesSent = 0;
8576
+ let audioBytesReceived = 0;
8577
+ let videoBytesSent = 0;
8578
+ let videoBytesReceived = 0;
8579
+ let transportSent = 0;
8580
+ let transportReceived = 0;
8581
+ let packetsLost = 0;
8540
8582
 
8541
- this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8542
- this.sessionNetworkStats[sessionId].push(networkStats);
8583
+ stats.forEach(report => {
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') {
8588
+ audioBytesSent += report.bytesSent;
8589
+ }
8590
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
8591
+ videoBytesSent += report.bytesSent + report.headerBytesSent;
8592
+ }
8593
+ if (report.type === 'inbound-rtp' && report.kind === 'audio') {
8594
+ packetsLost += report.packetsLost;
8595
+ networkStats.packetsReceived = report.packetsReceived;
8596
+ audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
8597
+ }
8598
+ if (report.type === 'inbound-rtp' && report.kind === 'video') {
8599
+ videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
8600
+ }
8601
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
8602
+ if ('framesPerSecond' in report) {
8603
+ networkStats.framesPerSecond = report.framesPerSecond;
8604
+ }
8605
+ if ('framerateMean' in report) {
8606
+ // framerateMean is only available in FF
8607
+ networkStats.framesPerSecond = Math.round(report.framerateMean);
8543
8608
  }
8544
8609
  }
8610
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
8611
+ packetsLost += report.packetsLost;
8612
+ networkStats.roundTripTime = report.roundTripTime;
8613
+ networkStats.jitter = report.jitter;
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
+ }
8545
8622
  });
8623
+
8624
+ networkStats.packetsLost = packetsLost;
8625
+ networkStats.audioBytesSent = audioBytesSent;
8626
+ networkStats.audioBytesReceived = audioBytesReceived;
8627
+ networkStats.videoBytesSent = videoBytesSent;
8628
+ networkStats.videoBytesReceived = videoBytesReceived;
8629
+ networkStats.transportSent = transportSent;
8630
+ networkStats.transportReceived = transportReceived;
8631
+
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;
8637
+
8638
+ this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8639
+ this.sessionNetworkStats[sessionId].push(networkStats);
8546
8640
  }
8547
8641
 
8548
8642
  }
@@ -8588,6 +8682,7 @@ const ON_MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
8588
8682
  const ON_NETWORK_STATS = 'onNetworkStats';
8589
8683
  const ON_CHAT = 'phone/ON_CHAT';
8590
8684
  const ON_SIGNAL = 'phone/ON_SIGNAL';
8685
+ const ON_DISCONNECTED = 'onDisconnected';
8591
8686
 
8592
8687
  const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
8593
8688
  const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
@@ -8627,6 +8722,7 @@ const events = [
8627
8722
  ON_CHAT,
8628
8723
  ON_SIGNAL,
8629
8724
  ON_NETWORK_STATS,
8725
+ ON_DISCONNECTED,
8630
8726
  ];
8631
8727
 
8632
8728
  const logger$7 = IssueReporter$1.loggerFor('webrtc-phone');
@@ -9979,6 +10075,11 @@ class WebRTCPhone extends Emitter {
9979
10075
  this.eventEmitter.emit(ON_UNREGISTERED);
9980
10076
  });
9981
10077
 
10078
+ this.client.on(this.client.ON_DISCONNECTED, () => {
10079
+ logger$7.info('WebRTC disconnected');
10080
+ this.eventEmitter.emit(ON_DISCONNECTED);
10081
+ });
10082
+
9982
10083
  this.client.on(this.client.REGISTERED, () => {
9983
10084
  logger$7.info('WebRTC registered', {
9984
10085
  shouldSendReinvite: this.shouldSendReinvite,
@@ -10235,6 +10336,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10235
10336
  ON_NETWORK_STATS: ON_NETWORK_STATS,
10236
10337
  ON_CHAT: ON_CHAT,
10237
10338
  ON_SIGNAL: ON_SIGNAL,
10339
+ ON_DISCONNECTED: ON_DISCONNECTED,
10238
10340
  MESSAGE_TYPE_CHAT: MESSAGE_TYPE_CHAT,
10239
10341
  MESSAGE_TYPE_SIGNAL: MESSAGE_TYPE_SIGNAL,
10240
10342
  events: events,
@@ -676,7 +676,7 @@ class IssueReporter {
676
676
  payload._retry = retry + 1;
677
677
  }
678
678
 
679
- this._sendDebugToGrafana(body, retry + 1);
679
+ this._sendDebugToGrafana(payload, retry + 1);
680
680
  }, 5000 + retry * 1000);
681
681
  });
682
682
  }
@@ -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
  }
@@ -8523,24 +8552,89 @@ class WebRTCClient extends Emitter {
8523
8552
  const session = this.getSipSession(sessionId);
8524
8553
 
8525
8554
  const stats = session ? await this.getStats(session) : null;
8526
- if (!stats) {
8555
+ if (!stats || !(sessionId in this.sessionNetworkStats)) {
8527
8556
  return;
8528
8557
  }
8529
8558
 
8530
- stats.forEach(report => {
8531
- if (report.type === 'inbound-rtp') {
8532
- if (report.kind === 'audio') {
8533
- const networkStats = {
8534
- packetsLost: report.packetsLost,
8535
- packetsReceived: report.packetsReceived,
8536
- jitter: report.jitter,
8537
- };
8559
+ const networkStats = {
8560
+ audioBytesSent: 0,
8561
+ videoBytesSent: 0,
8562
+ videoBytesReceived: 0,
8563
+ audioBytesReceived: 0,
8564
+ };
8565
+ const nbStats = this.sessionNetworkStats[sessionId].length;
8566
+ const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
8567
+ const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
8568
+ const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8569
+ const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8570
+ const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8571
+ const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8572
+ const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8573
+ let audioBytesSent = 0;
8574
+ let audioBytesReceived = 0;
8575
+ let videoBytesSent = 0;
8576
+ let videoBytesReceived = 0;
8577
+ let transportSent = 0;
8578
+ let transportReceived = 0;
8579
+ let packetsLost = 0;
8538
8580
 
8539
- this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8540
- this.sessionNetworkStats[sessionId].push(networkStats);
8581
+ stats.forEach(report => {
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') {
8586
+ audioBytesSent += report.bytesSent;
8587
+ }
8588
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
8589
+ videoBytesSent += report.bytesSent + report.headerBytesSent;
8590
+ }
8591
+ if (report.type === 'inbound-rtp' && report.kind === 'audio') {
8592
+ packetsLost += report.packetsLost;
8593
+ networkStats.packetsReceived = report.packetsReceived;
8594
+ audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
8595
+ }
8596
+ if (report.type === 'inbound-rtp' && report.kind === 'video') {
8597
+ videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
8598
+ }
8599
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
8600
+ if ('framesPerSecond' in report) {
8601
+ networkStats.framesPerSecond = report.framesPerSecond;
8602
+ }
8603
+ if ('framerateMean' in report) {
8604
+ // framerateMean is only available in FF
8605
+ networkStats.framesPerSecond = Math.round(report.framerateMean);
8541
8606
  }
8542
8607
  }
8608
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
8609
+ packetsLost += report.packetsLost;
8610
+ networkStats.roundTripTime = report.roundTripTime;
8611
+ networkStats.jitter = report.jitter;
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
+ }
8543
8620
  });
8621
+
8622
+ networkStats.packetsLost = packetsLost;
8623
+ networkStats.audioBytesSent = audioBytesSent;
8624
+ networkStats.audioBytesReceived = audioBytesReceived;
8625
+ networkStats.videoBytesSent = videoBytesSent;
8626
+ networkStats.videoBytesReceived = videoBytesReceived;
8627
+ networkStats.transportSent = transportSent;
8628
+ networkStats.transportReceived = transportReceived;
8629
+
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;
8635
+
8636
+ this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8637
+ this.sessionNetworkStats[sessionId].push(networkStats);
8544
8638
  }
8545
8639
 
8546
8640
  }
@@ -8586,6 +8680,7 @@ const ON_MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
8586
8680
  const ON_NETWORK_STATS = 'onNetworkStats';
8587
8681
  const ON_CHAT = 'phone/ON_CHAT';
8588
8682
  const ON_SIGNAL = 'phone/ON_SIGNAL';
8683
+ const ON_DISCONNECTED = 'onDisconnected';
8589
8684
 
8590
8685
  const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
8591
8686
  const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
@@ -8625,6 +8720,7 @@ const events = [
8625
8720
  ON_CHAT,
8626
8721
  ON_SIGNAL,
8627
8722
  ON_NETWORK_STATS,
8723
+ ON_DISCONNECTED,
8628
8724
  ];
8629
8725
 
8630
8726
  const logger$7 = IssueReporter$1.loggerFor('webrtc-phone');
@@ -9977,6 +10073,11 @@ class WebRTCPhone extends Emitter {
9977
10073
  this.eventEmitter.emit(ON_UNREGISTERED);
9978
10074
  });
9979
10075
 
10076
+ this.client.on(this.client.ON_DISCONNECTED, () => {
10077
+ logger$7.info('WebRTC disconnected');
10078
+ this.eventEmitter.emit(ON_DISCONNECTED);
10079
+ });
10080
+
9980
10081
  this.client.on(this.client.REGISTERED, () => {
9981
10082
  logger$7.info('WebRTC registered', {
9982
10083
  shouldSendReinvite: this.shouldSendReinvite,
@@ -10233,6 +10334,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10233
10334
  ON_NETWORK_STATS: ON_NETWORK_STATS,
10234
10335
  ON_CHAT: ON_CHAT,
10235
10336
  ON_SIGNAL: ON_SIGNAL,
10337
+ ON_DISCONNECTED: ON_DISCONNECTED,
10236
10338
  MESSAGE_TYPE_CHAT: MESSAGE_TYPE_CHAT,
10237
10339
  MESSAGE_TYPE_SIGNAL: MESSAGE_TYPE_SIGNAL,
10238
10340
  events: events,