@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
@@ -450,7 +450,7 @@ const logger$1 = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
450
450
 
451
451
  // Use a function here to be able to mock it in tests
452
452
  const realFetch = () => {
453
- if (typeof document !== 'undefined') {
453
+ if (typeof document !== 'undefined' && window.fetch) {
454
454
  // Browser
455
455
  return window.fetch;
456
456
  }
@@ -1910,7 +1910,7 @@ class Contact {
1910
1910
  this[key] = old[key] || this[key];
1911
1911
  });
1912
1912
 
1913
- if (old.lineState && !this.lineState) {
1913
+ if (old.lineState) {
1914
1914
  this.lineState = old.lineState;
1915
1915
  }
1916
1916
 
@@ -2617,8 +2617,9 @@ class ExternalApp {
2617
2617
 
2618
2618
 
2619
2619
 
2620
-
2620
+
2621
2621
 
2622
+
2622
2623
 
2623
2624
 
2624
2625
  class Meeting {
@@ -2629,9 +2630,10 @@ class Meeting {
2629
2630
 
2630
2631
 
2631
2632
 
2632
-
2633
+
2633
2634
 
2634
2635
 
2636
+
2635
2637
 
2636
2638
  static parse(plain ) {
2637
2639
  return new Meeting({
@@ -2641,8 +2643,9 @@ class Meeting {
2641
2643
  ownerUuids: plain.owner_uuids,
2642
2644
  port: plain.port,
2643
2645
  uuid: plain.uuid,
2644
- number: plain.number,
2646
+ extension: plain.exten,
2645
2647
  persistent: plain.persistent,
2648
+ creationTime: moment__default['default'](plain.creation_time).toDate(),
2646
2649
  });
2647
2650
  }
2648
2651
 
@@ -2664,8 +2667,9 @@ class Meeting {
2664
2667
  ownerUuids,
2665
2668
  port,
2666
2669
  uri,
2667
- number,
2670
+ extension,
2668
2671
  persistent,
2672
+ creationTime,
2669
2673
  } = {}) {
2670
2674
  this.guestSipAuthorization = guestSipAuthorization;
2671
2675
  this.uri = uri;
@@ -2673,8 +2677,9 @@ class Meeting {
2673
2677
  this.ownerUuids = ownerUuids;
2674
2678
  this.port = port;
2675
2679
  this.uuid = uuid;
2676
- this.number = number;
2680
+ this.extension = extension;
2677
2681
  this.persistent = persistent;
2682
+ this.creationTime = creationTime;
2678
2683
 
2679
2684
  // Useful to compare instead of instanceof with minified code
2680
2685
  this.type = 'Meeting';
@@ -1038,7 +1038,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
1038
1038
 
1039
1039
  // Use a function here to be able to mock it in tests
1040
1040
  const realFetch = () => {
1041
- if (typeof document !== 'undefined') {
1041
+ if (typeof document !== 'undefined' && window.fetch) {
1042
1042
  // Browser
1043
1043
  return window.fetch;
1044
1044
  }
@@ -2487,7 +2487,7 @@ class Contact {
2487
2487
  this[key] = old[key] || this[key];
2488
2488
  });
2489
2489
 
2490
- if (old.lineState && !this.lineState) {
2490
+ if (old.lineState) {
2491
2491
  this.lineState = old.lineState;
2492
2492
  }
2493
2493
 
@@ -3194,8 +3194,9 @@ class ExternalApp {
3194
3194
 
3195
3195
 
3196
3196
 
3197
-
3197
+
3198
3198
 
3199
+
3199
3200
 
3200
3201
 
3201
3202
  class Meeting {
@@ -3206,9 +3207,10 @@ class Meeting {
3206
3207
 
3207
3208
 
3208
3209
 
3209
-
3210
+
3210
3211
 
3211
3212
 
3213
+
3212
3214
 
3213
3215
  static parse(plain ) {
3214
3216
  return new Meeting({
@@ -3218,8 +3220,9 @@ class Meeting {
3218
3220
  ownerUuids: plain.owner_uuids,
3219
3221
  port: plain.port,
3220
3222
  uuid: plain.uuid,
3221
- number: plain.number,
3223
+ extension: plain.exten,
3222
3224
  persistent: plain.persistent,
3225
+ creationTime: moment__default['default'](plain.creation_time).toDate(),
3223
3226
  });
3224
3227
  }
3225
3228
 
@@ -3241,8 +3244,9 @@ class Meeting {
3241
3244
  ownerUuids,
3242
3245
  port,
3243
3246
  uri,
3244
- number,
3247
+ extension,
3245
3248
  persistent,
3249
+ creationTime,
3246
3250
  } = {}) {
3247
3251
  this.guestSipAuthorization = guestSipAuthorization;
3248
3252
  this.uri = uri;
@@ -3250,8 +3254,9 @@ class Meeting {
3250
3254
  this.ownerUuids = ownerUuids;
3251
3255
  this.port = port;
3252
3256
  this.uuid = uuid;
3253
- this.number = number;
3257
+ this.extension = extension;
3254
3258
  this.persistent = persistent;
3259
+ this.creationTime = creationTime;
3255
3260
 
3256
3261
  // Useful to compare instead of instanceof with minified code
3257
3262
  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;
@@ -47,7 +47,7 @@ IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
47
47
 
48
48
  // Use a function here to be able to mock it in tests
49
49
  const realFetch = () => {
50
- if (typeof document !== 'undefined') {
50
+ if (typeof document !== 'undefined' && window.fetch) {
51
51
  // Browser
52
52
  return window.fetch;
53
53
  }
@@ -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';
@@ -6067,11 +6072,16 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
6067
6072
 
6068
6073
  // $FlowFixMe
6069
6074
  setRemoteSessionDescription(sessionDescription ) {
6070
- const result = super.setRemoteSessionDescription(sessionDescription);
6075
+ try {
6076
+ const result = super.setRemoteSessionDescription(sessionDescription);
6071
6077
 
6072
- this.eventEmitter.emit('setDescription', sessionDescription);
6078
+ this.eventEmitter.emit('setDescription', sessionDescription);
6073
6079
 
6074
- return result;
6080
+ return result;
6081
+ } catch (error) {
6082
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
6083
+ throw error;
6084
+ }
6075
6085
  }
6076
6086
 
6077
6087
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -6976,7 +6986,7 @@ class WebRTCClient extends Emitter {
6976
6986
  }
6977
6987
 
6978
6988
  call(number , enableVideo , audioOnly = false, conference = false) {
6979
- logger$8.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6989
+ logger$8.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
6980
6990
  const inviterOptions = {
6981
6991
  sessionDescriptionHandlerOptionsReInvite: {
6982
6992
  conference,
@@ -8052,6 +8062,7 @@ class WebRTCClient extends Emitter {
8052
8062
  const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
8053
8063
  const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
8054
8064
  const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
8065
+ const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
8055
8066
 
8056
8067
  logger$8.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
8057
8068
 
@@ -8059,7 +8070,8 @@ class WebRTCClient extends Emitter {
8059
8070
  constraints: {
8060
8071
  // Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
8061
8072
  audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
8062
- video: screenSharing ? (isDesktop ? ({ mandatory: { chromeMediaSource: 'desktop' } }) : { cursor: 'always' })
8073
+ video: screenSharing ? (isDesktop
8074
+ ? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
8063
8075
  : this._getVideoConstraints(enableVideo),
8064
8076
  screen: screenSharing,
8065
8077
  desktop: isDesktop,
@@ -8394,12 +8406,14 @@ class WebRTCClient extends Emitter {
8394
8406
 
8395
8407
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
8396
8408
 
8397
- pc.oniceconnectionstatechange = () => {
8398
- logger$8.info('on ice connection state changed', { state: pc.iceConnectionState });
8399
- if (pc.iceConnectionState === 'disconnected') {
8400
- this.eventEmitter.emit(ON_DISCONNECTED$1);
8401
- }
8402
- };
8409
+ if (pc) {
8410
+ pc.oniceconnectionstatechange = () => {
8411
+ logger$8.info('on ice connection state changed', { state: pc.iceConnectionState });
8412
+ if (pc.iceConnectionState === 'disconnected') {
8413
+ this.eventEmitter.emit(ON_DISCONNECTED$1);
8414
+ }
8415
+ };
8416
+ }
8403
8417
 
8404
8418
  if (withEvent) {
8405
8419
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
@@ -8609,13 +8623,17 @@ class WebRTCClient extends Emitter {
8609
8623
  const nbStats = this.sessionNetworkStats[sessionId].length;
8610
8624
  const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
8611
8625
  const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
8626
+ const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
8612
8627
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8613
8628
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8629
+ const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
8614
8630
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8615
8631
  const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8616
8632
  const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8617
- let audioBytesSent = 0;
8618
- let audioBytesReceived = 0;
8633
+ let audioBytesSent = 0; // content + header
8634
+ let audioBytesReceived = 0; // content + header
8635
+ let audioContentSent = 0; // useful to detect blank call
8636
+ let audioContentReceived = 0;
8619
8637
  let videoBytesSent = 0;
8620
8638
  let videoBytesReceived = 0;
8621
8639
  let transportSent = 0;
@@ -8625,6 +8643,7 @@ class WebRTCClient extends Emitter {
8625
8643
  stats.forEach(report => {
8626
8644
  if (report.type === 'outbound-rtp' && report.kind === 'audio') {
8627
8645
  audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
8646
+ audioContentSent += Number(report.bytesSent);
8628
8647
  }
8629
8648
  if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
8630
8649
  audioBytesSent += Number(report.bytesSent);
@@ -8636,6 +8655,7 @@ class WebRTCClient extends Emitter {
8636
8655
  packetsLost += Number(report.packetsLost);
8637
8656
  networkStats.packetsReceived = Number(report.packetsReceived);
8638
8657
  audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
8658
+ audioContentReceived += Number(report.bytesReceived);
8639
8659
  }
8640
8660
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
8641
8661
  videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
@@ -8664,10 +8684,17 @@ class WebRTCClient extends Emitter {
8664
8684
  });
8665
8685
 
8666
8686
  networkStats.packetsLost = packetsLost;
8687
+
8667
8688
  networkStats.totalAudioBytesSent = audioBytesSent;
8668
8689
  networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
8669
8690
  networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
8670
8691
  networkStats.audioBytesReceived = audioBytesReceived;
8692
+
8693
+ networkStats.totalAudioContentSent = audioContentSent;
8694
+ networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
8695
+ networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
8696
+ networkStats.audioContentReceived = audioContentReceived;
8697
+
8671
8698
  networkStats.totalVideoBytesSent = videoBytesSent;
8672
8699
  networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
8673
8700
  networkStats.totalVideoBytesReceived = videoBytesReceived;
@@ -8879,6 +8906,7 @@ class WebRTCPhone extends Emitter {
8879
8906
  constraints,
8880
8907
  audioOnly,
8881
8908
  conference,
8909
+ iceRestart,
8882
8910
  });
8883
8911
 
8884
8912
  if (!sipSession) {
@@ -8982,6 +9010,11 @@ class WebRTCPhone extends Emitter {
8982
9010
 
8983
9011
  this.client.downgradeToAudio(sipSession);
8984
9012
 
9013
+ if (callSession) {
9014
+ callSession.cameraEnabled = false;
9015
+ this._updateCallSession(callSession);
9016
+ }
9017
+
8985
9018
  if (withMessage) {
8986
9019
  this._sendReinviteMessage(callSession, false);
8987
9020
  }
@@ -9009,6 +9042,11 @@ class WebRTCPhone extends Emitter {
9009
9042
 
9010
9043
  const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
9011
9044
 
9045
+ if (callSession) {
9046
+ callSession.cameraEnabled = true;
9047
+ this._updateCallSession(callSession);
9048
+ }
9049
+
9012
9050
  // If no stream is returned, it means we have to reinvite
9013
9051
  if (!newStream) {
9014
9052
  return true;
@@ -9278,7 +9316,7 @@ class WebRTCPhone extends Emitter {
9278
9316
  }
9279
9317
 
9280
9318
  _onCallAccepted(sipSession , cameraEnabled ) {
9281
- logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9319
+ logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9282
9320
 
9283
9321
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
9284
9322
  this.currentSipSession = sipSession;
@@ -9347,6 +9385,7 @@ class WebRTCPhone extends Emitter {
9347
9385
  _onCallTerminated(sipSession ) {
9348
9386
  logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
9349
9387
 
9388
+ const sipSessionId = this.getSipSessionId(sipSession);
9350
9389
  const callSession = this._createCallSession(sipSession);
9351
9390
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
9352
9391
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -9364,7 +9403,6 @@ class WebRTCPhone extends Emitter {
9364
9403
  }, 5);
9365
9404
  }
9366
9405
 
9367
- const sipSessionId = this.getSipSessionId(sipSession);
9368
9406
  if (sipSessionId) {
9369
9407
  this.removeIncomingSessions(sipSessionId);
9370
9408
  }
@@ -9790,7 +9828,7 @@ class WebRTCPhone extends Emitter {
9790
9828
  // @TODO: line is not used here
9791
9829
  async makeCall(number , line , cameraEnabled ,
9792
9830
  audioOnly = false, conference = false) {
9793
- logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
9831
+ logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
9794
9832
  if (!number) {
9795
9833
  return Promise.resolve(null);
9796
9834
  }
@@ -10009,8 +10047,12 @@ class WebRTCPhone extends Emitter {
10009
10047
  }
10010
10048
 
10011
10049
  const sessionId = this.incomingSessions[0];
10050
+ const sipSession = this.client.getSipSession(sessionId);
10051
+ if (!sipSession) {
10052
+ return null;
10053
+ }
10012
10054
 
10013
- return this._createCallSession(this.client.getSipSession(sessionId));
10055
+ return this._createCallSession(sipSession);
10014
10056
  }
10015
10057
 
10016
10058
  sendMessage(sipSession = null, body , contentType = 'text/plain') {
@@ -10151,9 +10193,13 @@ class WebRTCPhone extends Emitter {
10151
10193
  if (this.shouldSendReinvite && this.currentSipSession
10152
10194
  && this.currentSipSession.state === sessionState.SessionState.Established) {
10153
10195
  this.shouldSendReinvite = false;
10196
+ const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
10197
+ const isConference = pc ? pc.sfu : false;
10198
+ const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
10199
+
10154
10200
  try {
10155
10201
  // Send reinvite with iceRestart
10156
- this.sendReinvite(this.currentCallSession, null, false, false, true);
10202
+ this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
10157
10203
  } catch (e) {
10158
10204
  logger$7.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
10159
10205
  }
@@ -10237,6 +10283,15 @@ class WebRTCPhone extends Emitter {
10237
10283
  return this.client.getSipSessionId(sipSession);
10238
10284
  }
10239
10285
 
10286
+ _updateCallSession(callSession ) {
10287
+ const sipSession = this.findSipSession(callSession);
10288
+ const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
10289
+
10290
+ if (sipSessionId) {
10291
+ this.callSessions[sipSessionId] = callSession;
10292
+ }
10293
+ }
10294
+
10240
10295
  _onMessage(message ) {
10241
10296
  if (!message || message.method !== 'MESSAGE') {
10242
10297
  return;