@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
@@ -132,7 +132,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
132
132
 
133
133
  // Use a function here to be able to mock it in tests
134
134
  const realFetch = () => {
135
- if (typeof document !== 'undefined') {
135
+ if (typeof document !== 'undefined' && window.fetch) {
136
136
  // Browser
137
137
  return window.fetch;
138
138
  }
@@ -1949,7 +1949,7 @@ class Contact {
1949
1949
  this[key] = old[key] || this[key];
1950
1950
  });
1951
1951
 
1952
- if (old.lineState && !this.lineState) {
1952
+ if (old.lineState) {
1953
1953
  this.lineState = old.lineState;
1954
1954
  }
1955
1955
 
@@ -2656,8 +2656,9 @@ class ExternalApp {
2656
2656
 
2657
2657
 
2658
2658
 
2659
-
2659
+
2660
2660
 
2661
+
2661
2662
 
2662
2663
 
2663
2664
  class Meeting {
@@ -2668,9 +2669,10 @@ class Meeting {
2668
2669
 
2669
2670
 
2670
2671
 
2671
-
2672
+
2672
2673
 
2673
2674
 
2675
+
2674
2676
 
2675
2677
  static parse(plain ) {
2676
2678
  return new Meeting({
@@ -2680,8 +2682,9 @@ class Meeting {
2680
2682
  ownerUuids: plain.owner_uuids,
2681
2683
  port: plain.port,
2682
2684
  uuid: plain.uuid,
2683
- number: plain.number,
2685
+ extension: plain.exten,
2684
2686
  persistent: plain.persistent,
2687
+ creationTime: moment(plain.creation_time).toDate(),
2685
2688
  });
2686
2689
  }
2687
2690
 
@@ -2703,8 +2706,9 @@ class Meeting {
2703
2706
  ownerUuids,
2704
2707
  port,
2705
2708
  uri,
2706
- number,
2709
+ extension,
2707
2710
  persistent,
2711
+ creationTime,
2708
2712
  } = {}) {
2709
2713
  this.guestSipAuthorization = guestSipAuthorization;
2710
2714
  this.uri = uri;
@@ -2712,8 +2716,9 @@ class Meeting {
2712
2716
  this.ownerUuids = ownerUuids;
2713
2717
  this.port = port;
2714
2718
  this.uuid = uuid;
2715
- this.number = number;
2719
+ this.extension = extension;
2716
2720
  this.persistent = persistent;
2721
+ this.creationTime = creationTime;
2717
2722
 
2718
2723
  // Useful to compare instead of instanceof with minified code
2719
2724
  this.type = 'Meeting';
@@ -6057,11 +6062,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
6057
6062
 
6058
6063
  // $FlowFixMe
6059
6064
  setRemoteSessionDescription(sessionDescription ) {
6060
- const result = super.setRemoteSessionDescription(sessionDescription);
6065
+ try {
6066
+ const result = super.setRemoteSessionDescription(sessionDescription);
6061
6067
 
6062
- this.eventEmitter.emit('setDescription', sessionDescription);
6068
+ this.eventEmitter.emit('setDescription', sessionDescription);
6063
6069
 
6064
- return result;
6070
+ return result;
6071
+ } catch (error) {
6072
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
6073
+ throw error;
6074
+ }
6065
6075
  }
6066
6076
 
6067
6077
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -6966,7 +6976,7 @@ class WebRTCClient extends Emitter {
6966
6976
  }
6967
6977
 
6968
6978
  call(number , enableVideo , audioOnly = false, conference = false) {
6969
- logger$8.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6979
+ logger$8.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
6970
6980
  const inviterOptions = {
6971
6981
  sessionDescriptionHandlerOptionsReInvite: {
6972
6982
  conference,
@@ -8042,6 +8052,7 @@ class WebRTCClient extends Emitter {
8042
8052
  const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
8043
8053
  const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
8044
8054
  const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
8055
+ const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
8045
8056
 
8046
8057
  logger$8.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
8047
8058
 
@@ -8049,7 +8060,8 @@ class WebRTCClient extends Emitter {
8049
8060
  constraints: {
8050
8061
  // Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
8051
8062
  audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
8052
- video: screenSharing ? (isDesktop ? ({ mandatory: { chromeMediaSource: 'desktop' } }) : { cursor: 'always' })
8063
+ video: screenSharing ? (isDesktop
8064
+ ? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
8053
8065
  : this._getVideoConstraints(enableVideo),
8054
8066
  screen: screenSharing,
8055
8067
  desktop: isDesktop,
@@ -8384,12 +8396,14 @@ class WebRTCClient extends Emitter {
8384
8396
 
8385
8397
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
8386
8398
 
8387
- pc.oniceconnectionstatechange = () => {
8388
- logger$8.info('on ice connection state changed', { state: pc.iceConnectionState });
8389
- if (pc.iceConnectionState === 'disconnected') {
8390
- this.eventEmitter.emit(ON_DISCONNECTED$1);
8391
- }
8392
- };
8399
+ if (pc) {
8400
+ pc.oniceconnectionstatechange = () => {
8401
+ logger$8.info('on ice connection state changed', { state: pc.iceConnectionState });
8402
+ if (pc.iceConnectionState === 'disconnected') {
8403
+ this.eventEmitter.emit(ON_DISCONNECTED$1);
8404
+ }
8405
+ };
8406
+ }
8393
8407
 
8394
8408
  if (withEvent) {
8395
8409
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
@@ -8599,13 +8613,17 @@ class WebRTCClient extends Emitter {
8599
8613
  const nbStats = this.sessionNetworkStats[sessionId].length;
8600
8614
  const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
8601
8615
  const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
8616
+ const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
8602
8617
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8603
8618
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8619
+ const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
8604
8620
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8605
8621
  const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8606
8622
  const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8607
- let audioBytesSent = 0;
8608
- let audioBytesReceived = 0;
8623
+ let audioBytesSent = 0; // content + header
8624
+ let audioBytesReceived = 0; // content + header
8625
+ let audioContentSent = 0; // useful to detect blank call
8626
+ let audioContentReceived = 0;
8609
8627
  let videoBytesSent = 0;
8610
8628
  let videoBytesReceived = 0;
8611
8629
  let transportSent = 0;
@@ -8615,6 +8633,7 @@ class WebRTCClient extends Emitter {
8615
8633
  stats.forEach(report => {
8616
8634
  if (report.type === 'outbound-rtp' && report.kind === 'audio') {
8617
8635
  audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
8636
+ audioContentSent += Number(report.bytesSent);
8618
8637
  }
8619
8638
  if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
8620
8639
  audioBytesSent += Number(report.bytesSent);
@@ -8626,6 +8645,7 @@ class WebRTCClient extends Emitter {
8626
8645
  packetsLost += Number(report.packetsLost);
8627
8646
  networkStats.packetsReceived = Number(report.packetsReceived);
8628
8647
  audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
8648
+ audioContentReceived += Number(report.bytesReceived);
8629
8649
  }
8630
8650
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
8631
8651
  videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
@@ -8654,10 +8674,17 @@ class WebRTCClient extends Emitter {
8654
8674
  });
8655
8675
 
8656
8676
  networkStats.packetsLost = packetsLost;
8677
+
8657
8678
  networkStats.totalAudioBytesSent = audioBytesSent;
8658
8679
  networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
8659
8680
  networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
8660
8681
  networkStats.audioBytesReceived = audioBytesReceived;
8682
+
8683
+ networkStats.totalAudioContentSent = audioContentSent;
8684
+ networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
8685
+ networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
8686
+ networkStats.audioContentReceived = audioContentReceived;
8687
+
8661
8688
  networkStats.totalVideoBytesSent = videoBytesSent;
8662
8689
  networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
8663
8690
  networkStats.totalVideoBytesReceived = videoBytesReceived;
@@ -8869,6 +8896,7 @@ class WebRTCPhone extends Emitter {
8869
8896
  constraints,
8870
8897
  audioOnly,
8871
8898
  conference,
8899
+ iceRestart,
8872
8900
  });
8873
8901
 
8874
8902
  if (!sipSession) {
@@ -8972,6 +9000,11 @@ class WebRTCPhone extends Emitter {
8972
9000
 
8973
9001
  this.client.downgradeToAudio(sipSession);
8974
9002
 
9003
+ if (callSession) {
9004
+ callSession.cameraEnabled = false;
9005
+ this._updateCallSession(callSession);
9006
+ }
9007
+
8975
9008
  if (withMessage) {
8976
9009
  this._sendReinviteMessage(callSession, false);
8977
9010
  }
@@ -8999,6 +9032,11 @@ class WebRTCPhone extends Emitter {
8999
9032
 
9000
9033
  const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
9001
9034
 
9035
+ if (callSession) {
9036
+ callSession.cameraEnabled = true;
9037
+ this._updateCallSession(callSession);
9038
+ }
9039
+
9002
9040
  // If no stream is returned, it means we have to reinvite
9003
9041
  if (!newStream) {
9004
9042
  return true;
@@ -9268,7 +9306,7 @@ class WebRTCPhone extends Emitter {
9268
9306
  }
9269
9307
 
9270
9308
  _onCallAccepted(sipSession , cameraEnabled ) {
9271
- logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9309
+ logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9272
9310
 
9273
9311
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
9274
9312
  this.currentSipSession = sipSession;
@@ -9337,6 +9375,7 @@ class WebRTCPhone extends Emitter {
9337
9375
  _onCallTerminated(sipSession ) {
9338
9376
  logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
9339
9377
 
9378
+ const sipSessionId = this.getSipSessionId(sipSession);
9340
9379
  const callSession = this._createCallSession(sipSession);
9341
9380
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
9342
9381
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -9354,7 +9393,6 @@ class WebRTCPhone extends Emitter {
9354
9393
  }, 5);
9355
9394
  }
9356
9395
 
9357
- const sipSessionId = this.getSipSessionId(sipSession);
9358
9396
  if (sipSessionId) {
9359
9397
  this.removeIncomingSessions(sipSessionId);
9360
9398
  }
@@ -9780,7 +9818,7 @@ class WebRTCPhone extends Emitter {
9780
9818
  // @TODO: line is not used here
9781
9819
  async makeCall(number , line , cameraEnabled ,
9782
9820
  audioOnly = false, conference = false) {
9783
- logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
9821
+ logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
9784
9822
  if (!number) {
9785
9823
  return Promise.resolve(null);
9786
9824
  }
@@ -9999,8 +10037,12 @@ class WebRTCPhone extends Emitter {
9999
10037
  }
10000
10038
 
10001
10039
  const sessionId = this.incomingSessions[0];
10040
+ const sipSession = this.client.getSipSession(sessionId);
10041
+ if (!sipSession) {
10042
+ return null;
10043
+ }
10002
10044
 
10003
- return this._createCallSession(this.client.getSipSession(sessionId));
10045
+ return this._createCallSession(sipSession);
10004
10046
  }
10005
10047
 
10006
10048
  sendMessage(sipSession = null, body , contentType = 'text/plain') {
@@ -10141,9 +10183,13 @@ class WebRTCPhone extends Emitter {
10141
10183
  if (this.shouldSendReinvite && this.currentSipSession
10142
10184
  && this.currentSipSession.state === SessionState.Established) {
10143
10185
  this.shouldSendReinvite = false;
10186
+ const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
10187
+ const isConference = pc ? pc.sfu : false;
10188
+ const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
10189
+
10144
10190
  try {
10145
10191
  // Send reinvite with iceRestart
10146
- this.sendReinvite(this.currentCallSession, null, false, false, true);
10192
+ this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
10147
10193
  } catch (e) {
10148
10194
  logger$7.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
10149
10195
  }
@@ -10227,6 +10273,15 @@ class WebRTCPhone extends Emitter {
10227
10273
  return this.client.getSipSessionId(sipSession);
10228
10274
  }
10229
10275
 
10276
+ _updateCallSession(callSession ) {
10277
+ const sipSession = this.findSipSession(callSession);
10278
+ const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
10279
+
10280
+ if (sipSessionId) {
10281
+ this.callSessions[sipSessionId] = callSession;
10282
+ }
10283
+ }
10284
+
10230
10285
  _onMessage(message ) {
10231
10286
  if (!message || message.method !== 'MESSAGE') {
10232
10287
  return;
@@ -132,7 +132,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
132
132
 
133
133
  // Use a function here to be able to mock it in tests
134
134
  const realFetch = () => {
135
- if (typeof document !== 'undefined') {
135
+ if (typeof document !== 'undefined' && window.fetch) {
136
136
  // Browser
137
137
  return window.fetch;
138
138
  }
@@ -1949,7 +1949,7 @@ class Contact {
1949
1949
  this[key] = old[key] || this[key];
1950
1950
  });
1951
1951
 
1952
- if (old.lineState && !this.lineState) {
1952
+ if (old.lineState) {
1953
1953
  this.lineState = old.lineState;
1954
1954
  }
1955
1955
 
@@ -2656,8 +2656,9 @@ class ExternalApp {
2656
2656
 
2657
2657
 
2658
2658
 
2659
-
2659
+
2660
2660
 
2661
+
2661
2662
 
2662
2663
 
2663
2664
  class Meeting {
@@ -2668,9 +2669,10 @@ class Meeting {
2668
2669
 
2669
2670
 
2670
2671
 
2671
-
2672
+
2672
2673
 
2673
2674
 
2675
+
2674
2676
 
2675
2677
  static parse(plain ) {
2676
2678
  return new Meeting({
@@ -2680,8 +2682,9 @@ class Meeting {
2680
2682
  ownerUuids: plain.owner_uuids,
2681
2683
  port: plain.port,
2682
2684
  uuid: plain.uuid,
2683
- number: plain.number,
2685
+ extension: plain.exten,
2684
2686
  persistent: plain.persistent,
2687
+ creationTime: moment(plain.creation_time).toDate(),
2685
2688
  });
2686
2689
  }
2687
2690
 
@@ -2703,8 +2706,9 @@ class Meeting {
2703
2706
  ownerUuids,
2704
2707
  port,
2705
2708
  uri,
2706
- number,
2709
+ extension,
2707
2710
  persistent,
2711
+ creationTime,
2708
2712
  } = {}) {
2709
2713
  this.guestSipAuthorization = guestSipAuthorization;
2710
2714
  this.uri = uri;
@@ -2712,8 +2716,9 @@ class Meeting {
2712
2716
  this.ownerUuids = ownerUuids;
2713
2717
  this.port = port;
2714
2718
  this.uuid = uuid;
2715
- this.number = number;
2719
+ this.extension = extension;
2716
2720
  this.persistent = persistent;
2721
+ this.creationTime = creationTime;
2717
2722
 
2718
2723
  // Useful to compare instead of instanceof with minified code
2719
2724
  this.type = 'Meeting';
@@ -6057,11 +6062,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
6057
6062
 
6058
6063
  // $FlowFixMe
6059
6064
  setRemoteSessionDescription(sessionDescription ) {
6060
- const result = super.setRemoteSessionDescription(sessionDescription);
6065
+ try {
6066
+ const result = super.setRemoteSessionDescription(sessionDescription);
6061
6067
 
6062
- this.eventEmitter.emit('setDescription', sessionDescription);
6068
+ this.eventEmitter.emit('setDescription', sessionDescription);
6063
6069
 
6064
- return result;
6070
+ return result;
6071
+ } catch (error) {
6072
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
6073
+ throw error;
6074
+ }
6065
6075
  }
6066
6076
 
6067
6077
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -6966,7 +6976,7 @@ class WebRTCClient extends Emitter {
6966
6976
  }
6967
6977
 
6968
6978
  call(number , enableVideo , audioOnly = false, conference = false) {
6969
- logger$8.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6979
+ logger$8.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
6970
6980
  const inviterOptions = {
6971
6981
  sessionDescriptionHandlerOptionsReInvite: {
6972
6982
  conference,
@@ -8042,6 +8052,7 @@ class WebRTCClient extends Emitter {
8042
8052
  const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
8043
8053
  const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
8044
8054
  const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
8055
+ const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
8045
8056
 
8046
8057
  logger$8.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
8047
8058
 
@@ -8049,7 +8060,8 @@ class WebRTCClient extends Emitter {
8049
8060
  constraints: {
8050
8061
  // Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
8051
8062
  audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
8052
- video: screenSharing ? (isDesktop ? ({ mandatory: { chromeMediaSource: 'desktop' } }) : { cursor: 'always' })
8063
+ video: screenSharing ? (isDesktop
8064
+ ? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
8053
8065
  : this._getVideoConstraints(enableVideo),
8054
8066
  screen: screenSharing,
8055
8067
  desktop: isDesktop,
@@ -8384,12 +8396,14 @@ class WebRTCClient extends Emitter {
8384
8396
 
8385
8397
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
8386
8398
 
8387
- pc.oniceconnectionstatechange = () => {
8388
- logger$8.info('on ice connection state changed', { state: pc.iceConnectionState });
8389
- if (pc.iceConnectionState === 'disconnected') {
8390
- this.eventEmitter.emit(ON_DISCONNECTED$1);
8391
- }
8392
- };
8399
+ if (pc) {
8400
+ pc.oniceconnectionstatechange = () => {
8401
+ logger$8.info('on ice connection state changed', { state: pc.iceConnectionState });
8402
+ if (pc.iceConnectionState === 'disconnected') {
8403
+ this.eventEmitter.emit(ON_DISCONNECTED$1);
8404
+ }
8405
+ };
8406
+ }
8393
8407
 
8394
8408
  if (withEvent) {
8395
8409
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
@@ -8599,13 +8613,17 @@ class WebRTCClient extends Emitter {
8599
8613
  const nbStats = this.sessionNetworkStats[sessionId].length;
8600
8614
  const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
8601
8615
  const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
8616
+ const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
8602
8617
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8603
8618
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8619
+ const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
8604
8620
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8605
8621
  const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8606
8622
  const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8607
- let audioBytesSent = 0;
8608
- let audioBytesReceived = 0;
8623
+ let audioBytesSent = 0; // content + header
8624
+ let audioBytesReceived = 0; // content + header
8625
+ let audioContentSent = 0; // useful to detect blank call
8626
+ let audioContentReceived = 0;
8609
8627
  let videoBytesSent = 0;
8610
8628
  let videoBytesReceived = 0;
8611
8629
  let transportSent = 0;
@@ -8615,6 +8633,7 @@ class WebRTCClient extends Emitter {
8615
8633
  stats.forEach(report => {
8616
8634
  if (report.type === 'outbound-rtp' && report.kind === 'audio') {
8617
8635
  audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
8636
+ audioContentSent += Number(report.bytesSent);
8618
8637
  }
8619
8638
  if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
8620
8639
  audioBytesSent += Number(report.bytesSent);
@@ -8626,6 +8645,7 @@ class WebRTCClient extends Emitter {
8626
8645
  packetsLost += Number(report.packetsLost);
8627
8646
  networkStats.packetsReceived = Number(report.packetsReceived);
8628
8647
  audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
8648
+ audioContentReceived += Number(report.bytesReceived);
8629
8649
  }
8630
8650
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
8631
8651
  videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
@@ -8654,10 +8674,17 @@ class WebRTCClient extends Emitter {
8654
8674
  });
8655
8675
 
8656
8676
  networkStats.packetsLost = packetsLost;
8677
+
8657
8678
  networkStats.totalAudioBytesSent = audioBytesSent;
8658
8679
  networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
8659
8680
  networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
8660
8681
  networkStats.audioBytesReceived = audioBytesReceived;
8682
+
8683
+ networkStats.totalAudioContentSent = audioContentSent;
8684
+ networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
8685
+ networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
8686
+ networkStats.audioContentReceived = audioContentReceived;
8687
+
8661
8688
  networkStats.totalVideoBytesSent = videoBytesSent;
8662
8689
  networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
8663
8690
  networkStats.totalVideoBytesReceived = videoBytesReceived;
@@ -8869,6 +8896,7 @@ class WebRTCPhone extends Emitter {
8869
8896
  constraints,
8870
8897
  audioOnly,
8871
8898
  conference,
8899
+ iceRestart,
8872
8900
  });
8873
8901
 
8874
8902
  if (!sipSession) {
@@ -8972,6 +9000,11 @@ class WebRTCPhone extends Emitter {
8972
9000
 
8973
9001
  this.client.downgradeToAudio(sipSession);
8974
9002
 
9003
+ if (callSession) {
9004
+ callSession.cameraEnabled = false;
9005
+ this._updateCallSession(callSession);
9006
+ }
9007
+
8975
9008
  if (withMessage) {
8976
9009
  this._sendReinviteMessage(callSession, false);
8977
9010
  }
@@ -8999,6 +9032,11 @@ class WebRTCPhone extends Emitter {
8999
9032
 
9000
9033
  const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
9001
9034
 
9035
+ if (callSession) {
9036
+ callSession.cameraEnabled = true;
9037
+ this._updateCallSession(callSession);
9038
+ }
9039
+
9002
9040
  // If no stream is returned, it means we have to reinvite
9003
9041
  if (!newStream) {
9004
9042
  return true;
@@ -9268,7 +9306,7 @@ class WebRTCPhone extends Emitter {
9268
9306
  }
9269
9307
 
9270
9308
  _onCallAccepted(sipSession , cameraEnabled ) {
9271
- logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9309
+ logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9272
9310
 
9273
9311
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
9274
9312
  this.currentSipSession = sipSession;
@@ -9337,6 +9375,7 @@ class WebRTCPhone extends Emitter {
9337
9375
  _onCallTerminated(sipSession ) {
9338
9376
  logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
9339
9377
 
9378
+ const sipSessionId = this.getSipSessionId(sipSession);
9340
9379
  const callSession = this._createCallSession(sipSession);
9341
9380
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
9342
9381
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -9354,7 +9393,6 @@ class WebRTCPhone extends Emitter {
9354
9393
  }, 5);
9355
9394
  }
9356
9395
 
9357
- const sipSessionId = this.getSipSessionId(sipSession);
9358
9396
  if (sipSessionId) {
9359
9397
  this.removeIncomingSessions(sipSessionId);
9360
9398
  }
@@ -9780,7 +9818,7 @@ class WebRTCPhone extends Emitter {
9780
9818
  // @TODO: line is not used here
9781
9819
  async makeCall(number , line , cameraEnabled ,
9782
9820
  audioOnly = false, conference = false) {
9783
- logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
9821
+ logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
9784
9822
  if (!number) {
9785
9823
  return Promise.resolve(null);
9786
9824
  }
@@ -9999,8 +10037,12 @@ class WebRTCPhone extends Emitter {
9999
10037
  }
10000
10038
 
10001
10039
  const sessionId = this.incomingSessions[0];
10040
+ const sipSession = this.client.getSipSession(sessionId);
10041
+ if (!sipSession) {
10042
+ return null;
10043
+ }
10002
10044
 
10003
- return this._createCallSession(this.client.getSipSession(sessionId));
10045
+ return this._createCallSession(sipSession);
10004
10046
  }
10005
10047
 
10006
10048
  sendMessage(sipSession = null, body , contentType = 'text/plain') {
@@ -10141,9 +10183,13 @@ class WebRTCPhone extends Emitter {
10141
10183
  if (this.shouldSendReinvite && this.currentSipSession
10142
10184
  && this.currentSipSession.state === SessionState.Established) {
10143
10185
  this.shouldSendReinvite = false;
10186
+ const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
10187
+ const isConference = pc ? pc.sfu : false;
10188
+ const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
10189
+
10144
10190
  try {
10145
10191
  // Send reinvite with iceRestart
10146
- this.sendReinvite(this.currentCallSession, null, false, false, true);
10192
+ this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
10147
10193
  } catch (e) {
10148
10194
  logger$7.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
10149
10195
  }
@@ -10227,6 +10273,15 @@ class WebRTCPhone extends Emitter {
10227
10273
  return this.client.getSipSessionId(sipSession);
10228
10274
  }
10229
10275
 
10276
+ _updateCallSession(callSession ) {
10277
+ const sipSession = this.findSipSession(callSession);
10278
+ const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
10279
+
10280
+ if (sipSessionId) {
10281
+ this.callSessions[sipSessionId] = callSession;
10282
+ }
10283
+ }
10284
+
10230
10285
  _onMessage(message ) {
10231
10286
  if (!message || message.method !== 'MESSAGE') {
10232
10287
  return;