@wazo/sdk 0.37.23 → 0.37.27

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 (118) hide show
  1. package/README.md +95 -57
  2. package/dist/wazo-sdk.js +3 -3
  3. package/esm/__tests__/api-client.test.js +12 -7
  4. package/esm/__tests__/web-rtc-client.test.js +47 -20
  5. package/esm/api/agentd.js +1 -1
  6. package/esm/api/amid.js +1 -1
  7. package/esm/api/application.js +1 -1
  8. package/esm/api/auth.js +1 -1
  9. package/esm/api/call-logd.js +1 -1
  10. package/esm/api/calld.js +1 -1
  11. package/esm/api/chatd.js +1 -1
  12. package/esm/api/confd.js +11 -6
  13. package/esm/api/ctid-ng.js +1 -1
  14. package/esm/api/dird.js +2 -2
  15. package/esm/api/webhookd.js +1 -1
  16. package/esm/api-client.js +12 -7
  17. package/esm/checker/Checker.js +47 -20
  18. package/esm/checker/checks/aor.js +12 -7
  19. package/esm/checker/checks/api.js +12 -7
  20. package/esm/checker/checks/index.js +47 -20
  21. package/esm/checker/checks/wazo-websocket.js +1 -1
  22. package/esm/checker/checks/webrtc-transport.js +47 -20
  23. package/esm/checker/checks/webrtc.js +47 -20
  24. package/esm/domain/AdHocAPIConference.js +12 -7
  25. package/esm/domain/Contact.js +1 -1
  26. package/esm/domain/Features.js +12 -7
  27. package/esm/domain/Meeting.js +12 -5
  28. package/esm/domain/Phone/CTIPhone.js +12 -7
  29. package/esm/domain/Phone/WebRTCPhone.js +34 -6
  30. package/esm/domain/__tests__/Contact.test.js +1 -1
  31. package/esm/domain/__tests__/Meeting.test.js +144 -0
  32. package/esm/index.js +80 -25
  33. package/esm/lib/WazoSessionDescriptionHandler.js +9 -4
  34. package/esm/service/CallApi.js +12 -7
  35. package/esm/service/IssueReporter.js +1 -1
  36. package/esm/service/__tests__/IssueReporter.test.js +1 -1
  37. package/esm/service/getApiClient.js +12 -7
  38. package/esm/simple/Auth.js +80 -25
  39. package/esm/simple/Configuration.js +80 -25
  40. package/esm/simple/Directory.js +12 -7
  41. package/esm/simple/Phone.js +80 -25
  42. package/esm/simple/Websocket.js +1 -1
  43. package/esm/simple/index.js +80 -25
  44. package/esm/simple/room/LocalParticipant.js +80 -25
  45. package/esm/simple/room/Participant.js +80 -25
  46. package/esm/simple/room/RemoteParticipant.js +80 -25
  47. package/esm/simple/room/Room.js +80 -25
  48. package/esm/simple/room/SipRoom.js +80 -25
  49. package/esm/simple/room/Stream.js +80 -25
  50. package/esm/simple/room/__tests__/RemoteParticipant.test.js +80 -25
  51. package/esm/simple/utils.js +80 -25
  52. package/esm/types/WebSocketMessage.js +1 -1
  53. package/esm/utils/__tests__/api-requester.test.js +1 -1
  54. package/esm/utils/api-requester.js +1 -1
  55. package/esm/web-rtc-client.js +47 -20
  56. package/esm/websocket-client.js +1 -1
  57. package/lib/__tests__/api-client.test.js +12 -7
  58. package/lib/__tests__/web-rtc-client.test.js +47 -20
  59. package/lib/api/agentd.js +1 -1
  60. package/lib/api/amid.js +1 -1
  61. package/lib/api/application.js +1 -1
  62. package/lib/api/auth.js +1 -1
  63. package/lib/api/call-logd.js +1 -1
  64. package/lib/api/calld.js +1 -1
  65. package/lib/api/chatd.js +1 -1
  66. package/lib/api/confd.js +11 -6
  67. package/lib/api/ctid-ng.js +1 -1
  68. package/lib/api/dird.js +2 -2
  69. package/lib/api/webhookd.js +1 -1
  70. package/lib/api-client.js +12 -7
  71. package/lib/checker/Checker.js +47 -20
  72. package/lib/checker/checks/aor.js +12 -7
  73. package/lib/checker/checks/api.js +12 -7
  74. package/lib/checker/checks/index.js +47 -20
  75. package/lib/checker/checks/wazo-websocket.js +1 -1
  76. package/lib/checker/checks/webrtc-transport.js +47 -20
  77. package/lib/checker/checks/webrtc.js +47 -20
  78. package/lib/domain/AdHocAPIConference.js +12 -7
  79. package/lib/domain/Contact.js +1 -1
  80. package/lib/domain/Features.js +12 -7
  81. package/lib/domain/Meeting.js +16 -5
  82. package/lib/domain/Phone/CTIPhone.js +12 -7
  83. package/lib/domain/Phone/WebRTCPhone.js +34 -6
  84. package/lib/domain/__tests__/Contact.test.js +1 -1
  85. package/lib/domain/__tests__/Meeting.test.js +150 -0
  86. package/lib/index.js +80 -25
  87. package/lib/lib/WazoSessionDescriptionHandler.js +9 -4
  88. package/lib/service/CallApi.js +12 -7
  89. package/lib/service/IssueReporter.js +1 -1
  90. package/lib/service/__tests__/IssueReporter.test.js +1 -1
  91. package/lib/service/getApiClient.js +12 -7
  92. package/lib/simple/Auth.js +80 -25
  93. package/lib/simple/Configuration.js +80 -25
  94. package/lib/simple/Directory.js +12 -7
  95. package/lib/simple/Phone.js +80 -25
  96. package/lib/simple/Websocket.js +1 -1
  97. package/lib/simple/index.js +80 -25
  98. package/lib/simple/room/LocalParticipant.js +80 -25
  99. package/lib/simple/room/Participant.js +80 -25
  100. package/lib/simple/room/RemoteParticipant.js +80 -25
  101. package/lib/simple/room/Room.js +80 -25
  102. package/lib/simple/room/SipRoom.js +80 -25
  103. package/lib/simple/room/Stream.js +80 -25
  104. package/lib/simple/room/__tests__/RemoteParticipant.test.js +80 -25
  105. package/lib/simple/utils.js +80 -25
  106. package/lib/types/WebSocketMessage.js +2 -0
  107. package/lib/utils/__tests__/api-requester.test.js +1 -1
  108. package/lib/utils/api-requester.js +1 -1
  109. package/lib/web-rtc-client.js +47 -20
  110. package/lib/websocket-client.js +1 -1
  111. package/package.json +1 -1
  112. package/src/domain/Contact.js +1 -1
  113. package/src/domain/Meeting.js +12 -5
  114. package/src/domain/Phone/WebRTCPhone.js +33 -5
  115. package/src/domain/__tests__/Meeting.test.js +50 -0
  116. package/src/lib/WazoSessionDescriptionHandler.js +8 -3
  117. package/src/utils/api-requester.js +1 -1
  118. package/src/web-rtc-client.js +27 -10
