@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
@@ -410,7 +410,7 @@ class IssueReporter {
410
410
  payload._retry = retry + 1;
411
411
  }
412
412
 
413
- this._sendDebugToGrafana(body, retry + 1);
413
+ this._sendDebugToGrafana(payload, retry + 1);
414
414
  }, 5000 + retry * 1000);
415
415
  });
416
416
  }
@@ -2613,7 +2613,8 @@ class ExternalApp {
2613
2613
 
2614
2614
 
2615
2615
 
2616
-
2616
+
2617
+
2617
2618
 
2618
2619
 
2619
2620
  class Meeting {
@@ -2625,6 +2626,7 @@ class Meeting {
2625
2626
 
2626
2627
 
2627
2628
 
2629
+
2628
2630
 
2629
2631
 
2630
2632
  static parse(plain ) {
@@ -2636,6 +2638,7 @@ class Meeting {
2636
2638
  port: plain.port,
2637
2639
  uuid: plain.uuid,
2638
2640
  number: plain.number,
2641
+ persistent: plain.persistent,
2639
2642
  });
2640
2643
  }
2641
2644
 
@@ -2643,7 +2646,7 @@ class Meeting {
2643
2646
  return newFrom(meeting, Meeting);
2644
2647
  }
2645
2648
 
2646
- constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
2649
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
2647
2650
  this.guestSipAuthorization = guestSipAuthorization;
2648
2651
  this.uri = uri;
2649
2652
  this.name = name;
@@ -2651,6 +2654,7 @@ class Meeting {
2651
2654
  this.port = port;
2652
2655
  this.uuid = uuid;
2653
2656
  this.number = number;
2657
+ this.persistent = persistent;
2654
2658
 
2655
2659
  // Useful to compare instead of instanceof with minified code
2656
2660
  this.type = 'Meeting';
@@ -3240,7 +3244,7 @@ class Recording {
3240
3244
 
3241
3245
 
3242
3246
 
3243
- static parseMany(recordings ) {
3247
+ static parseMany(recordings = []) {
3244
3248
  return recordings.map(item => Recording.parse(item));
3245
3249
  }
3246
3250
 
@@ -3366,7 +3370,7 @@ class CallLog {
3366
3370
  duration: (plain.duration || 0) * 1000, // duration is in seconds
3367
3371
  start: moment__default['default'](plain.start).toDate(),
3368
3372
  end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3369
- recordings: Recording.parseMany(plain.recordings),
3373
+ recordings: Recording.parseMany(plain.recordings || []),
3370
3374
  });
3371
3375
  }
3372
3376
 
@@ -5881,6 +5885,7 @@ const ON_REINVITE = 'reinvite';
5881
5885
  const ON_ERROR = 'onError';
5882
5886
  const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
5883
5887
  const ON_NETWORK_STATS = 'onNetworkStats';
5888
+ const ON_DISCONNECTED = 'onDisconnected';
5884
5889
  class CanceledCallError extends Error {}
5885
5890
 
5886
5891
  const MAX_REGISTER_TRIES = 10;
@@ -5954,6 +5959,7 @@ class WebRTCClient extends Emitter {
5954
5959
 
5955
5960
 
5956
5961
 
5962
+
5957
5963
 
5958
5964
  static isAPrivateIp(ip ) {
5959
5965
  const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
@@ -6019,6 +6025,7 @@ class WebRTCClient extends Emitter {
6019
6025
  this.ON_ERROR = ON_ERROR;
6020
6026
  this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
6021
6027
  this.ON_NETWORK_STATS = ON_NETWORK_STATS;
6028
+ this.ON_DISCONNECTED = ON_DISCONNECTED;
6022
6029
  }
6023
6030
 
6024
6031
  configureMedia(media ) {
@@ -6620,7 +6627,7 @@ class WebRTCClient extends Emitter {
6620
6627
  // We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
6621
6628
  const transceivers = pc.getTransceivers();
6622
6629
  const transceiverIdx = lastIndexOf(transceivers, transceiver =>
6623
- transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
6630
+ transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
6624
6631
 
6625
6632
  videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
6626
6633
  } else {
@@ -6866,10 +6873,13 @@ class WebRTCClient extends Emitter {
6866
6873
  return null;
6867
6874
  }
6868
6875
 
6869
- // let's update the local value
6870
- if (this.audio && this.audio.deviceId) {
6871
- // $FlowFixMe
6872
- this.audio.deviceId.exact = id;
6876
+ // let's update the local audio value
6877
+ if (this.audio) {
6878
+ this.audio = {
6879
+ deviceId: {
6880
+ exact: id,
6881
+ },
6882
+ };
6873
6883
  }
6874
6884
 
6875
6885
  if (session) {
@@ -6882,6 +6892,9 @@ class WebRTCClient extends Emitter {
6882
6892
  const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
6883
6893
 
6884
6894
  if (sender) {
6895
+ if (sender.track) {
6896
+ audioTrack.enabled = sender.track.enabled;
6897
+ }
6885
6898
  sender.replaceTrack(audioTrack);
6886
6899
  }
6887
6900
 
@@ -6906,7 +6919,7 @@ class WebRTCClient extends Emitter {
6906
6919
  return null;
6907
6920
  }
6908
6921
 
6909
- // let's update the local value
6922
+ // let's update the local video value
6910
6923
  if (this.video) {
6911
6924
  this.video = {
6912
6925
  deviceId: {
@@ -6941,12 +6954,21 @@ class WebRTCClient extends Emitter {
6941
6954
  return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
6942
6955
  const videoTrack = stream.getVideoTracks()[0];
6943
6956
  let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
6957
+ let wasTrackEnabled = false;
6944
6958
  if (!sender) {
6945
6959
  sender = pc && pc.getSenders().find(s => !s.track);
6946
6960
  }
6947
6961
 
6948
6962
  if (sender) {
6949
- sender.replaceTrack(videoTrack);
6963
+ // No video track means video not enabled
6964
+ wasTrackEnabled = sender.track ? sender.track.enabled : false;
6965
+ videoTrack.enabled = wasTrackEnabled;
6966
+
6967
+ if (!wasTrackEnabled) {
6968
+ videoTrack.stop();
6969
+ }
6970
+
6971
+ sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
6950
6972
  }
6951
6973
 
6952
6974
  // let's update the local stream
@@ -7630,6 +7652,7 @@ class WebRTCClient extends Emitter {
7630
7652
 
7631
7653
  this.updateRemoteStream(this.getSipSessionId(session));
7632
7654
 
7655
+ const pc = session.sessionDescriptionHandler.peerConnection;
7633
7656
  const onTrack = (event ) => {
7634
7657
  const isAudioOnly = this._isAudioOnly(session);
7635
7658
  const { kind, label, readyState, id, muted } = event.track;
@@ -7649,6 +7672,12 @@ class WebRTCClient extends Emitter {
7649
7672
 
7650
7673
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
7651
7674
 
7675
+ pc.oniceconnectionstatechange = () => {
7676
+ if (pc.iceConnectionState === 'disconnected') {
7677
+ this.eventEmitter.emit(ON_DISCONNECTED);
7678
+ }
7679
+ };
7680
+
7652
7681
  if (withEvent) {
7653
7682
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
7654
7683
  }
@@ -7844,24 +7873,89 @@ class WebRTCClient extends Emitter {
7844
7873
  const session = this.getSipSession(sessionId);
7845
7874
 
7846
7875
  const stats = session ? await this.getStats(session) : null;
7847
- if (!stats) {
7876
+ if (!stats || !(sessionId in this.sessionNetworkStats)) {
7848
7877
  return;
7849
7878
  }
7850
7879
 
7851
- stats.forEach(report => {
7852
- if (report.type === 'inbound-rtp') {
7853
- if (report.kind === 'audio') {
7854
- const networkStats = {
7855
- packetsLost: report.packetsLost,
7856
- packetsReceived: report.packetsReceived,
7857
- jitter: report.jitter,
7858
- };
7880
+ const networkStats = {
7881
+ audioBytesSent: 0,
7882
+ videoBytesSent: 0,
7883
+ videoBytesReceived: 0,
7884
+ audioBytesReceived: 0,
7885
+ };
7886
+ const nbStats = this.sessionNetworkStats[sessionId].length;
7887
+ const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
7888
+ const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
7889
+ const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
7890
+ const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
7891
+ const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
7892
+ const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
7893
+ const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
7894
+ let audioBytesSent = 0;
7895
+ let audioBytesReceived = 0;
7896
+ let videoBytesSent = 0;
7897
+ let videoBytesReceived = 0;
7898
+ let transportSent = 0;
7899
+ let transportReceived = 0;
7900
+ let packetsLost = 0;
7859
7901
 
7860
- this.eventEmitter.emit(ON_NETWORK_STATS, session, networkStats, this.sessionNetworkStats[sessionId]);
7861
- this.sessionNetworkStats[sessionId].push(networkStats);
7902
+ stats.forEach(report => {
7903
+ if (report.type === 'outbound-rtp' && report.kind === 'audio') {
7904
+ audioBytesSent += report.bytesSent + report.headerBytesSent;
7905
+ }
7906
+ if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
7907
+ audioBytesSent += report.bytesSent;
7908
+ }
7909
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
7910
+ videoBytesSent += report.bytesSent + report.headerBytesSent;
7911
+ }
7912
+ if (report.type === 'inbound-rtp' && report.kind === 'audio') {
7913
+ packetsLost += report.packetsLost;
7914
+ networkStats.packetsReceived = report.packetsReceived;
7915
+ audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
7916
+ }
7917
+ if (report.type === 'inbound-rtp' && report.kind === 'video') {
7918
+ videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
7919
+ }
7920
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
7921
+ if ('framesPerSecond' in report) {
7922
+ networkStats.framesPerSecond = report.framesPerSecond;
7862
7923
  }
7924
+ if ('framerateMean' in report) {
7925
+ // framerateMean is only available in FF
7926
+ networkStats.framesPerSecond = Math.round(report.framerateMean);
7927
+ }
7928
+ }
7929
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
7930
+ packetsLost += report.packetsLost;
7931
+ networkStats.roundTripTime = report.roundTripTime;
7932
+ networkStats.jitter = report.jitter;
7933
+ }
7934
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
7935
+ packetsLost += report.packetsLost;
7936
+ }
7937
+ if (report.type === 'transport') {
7938
+ transportSent += report.bytesSent;
7939
+ transportReceived += report.bytesReceived;
7863
7940
  }
7864
7941
  });
7942
+
7943
+ networkStats.packetsLost = packetsLost;
7944
+ networkStats.audioBytesSent = audioBytesSent;
7945
+ networkStats.audioBytesReceived = audioBytesReceived;
7946
+ networkStats.videoBytesSent = videoBytesSent;
7947
+ networkStats.videoBytesReceived = videoBytesReceived;
7948
+ networkStats.transportSent = transportSent;
7949
+ networkStats.transportReceived = transportReceived;
7950
+
7951
+ const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
7952
+ + (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
7953
+ + (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
7954
+
7955
+ networkStats.bandwidth = bandwidth;
7956
+
7957
+ this.eventEmitter.emit(ON_NETWORK_STATS, session, networkStats, this.sessionNetworkStats[sessionId]);
7958
+ this.sessionNetworkStats[sessionId].push(networkStats);
7865
7959
  }
7866
7960
 
7867
7961
  }
@@ -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
 
@@ -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
 
@@ -410,7 +410,7 @@ class IssueReporter {
410
410
  payload._retry = retry + 1;
411
411
  }
412
412
 
413
- this._sendDebugToGrafana(body, retry + 1);
413
+ this._sendDebugToGrafana(payload, retry + 1);
414
414
  }, 5000 + retry * 1000);
415
415
  });
416
416
  }
@@ -2613,7 +2613,8 @@ class ExternalApp {
2613
2613
 
2614
2614
 
2615
2615
 
2616
-
2616
+
2617
+
2617
2618
 
2618
2619
 
2619
2620
  class Meeting {
@@ -2625,6 +2626,7 @@ class Meeting {
2625
2626
 
2626
2627
 
2627
2628
 
2629
+
2628
2630
 
2629
2631
 
2630
2632
  static parse(plain ) {
@@ -2636,6 +2638,7 @@ class Meeting {
2636
2638
  port: plain.port,
2637
2639
  uuid: plain.uuid,
2638
2640
  number: plain.number,
2641
+ persistent: plain.persistent,
2639
2642
  });
2640
2643
  }
2641
2644
 
@@ -2643,7 +2646,7 @@ class Meeting {
2643
2646
  return newFrom(meeting, Meeting);
2644
2647
  }
2645
2648
 
2646
- constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
2649
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
2647
2650
  this.guestSipAuthorization = guestSipAuthorization;
2648
2651
  this.uri = uri;
2649
2652
  this.name = name;
@@ -2651,6 +2654,7 @@ class Meeting {
2651
2654
  this.port = port;
2652
2655
  this.uuid = uuid;
2653
2656
  this.number = number;
2657
+ this.persistent = persistent;
2654
2658
 
2655
2659
  // Useful to compare instead of instanceof with minified code
2656
2660
  this.type = 'Meeting';
@@ -3240,7 +3244,7 @@ class Recording {
3240
3244
 
3241
3245
 
3242
3246
 
3243
- static parseMany(recordings ) {
3247
+ static parseMany(recordings = []) {
3244
3248
  return recordings.map(item => Recording.parse(item));
3245
3249
  }
3246
3250
 
@@ -3366,7 +3370,7 @@ class CallLog {
3366
3370
  duration: (plain.duration || 0) * 1000, // duration is in seconds
3367
3371
  start: moment__default['default'](plain.start).toDate(),
3368
3372
  end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3369
- recordings: Recording.parseMany(plain.recordings),
3373
+ recordings: Recording.parseMany(plain.recordings || []),
3370
3374
  });
3371
3375
  }
3372
3376
 
@@ -5881,6 +5885,7 @@ const ON_REINVITE = 'reinvite';
5881
5885
  const ON_ERROR = 'onError';
5882
5886
  const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
5883
5887
  const ON_NETWORK_STATS = 'onNetworkStats';
5888
+ const ON_DISCONNECTED = 'onDisconnected';
5884
5889
  class CanceledCallError extends Error {}
5885
5890
 
5886
5891
  const MAX_REGISTER_TRIES = 10;
@@ -5954,6 +5959,7 @@ class WebRTCClient extends Emitter {
5954
5959
 
5955
5960
 
5956
5961
 
5962
+
5957
5963
 
5958
5964
  static isAPrivateIp(ip ) {
5959
5965
  const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
@@ -6019,6 +6025,7 @@ class WebRTCClient extends Emitter {
6019
6025
  this.ON_ERROR = ON_ERROR;
6020
6026
  this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
6021
6027
  this.ON_NETWORK_STATS = ON_NETWORK_STATS;
6028
+ this.ON_DISCONNECTED = ON_DISCONNECTED;
6022
6029
  }
6023
6030
 
6024
6031
  configureMedia(media ) {
@@ -6620,7 +6627,7 @@ class WebRTCClient extends Emitter {
6620
6627
  // We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
6621
6628
  const transceivers = pc.getTransceivers();
6622
6629
  const transceiverIdx = lastIndexOf(transceivers, transceiver =>
6623
- transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
6630
+ transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
6624
6631
 
6625
6632
  videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
6626
6633
  } else {
@@ -6866,10 +6873,13 @@ class WebRTCClient extends Emitter {
6866
6873
  return null;
6867
6874
  }
6868
6875
 
6869
- // let's update the local value
6870
- if (this.audio && this.audio.deviceId) {
6871
- // $FlowFixMe
6872
- this.audio.deviceId.exact = id;
6876
+ // let's update the local audio value
6877
+ if (this.audio) {
6878
+ this.audio = {
6879
+ deviceId: {
6880
+ exact: id,
6881
+ },
6882
+ };
6873
6883
  }
6874
6884
 
6875
6885
  if (session) {
@@ -6882,6 +6892,9 @@ class WebRTCClient extends Emitter {
6882
6892
  const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
6883
6893
 
6884
6894
  if (sender) {
6895
+ if (sender.track) {
6896
+ audioTrack.enabled = sender.track.enabled;
6897
+ }
6885
6898
  sender.replaceTrack(audioTrack);
6886
6899
  }
6887
6900
 
@@ -6906,7 +6919,7 @@ class WebRTCClient extends Emitter {
6906
6919
  return null;
6907
6920
  }
6908
6921
 
6909
- // let's update the local value
6922
+ // let's update the local video value
6910
6923
  if (this.video) {
6911
6924
  this.video = {
6912
6925
  deviceId: {
@@ -6941,12 +6954,21 @@ class WebRTCClient extends Emitter {
6941
6954
  return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
6942
6955
  const videoTrack = stream.getVideoTracks()[0];
6943
6956
  let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
6957
+ let wasTrackEnabled = false;
6944
6958
  if (!sender) {
6945
6959
  sender = pc && pc.getSenders().find(s => !s.track);
6946
6960
  }
6947
6961
 
6948
6962
  if (sender) {
6949
- sender.replaceTrack(videoTrack);
6963
+ // No video track means video not enabled
6964
+ wasTrackEnabled = sender.track ? sender.track.enabled : false;
6965
+ videoTrack.enabled = wasTrackEnabled;
6966
+
6967
+ if (!wasTrackEnabled) {
6968
+ videoTrack.stop();
6969
+ }
6970
+
6971
+ sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
6950
6972
  }
6951
6973
 
6952
6974
  // let's update the local stream
@@ -7630,6 +7652,7 @@ class WebRTCClient extends Emitter {
7630
7652
 
7631
7653
  this.updateRemoteStream(this.getSipSessionId(session));
7632
7654
 
7655
+ const pc = session.sessionDescriptionHandler.peerConnection;
7633
7656
  const onTrack = (event ) => {
7634
7657
  const isAudioOnly = this._isAudioOnly(session);
7635
7658
  const { kind, label, readyState, id, muted } = event.track;
@@ -7649,6 +7672,12 @@ class WebRTCClient extends Emitter {
7649
7672
 
7650
7673
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
7651
7674
 
7675
+ pc.oniceconnectionstatechange = () => {
7676
+ if (pc.iceConnectionState === 'disconnected') {
7677
+ this.eventEmitter.emit(ON_DISCONNECTED);
7678
+ }
7679
+ };
7680
+
7652
7681
  if (withEvent) {
7653
7682
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
7654
7683
  }
@@ -7844,24 +7873,89 @@ class WebRTCClient extends Emitter {
7844
7873
  const session = this.getSipSession(sessionId);
7845
7874
 
7846
7875
  const stats = session ? await this.getStats(session) : null;
7847
- if (!stats) {
7876
+ if (!stats || !(sessionId in this.sessionNetworkStats)) {
7848
7877
  return;
7849
7878
  }
7850
7879
 
7851
- stats.forEach(report => {
7852
- if (report.type === 'inbound-rtp') {
7853
- if (report.kind === 'audio') {
7854
- const networkStats = {
7855
- packetsLost: report.packetsLost,
7856
- packetsReceived: report.packetsReceived,
7857
- jitter: report.jitter,
7858
- };
7880
+ const networkStats = {
7881
+ audioBytesSent: 0,
7882
+ videoBytesSent: 0,
7883
+ videoBytesReceived: 0,
7884
+ audioBytesReceived: 0,
7885
+ };
7886
+ const nbStats = this.sessionNetworkStats[sessionId].length;
7887
+ const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
7888
+ const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
7889
+ const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
7890
+ const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
7891
+ const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
7892
+ const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
7893
+ const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
7894
+ let audioBytesSent = 0;
7895
+ let audioBytesReceived = 0;
7896
+ let videoBytesSent = 0;
7897
+ let videoBytesReceived = 0;
7898
+ let transportSent = 0;
7899
+ let transportReceived = 0;
7900
+ let packetsLost = 0;
7859
7901
 
7860
- this.eventEmitter.emit(ON_NETWORK_STATS, session, networkStats, this.sessionNetworkStats[sessionId]);
7861
- this.sessionNetworkStats[sessionId].push(networkStats);
7902
+ stats.forEach(report => {
7903
+ if (report.type === 'outbound-rtp' && report.kind === 'audio') {
7904
+ audioBytesSent += report.bytesSent + report.headerBytesSent;
7905
+ }
7906
+ if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
7907
+ audioBytesSent += report.bytesSent;
7908
+ }
7909
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
7910
+ videoBytesSent += report.bytesSent + report.headerBytesSent;
7911
+ }
7912
+ if (report.type === 'inbound-rtp' && report.kind === 'audio') {
7913
+ packetsLost += report.packetsLost;
7914
+ networkStats.packetsReceived = report.packetsReceived;
7915
+ audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
7916
+ }
7917
+ if (report.type === 'inbound-rtp' && report.kind === 'video') {
7918
+ videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
7919
+ }
7920
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
7921
+ if ('framesPerSecond' in report) {
7922
+ networkStats.framesPerSecond = report.framesPerSecond;
7862
7923
  }
7924
+ if ('framerateMean' in report) {
7925
+ // framerateMean is only available in FF
7926
+ networkStats.framesPerSecond = Math.round(report.framerateMean);
7927
+ }
7928
+ }
7929
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
7930
+ packetsLost += report.packetsLost;
7931
+ networkStats.roundTripTime = report.roundTripTime;
7932
+ networkStats.jitter = report.jitter;
7933
+ }
7934
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
7935
+ packetsLost += report.packetsLost;
7936
+ }
7937
+ if (report.type === 'transport') {
7938
+ transportSent += report.bytesSent;
7939
+ transportReceived += report.bytesReceived;
7863
7940
  }
7864
7941
  });
7942
+
7943
+ networkStats.packetsLost = packetsLost;
7944
+ networkStats.audioBytesSent = audioBytesSent;
7945
+ networkStats.audioBytesReceived = audioBytesReceived;
7946
+ networkStats.videoBytesSent = videoBytesSent;
7947
+ networkStats.videoBytesReceived = videoBytesReceived;
7948
+ networkStats.transportSent = transportSent;
7949
+ networkStats.transportReceived = transportReceived;
7950
+
7951
+ const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
7952
+ + (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
7953
+ + (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
7954
+
7955
+ networkStats.bandwidth = bandwidth;
7956
+
7957
+ this.eventEmitter.emit(ON_NETWORK_STATS, session, networkStats, this.sessionNetworkStats[sessionId]);
7958
+ this.sessionNetworkStats[sessionId].push(networkStats);
7865
7959
  }
7866
7960
 
7867
7961
  }