@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
@@ -1886,7 +1886,7 @@ class IssueReporter {
1886
1886
  payload._retry = retry + 1;
1887
1887
  }
1888
1888
 
1889
- this._sendDebugToGrafana(body, retry + 1);
1889
+ this._sendDebugToGrafana(payload, retry + 1);
1890
1890
  }, 5000 + retry * 1000);
1891
1891
  });
1892
1892
  }
@@ -2604,7 +2604,8 @@ class ExternalApp {
2604
2604
 
2605
2605
 
2606
2606
 
2607
-
2607
+
2608
+
2608
2609
 
2609
2610
 
2610
2611
  class Meeting {
@@ -2616,6 +2617,7 @@ class Meeting {
2616
2617
 
2617
2618
 
2618
2619
 
2620
+
2619
2621
 
2620
2622
 
2621
2623
  static parse(plain ) {
@@ -2627,6 +2629,7 @@ class Meeting {
2627
2629
  port: plain.port,
2628
2630
  uuid: plain.uuid,
2629
2631
  number: plain.number,
2632
+ persistent: plain.persistent,
2630
2633
  });
2631
2634
  }
2632
2635
 
@@ -2634,7 +2637,7 @@ class Meeting {
2634
2637
  return newFrom(meeting, Meeting);
2635
2638
  }
2636
2639
 
2637
- constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
2640
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
2638
2641
  this.guestSipAuthorization = guestSipAuthorization;
2639
2642
  this.uri = uri;
2640
2643
  this.name = name;
@@ -2642,6 +2645,7 @@ class Meeting {
2642
2645
  this.port = port;
2643
2646
  this.uuid = uuid;
2644
2647
  this.number = number;
2648
+ this.persistent = persistent;
2645
2649
 
2646
2650
  // Useful to compare instead of instanceof with minified code
2647
2651
  this.type = 'Meeting';
@@ -3576,7 +3580,7 @@ class Recording {
3576
3580
 
3577
3581
 
3578
3582
 
3579
- static parseMany(recordings ) {
3583
+ static parseMany(recordings = []) {
3580
3584
  return recordings.map(item => Recording.parse(item));
3581
3585
  }
3582
3586
 
@@ -3702,7 +3706,7 @@ class CallLog {
3702
3706
  duration: (plain.duration || 0) * 1000, // duration is in seconds
3703
3707
  start: moment(plain.start).toDate(),
3704
3708
  end: plain.end ? moment(plain.end).toDate() : null,
3705
- recordings: Recording.parseMany(plain.recordings),
3709
+ recordings: Recording.parseMany(plain.recordings || []),
3706
3710
  });
3707
3711
  }
3708
3712
 
@@ -6547,6 +6551,7 @@ const ON_REINVITE$1 = 'reinvite';
6547
6551
  const ON_ERROR = 'onError';
6548
6552
  const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
6549
6553
  const ON_NETWORK_STATS$1 = 'onNetworkStats';
6554
+ const ON_DISCONNECTED$1 = 'onDisconnected';
6550
6555
 
6551
6556
  const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
6552
6557
  const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
@@ -6623,6 +6628,7 @@ class WebRTCClient extends Emitter {
6623
6628
 
6624
6629
 
6625
6630
 
6631
+
6626
6632
 
6627
6633
  static isAPrivateIp(ip ) {
6628
6634
  const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
@@ -6688,6 +6694,7 @@ class WebRTCClient extends Emitter {
6688
6694
  this.ON_ERROR = ON_ERROR;
6689
6695
  this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
6690
6696
  this.ON_NETWORK_STATS = ON_NETWORK_STATS$1;
6697
+ this.ON_DISCONNECTED = ON_DISCONNECTED$1;
6691
6698
  }
6692
6699
 
6693
6700
  configureMedia(media ) {
@@ -7289,7 +7296,7 @@ class WebRTCClient extends Emitter {
7289
7296
  // We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
7290
7297
  const transceivers = pc.getTransceivers();
7291
7298
  const transceiverIdx = lastIndexOf(transceivers, transceiver =>
7292
- transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
7299
+ transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
7293
7300
 
7294
7301
  videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
7295
7302
  } else {
@@ -7535,10 +7542,13 @@ class WebRTCClient extends Emitter {
7535
7542
  return null;
7536
7543
  }
7537
7544
 
7538
- // let's update the local value
7539
- if (this.audio && this.audio.deviceId) {
7540
- // $FlowFixMe
7541
- this.audio.deviceId.exact = id;
7545
+ // let's update the local audio value
7546
+ if (this.audio) {
7547
+ this.audio = {
7548
+ deviceId: {
7549
+ exact: id,
7550
+ },
7551
+ };
7542
7552
  }
7543
7553
 
7544
7554
  if (session) {
@@ -7551,6 +7561,9 @@ class WebRTCClient extends Emitter {
7551
7561
  const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
7552
7562
 
7553
7563
  if (sender) {
7564
+ if (sender.track) {
7565
+ audioTrack.enabled = sender.track.enabled;
7566
+ }
7554
7567
  sender.replaceTrack(audioTrack);
7555
7568
  }
7556
7569
 
@@ -7575,7 +7588,7 @@ class WebRTCClient extends Emitter {
7575
7588
  return null;
7576
7589
  }
7577
7590
 
7578
- // let's update the local value
7591
+ // let's update the local video value
7579
7592
  if (this.video) {
7580
7593
  this.video = {
7581
7594
  deviceId: {
@@ -7610,12 +7623,21 @@ class WebRTCClient extends Emitter {
7610
7623
  return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
7611
7624
  const videoTrack = stream.getVideoTracks()[0];
7612
7625
  let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
7626
+ let wasTrackEnabled = false;
7613
7627
  if (!sender) {
7614
7628
  sender = pc && pc.getSenders().find(s => !s.track);
7615
7629
  }
7616
7630
 
7617
7631
  if (sender) {
7618
- sender.replaceTrack(videoTrack);
7632
+ // No video track means video not enabled
7633
+ wasTrackEnabled = sender.track ? sender.track.enabled : false;
7634
+ videoTrack.enabled = wasTrackEnabled;
7635
+
7636
+ if (!wasTrackEnabled) {
7637
+ videoTrack.stop();
7638
+ }
7639
+
7640
+ sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
7619
7641
  }
7620
7642
 
7621
7643
  // let's update the local stream
@@ -8299,6 +8321,7 @@ class WebRTCClient extends Emitter {
8299
8321
 
8300
8322
  this.updateRemoteStream(this.getSipSessionId(session));
8301
8323
 
8324
+ const pc = session.sessionDescriptionHandler.peerConnection;
8302
8325
  const onTrack = (event ) => {
8303
8326
  const isAudioOnly = this._isAudioOnly(session);
8304
8327
  const { kind, label, readyState, id, muted } = event.track;
@@ -8318,6 +8341,12 @@ class WebRTCClient extends Emitter {
8318
8341
 
8319
8342
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
8320
8343
 
8344
+ pc.oniceconnectionstatechange = () => {
8345
+ if (pc.iceConnectionState === 'disconnected') {
8346
+ this.eventEmitter.emit(ON_DISCONNECTED$1);
8347
+ }
8348
+ };
8349
+
8321
8350
  if (withEvent) {
8322
8351
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
8323
8352
  }
@@ -8513,24 +8542,89 @@ class WebRTCClient extends Emitter {
8513
8542
  const session = this.getSipSession(sessionId);
8514
8543
 
8515
8544
  const stats = session ? await this.getStats(session) : null;
8516
- if (!stats) {
8545
+ if (!stats || !(sessionId in this.sessionNetworkStats)) {
8517
8546
  return;
8518
8547
  }
8519
8548
 
8520
- stats.forEach(report => {
8521
- if (report.type === 'inbound-rtp') {
8522
- if (report.kind === 'audio') {
8523
- const networkStats = {
8524
- packetsLost: report.packetsLost,
8525
- packetsReceived: report.packetsReceived,
8526
- jitter: report.jitter,
8527
- };
8549
+ const networkStats = {
8550
+ audioBytesSent: 0,
8551
+ videoBytesSent: 0,
8552
+ videoBytesReceived: 0,
8553
+ audioBytesReceived: 0,
8554
+ };
8555
+ const nbStats = this.sessionNetworkStats[sessionId].length;
8556
+ const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
8557
+ const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
8558
+ const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8559
+ const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8560
+ const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8561
+ const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8562
+ const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8563
+ let audioBytesSent = 0;
8564
+ let audioBytesReceived = 0;
8565
+ let videoBytesSent = 0;
8566
+ let videoBytesReceived = 0;
8567
+ let transportSent = 0;
8568
+ let transportReceived = 0;
8569
+ let packetsLost = 0;
8528
8570
 
8529
- this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8530
- this.sessionNetworkStats[sessionId].push(networkStats);
8571
+ stats.forEach(report => {
8572
+ if (report.type === 'outbound-rtp' && report.kind === 'audio') {
8573
+ audioBytesSent += report.bytesSent + report.headerBytesSent;
8574
+ }
8575
+ if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
8576
+ audioBytesSent += report.bytesSent;
8577
+ }
8578
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
8579
+ videoBytesSent += report.bytesSent + report.headerBytesSent;
8580
+ }
8581
+ if (report.type === 'inbound-rtp' && report.kind === 'audio') {
8582
+ packetsLost += report.packetsLost;
8583
+ networkStats.packetsReceived = report.packetsReceived;
8584
+ audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
8585
+ }
8586
+ if (report.type === 'inbound-rtp' && report.kind === 'video') {
8587
+ videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
8588
+ }
8589
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
8590
+ if ('framesPerSecond' in report) {
8591
+ networkStats.framesPerSecond = report.framesPerSecond;
8592
+ }
8593
+ if ('framerateMean' in report) {
8594
+ // framerateMean is only available in FF
8595
+ networkStats.framesPerSecond = Math.round(report.framerateMean);
8531
8596
  }
8532
8597
  }
8598
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
8599
+ packetsLost += report.packetsLost;
8600
+ networkStats.roundTripTime = report.roundTripTime;
8601
+ networkStats.jitter = report.jitter;
8602
+ }
8603
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
8604
+ packetsLost += report.packetsLost;
8605
+ }
8606
+ if (report.type === 'transport') {
8607
+ transportSent += report.bytesSent;
8608
+ transportReceived += report.bytesReceived;
8609
+ }
8533
8610
  });
8611
+
8612
+ networkStats.packetsLost = packetsLost;
8613
+ networkStats.audioBytesSent = audioBytesSent;
8614
+ networkStats.audioBytesReceived = audioBytesReceived;
8615
+ networkStats.videoBytesSent = videoBytesSent;
8616
+ networkStats.videoBytesReceived = videoBytesReceived;
8617
+ networkStats.transportSent = transportSent;
8618
+ networkStats.transportReceived = transportReceived;
8619
+
8620
+ const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
8621
+ + (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
8622
+ + (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
8623
+
8624
+ networkStats.bandwidth = bandwidth;
8625
+
8626
+ this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8627
+ this.sessionNetworkStats[sessionId].push(networkStats);
8534
8628
  }
8535
8629
 
8536
8630
  }
@@ -8576,6 +8670,7 @@ const ON_MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
8576
8670
  const ON_NETWORK_STATS = 'onNetworkStats';
8577
8671
  const ON_CHAT = 'phone/ON_CHAT';
8578
8672
  const ON_SIGNAL = 'phone/ON_SIGNAL';
8673
+ const ON_DISCONNECTED = 'onDisconnected';
8579
8674
 
8580
8675
  const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
8581
8676
  const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
@@ -8615,6 +8710,7 @@ const events = [
8615
8710
  ON_CHAT,
8616
8711
  ON_SIGNAL,
8617
8712
  ON_NETWORK_STATS,
8713
+ ON_DISCONNECTED,
8618
8714
  ];
8619
8715
 
8620
8716
  const logger$7 = IssueReporter$1.loggerFor('webrtc-phone');
@@ -9967,6 +10063,11 @@ class WebRTCPhone extends Emitter {
9967
10063
  this.eventEmitter.emit(ON_UNREGISTERED);
9968
10064
  });
9969
10065
 
10066
+ this.client.on(this.client.ON_DISCONNECTED, () => {
10067
+ logger$7.info('WebRTC disconnected');
10068
+ this.eventEmitter.emit(ON_DISCONNECTED);
10069
+ });
10070
+
9970
10071
  this.client.on(this.client.REGISTERED, () => {
9971
10072
  logger$7.info('WebRTC registered', {
9972
10073
  shouldSendReinvite: this.shouldSendReinvite,
@@ -10223,6 +10324,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10223
10324
  ON_NETWORK_STATS: ON_NETWORK_STATS,
10224
10325
  ON_CHAT: ON_CHAT,
10225
10326
  ON_SIGNAL: ON_SIGNAL,
10327
+ ON_DISCONNECTED: ON_DISCONNECTED,
10226
10328
  MESSAGE_TYPE_CHAT: MESSAGE_TYPE_CHAT,
10227
10329
  MESSAGE_TYPE_SIGNAL: MESSAGE_TYPE_SIGNAL,
10228
10330
  events: events,
@@ -378,7 +378,7 @@ class IssueReporter {
378
378
  payload._retry = retry + 1;
379
379
  }
380
380
 
381
- this._sendDebugToGrafana(body, retry + 1);
381
+ this._sendDebugToGrafana(payload, retry + 1);
382
382
  }, 5000 + retry * 1000);
383
383
  });
384
384
  }
@@ -378,7 +378,7 @@ class IssueReporter {
378
378
  payload._retry = retry + 1;
379
379
  }
380
380
 
381
- this._sendDebugToGrafana(body, retry + 1);
381
+ this._sendDebugToGrafana(payload, retry + 1);
382
382
  }, 5000 + retry * 1000);
383
383
  });
384
384
  }
@@ -664,7 +664,7 @@ class IssueReporter {
664
664
  payload._retry = retry + 1;
665
665
  }
666
666
 
667
- this._sendDebugToGrafana(body, retry + 1);
667
+ this._sendDebugToGrafana(payload, retry + 1);
668
668
  }, 5000 + retry * 1000);
669
669
  });
670
670
  }
@@ -3166,7 +3166,8 @@ class ExternalApp {
3166
3166
 
3167
3167
 
3168
3168
 
3169
-
3169
+
3170
+
3170
3171
 
3171
3172
 
3172
3173
  class Meeting {
@@ -3178,6 +3179,7 @@ class Meeting {
3178
3179
 
3179
3180
 
3180
3181
 
3182
+
3181
3183
 
3182
3184
 
3183
3185
  static parse(plain ) {
@@ -3189,6 +3191,7 @@ class Meeting {
3189
3191
  port: plain.port,
3190
3192
  uuid: plain.uuid,
3191
3193
  number: plain.number,
3194
+ persistent: plain.persistent,
3192
3195
  });
3193
3196
  }
3194
3197
 
@@ -3196,7 +3199,7 @@ class Meeting {
3196
3199
  return newFrom(meeting, Meeting);
3197
3200
  }
3198
3201
 
3199
- constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
3202
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
3200
3203
  this.guestSipAuthorization = guestSipAuthorization;
3201
3204
  this.uri = uri;
3202
3205
  this.name = name;
@@ -3204,6 +3207,7 @@ class Meeting {
3204
3207
  this.port = port;
3205
3208
  this.uuid = uuid;
3206
3209
  this.number = number;
3210
+ this.persistent = persistent;
3207
3211
 
3208
3212
  // Useful to compare instead of instanceof with minified code
3209
3213
  this.type = 'Meeting';
@@ -3767,7 +3771,7 @@ class Recording {
3767
3771
 
3768
3772
 
3769
3773
 
3770
- static parseMany(recordings ) {
3774
+ static parseMany(recordings = []) {
3771
3775
  return recordings.map(item => Recording.parse(item));
3772
3776
  }
3773
3777
 
@@ -3893,7 +3897,7 @@ class CallLog {
3893
3897
  duration: (plain.duration || 0) * 1000, // duration is in seconds
3894
3898
  start: moment(plain.start).toDate(),
3895
3899
  end: plain.end ? moment(plain.end).toDate() : null,
3896
- recordings: Recording.parseMany(plain.recordings),
3900
+ recordings: Recording.parseMany(plain.recordings || []),
3897
3901
  });
3898
3902
  }
3899
3903
 
@@ -5288,6 +5292,7 @@ const ON_REINVITE = 'reinvite';
5288
5292
  const ON_ERROR = 'onError';
5289
5293
  const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
5290
5294
  const ON_NETWORK_STATS = 'onNetworkStats';
5295
+ const ON_DISCONNECTED = 'onDisconnected';
5291
5296
 
5292
5297
  const events = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
5293
5298
  const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
@@ -5364,6 +5369,7 @@ class WebRTCClient extends Emitter {
5364
5369
 
5365
5370
 
5366
5371
 
5372
+
5367
5373
 
5368
5374
  static isAPrivateIp(ip ) {
5369
5375
  const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
@@ -5429,6 +5435,7 @@ class WebRTCClient extends Emitter {
5429
5435
  this.ON_ERROR = ON_ERROR;
5430
5436
  this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
5431
5437
  this.ON_NETWORK_STATS = ON_NETWORK_STATS;
5438
+ this.ON_DISCONNECTED = ON_DISCONNECTED;
5432
5439
  }
5433
5440
 
5434
5441
  configureMedia(media ) {
@@ -6030,7 +6037,7 @@ class WebRTCClient extends Emitter {
6030
6037
  // We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
6031
6038
  const transceivers = pc.getTransceivers();
6032
6039
  const transceiverIdx = lastIndexOf(transceivers, transceiver =>
6033
- transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
6040
+ transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
6034
6041
 
6035
6042
  videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
6036
6043
  } else {
@@ -6276,10 +6283,13 @@ class WebRTCClient extends Emitter {
6276
6283
  return null;
6277
6284
  }
6278
6285
 
6279
- // let's update the local value
6280
- if (this.audio && this.audio.deviceId) {
6281
- // $FlowFixMe
6282
- this.audio.deviceId.exact = id;
6286
+ // let's update the local audio value
6287
+ if (this.audio) {
6288
+ this.audio = {
6289
+ deviceId: {
6290
+ exact: id,
6291
+ },
6292
+ };
6283
6293
  }
6284
6294
 
6285
6295
  if (session) {
@@ -6292,6 +6302,9 @@ class WebRTCClient extends Emitter {
6292
6302
  const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
6293
6303
 
6294
6304
  if (sender) {
6305
+ if (sender.track) {
6306
+ audioTrack.enabled = sender.track.enabled;
6307
+ }
6295
6308
  sender.replaceTrack(audioTrack);
6296
6309
  }
6297
6310
 
@@ -6316,7 +6329,7 @@ class WebRTCClient extends Emitter {
6316
6329
  return null;
6317
6330
  }
6318
6331
 
6319
- // let's update the local value
6332
+ // let's update the local video value
6320
6333
  if (this.video) {
6321
6334
  this.video = {
6322
6335
  deviceId: {
@@ -6351,12 +6364,21 @@ class WebRTCClient extends Emitter {
6351
6364
  return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
6352
6365
  const videoTrack = stream.getVideoTracks()[0];
6353
6366
  let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
6367
+ let wasTrackEnabled = false;
6354
6368
  if (!sender) {
6355
6369
  sender = pc && pc.getSenders().find(s => !s.track);
6356
6370
  }
6357
6371
 
6358
6372
  if (sender) {
6359
- sender.replaceTrack(videoTrack);
6373
+ // No video track means video not enabled
6374
+ wasTrackEnabled = sender.track ? sender.track.enabled : false;
6375
+ videoTrack.enabled = wasTrackEnabled;
6376
+
6377
+ if (!wasTrackEnabled) {
6378
+ videoTrack.stop();
6379
+ }
6380
+
6381
+ sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
6360
6382
  }
6361
6383
 
6362
6384
  // let's update the local stream
@@ -7040,6 +7062,7 @@ class WebRTCClient extends Emitter {
7040
7062
 
7041
7063
  this.updateRemoteStream(this.getSipSessionId(session));
7042
7064
 
7065
+ const pc = session.sessionDescriptionHandler.peerConnection;
7043
7066
  const onTrack = (event ) => {
7044
7067
  const isAudioOnly = this._isAudioOnly(session);
7045
7068
  const { kind, label, readyState, id, muted } = event.track;
@@ -7059,6 +7082,12 @@ class WebRTCClient extends Emitter {
7059
7082
 
7060
7083
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
7061
7084
 
7085
+ pc.oniceconnectionstatechange = () => {
7086
+ if (pc.iceConnectionState === 'disconnected') {
7087
+ this.eventEmitter.emit(ON_DISCONNECTED);
7088
+ }
7089
+ };
7090
+
7062
7091
  if (withEvent) {
7063
7092
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
7064
7093
  }
@@ -7254,24 +7283,89 @@ class WebRTCClient extends Emitter {
7254
7283
  const session = this.getSipSession(sessionId);
7255
7284
 
7256
7285
  const stats = session ? await this.getStats(session) : null;
7257
- if (!stats) {
7286
+ if (!stats || !(sessionId in this.sessionNetworkStats)) {
7258
7287
  return;
7259
7288
  }
7260
7289
 
7290
+ const networkStats = {
7291
+ audioBytesSent: 0,
7292
+ videoBytesSent: 0,
7293
+ videoBytesReceived: 0,
7294
+ audioBytesReceived: 0,
7295
+ };
7296
+ const nbStats = this.sessionNetworkStats[sessionId].length;
7297
+ const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
7298
+ const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
7299
+ const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
7300
+ const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
7301
+ const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
7302
+ const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
7303
+ const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
7304
+ let audioBytesSent = 0;
7305
+ let audioBytesReceived = 0;
7306
+ let videoBytesSent = 0;
7307
+ let videoBytesReceived = 0;
7308
+ let transportSent = 0;
7309
+ let transportReceived = 0;
7310
+ let packetsLost = 0;
7311
+
7261
7312
  stats.forEach(report => {
7262
- if (report.type === 'inbound-rtp') {
7263
- if (report.kind === 'audio') {
7264
- const networkStats = {
7265
- packetsLost: report.packetsLost,
7266
- packetsReceived: report.packetsReceived,
7267
- jitter: report.jitter,
7268
- };
7269
-
7270
- this.eventEmitter.emit(ON_NETWORK_STATS, session, networkStats, this.sessionNetworkStats[sessionId]);
7271
- this.sessionNetworkStats[sessionId].push(networkStats);
7313
+ if (report.type === 'outbound-rtp' && report.kind === 'audio') {
7314
+ audioBytesSent += report.bytesSent + report.headerBytesSent;
7315
+ }
7316
+ if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
7317
+ audioBytesSent += report.bytesSent;
7318
+ }
7319
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
7320
+ videoBytesSent += report.bytesSent + report.headerBytesSent;
7321
+ }
7322
+ if (report.type === 'inbound-rtp' && report.kind === 'audio') {
7323
+ packetsLost += report.packetsLost;
7324
+ networkStats.packetsReceived = report.packetsReceived;
7325
+ audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
7326
+ }
7327
+ if (report.type === 'inbound-rtp' && report.kind === 'video') {
7328
+ videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
7329
+ }
7330
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
7331
+ if ('framesPerSecond' in report) {
7332
+ networkStats.framesPerSecond = report.framesPerSecond;
7272
7333
  }
7334
+ if ('framerateMean' in report) {
7335
+ // framerateMean is only available in FF
7336
+ networkStats.framesPerSecond = Math.round(report.framerateMean);
7337
+ }
7338
+ }
7339
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
7340
+ packetsLost += report.packetsLost;
7341
+ networkStats.roundTripTime = report.roundTripTime;
7342
+ networkStats.jitter = report.jitter;
7343
+ }
7344
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
7345
+ packetsLost += report.packetsLost;
7346
+ }
7347
+ if (report.type === 'transport') {
7348
+ transportSent += report.bytesSent;
7349
+ transportReceived += report.bytesReceived;
7273
7350
  }
7274
7351
  });
7352
+
7353
+ networkStats.packetsLost = packetsLost;
7354
+ networkStats.audioBytesSent = audioBytesSent;
7355
+ networkStats.audioBytesReceived = audioBytesReceived;
7356
+ networkStats.videoBytesSent = videoBytesSent;
7357
+ networkStats.videoBytesReceived = videoBytesReceived;
7358
+ networkStats.transportSent = transportSent;
7359
+ networkStats.transportReceived = transportReceived;
7360
+
7361
+ const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
7362
+ + (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
7363
+ + (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
7364
+
7365
+ networkStats.bandwidth = bandwidth;
7366
+
7367
+ this.eventEmitter.emit(ON_NETWORK_STATS, session, networkStats, this.sessionNetworkStats[sessionId]);
7368
+ this.sessionNetworkStats[sessionId].push(networkStats);
7275
7369
  }
7276
7370
 
7277
7371
  }
@@ -373,7 +373,7 @@ class IssueReporter {
373
373
  payload._retry = retry + 1;
374
374
  }
375
375
 
376
- this._sendDebugToGrafana(body, retry + 1);
376
+ this._sendDebugToGrafana(payload, retry + 1);
377
377
  }, 5000 + retry * 1000);
378
378
  });
379
379
  }
@@ -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