@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';
@@ -1028,7 +1028,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
1028
1028
 
1029
1029
  // Use a function here to be able to mock it in tests
1030
1030
  const realFetch = () => {
1031
- if (typeof document !== 'undefined') {
1031
+ if (typeof document !== 'undefined' && window.fetch) {
1032
1032
  // Browser
1033
1033
  return window.fetch;
1034
1034
  }
@@ -2477,7 +2477,7 @@ class Contact {
2477
2477
  this[key] = old[key] || this[key];
2478
2478
  });
2479
2479
 
2480
- if (old.lineState && !this.lineState) {
2480
+ if (old.lineState) {
2481
2481
  this.lineState = old.lineState;
2482
2482
  }
2483
2483
 
@@ -3184,8 +3184,9 @@ class ExternalApp {
3184
3184
 
3185
3185
 
3186
3186
 
3187
-
3187
+
3188
3188
 
3189
+
3189
3190
 
3190
3191
 
3191
3192
  class Meeting {
@@ -3196,9 +3197,10 @@ class Meeting {
3196
3197
 
3197
3198
 
3198
3199
 
3199
-
3200
+
3200
3201
 
3201
3202
 
3203
+
3202
3204
 
3203
3205
  static parse(plain ) {
3204
3206
  return new Meeting({
@@ -3208,8 +3210,9 @@ class Meeting {
3208
3210
  ownerUuids: plain.owner_uuids,
3209
3211
  port: plain.port,
3210
3212
  uuid: plain.uuid,
3211
- number: plain.number,
3213
+ extension: plain.exten,
3212
3214
  persistent: plain.persistent,
3215
+ creationTime: moment(plain.creation_time).toDate(),
3213
3216
  });
3214
3217
  }
3215
3218
 
@@ -3231,8 +3234,9 @@ class Meeting {
3231
3234
  ownerUuids,
3232
3235
  port,
3233
3236
  uri,
3234
- number,
3237
+ extension,
3235
3238
  persistent,
3239
+ creationTime,
3236
3240
  } = {}) {
3237
3241
  this.guestSipAuthorization = guestSipAuthorization;
3238
3242
  this.uri = uri;
@@ -3240,8 +3244,9 @@ class Meeting {
3240
3244
  this.ownerUuids = ownerUuids;
3241
3245
  this.port = port;
3242
3246
  this.uuid = uuid;
3243
- this.number = number;
3247
+ this.extension = extension;
3244
3248
  this.persistent = persistent;
3249
+ this.creationTime = creationTime;
3245
3250
 
3246
3251
  // Useful to compare instead of instanceof with minified code
3247
3252
  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;
@@ -39,7 +39,7 @@ IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
39
39
 
40
40
  // Use a function here to be able to mock it in tests
41
41
  const realFetch = () => {
42
- if (typeof document !== 'undefined') {
42
+ if (typeof document !== 'undefined' && window.fetch) {
43
43
  // Browser
44
44
  return window.fetch;
45
45
  }
@@ -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';
@@ -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;