@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
@@ -444,7 +444,7 @@ const logger$1 = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
444
444
 
445
445
  // Use a function here to be able to mock it in tests
446
446
  const realFetch = () => {
447
- if (typeof document !== 'undefined') {
447
+ if (typeof document !== 'undefined' && window.fetch) {
448
448
  // Browser
449
449
  return window.fetch;
450
450
  }
@@ -1904,7 +1904,7 @@ class Contact {
1904
1904
  this[key] = old[key] || this[key];
1905
1905
  });
1906
1906
 
1907
- if (old.lineState && !this.lineState) {
1907
+ if (old.lineState) {
1908
1908
  this.lineState = old.lineState;
1909
1909
  }
1910
1910
 
@@ -2611,8 +2611,9 @@ class ExternalApp {
2611
2611
 
2612
2612
 
2613
2613
 
2614
-
2614
+
2615
2615
 
2616
+
2616
2617
 
2617
2618
 
2618
2619
  class Meeting {
@@ -2623,9 +2624,10 @@ class Meeting {
2623
2624
 
2624
2625
 
2625
2626
 
2626
-
2627
+
2627
2628
 
2628
2629
 
2630
+
2629
2631
 
2630
2632
  static parse(plain ) {
2631
2633
  return new Meeting({
@@ -2635,8 +2637,9 @@ class Meeting {
2635
2637
  ownerUuids: plain.owner_uuids,
2636
2638
  port: plain.port,
2637
2639
  uuid: plain.uuid,
2638
- number: plain.number,
2640
+ extension: plain.exten,
2639
2641
  persistent: plain.persistent,
2642
+ creationTime: moment(plain.creation_time).toDate(),
2640
2643
  });
2641
2644
  }
2642
2645
 
@@ -2658,8 +2661,9 @@ class Meeting {
2658
2661
  ownerUuids,
2659
2662
  port,
2660
2663
  uri,
2661
- number,
2664
+ extension,
2662
2665
  persistent,
2666
+ creationTime,
2663
2667
  } = {}) {
2664
2668
  this.guestSipAuthorization = guestSipAuthorization;
2665
2669
  this.uri = uri;
@@ -2667,8 +2671,9 @@ class Meeting {
2667
2671
  this.ownerUuids = ownerUuids;
2668
2672
  this.port = port;
2669
2673
  this.uuid = uuid;
2670
- this.number = number;
2674
+ this.extension = extension;
2671
2675
  this.persistent = persistent;
2676
+ this.creationTime = creationTime;
2672
2677
 
2673
2678
  // Useful to compare instead of instanceof with minified code
2674
2679
  this.type = 'Meeting';
@@ -1236,7 +1236,7 @@ class Contact {
1236
1236
  this[key] = old[key] || this[key];
1237
1237
  });
1238
1238
 
1239
- if (old.lineState && !this.lineState) {
1239
+ if (old.lineState) {
1240
1240
  this.lineState = old.lineState;
1241
1241
  }
1242
1242
 
@@ -1951,7 +1951,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
1951
1951
 
1952
1952
  // Use a function here to be able to mock it in tests
1953
1953
  const realFetch = () => {
1954
- if (typeof document !== 'undefined') {
1954
+ if (typeof document !== 'undefined' && window.fetch) {
1955
1955
  // Browser
1956
1956
  return window.fetch;
1957
1957
  }
@@ -2630,8 +2630,9 @@ class ExternalApp {
2630
2630
 
2631
2631
 
2632
2632
 
2633
-
2633
+
2634
2634
 
2635
+
2635
2636
 
2636
2637
 
2637
2638
  class Meeting {
@@ -2642,9 +2643,10 @@ class Meeting {
2642
2643
 
2643
2644
 
2644
2645
 
2645
-
2646
+
2646
2647
 
2647
2648
 
2649
+
2648
2650
 
2649
2651
  static parse(plain ) {
2650
2652
  return new Meeting({
@@ -2654,8 +2656,9 @@ class Meeting {
2654
2656
  ownerUuids: plain.owner_uuids,
2655
2657
  port: plain.port,
2656
2658
  uuid: plain.uuid,
2657
- number: plain.number,
2659
+ extension: plain.exten,
2658
2660
  persistent: plain.persistent,
2661
+ creationTime: moment(plain.creation_time).toDate(),
2659
2662
  });
2660
2663
  }
2661
2664
 
@@ -2677,8 +2680,9 @@ class Meeting {
2677
2680
  ownerUuids,
2678
2681
  port,
2679
2682
  uri,
2680
- number,
2683
+ extension,
2681
2684
  persistent,
2685
+ creationTime,
2682
2686
  } = {}) {
2683
2687
  this.guestSipAuthorization = guestSipAuthorization;
2684
2688
  this.uri = uri;
@@ -2686,8 +2690,9 @@ class Meeting {
2686
2690
  this.ownerUuids = ownerUuids;
2687
2691
  this.port = port;
2688
2692
  this.uuid = uuid;
2689
- this.number = number;
2693
+ this.extension = extension;
2690
2694
  this.persistent = persistent;
2695
+ this.creationTime = creationTime;
2691
2696
 
2692
2697
  // Useful to compare instead of instanceof with minified code
2693
2698
  this.type = 'Meeting';
@@ -5793,11 +5798,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5793
5798
 
5794
5799
  // $FlowFixMe
5795
5800
  setRemoteSessionDescription(sessionDescription ) {
5796
- const result = super.setRemoteSessionDescription(sessionDescription);
5801
+ try {
5802
+ const result = super.setRemoteSessionDescription(sessionDescription);
5797
5803
 
5798
- this.eventEmitter.emit('setDescription', sessionDescription);
5804
+ this.eventEmitter.emit('setDescription', sessionDescription);
5799
5805
 
5800
- return result;
5806
+ return result;
5807
+ } catch (error) {
5808
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
5809
+ throw error;
5810
+ }
5801
5811
  }
5802
5812
 
5803
5813
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -6702,7 +6712,7 @@ class WebRTCClient extends Emitter {
6702
6712
  }
6703
6713
 
6704
6714
  call(number , enableVideo , audioOnly = false, conference = false) {
6705
- logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6715
+ logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
6706
6716
  const inviterOptions = {
6707
6717
  sessionDescriptionHandlerOptionsReInvite: {
6708
6718
  conference,
@@ -7778,6 +7788,7 @@ class WebRTCClient extends Emitter {
7778
7788
  const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
7779
7789
  const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
7780
7790
  const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
7791
+ const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
7781
7792
 
7782
7793
  logger$9.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
7783
7794
 
@@ -7785,7 +7796,8 @@ class WebRTCClient extends Emitter {
7785
7796
  constraints: {
7786
7797
  // Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
7787
7798
  audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
7788
- video: screenSharing ? (isDesktop ? ({ mandatory: { chromeMediaSource: 'desktop' } }) : { cursor: 'always' })
7799
+ video: screenSharing ? (isDesktop
7800
+ ? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
7789
7801
  : this._getVideoConstraints(enableVideo),
7790
7802
  screen: screenSharing,
7791
7803
  desktop: isDesktop,
@@ -8120,12 +8132,14 @@ class WebRTCClient extends Emitter {
8120
8132
 
8121
8133
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
8122
8134
 
8123
- pc.oniceconnectionstatechange = () => {
8124
- logger$9.info('on ice connection state changed', { state: pc.iceConnectionState });
8125
- if (pc.iceConnectionState === 'disconnected') {
8126
- this.eventEmitter.emit(ON_DISCONNECTED$1);
8127
- }
8128
- };
8135
+ if (pc) {
8136
+ pc.oniceconnectionstatechange = () => {
8137
+ logger$9.info('on ice connection state changed', { state: pc.iceConnectionState });
8138
+ if (pc.iceConnectionState === 'disconnected') {
8139
+ this.eventEmitter.emit(ON_DISCONNECTED$1);
8140
+ }
8141
+ };
8142
+ }
8129
8143
 
8130
8144
  if (withEvent) {
8131
8145
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
@@ -8335,13 +8349,17 @@ class WebRTCClient extends Emitter {
8335
8349
  const nbStats = this.sessionNetworkStats[sessionId].length;
8336
8350
  const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
8337
8351
  const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
8352
+ const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
8338
8353
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8339
8354
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8355
+ const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
8340
8356
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8341
8357
  const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8342
8358
  const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8343
- let audioBytesSent = 0;
8344
- let audioBytesReceived = 0;
8359
+ let audioBytesSent = 0; // content + header
8360
+ let audioBytesReceived = 0; // content + header
8361
+ let audioContentSent = 0; // useful to detect blank call
8362
+ let audioContentReceived = 0;
8345
8363
  let videoBytesSent = 0;
8346
8364
  let videoBytesReceived = 0;
8347
8365
  let transportSent = 0;
@@ -8351,6 +8369,7 @@ class WebRTCClient extends Emitter {
8351
8369
  stats.forEach(report => {
8352
8370
  if (report.type === 'outbound-rtp' && report.kind === 'audio') {
8353
8371
  audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
8372
+ audioContentSent += Number(report.bytesSent);
8354
8373
  }
8355
8374
  if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
8356
8375
  audioBytesSent += Number(report.bytesSent);
@@ -8362,6 +8381,7 @@ class WebRTCClient extends Emitter {
8362
8381
  packetsLost += Number(report.packetsLost);
8363
8382
  networkStats.packetsReceived = Number(report.packetsReceived);
8364
8383
  audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
8384
+ audioContentReceived += Number(report.bytesReceived);
8365
8385
  }
8366
8386
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
8367
8387
  videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
@@ -8390,10 +8410,17 @@ class WebRTCClient extends Emitter {
8390
8410
  });
8391
8411
 
8392
8412
  networkStats.packetsLost = packetsLost;
8413
+
8393
8414
  networkStats.totalAudioBytesSent = audioBytesSent;
8394
8415
  networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
8395
8416
  networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
8396
8417
  networkStats.audioBytesReceived = audioBytesReceived;
8418
+
8419
+ networkStats.totalAudioContentSent = audioContentSent;
8420
+ networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
8421
+ networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
8422
+ networkStats.audioContentReceived = audioContentReceived;
8423
+
8397
8424
  networkStats.totalVideoBytesSent = videoBytesSent;
8398
8425
  networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
8399
8426
  networkStats.totalVideoBytesReceived = videoBytesReceived;
@@ -8605,6 +8632,7 @@ class WebRTCPhone extends Emitter {
8605
8632
  constraints,
8606
8633
  audioOnly,
8607
8634
  conference,
8635
+ iceRestart,
8608
8636
  });
8609
8637
 
8610
8638
  if (!sipSession) {
@@ -8708,6 +8736,11 @@ class WebRTCPhone extends Emitter {
8708
8736
 
8709
8737
  this.client.downgradeToAudio(sipSession);
8710
8738
 
8739
+ if (callSession) {
8740
+ callSession.cameraEnabled = false;
8741
+ this._updateCallSession(callSession);
8742
+ }
8743
+
8711
8744
  if (withMessage) {
8712
8745
  this._sendReinviteMessage(callSession, false);
8713
8746
  }
@@ -8735,6 +8768,11 @@ class WebRTCPhone extends Emitter {
8735
8768
 
8736
8769
  const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
8737
8770
 
8771
+ if (callSession) {
8772
+ callSession.cameraEnabled = true;
8773
+ this._updateCallSession(callSession);
8774
+ }
8775
+
8738
8776
  // If no stream is returned, it means we have to reinvite
8739
8777
  if (!newStream) {
8740
8778
  return true;
@@ -9004,7 +9042,7 @@ class WebRTCPhone extends Emitter {
9004
9042
  }
9005
9043
 
9006
9044
  _onCallAccepted(sipSession , cameraEnabled ) {
9007
- logger$8.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9045
+ logger$8.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9008
9046
 
9009
9047
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
9010
9048
  this.currentSipSession = sipSession;
@@ -9073,6 +9111,7 @@ class WebRTCPhone extends Emitter {
9073
9111
  _onCallTerminated(sipSession ) {
9074
9112
  logger$8.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
9075
9113
 
9114
+ const sipSessionId = this.getSipSessionId(sipSession);
9076
9115
  const callSession = this._createCallSession(sipSession);
9077
9116
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
9078
9117
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -9090,7 +9129,6 @@ class WebRTCPhone extends Emitter {
9090
9129
  }, 5);
9091
9130
  }
9092
9131
 
9093
- const sipSessionId = this.getSipSessionId(sipSession);
9094
9132
  if (sipSessionId) {
9095
9133
  this.removeIncomingSessions(sipSessionId);
9096
9134
  }
@@ -9516,7 +9554,7 @@ class WebRTCPhone extends Emitter {
9516
9554
  // @TODO: line is not used here
9517
9555
  async makeCall(number , line , cameraEnabled ,
9518
9556
  audioOnly = false, conference = false) {
9519
- logger$8.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
9557
+ logger$8.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
9520
9558
  if (!number) {
9521
9559
  return Promise.resolve(null);
9522
9560
  }
@@ -9735,8 +9773,12 @@ class WebRTCPhone extends Emitter {
9735
9773
  }
9736
9774
 
9737
9775
  const sessionId = this.incomingSessions[0];
9776
+ const sipSession = this.client.getSipSession(sessionId);
9777
+ if (!sipSession) {
9778
+ return null;
9779
+ }
9738
9780
 
9739
- return this._createCallSession(this.client.getSipSession(sessionId));
9781
+ return this._createCallSession(sipSession);
9740
9782
  }
9741
9783
 
9742
9784
  sendMessage(sipSession = null, body , contentType = 'text/plain') {
@@ -9877,9 +9919,13 @@ class WebRTCPhone extends Emitter {
9877
9919
  if (this.shouldSendReinvite && this.currentSipSession
9878
9920
  && this.currentSipSession.state === SessionState.Established) {
9879
9921
  this.shouldSendReinvite = false;
9922
+ const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
9923
+ const isConference = pc ? pc.sfu : false;
9924
+ const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
9925
+
9880
9926
  try {
9881
9927
  // Send reinvite with iceRestart
9882
- this.sendReinvite(this.currentCallSession, null, false, false, true);
9928
+ this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
9883
9929
  } catch (e) {
9884
9930
  logger$8.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
9885
9931
  }
@@ -9963,6 +10009,15 @@ class WebRTCPhone extends Emitter {
9963
10009
  return this.client.getSipSessionId(sipSession);
9964
10010
  }
9965
10011
 
10012
+ _updateCallSession(callSession ) {
10013
+ const sipSession = this.findSipSession(callSession);
10014
+ const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
10015
+
10016
+ if (sipSessionId) {
10017
+ this.callSessions[sipSessionId] = callSession;
10018
+ }
10019
+ }
10020
+
9966
10021
  _onMessage(message ) {
9967
10022
  if (!message || message.method !== 'MESSAGE') {
9968
10023
  return;
@@ -1236,7 +1236,7 @@ class Contact {
1236
1236
  this[key] = old[key] || this[key];
1237
1237
  });
1238
1238
 
1239
- if (old.lineState && !this.lineState) {
1239
+ if (old.lineState) {
1240
1240
  this.lineState = old.lineState;
1241
1241
  }
1242
1242
 
@@ -1951,7 +1951,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
1951
1951
 
1952
1952
  // Use a function here to be able to mock it in tests
1953
1953
  const realFetch = () => {
1954
- if (typeof document !== 'undefined') {
1954
+ if (typeof document !== 'undefined' && window.fetch) {
1955
1955
  // Browser
1956
1956
  return window.fetch;
1957
1957
  }
@@ -2630,8 +2630,9 @@ class ExternalApp {
2630
2630
 
2631
2631
 
2632
2632
 
2633
-
2633
+
2634
2634
 
2635
+
2635
2636
 
2636
2637
 
2637
2638
  class Meeting {
@@ -2642,9 +2643,10 @@ class Meeting {
2642
2643
 
2643
2644
 
2644
2645
 
2645
-
2646
+
2646
2647
 
2647
2648
 
2649
+
2648
2650
 
2649
2651
  static parse(plain ) {
2650
2652
  return new Meeting({
@@ -2654,8 +2656,9 @@ class Meeting {
2654
2656
  ownerUuids: plain.owner_uuids,
2655
2657
  port: plain.port,
2656
2658
  uuid: plain.uuid,
2657
- number: plain.number,
2659
+ extension: plain.exten,
2658
2660
  persistent: plain.persistent,
2661
+ creationTime: moment(plain.creation_time).toDate(),
2659
2662
  });
2660
2663
  }
2661
2664
 
@@ -2677,8 +2680,9 @@ class Meeting {
2677
2680
  ownerUuids,
2678
2681
  port,
2679
2682
  uri,
2680
- number,
2683
+ extension,
2681
2684
  persistent,
2685
+ creationTime,
2682
2686
  } = {}) {
2683
2687
  this.guestSipAuthorization = guestSipAuthorization;
2684
2688
  this.uri = uri;
@@ -2686,8 +2690,9 @@ class Meeting {
2686
2690
  this.ownerUuids = ownerUuids;
2687
2691
  this.port = port;
2688
2692
  this.uuid = uuid;
2689
- this.number = number;
2693
+ this.extension = extension;
2690
2694
  this.persistent = persistent;
2695
+ this.creationTime = creationTime;
2691
2696
 
2692
2697
  // Useful to compare instead of instanceof with minified code
2693
2698
  this.type = 'Meeting';
@@ -5793,11 +5798,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5793
5798
 
5794
5799
  // $FlowFixMe
5795
5800
  setRemoteSessionDescription(sessionDescription ) {
5796
- const result = super.setRemoteSessionDescription(sessionDescription);
5801
+ try {
5802
+ const result = super.setRemoteSessionDescription(sessionDescription);
5797
5803
 
5798
- this.eventEmitter.emit('setDescription', sessionDescription);
5804
+ this.eventEmitter.emit('setDescription', sessionDescription);
5799
5805
 
5800
- return result;
5806
+ return result;
5807
+ } catch (error) {
5808
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
5809
+ throw error;
5810
+ }
5801
5811
  }
5802
5812
 
5803
5813
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -6702,7 +6712,7 @@ class WebRTCClient extends Emitter {
6702
6712
  }
6703
6713
 
6704
6714
  call(number , enableVideo , audioOnly = false, conference = false) {
6705
- logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6715
+ logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
6706
6716
  const inviterOptions = {
6707
6717
  sessionDescriptionHandlerOptionsReInvite: {
6708
6718
  conference,
@@ -7778,6 +7788,7 @@ class WebRTCClient extends Emitter {
7778
7788
  const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
7779
7789
  const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
7780
7790
  const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
7791
+ const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
7781
7792
 
7782
7793
  logger$9.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
7783
7794
 
@@ -7785,7 +7796,8 @@ class WebRTCClient extends Emitter {
7785
7796
  constraints: {
7786
7797
  // Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
7787
7798
  audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
7788
- video: screenSharing ? (isDesktop ? ({ mandatory: { chromeMediaSource: 'desktop' } }) : { cursor: 'always' })
7799
+ video: screenSharing ? (isDesktop
7800
+ ? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
7789
7801
  : this._getVideoConstraints(enableVideo),
7790
7802
  screen: screenSharing,
7791
7803
  desktop: isDesktop,
@@ -8120,12 +8132,14 @@ class WebRTCClient extends Emitter {
8120
8132
 
8121
8133
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
8122
8134
 
8123
- pc.oniceconnectionstatechange = () => {
8124
- logger$9.info('on ice connection state changed', { state: pc.iceConnectionState });
8125
- if (pc.iceConnectionState === 'disconnected') {
8126
- this.eventEmitter.emit(ON_DISCONNECTED$1);
8127
- }
8128
- };
8135
+ if (pc) {
8136
+ pc.oniceconnectionstatechange = () => {
8137
+ logger$9.info('on ice connection state changed', { state: pc.iceConnectionState });
8138
+ if (pc.iceConnectionState === 'disconnected') {
8139
+ this.eventEmitter.emit(ON_DISCONNECTED$1);
8140
+ }
8141
+ };
8142
+ }
8129
8143
 
8130
8144
  if (withEvent) {
8131
8145
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
@@ -8335,13 +8349,17 @@ class WebRTCClient extends Emitter {
8335
8349
  const nbStats = this.sessionNetworkStats[sessionId].length;
8336
8350
  const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
8337
8351
  const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
8352
+ const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
8338
8353
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8339
8354
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8355
+ const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
8340
8356
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8341
8357
  const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8342
8358
  const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8343
- let audioBytesSent = 0;
8344
- let audioBytesReceived = 0;
8359
+ let audioBytesSent = 0; // content + header
8360
+ let audioBytesReceived = 0; // content + header
8361
+ let audioContentSent = 0; // useful to detect blank call
8362
+ let audioContentReceived = 0;
8345
8363
  let videoBytesSent = 0;
8346
8364
  let videoBytesReceived = 0;
8347
8365
  let transportSent = 0;
@@ -8351,6 +8369,7 @@ class WebRTCClient extends Emitter {
8351
8369
  stats.forEach(report => {
8352
8370
  if (report.type === 'outbound-rtp' && report.kind === 'audio') {
8353
8371
  audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
8372
+ audioContentSent += Number(report.bytesSent);
8354
8373
  }
8355
8374
  if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
8356
8375
  audioBytesSent += Number(report.bytesSent);
@@ -8362,6 +8381,7 @@ class WebRTCClient extends Emitter {
8362
8381
  packetsLost += Number(report.packetsLost);
8363
8382
  networkStats.packetsReceived = Number(report.packetsReceived);
8364
8383
  audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
8384
+ audioContentReceived += Number(report.bytesReceived);
8365
8385
  }
8366
8386
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
8367
8387
  videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
@@ -8390,10 +8410,17 @@ class WebRTCClient extends Emitter {
8390
8410
  });
8391
8411
 
8392
8412
  networkStats.packetsLost = packetsLost;
8413
+
8393
8414
  networkStats.totalAudioBytesSent = audioBytesSent;
8394
8415
  networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
8395
8416
  networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
8396
8417
  networkStats.audioBytesReceived = audioBytesReceived;
8418
+
8419
+ networkStats.totalAudioContentSent = audioContentSent;
8420
+ networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
8421
+ networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
8422
+ networkStats.audioContentReceived = audioContentReceived;
8423
+
8397
8424
  networkStats.totalVideoBytesSent = videoBytesSent;
8398
8425
  networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
8399
8426
  networkStats.totalVideoBytesReceived = videoBytesReceived;
@@ -8605,6 +8632,7 @@ class WebRTCPhone extends Emitter {
8605
8632
  constraints,
8606
8633
  audioOnly,
8607
8634
  conference,
8635
+ iceRestart,
8608
8636
  });
8609
8637
 
8610
8638
  if (!sipSession) {
@@ -8708,6 +8736,11 @@ class WebRTCPhone extends Emitter {
8708
8736
 
8709
8737
  this.client.downgradeToAudio(sipSession);
8710
8738
 
8739
+ if (callSession) {
8740
+ callSession.cameraEnabled = false;
8741
+ this._updateCallSession(callSession);
8742
+ }
8743
+
8711
8744
  if (withMessage) {
8712
8745
  this._sendReinviteMessage(callSession, false);
8713
8746
  }
@@ -8735,6 +8768,11 @@ class WebRTCPhone extends Emitter {
8735
8768
 
8736
8769
  const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
8737
8770
 
8771
+ if (callSession) {
8772
+ callSession.cameraEnabled = true;
8773
+ this._updateCallSession(callSession);
8774
+ }
8775
+
8738
8776
  // If no stream is returned, it means we have to reinvite
8739
8777
  if (!newStream) {
8740
8778
  return true;
@@ -9004,7 +9042,7 @@ class WebRTCPhone extends Emitter {
9004
9042
  }
9005
9043
 
9006
9044
  _onCallAccepted(sipSession , cameraEnabled ) {
9007
- logger$8.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9045
+ logger$8.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9008
9046
 
9009
9047
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
9010
9048
  this.currentSipSession = sipSession;
@@ -9073,6 +9111,7 @@ class WebRTCPhone extends Emitter {
9073
9111
  _onCallTerminated(sipSession ) {
9074
9112
  logger$8.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
9075
9113
 
9114
+ const sipSessionId = this.getSipSessionId(sipSession);
9076
9115
  const callSession = this._createCallSession(sipSession);
9077
9116
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
9078
9117
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -9090,7 +9129,6 @@ class WebRTCPhone extends Emitter {
9090
9129
  }, 5);
9091
9130
  }
9092
9131
 
9093
- const sipSessionId = this.getSipSessionId(sipSession);
9094
9132
  if (sipSessionId) {
9095
9133
  this.removeIncomingSessions(sipSessionId);
9096
9134
  }
@@ -9516,7 +9554,7 @@ class WebRTCPhone extends Emitter {
9516
9554
  // @TODO: line is not used here
9517
9555
  async makeCall(number , line , cameraEnabled ,
9518
9556
  audioOnly = false, conference = false) {
9519
- logger$8.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
9557
+ logger$8.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
9520
9558
  if (!number) {
9521
9559
  return Promise.resolve(null);
9522
9560
  }
@@ -9735,8 +9773,12 @@ class WebRTCPhone extends Emitter {
9735
9773
  }
9736
9774
 
9737
9775
  const sessionId = this.incomingSessions[0];
9776
+ const sipSession = this.client.getSipSession(sessionId);
9777
+ if (!sipSession) {
9778
+ return null;
9779
+ }
9738
9780
 
9739
- return this._createCallSession(this.client.getSipSession(sessionId));
9781
+ return this._createCallSession(sipSession);
9740
9782
  }
9741
9783
 
9742
9784
  sendMessage(sipSession = null, body , contentType = 'text/plain') {
@@ -9877,9 +9919,13 @@ class WebRTCPhone extends Emitter {
9877
9919
  if (this.shouldSendReinvite && this.currentSipSession
9878
9920
  && this.currentSipSession.state === SessionState.Established) {
9879
9921
  this.shouldSendReinvite = false;
9922
+ const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
9923
+ const isConference = pc ? pc.sfu : false;
9924
+ const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
9925
+
9880
9926
  try {
9881
9927
  // Send reinvite with iceRestart
9882
- this.sendReinvite(this.currentCallSession, null, false, false, true);
9928
+ this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
9883
9929
  } catch (e) {
9884
9930
  logger$8.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
9885
9931
  }
@@ -9963,6 +10009,15 @@ class WebRTCPhone extends Emitter {
9963
10009
  return this.client.getSipSessionId(sipSession);
9964
10010
  }
9965
10011
 
10012
+ _updateCallSession(callSession ) {
10013
+ const sipSession = this.findSipSession(callSession);
10014
+ const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
10015
+
10016
+ if (sipSessionId) {
10017
+ this.callSessions[sipSessionId] = callSession;
10018
+ }
10019
+ }
10020
+
9966
10021
  _onMessage(message ) {
9967
10022
  if (!message || message.method !== 'MESSAGE') {
9968
10023
  return;