@@ -17,7 +17,7 @@ IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
17
17
 
18
18
  // Use a function here to be able to mock it in tests
19
19
  const realFetch = () => {
20
- if (typeof document !== 'undefined') {
20
+ if (typeof document !== 'undefined' && window.fetch) {
21
21
  // Browser
22
22
  return window.fetch;
23
23
  }
@@ -452,7 +452,7 @@ const logger$1 = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
452
452
 
453
453
  // Use a function here to be able to mock it in tests
454
454
  const realFetch = () => {
455
- if (typeof document !== 'undefined') {
455
+ if (typeof document !== 'undefined' && window.fetch) {
456
456
  // Browser
457
457
  return window.fetch;
458
458
  }
@@ -1912,7 +1912,7 @@ class Contact {
1912
1912
  this[key] = old[key] || this[key];
1913
1913
  });
1914
1914
 
1915
- if (old.lineState && !this.lineState) {
1915
+ if (old.lineState) {
1916
1916
  this.lineState = old.lineState;
1917
1917
  }
1918
1918
 
@@ -2619,8 +2619,9 @@ class ExternalApp {
2619
2619
 
2620
2620
 
2621
2621
 
2622
-
2622
+
2623
2623
 
2624
+
2624
2625
 
2625
2626
 
2626
2627
  class Meeting {
@@ -2631,9 +2632,10 @@ class Meeting {
2631
2632
 
2632
2633
 
2633
2634
 
2634
-
2635
+
2635
2636
 
2636
2637
 
2638
+
2637
2639
 
2638
2640
  static parse(plain ) {
2639
2641
  return new Meeting({
@@ -2643,8 +2645,9 @@ class Meeting {
2643
2645
  ownerUuids: plain.owner_uuids,
2644
2646
  port: plain.port,
2645
2647
  uuid: plain.uuid,
2646
- number: plain.number,
2648
+ extension: plain.exten,
2647
2649
  persistent: plain.persistent,
2650
+ creationTime: moment__default['default'](plain.creation_time).toDate(),
2648
2651
  });
2649
2652
  }
2650
2653
 
@@ -2666,8 +2669,9 @@ class Meeting {
2666
2669
  ownerUuids,
2667
2670
  port,
2668
2671
  uri,
2669
- number,
2672
+ extension,
2670
2673
  persistent,
2674
+ creationTime,
2671
2675
  } = {}) {
2672
2676
  this.guestSipAuthorization = guestSipAuthorization;
2673
2677
  this.uri = uri;
@@ -2675,8 +2679,9 @@ class Meeting {
2675
2679
  this.ownerUuids = ownerUuids;
2676
2680
  this.port = port;
2677
2681
  this.uuid = uuid;
2678
- this.number = number;
2682
+ this.extension = extension;
2679
2683
  this.persistent = persistent;
2684
+ this.creationTime = creationTime;
2680
2685
 
2681
2686
  // Useful to compare instead of instanceof with minified code
2682
2687
  this.type = 'Meeting';
@@ -1248,7 +1248,7 @@ class Contact {
1248
1248
  this[key] = old[key] || this[key];
1249
1249
  });
1250
1250
 
1251
- if (old.lineState && !this.lineState) {
1251
+ if (old.lineState) {
1252
1252
  this.lineState = old.lineState;
1253
1253
  }
1254
1254
 
@@ -1963,7 +1963,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
1963
1963
 
1964
1964
  // Use a function here to be able to mock it in tests
1965
1965
  const realFetch = () => {
1966
- if (typeof document !== 'undefined') {
1966
+ if (typeof document !== 'undefined' && window.fetch) {
1967
1967
  // Browser
1968
1968
  return window.fetch;
1969
1969
  }
@@ -2642,8 +2642,9 @@ class ExternalApp {
2642
2642
 
2643
2643
 
2644
2644
 
2645
-
2645
+
2646
2646
 
2647
+
2647
2648
 
2648
2649
 
2649
2650
  class Meeting {
@@ -2654,9 +2655,10 @@ class Meeting {
2654
2655
 
2655
2656
 
2656
2657
 
2657
-
2658
+
2658
2659
 
2659
2660
 
2661
+
2660
2662
 
2661
2663
  static parse(plain ) {
2662
2664
  return new Meeting({
@@ -2666,8 +2668,9 @@ class Meeting {
2666
2668
  ownerUuids: plain.owner_uuids,
2667
2669
  port: plain.port,
2668
2670
  uuid: plain.uuid,
2669
- number: plain.number,
2671
+ extension: plain.exten,
2670
2672
  persistent: plain.persistent,
2673
+ creationTime: moment__default['default'](plain.creation_time).toDate(),
2671
2674
  });
2672
2675
  }
2673
2676
 
@@ -2689,8 +2692,9 @@ class Meeting {
2689
2692
  ownerUuids,
2690
2693
  port,
2691
2694
  uri,
2692
- number,
2695
+ extension,
2693
2696
  persistent,
2697
+ creationTime,
2694
2698
  } = {}) {
2695
2699
  this.guestSipAuthorization = guestSipAuthorization;
2696
2700
  this.uri = uri;
@@ -2698,8 +2702,9 @@ class Meeting {
2698
2702
  this.ownerUuids = ownerUuids;
2699
2703
  this.port = port;
2700
2704
  this.uuid = uuid;
2701
- this.number = number;
2705
+ this.extension = extension;
2702
2706
  this.persistent = persistent;
2707
+ this.creationTime = creationTime;
2703
2708
 
2704
2709
  // Useful to compare instead of instanceof with minified code
2705
2710
  this.type = 'Meeting';
@@ -5805,11 +5810,16 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5805
5810
 
5806
5811
  // $FlowFixMe
5807
5812
  setRemoteSessionDescription(sessionDescription ) {
5808
- const result = super.setRemoteSessionDescription(sessionDescription);
5813
+ try {
5814
+ const result = super.setRemoteSessionDescription(sessionDescription);
5809
5815
 
5810
- this.eventEmitter.emit('setDescription', sessionDescription);
5816
+ this.eventEmitter.emit('setDescription', sessionDescription);
5811
5817
 
5812
- return result;
5818
+ return result;
5819
+ } catch (error) {
5820
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
5821
+ throw error;
5822
+ }
5813
5823
  }
5814
5824
 
5815
5825
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -6714,7 +6724,7 @@ class WebRTCClient extends Emitter {
6714
6724
  }
6715
6725
 
6716
6726
  call(number , enableVideo , audioOnly = false, conference = false) {
6717
- logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6727
+ logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
6718
6728
  const inviterOptions = {
6719
6729
  sessionDescriptionHandlerOptionsReInvite: {
6720
6730
  conference,
@@ -7790,6 +7800,7 @@ class WebRTCClient extends Emitter {
7790
7800
  const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
7791
7801
  const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
7792
7802
  const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
7803
+ const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
7793
7804
 
7794
7805
  logger$9.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
7795
7806
 
@@ -7797,7 +7808,8 @@ class WebRTCClient extends Emitter {
7797
7808
  constraints: {
7798
7809
  // Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
7799
7810
  audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
7800
- video: screenSharing ? (isDesktop ? ({ mandatory: { chromeMediaSource: 'desktop' } }) : { cursor: 'always' })
7811
+ video: screenSharing ? (isDesktop
7812
+ ? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
7801
7813
  : this._getVideoConstraints(enableVideo),
7802
7814
  screen: screenSharing,
7803
7815
  desktop: isDesktop,
@@ -8132,12 +8144,14 @@ class WebRTCClient extends Emitter {
8132
8144
 
8133
8145
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
8134
8146
 
8135
- pc.oniceconnectionstatechange = () => {
8136
- logger$9.info('on ice connection state changed', { state: pc.iceConnectionState });
8137
- if (pc.iceConnectionState === 'disconnected') {
8138
- this.eventEmitter.emit(ON_DISCONNECTED$1);
8139
- }
8140
- };
8147
+ if (pc) {
8148
+ pc.oniceconnectionstatechange = () => {
8149
+ logger$9.info('on ice connection state changed', { state: pc.iceConnectionState });
8150
+ if (pc.iceConnectionState === 'disconnected') {
8151
+ this.eventEmitter.emit(ON_DISCONNECTED$1);
8152
+ }
8153
+ };
8154
+ }
8141
8155
 
8142
8156
  if (withEvent) {
8143
8157
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
@@ -8347,13 +8361,17 @@ class WebRTCClient extends Emitter {
8347
8361
  const nbStats = this.sessionNetworkStats[sessionId].length;
8348
8362
  const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
8349
8363
  const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
8364
+ const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
8350
8365
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8351
8366
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8367
+ const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
8352
8368
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8353
8369
  const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8354
8370
  const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8355
- let audioBytesSent = 0;
8356
- let audioBytesReceived = 0;
8371
+ let audioBytesSent = 0; // content + header
8372
+ let audioBytesReceived = 0; // content + header
8373
+ let audioContentSent = 0; // useful to detect blank call
8374
+ let audioContentReceived = 0;
8357
8375
  let videoBytesSent = 0;
8358
8376
  let videoBytesReceived = 0;
8359
8377
  let transportSent = 0;
@@ -8363,6 +8381,7 @@ class WebRTCClient extends Emitter {
8363
8381
  stats.forEach(report => {
8364
8382
  if (report.type === 'outbound-rtp' && report.kind === 'audio') {
8365
8383
  audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
8384
+ audioContentSent += Number(report.bytesSent);
8366
8385
  }
8367
8386
  if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
8368
8387
  audioBytesSent += Number(report.bytesSent);
@@ -8374,6 +8393,7 @@ class WebRTCClient extends Emitter {
8374
8393
  packetsLost += Number(report.packetsLost);
8375
8394
  networkStats.packetsReceived = Number(report.packetsReceived);
8376
8395
  audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
8396
+ audioContentReceived += Number(report.bytesReceived);
8377
8397
  }
8378
8398
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
8379
8399
  videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
@@ -8402,10 +8422,17 @@ class WebRTCClient extends Emitter {
8402
8422
  });
8403
8423
 
8404
8424
  networkStats.packetsLost = packetsLost;
8425
+
8405
8426
  networkStats.totalAudioBytesSent = audioBytesSent;
8406
8427
  networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
8407
8428
  networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
8408
8429
  networkStats.audioBytesReceived = audioBytesReceived;
8430
+
8431
+ networkStats.totalAudioContentSent = audioContentSent;
8432
+ networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
8433
+ networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
8434
+ networkStats.audioContentReceived = audioContentReceived;
8435
+
8409
8436
  networkStats.totalVideoBytesSent = videoBytesSent;
8410
8437
  networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
8411
8438
  networkStats.totalVideoBytesReceived = videoBytesReceived;
@@ -8617,6 +8644,7 @@ class WebRTCPhone extends Emitter {
8617
8644
  constraints,
8618
8645
  audioOnly,
8619
8646
  conference,
8647
+ iceRestart,
8620
8648
  });
8621
8649
 
8622
8650
  if (!sipSession) {
@@ -8720,6 +8748,11 @@ class WebRTCPhone extends Emitter {
8720
8748
 
8721
8749
  this.client.downgradeToAudio(sipSession);
8722
8750
 
8751
+ if (callSession) {
8752
+ callSession.cameraEnabled = false;
8753
+ this._updateCallSession(callSession);
8754
+ }
8755
+
8723
8756
  if (withMessage) {
8724
8757
  this._sendReinviteMessage(callSession, false);
8725
8758
  }
@@ -8747,6 +8780,11 @@ class WebRTCPhone extends Emitter {
8747
8780
 
8748
8781
  const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
8749
8782
 
8783
+ if (callSession) {
8784
+ callSession.cameraEnabled = true;
8785
+ this._updateCallSession(callSession);
8786
+ }
8787
+
8750
8788
  // If no stream is returned, it means we have to reinvite
8751
8789
  if (!newStream) {
8752
8790
  return true;
@@ -9016,7 +9054,7 @@ class WebRTCPhone extends Emitter {
9016
9054
  }
9017
9055
 
9018
9056
  _onCallAccepted(sipSession , cameraEnabled ) {
9019
- logger$8.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9057
+ logger$8.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9020
9058
 
9021
9059
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
9022
9060
  this.currentSipSession = sipSession;
@@ -9085,6 +9123,7 @@ class WebRTCPhone extends Emitter {
9085
9123
  _onCallTerminated(sipSession ) {
9086
9124
  logger$8.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
9087
9125
 
9126
+ const sipSessionId = this.getSipSessionId(sipSession);
9088
9127
  const callSession = this._createCallSession(sipSession);
9089
9128
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
9090
9129
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -9102,7 +9141,6 @@ class WebRTCPhone extends Emitter {
9102
9141
  }, 5);
9103
9142
  }
9104
9143
 
9105
- const sipSessionId = this.getSipSessionId(sipSession);
9106
9144
  if (sipSessionId) {
9107
9145
  this.removeIncomingSessions(sipSessionId);
9108
9146
  }
@@ -9528,7 +9566,7 @@ class WebRTCPhone extends Emitter {
9528
9566
  // @TODO: line is not used here
9529
9567
  async makeCall(number , line , cameraEnabled ,
9530
9568
  audioOnly = false, conference = false) {
9531
- logger$8.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
9569
+ logger$8.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
9532
9570
  if (!number) {
9533
9571
  return Promise.resolve(null);
9534
9572
  }
@@ -9747,8 +9785,12 @@ class WebRTCPhone extends Emitter {
9747
9785
  }
9748
9786
 
9749
9787
  const sessionId = this.incomingSessions[0];
9788
+ const sipSession = this.client.getSipSession(sessionId);
9789
+ if (!sipSession) {
9790
+ return null;
9791
+ }
9750
9792
 
9751
- return this._createCallSession(this.client.getSipSession(sessionId));
9793
+ return this._createCallSession(sipSession);
9752
9794
  }
9753
9795
 
9754
9796
  sendMessage(sipSession = null, body , contentType = 'text/plain') {
@@ -9889,9 +9931,13 @@ class WebRTCPhone extends Emitter {
9889
9931
  if (this.shouldSendReinvite && this.currentSipSession
9890
9932
  && this.currentSipSession.state === sessionState.SessionState.Established) {
9891
9933
  this.shouldSendReinvite = false;
9934
+ const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
9935
+ const isConference = pc ? pc.sfu : false;
9936
+ const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
9937
+
9892
9938
  try {
9893
9939
  // Send reinvite with iceRestart
9894
- this.sendReinvite(this.currentCallSession, null, false, false, true);
9940
+ this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
9895
9941
  } catch (e) {
9896
9942
  logger$8.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
9897
9943
  }
@@ -9975,6 +10021,15 @@ class WebRTCPhone extends Emitter {
9975
10021
  return this.client.getSipSessionId(sipSession);
9976
10022
  }
9977
10023
 
10024
+ _updateCallSession(callSession ) {
10025
+ const sipSession = this.findSipSession(callSession);
10026
+ const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
10027
+
10028
+ if (sipSessionId) {
10029
+ this.callSessions[sipSessionId] = callSession;
10030
+ }
10031
+ }
10032
+
9978
10033
  _onMessage(message ) {
9979
10034
  if (!message || message.method !== 'MESSAGE') {
9980
10035
  return;
@@ -1246,7 +1246,7 @@ class Contact {
1246
1246
  this[key] = old[key] || this[key];
1247
1247
  });
1248
1248
 
1249
- if (old.lineState && !this.lineState) {
1249
+ if (old.lineState) {
1250
1250
  this.lineState = old.lineState;
1251
1251
  }
1252
1252
 
@@ -1961,7 +1961,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
1961
1961
 
1962
1962
  // Use a function here to be able to mock it in tests
1963
1963
  const realFetch = () => {
1964
- if (typeof document !== 'undefined') {
1964
+ if (typeof document !== 'undefined' && window.fetch) {
1965
1965
  // Browser
1966
1966
  return window.fetch;
1967
1967
  }
@@ -2640,8 +2640,9 @@ class ExternalApp {
2640
2640
 
2641
2641
 
2642
2642
 
2643
-
2643
+
2644
2644
 
2645
+
2645
2646
 
2646
2647
 
2647
2648
  class Meeting {
@@ -2652,9 +2653,10 @@ class Meeting {
2652
2653
 
2653
2654
 
2654
2655
 
2655
-
2656
+
2656
2657
 
2657
2658
 
2659
+
2658
2660
 
2659
2661
  static parse(plain ) {
2660
2662
  return new Meeting({
@@ -2664,8 +2666,9 @@ class Meeting {
2664
2666
  ownerUuids: plain.owner_uuids,
2665
2667
  port: plain.port,
2666
2668
  uuid: plain.uuid,
2667
- number: plain.number,
2669
+ extension: plain.exten,
2668
2670
  persistent: plain.persistent,
2671
+ creationTime: moment__default['default'](plain.creation_time).toDate(),
2669
2672
  });
2670
2673
  }
2671
2674
 
@@ -2687,8 +2690,9 @@ class Meeting {
2687
2690
  ownerUuids,
2688
2691
  port,
2689
2692
  uri,
2690
- number,
2693
+ extension,
2691
2694
  persistent,
2695
+ creationTime,
2692
2696
  } = {}) {
2693
2697
  this.guestSipAuthorization = guestSipAuthorization;
2694
2698
  this.uri = uri;
@@ -2696,8 +2700,9 @@ class Meeting {
2696
2700
  this.ownerUuids = ownerUuids;
2697
2701
  this.port = port;
2698
2702
  this.uuid = uuid;
2699
- this.number = number;
2703
+ this.extension = extension;
2700
2704
  this.persistent = persistent;
2705
+ this.creationTime = creationTime;
2701
2706
 
2702
2707
  // Useful to compare instead of instanceof with minified code
2703
2708
  this.type = 'Meeting';
@@ -5803,11 +5808,16 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5803
5808
 
5804
5809
  // $FlowFixMe
5805
5810
  setRemoteSessionDescription(sessionDescription ) {
5806
- const result = super.setRemoteSessionDescription(sessionDescription);
5811
+ try {
5812
+ const result = super.setRemoteSessionDescription(sessionDescription);
5807
5813
 
5808
- this.eventEmitter.emit('setDescription', sessionDescription);
5814
+ this.eventEmitter.emit('setDescription', sessionDescription);
5809
5815
 
5810
- return result;
5816
+ return result;
5817
+ } catch (error) {
5818
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
5819
+ throw error;
5820
+ }
5811
5821
  }
5812
5822
 
5813
5823
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -6712,7 +6722,7 @@ class WebRTCClient extends Emitter {
6712
6722
  }
6713
6723
 
6714
6724
  call(number , enableVideo , audioOnly = false, conference = false) {
6715
- logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6725
+ logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
6716
6726
  const inviterOptions = {
6717
6727
  sessionDescriptionHandlerOptionsReInvite: {
6718
6728
  conference,
@@ -7788,6 +7798,7 @@ class WebRTCClient extends Emitter {
7788
7798
  const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
7789
7799
  const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
7790
7800
  const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
7801
+ const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
7791
7802
 
7792
7803
  logger$9.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
7793
7804
 
@@ -7795,7 +7806,8 @@ class WebRTCClient extends Emitter {
7795
7806
  constraints: {
7796
7807
  // Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
7797
7808
  audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
7798
- video: screenSharing ? (isDesktop ? ({ mandatory: { chromeMediaSource: 'desktop' } }) : { cursor: 'always' })
7809
+ video: screenSharing ? (isDesktop
7810
+ ? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
7799
7811
  : this._getVideoConstraints(enableVideo),
7800
7812
  screen: screenSharing,
7801
7813
  desktop: isDesktop,
@@ -8130,12 +8142,14 @@ class WebRTCClient extends Emitter {
8130
8142
 
8131
8143
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
8132
8144
 
8133
- pc.oniceconnectionstatechange = () => {
8134
- logger$9.info('on ice connection state changed', { state: pc.iceConnectionState });
8135
- if (pc.iceConnectionState === 'disconnected') {
8136
- this.eventEmitter.emit(ON_DISCONNECTED$1);
8137
- }
8138
- };
8145
+ if (pc) {
8146
+ pc.oniceconnectionstatechange = () => {
8147
+ logger$9.info('on ice connection state changed', { state: pc.iceConnectionState });
8148
+ if (pc.iceConnectionState === 'disconnected') {
8149
+ this.eventEmitter.emit(ON_DISCONNECTED$1);
8150
+ }
8151
+ };
8152
+ }
8139
8153
 
8140
8154
  if (withEvent) {
8141
8155
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
@@ -8345,13 +8359,17 @@ class WebRTCClient extends Emitter {
8345
8359
  const nbStats = this.sessionNetworkStats[sessionId].length;
8346
8360
  const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
8347
8361
  const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
8362
+ const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
8348
8363
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8349
8364
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8365
+ const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
8350
8366
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8351
8367
  const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8352
8368
  const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8353
- let audioBytesSent = 0;
8354
- let audioBytesReceived = 0;
8369
+ let audioBytesSent = 0; // content + header
8370
+ let audioBytesReceived = 0; // content + header
8371
+ let audioContentSent = 0; // useful to detect blank call
8372
+ let audioContentReceived = 0;
8355
8373
  let videoBytesSent = 0;
8356
8374
  let videoBytesReceived = 0;
8357
8375
  let transportSent = 0;
@@ -8361,6 +8379,7 @@ class WebRTCClient extends Emitter {
8361
8379
  stats.forEach(report => {
8362
8380
  if (report.type === 'outbound-rtp' && report.kind === 'audio') {
8363
8381
  audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
8382
+ audioContentSent += Number(report.bytesSent);
8364
8383
  }
8365
8384
  if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
8366
8385
  audioBytesSent += Number(report.bytesSent);
@@ -8372,6 +8391,7 @@ class WebRTCClient extends Emitter {
8372
8391
  packetsLost += Number(report.packetsLost);
8373
8392
  networkStats.packetsReceived = Number(report.packetsReceived);
8374
8393
  audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
8394
+ audioContentReceived += Number(report.bytesReceived);
8375
8395
  }
8376
8396
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
8377
8397
  videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
@@ -8400,10 +8420,17 @@ class WebRTCClient extends Emitter {
8400
8420
  });
8401
8421
 
8402
8422
  networkStats.packetsLost = packetsLost;
8423
+
8403
8424
  networkStats.totalAudioBytesSent = audioBytesSent;
8404
8425
  networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
8405
8426
  networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
8406
8427
  networkStats.audioBytesReceived = audioBytesReceived;
8428
+
8429
+ networkStats.totalAudioContentSent = audioContentSent;
8430
+ networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
8431
+ networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
8432
+ networkStats.audioContentReceived = audioContentReceived;
8433
+
8407
8434
  networkStats.totalVideoBytesSent = videoBytesSent;
8408
8435
  networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
8409
8436
  networkStats.totalVideoBytesReceived = videoBytesReceived;
@@ -8615,6 +8642,7 @@ class WebRTCPhone extends Emitter {
8615
8642
  constraints,
8616
8643
  audioOnly,
8617
8644
  conference,
8645
+ iceRestart,
8618
8646
  });
8619
8647
 
8620
8648
  if (!sipSession) {
@@ -8718,6 +8746,11 @@ class WebRTCPhone extends Emitter {
8718
8746
 
8719
8747
  this.client.downgradeToAudio(sipSession);
8720
8748
 
8749
+ if (callSession) {
8750
+ callSession.cameraEnabled = false;
8751
+ this._updateCallSession(callSession);
8752
+ }
8753
+
8721
8754
  if (withMessage) {
8722
8755
  this._sendReinviteMessage(callSession, false);
8723
8756
  }
@@ -8745,6 +8778,11 @@ class WebRTCPhone extends Emitter {
8745
8778
 
8746
8779
  const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
8747
8780
 
8781
+ if (callSession) {
8782
+ callSession.cameraEnabled = true;
8783
+ this._updateCallSession(callSession);
8784
+ }
8785
+
8748
8786
  // If no stream is returned, it means we have to reinvite
8749
8787
  if (!newStream) {
8750
8788
  return true;
@@ -9014,7 +9052,7 @@ class WebRTCPhone extends Emitter {
9014
9052
  }
9015
9053
 
9016
9054
  _onCallAccepted(sipSession , cameraEnabled ) {
9017
- logger$8.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9055
+ logger$8.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9018
9056
 
9019
9057
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
9020
9058
  this.currentSipSession = sipSession;
@@ -9083,6 +9121,7 @@ class WebRTCPhone extends Emitter {
9083
9121
  _onCallTerminated(sipSession ) {
9084
9122
  logger$8.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
9085
9123
 
9124
+ const sipSessionId = this.getSipSessionId(sipSession);
9086
9125
  const callSession = this._createCallSession(sipSession);
9087
9126
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
9088
9127
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -9100,7 +9139,6 @@ class WebRTCPhone extends Emitter {
9100
9139
  }, 5);
9101
9140
  }
9102
9141
 
9103
- const sipSessionId = this.getSipSessionId(sipSession);
9104
9142
  if (sipSessionId) {
9105
9143
  this.removeIncomingSessions(sipSessionId);
9106
9144
  }
@@ -9526,7 +9564,7 @@ class WebRTCPhone extends Emitter {
9526
9564
  // @TODO: line is not used here
9527
9565
  async makeCall(number , line , cameraEnabled ,
9528
9566
  audioOnly = false, conference = false) {
9529
- logger$8.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
9567
+ logger$8.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
9530
9568
  if (!number) {
9531
9569
  return Promise.resolve(null);
9532
9570
  }
@@ -9745,8 +9783,12 @@ class WebRTCPhone extends Emitter {
9745
9783
  }
9746
9784
 
9747
9785
  const sessionId = this.incomingSessions[0];
9786
+ const sipSession = this.client.getSipSession(sessionId);
9787
+ if (!sipSession) {
9788
+ return null;
9789
+ }
9748
9790
 
9749
- return this._createCallSession(this.client.getSipSession(sessionId));
9791
+ return this._createCallSession(sipSession);
9750
9792
  }
9751
9793
 
9752
9794
  sendMessage(sipSession = null, body , contentType = 'text/plain') {
@@ -9887,9 +9929,13 @@ class WebRTCPhone extends Emitter {
9887
9929
  if (this.shouldSendReinvite && this.currentSipSession
9888
9930
  && this.currentSipSession.state === sessionState.SessionState.Established) {
9889
9931
  this.shouldSendReinvite = false;
9932
+ const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
9933
+ const isConference = pc ? pc.sfu : false;
9934
+ const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
9935
+
9890
9936
  try {
9891
9937
  // Send reinvite with iceRestart
9892
- this.sendReinvite(this.currentCallSession, null, false, false, true);
9938
+ this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
9893
9939
  } catch (e) {
9894
9940
  logger$8.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
9895
9941
  }
@@ -9973,6 +10019,15 @@ class WebRTCPhone extends Emitter {
9973
10019
  return this.client.getSipSessionId(sipSession);
9974
10020
  }
9975
10021
 
10022
+ _updateCallSession(callSession ) {
10023
+ const sipSession = this.findSipSession(callSession);
10024
+ const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
10025
+
10026
+ if (sipSessionId) {
10027
+ this.callSessions[sipSessionId] = callSession;
10028
+ }
10029
+ }
10030
+
9976
10031
  _onMessage(message ) {
9977
10032
  if (!message || message.method !== 'MESSAGE') {
9978
10033
  return;