@wazo/sdk 0.37.21 → 0.37.25

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/dist/wazo-sdk.js +5 -5
  2. package/esm/__tests__/api-client.test.js +36 -5
  3. package/esm/__tests__/web-rtc-client.test.js +77 -66
  4. package/esm/api/call-logd.js +7 -0
  5. package/esm/api/calld.js +10 -0
  6. package/esm/api/chatd.js +7 -0
  7. package/esm/api/confd.js +13 -5
  8. package/esm/api/ctid-ng.js +10 -0
  9. package/esm/api/dird.js +3 -0
  10. package/esm/api-client.js +36 -5
  11. package/esm/checker/Checker.js +77 -66
  12. package/esm/checker/checks/aor.js +36 -5
  13. package/esm/checker/checks/api.js +36 -5
  14. package/esm/checker/checks/index.js +77 -66
  15. package/esm/checker/checks/webrtc-transport.js +77 -66
  16. package/esm/checker/checks/webrtc.js +77 -66
  17. package/esm/domain/AdHocAPIConference.js +36 -5
  18. package/esm/domain/Call.js +3 -0
  19. package/esm/domain/CallLog.js +7 -0
  20. package/esm/domain/ChatMessage.js +4 -0
  21. package/esm/domain/ChatRoom.js +3 -0
  22. package/esm/domain/Contact.js +3 -0
  23. package/esm/domain/Features.js +36 -5
  24. package/esm/domain/Meeting.js +15 -5
  25. package/esm/domain/Phone/CTIPhone.js +40 -5
  26. package/esm/domain/Phone/WebRTCPhone.js +45 -16
  27. package/esm/domain/Recording.js +3 -0
  28. package/esm/domain/Voicemail.js +3 -0
  29. package/esm/domain/__tests__/Call.test.js +3 -0
  30. package/esm/domain/__tests__/CallLog.test.js +7 -0
  31. package/esm/domain/__tests__/Contact.test.js +3 -0
  32. package/esm/domain/__tests__/Meeting.test.js +144 -0
  33. package/esm/domain/__tests__/Voicemail.test.js +3 -0
  34. package/esm/index.js +125 -81
  35. package/esm/lib/WazoSessionDescriptionHandler.js +0 -38
  36. package/esm/service/CallApi.js +36 -5
  37. package/esm/service/getApiClient.js +36 -5
  38. package/esm/simple/Auth.js +125 -81
  39. package/esm/simple/Configuration.js +125 -81
  40. package/esm/simple/Directory.js +36 -5
  41. package/esm/simple/Phone.js +125 -81
  42. package/esm/simple/index.js +125 -81
  43. package/esm/simple/room/LocalParticipant.js +125 -81
  44. package/esm/simple/room/Participant.js +125 -81
  45. package/esm/simple/room/RemoteParticipant.js +125 -81
  46. package/esm/simple/room/Room.js +125 -81
  47. package/esm/simple/room/SipRoom.js +125 -81
  48. package/esm/simple/room/Stream.js +125 -81
  49. package/esm/simple/room/__tests__/RemoteParticipant.test.js +125 -81
  50. package/esm/simple/utils.js +125 -81
  51. package/esm/types/WebSocketMessage.js +1 -1
  52. package/esm/web-rtc-client.js +77 -66
  53. package/lib/__tests__/api-client.test.js +36 -5
  54. package/lib/__tests__/web-rtc-client.test.js +77 -66
  55. package/lib/api/call-logd.js +7 -0
  56. package/lib/api/calld.js +10 -0
  57. package/lib/api/chatd.js +7 -0
  58. package/lib/api/confd.js +13 -5
  59. package/lib/api/ctid-ng.js +10 -0
  60. package/lib/api/dird.js +3 -0
  61. package/lib/api-client.js +36 -5
  62. package/lib/checker/Checker.js +77 -66
  63. package/lib/checker/checks/aor.js +36 -5
  64. package/lib/checker/checks/api.js +36 -5
  65. package/lib/checker/checks/index.js +77 -66
  66. package/lib/checker/checks/webrtc-transport.js +77 -66
  67. package/lib/checker/checks/webrtc.js +77 -66
  68. package/lib/domain/AdHocAPIConference.js +36 -5
  69. package/lib/domain/Call.js +3 -0
  70. package/lib/domain/CallLog.js +7 -0
  71. package/lib/domain/ChatMessage.js +4 -0
  72. package/lib/domain/ChatRoom.js +3 -0
  73. package/lib/domain/Contact.js +3 -0
  74. package/lib/domain/Features.js +36 -5
  75. package/lib/domain/Meeting.js +19 -5
  76. package/lib/domain/Phone/CTIPhone.js +40 -5
  77. package/lib/domain/Phone/WebRTCPhone.js +45 -16
  78. package/lib/domain/Recording.js +3 -0
  79. package/lib/domain/Voicemail.js +3 -0
  80. package/lib/domain/__tests__/Call.test.js +3 -0
  81. package/lib/domain/__tests__/CallLog.test.js +7 -0
  82. package/lib/domain/__tests__/Contact.test.js +3 -0
  83. package/lib/domain/__tests__/Meeting.test.js +150 -0
  84. package/lib/domain/__tests__/Voicemail.test.js +3 -0
  85. package/lib/index.js +125 -81
  86. package/lib/lib/WazoSessionDescriptionHandler.js +0 -38
  87. package/lib/service/CallApi.js +36 -5
  88. package/lib/service/getApiClient.js +36 -5
  89. package/lib/simple/Auth.js +125 -81
  90. package/lib/simple/Configuration.js +125 -81
  91. package/lib/simple/Directory.js +36 -5
  92. package/lib/simple/Phone.js +125 -81
  93. package/lib/simple/index.js +125 -81
  94. package/lib/simple/room/LocalParticipant.js +125 -81
  95. package/lib/simple/room/Participant.js +125 -81
  96. package/lib/simple/room/RemoteParticipant.js +125 -81
  97. package/lib/simple/room/Room.js +125 -81
  98. package/lib/simple/room/SipRoom.js +125 -81
  99. package/lib/simple/room/Stream.js +125 -81
  100. package/lib/simple/room/__tests__/RemoteParticipant.test.js +125 -81
  101. package/lib/simple/utils.js +125 -81
  102. package/lib/types/WebSocketMessage.js +2 -0
  103. package/lib/web-rtc-client.js +77 -66
  104. package/package.json +1 -1
  105. package/src/domain/Call.js +3 -0
  106. package/src/domain/CallLog.js +4 -0
  107. package/src/domain/ChatMessage.js +4 -0
  108. package/src/domain/ChatRoom.js +3 -0
  109. package/src/domain/Contact.js +3 -0
  110. package/src/domain/Meeting.js +15 -5
  111. package/src/domain/Phone/CTIPhone.js +4 -0
  112. package/src/domain/Phone/Phone.js +2 -0
  113. package/src/domain/Phone/WebRTCPhone.js +45 -16
  114. package/src/domain/Recording.js +3 -0
  115. package/src/domain/Voicemail.js +3 -0
  116. package/src/domain/__tests__/Meeting.test.js +50 -0
  117. package/src/lib/WazoSessionDescriptionHandler.js +1 -35
  118. package/src/web-rtc-client.js +41 -23
@@ -724,10 +724,6 @@ const getSrflxOrRelay = (candidates ) =>
724
724
  candidates
725
725
  .filter(candidate => candidate && (candidate.type === 'srflx' || candidate.type === 'relay'));
726
726
 
727
- const areCandidateValid = (candidates ) =>
728
- getSrflxOrRelay(candidates)
729
- .length > 0;
730
-
731
727
  const getVideoDirection = (sdp ) => {
732
728
  const parsedSdp = sdpParser.parse(sdp);
733
729
  const videoMedia = parsedSdp.media.find(media => media.type === 'video');
@@ -780,8 +776,6 @@ const fixSdp = (sdp , candidates , forcePort = true)
780
776
  /* global RTCSessionDescriptionInit, navigator */
781
777
 
782
778
  const wazoLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-sdh') : console;
783
- const MAX_WAIT_FOR_ICE_TRIES = 20;
784
- const WAIT_FOR_ICE_TIMEOUT = 500;
785
779
 
786
780
  // Customized mediaStreamFactory allowing to send screensharing stream directory when upgrading
787
781
  const wazoMediaStreamFactory = (constraints ) => {
@@ -971,38 +965,6 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
971
965
  this._peerConnection = undefined;
972
966
  }
973
967
 
974
- async _waitForValidGatheredIce() {
975
- let tries = 0;
976
-
977
- while (!areCandidateValid(this.gatheredCandidates) && tries < MAX_WAIT_FOR_ICE_TRIES) {
978
- wazoLogger.trace('SessionDescriptionHandler._waitForValidGatheredIce, waiting for ice', {
979
- tries,
980
- max: MAX_WAIT_FOR_ICE_TRIES,
981
- });
982
-
983
- tries++;
984
-
985
- // eslint-disable-next-line no-await-in-loop
986
- await new Promise(resolve => setTimeout(resolve, WAIT_FOR_ICE_TIMEOUT));
987
- }
988
-
989
- if (tries >= MAX_WAIT_FOR_ICE_TRIES) {
990
- const errorMsg = 'No valid candidates found, can\'t answer the call';
991
- const error = new Error(errorMsg);
992
- wazoLogger.error(errorMsg, { tries, max: MAX_WAIT_FOR_ICE_TRIES });
993
-
994
- // Emit an error, because sip.js catches the exception and switch to status Terminated.
995
- this.eventEmitter.emit('error', error);
996
-
997
- wazoLogger.error('No valid candidates found', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
998
- }
999
-
1000
- // eslint-disable-next-line
1001
- wazoLogger.trace('Found valid candidates', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
1002
-
1003
- return this.getLocalSessionDescription();
1004
- }
1005
-
1006
968
  // Overridden to send `inactive` in conference
1007
969
  updateDirection(options , isConference = false,
1008
970
  audioOnly = false) {
@@ -2112,6 +2074,9 @@ class Contact {
2112
2074
  }
2113
2075
 
2114
2076
  static parseMany(response ) {
2077
+ if (!response || !response.results) {
2078
+ return [];
2079
+ }
2115
2080
  return response.results.map(r => Contact.parse(r, response.column_types));
2116
2081
  }
2117
2082
 
@@ -3189,8 +3154,9 @@ class ExternalApp {
3189
3154
 
3190
3155
 
3191
3156
 
3192
-
3157
+
3193
3158
 
3159
+
3194
3160
 
3195
3161
 
3196
3162
  class Meeting {
@@ -3201,9 +3167,10 @@ class Meeting {
3201
3167
 
3202
3168
 
3203
3169
 
3204
-
3170
+
3205
3171
 
3206
3172
 
3173
+
3207
3174
 
3208
3175
  static parse(plain ) {
3209
3176
  return new Meeting({
@@ -3213,12 +3180,16 @@ class Meeting {
3213
3180
  ownerUuids: plain.owner_uuids,
3214
3181
  port: plain.port,
3215
3182
  uuid: plain.uuid,
3216
- number: plain.number,
3183
+ extension: plain.exten,
3217
3184
  persistent: plain.persistent,
3185
+ creationTime: moment(plain.creation_time).toDate(),
3218
3186
  });
3219
3187
  }
3220
3188
 
3221
3189
  static parseMany(items ) {
3190
+ if (!items) {
3191
+ return [];
3192
+ }
3222
3193
  return items.map(plain => Meeting.parse(plain));
3223
3194
  }
3224
3195
 
@@ -3233,8 +3204,9 @@ class Meeting {
3233
3204
  ownerUuids,
3234
3205
  port,
3235
3206
  uri,
3236
- number,
3207
+ extension,
3237
3208
  persistent,
3209
+ creationTime,
3238
3210
  } = {}) {
3239
3211
  this.guestSipAuthorization = guestSipAuthorization;
3240
3212
  this.uri = uri;
@@ -3242,8 +3214,9 @@ class Meeting {
3242
3214
  this.ownerUuids = ownerUuids;
3243
3215
  this.port = port;
3244
3216
  this.uuid = uuid;
3245
- this.number = number;
3217
+ this.extension = extension;
3246
3218
  this.persistent = persistent;
3219
+ this.creationTime = creationTime;
3247
3220
 
3248
3221
  // Useful to compare instead of instanceof with minified code
3249
3222
  this.type = 'Meeting';
@@ -3421,6 +3394,10 @@ class ChatMessage {
3421
3394
 
3422
3395
 
3423
3396
  static parseMany(plain ) {
3397
+ if (!plain || !plain.items) {
3398
+ return [];
3399
+ }
3400
+
3424
3401
  return plain.items.map(item => ChatMessage.parse(item));
3425
3402
  }
3426
3403
 
@@ -3530,6 +3507,9 @@ class Voicemail {
3530
3507
  }
3531
3508
 
3532
3509
  static parseMany(plain ) {
3510
+ if (!plain) {
3511
+ return [];
3512
+ }
3533
3513
  const plainUnread = plain.folders.filter(folder => folder.type === 'new')[0].messages;
3534
3514
  const plainRead = plain.folders.filter(folder => folder.type === 'old')[0].messages;
3535
3515
 
@@ -3639,6 +3619,9 @@ class Call {
3639
3619
 
3640
3620
 
3641
3621
  static parseMany(plain ) {
3622
+ if (!plain) {
3623
+ return [];
3624
+ }
3642
3625
  return plain.map((plainCall ) => Call.parse(plainCall));
3643
3626
  }
3644
3627
 
@@ -3811,6 +3794,9 @@ class Recording {
3811
3794
 
3812
3795
 
3813
3796
  static parseMany(recordings = []) {
3797
+ if (!recordings) {
3798
+ return [];
3799
+ }
3814
3800
  return recordings.map(item => Recording.parse(item));
3815
3801
  }
3816
3802
 
@@ -3912,6 +3898,10 @@ class CallLog {
3912
3898
  }
3913
3899
 
3914
3900
  static parseMany(plain ) {
3901
+ if (!plain || !plain.items) {
3902
+ return [];
3903
+ }
3904
+
3915
3905
  return plain.items.map(item => CallLog.parse(item));
3916
3906
  }
3917
3907
 
@@ -4484,6 +4474,9 @@ class ChatRoom {
4484
4474
 
4485
4475
 
4486
4476
  static parseMany(plain ) {
4477
+ if (!plain || !plain.items) {
4478
+ return [];
4479
+ }
4487
4480
  return plain.items.map(item => ChatRoom.parse(item));
4488
4481
  }
4489
4482
 
@@ -5712,7 +5705,7 @@ class WebRTCClient extends Emitter {
5712
5705
  }
5713
5706
 
5714
5707
  call(number , enableVideo , audioOnly = false, conference = false) {
5715
- logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
5708
+ logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
5716
5709
  const inviterOptions = {
5717
5710
  sessionDescriptionHandlerOptionsReInvite: {
5718
5711
  conference,
@@ -6788,6 +6781,7 @@ class WebRTCClient extends Emitter {
6788
6781
  const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
6789
6782
  const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
6790
6783
  const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
6784
+ const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
6791
6785
 
6792
6786
  logger.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
6793
6787
 
@@ -6795,7 +6789,8 @@ class WebRTCClient extends Emitter {
6795
6789
  constraints: {
6796
6790
  // Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
6797
6791
  audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
6798
- video: screenSharing ? (isDesktop ? ({ mandatory: { chromeMediaSource: 'desktop' } }) : { cursor: 'always' })
6792
+ video: screenSharing ? (isDesktop
6793
+ ? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
6799
6794
  : this._getVideoConstraints(enableVideo),
6800
6795
  screen: screenSharing,
6801
6796
  desktop: isDesktop,
@@ -7130,11 +7125,14 @@ class WebRTCClient extends Emitter {
7130
7125
 
7131
7126
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
7132
7127
 
7133
- pc.oniceconnectionstatechange = () => {
7134
- if (pc.iceConnectionState === 'disconnected') {
7135
- this.eventEmitter.emit(ON_DISCONNECTED);
7136
- }
7137
- };
7128
+ if (pc) {
7129
+ pc.oniceconnectionstatechange = () => {
7130
+ logger.info('on ice connection state changed', { state: pc.iceConnectionState });
7131
+ if (pc.iceConnectionState === 'disconnected') {
7132
+ this.eventEmitter.emit(ON_DISCONNECTED);
7133
+ }
7134
+ };
7135
+ }
7138
7136
 
7139
7137
  if (withEvent) {
7140
7138
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
@@ -7344,13 +7342,17 @@ class WebRTCClient extends Emitter {
7344
7342
  const nbStats = this.sessionNetworkStats[sessionId].length;
7345
7343
  const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
7346
7344
  const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
7345
+ const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
7347
7346
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
7348
7347
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
7348
+ const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
7349
7349
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
7350
7350
  const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
7351
7351
  const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
7352
- let audioBytesSent = 0;
7353
- let audioBytesReceived = 0;
7352
+ let audioBytesSent = 0; // content + header
7353
+ let audioBytesReceived = 0; // content + header
7354
+ let audioContentSent = 0; // useful to detect blank call
7355
+ let audioContentReceived = 0;
7354
7356
  let videoBytesSent = 0;
7355
7357
  let videoBytesReceived = 0;
7356
7358
  let transportSent = 0;
@@ -7359,25 +7361,27 @@ class WebRTCClient extends Emitter {
7359
7361
 
7360
7362
  stats.forEach(report => {
7361
7363
  if (report.type === 'outbound-rtp' && report.kind === 'audio') {
7362
- audioBytesSent += report.bytesSent + report.headerBytesSent;
7364
+ audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
7365
+ audioContentSent += Number(report.bytesSent);
7363
7366
  }
7364
7367
  if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
7365
- audioBytesSent += report.bytesSent;
7368
+ audioBytesSent += Number(report.bytesSent);
7366
7369
  }
7367
7370
  if (report.type === 'outbound-rtp' && report.kind === 'video') {
7368
- videoBytesSent += report.bytesSent + report.headerBytesSent;
7371
+ videoBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
7369
7372
  }
7370
7373
  if (report.type === 'inbound-rtp' && report.kind === 'audio') {
7371
- packetsLost += report.packetsLost;
7372
- networkStats.packetsReceived = report.packetsReceived;
7373
- audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
7374
+ packetsLost += Number(report.packetsLost);
7375
+ networkStats.packetsReceived = Number(report.packetsReceived);
7376
+ audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
7377
+ audioContentReceived += Number(report.bytesReceived);
7374
7378
  }
7375
7379
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
7376
- videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
7380
+ videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
7377
7381
  }
7378
7382
  if (report.type === 'outbound-rtp' && report.kind === 'video') {
7379
7383
  if ('framesPerSecond' in report) {
7380
- networkStats.framesPerSecond = report.framesPerSecond;
7384
+ networkStats.framesPerSecond = Number(report.framesPerSecond);
7381
7385
  }
7382
7386
  if ('framerateMean' in report) {
7383
7387
  // framerateMean is only available in FF
@@ -7385,24 +7389,31 @@ class WebRTCClient extends Emitter {
7385
7389
  }
7386
7390
  }
7387
7391
  if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
7388
- packetsLost += report.packetsLost;
7389
- networkStats.roundTripTime = report.roundTripTime;
7390
- networkStats.jitter = report.jitter;
7392
+ packetsLost += Number(report.packetsLost);
7393
+ networkStats.roundTripTime = Number(report.roundTripTime);
7394
+ networkStats.jitter = Number(report.jitter);
7391
7395
  }
7392
7396
  if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
7393
- packetsLost += report.packetsLost;
7397
+ packetsLost += Number(report.packetsLost);
7394
7398
  }
7395
7399
  if (report.type === 'transport') {
7396
- transportSent += report.bytesSent;
7397
- transportReceived += report.bytesReceived;
7400
+ transportSent += Number(report.bytesSent);
7401
+ transportReceived += Number(report.bytesReceived);
7398
7402
  }
7399
7403
  });
7400
7404
 
7401
7405
  networkStats.packetsLost = packetsLost;
7406
+
7402
7407
  networkStats.totalAudioBytesSent = audioBytesSent;
7403
7408
  networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
7404
7409
  networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
7405
7410
  networkStats.audioBytesReceived = audioBytesReceived;
7411
+
7412
+ networkStats.totalAudioContentSent = audioContentSent;
7413
+ networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
7414
+ networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
7415
+ networkStats.audioContentReceived = audioContentReceived;
7416
+
7406
7417
  networkStats.totalVideoBytesSent = videoBytesSent;
7407
7418
  networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
7408
7419
  networkStats.totalVideoBytesReceived = videoBytesReceived;
@@ -724,10 +724,6 @@ const getSrflxOrRelay = (candidates ) =>
724
724
  candidates
725
725
  .filter(candidate => candidate && (candidate.type === 'srflx' || candidate.type === 'relay'));
726
726
 
727
- const areCandidateValid = (candidates ) =>
728
- getSrflxOrRelay(candidates)
729
- .length > 0;
730
-
731
727
  const getVideoDirection = (sdp ) => {
732
728
  const parsedSdp = sdpParser.parse(sdp);
733
729
  const videoMedia = parsedSdp.media.find(media => media.type === 'video');
@@ -780,8 +776,6 @@ const fixSdp = (sdp , candidates , forcePort = true)
780
776
  /* global RTCSessionDescriptionInit, navigator */
781
777
 
782
778
  const wazoLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-sdh') : console;
783
- const MAX_WAIT_FOR_ICE_TRIES = 20;
784
- const WAIT_FOR_ICE_TIMEOUT = 500;
785
779
 
786
780
  // Customized mediaStreamFactory allowing to send screensharing stream directory when upgrading
787
781
  const wazoMediaStreamFactory = (constraints ) => {
@@ -971,38 +965,6 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
971
965
  this._peerConnection = undefined;
972
966
  }
973
967
 
974
- async _waitForValidGatheredIce() {
975
- let tries = 0;
976
-
977
- while (!areCandidateValid(this.gatheredCandidates) && tries < MAX_WAIT_FOR_ICE_TRIES) {
978
- wazoLogger.trace('SessionDescriptionHandler._waitForValidGatheredIce, waiting for ice', {
979
- tries,
980
- max: MAX_WAIT_FOR_ICE_TRIES,
981
- });
982
-
983
- tries++;
984
-
985
- // eslint-disable-next-line no-await-in-loop
986
- await new Promise(resolve => setTimeout(resolve, WAIT_FOR_ICE_TIMEOUT));
987
- }
988
-
989
- if (tries >= MAX_WAIT_FOR_ICE_TRIES) {
990
- const errorMsg = 'No valid candidates found, can\'t answer the call';
991
- const error = new Error(errorMsg);
992
- wazoLogger.error(errorMsg, { tries, max: MAX_WAIT_FOR_ICE_TRIES });
993
-
994
- // Emit an error, because sip.js catches the exception and switch to status Terminated.
995
- this.eventEmitter.emit('error', error);
996
-
997
- wazoLogger.error('No valid candidates found', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
998
- }
999
-
1000
- // eslint-disable-next-line
1001
- wazoLogger.trace('Found valid candidates', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
1002
-
1003
- return this.getLocalSessionDescription();
1004
- }
1005
-
1006
968
  // Overridden to send `inactive` in conference
1007
969
  updateDirection(options , isConference = false,
1008
970
  audioOnly = false) {
@@ -2112,6 +2074,9 @@ class Contact {
2112
2074
  }
2113
2075
 
2114
2076
  static parseMany(response ) {
2077
+ if (!response || !response.results) {
2078
+ return [];
2079
+ }
2115
2080
  return response.results.map(r => Contact.parse(r, response.column_types));
2116
2081
  }
2117
2082
 
@@ -3189,8 +3154,9 @@ class ExternalApp {
3189
3154
 
3190
3155
 
3191
3156
 
3192
-
3157
+
3193
3158
 
3159
+
3194
3160
 
3195
3161
 
3196
3162
  class Meeting {
@@ -3201,9 +3167,10 @@ class Meeting {
3201
3167
 
3202
3168
 
3203
3169
 
3204
-
3170
+
3205
3171
 
3206
3172
 
3173
+
3207
3174
 
3208
3175
  static parse(plain ) {
3209
3176
  return new Meeting({
@@ -3213,12 +3180,16 @@ class Meeting {
3213
3180
  ownerUuids: plain.owner_uuids,
3214
3181
  port: plain.port,
3215
3182
  uuid: plain.uuid,
3216
- number: plain.number,
3183
+ extension: plain.exten,
3217
3184
  persistent: plain.persistent,
3185
+ creationTime: moment(plain.creation_time).toDate(),
3218
3186
  });
3219
3187
  }
3220
3188
 
3221
3189
  static parseMany(items ) {
3190
+ if (!items) {
3191
+ return [];
3192
+ }
3222
3193
  return items.map(plain => Meeting.parse(plain));
3223
3194
  }
3224
3195
 
@@ -3233,8 +3204,9 @@ class Meeting {
3233
3204
  ownerUuids,
3234
3205
  port,
3235
3206
  uri,
3236
- number,
3207
+ extension,
3237
3208
  persistent,
3209
+ creationTime,
3238
3210
  } = {}) {
3239
3211
  this.guestSipAuthorization = guestSipAuthorization;
3240
3212
  this.uri = uri;
@@ -3242,8 +3214,9 @@ class Meeting {
3242
3214
  this.ownerUuids = ownerUuids;
3243
3215
  this.port = port;
3244
3216
  this.uuid = uuid;
3245
- this.number = number;
3217
+ this.extension = extension;
3246
3218
  this.persistent = persistent;
3219
+ this.creationTime = creationTime;
3247
3220
 
3248
3221
  // Useful to compare instead of instanceof with minified code
3249
3222
  this.type = 'Meeting';
@@ -3421,6 +3394,10 @@ class ChatMessage {
3421
3394
 
3422
3395
 
3423
3396
  static parseMany(plain ) {
3397
+ if (!plain || !plain.items) {
3398
+ return [];
3399
+ }
3400
+
3424
3401
  return plain.items.map(item => ChatMessage.parse(item));
3425
3402
  }
3426
3403
 
@@ -3530,6 +3507,9 @@ class Voicemail {
3530
3507
  }
3531
3508
 
3532
3509
  static parseMany(plain ) {
3510
+ if (!plain) {
3511
+ return [];
3512
+ }
3533
3513
  const plainUnread = plain.folders.filter(folder => folder.type === 'new')[0].messages;
3534
3514
  const plainRead = plain.folders.filter(folder => folder.type === 'old')[0].messages;
3535
3515
 
@@ -3639,6 +3619,9 @@ class Call {
3639
3619
 
3640
3620
 
3641
3621
  static parseMany(plain ) {
3622
+ if (!plain) {
3623
+ return [];
3624
+ }
3642
3625
  return plain.map((plainCall ) => Call.parse(plainCall));
3643
3626
  }
3644
3627
 
@@ -3811,6 +3794,9 @@ class Recording {
3811
3794
 
3812
3795
 
3813
3796
  static parseMany(recordings = []) {
3797
+ if (!recordings) {
3798
+ return [];
3799
+ }
3814
3800
  return recordings.map(item => Recording.parse(item));
3815
3801
  }
3816
3802
 
@@ -3912,6 +3898,10 @@ class CallLog {
3912
3898
  }
3913
3899
 
3914
3900
  static parseMany(plain ) {
3901
+ if (!plain || !plain.items) {
3902
+ return [];
3903
+ }
3904
+
3915
3905
  return plain.items.map(item => CallLog.parse(item));
3916
3906
  }
3917
3907
 
@@ -4484,6 +4474,9 @@ class ChatRoom {
4484
4474
 
4485
4475
 
4486
4476
  static parseMany(plain ) {
4477
+ if (!plain || !plain.items) {
4478
+ return [];
4479
+ }
4487
4480
  return plain.items.map(item => ChatRoom.parse(item));
4488
4481
  }
4489
4482
 
@@ -5712,7 +5705,7 @@ class WebRTCClient extends Emitter {
5712
5705
  }
5713
5706
 
5714
5707
  call(number , enableVideo , audioOnly = false, conference = false) {
5715
- logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
5708
+ logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
5716
5709
  const inviterOptions = {
5717
5710
  sessionDescriptionHandlerOptionsReInvite: {
5718
5711
  conference,
@@ -6788,6 +6781,7 @@ class WebRTCClient extends Emitter {
6788
6781
  const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
6789
6782
  const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
6790
6783
  const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
6784
+ const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
6791
6785
 
6792
6786
  logger.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
6793
6787
 
@@ -6795,7 +6789,8 @@ class WebRTCClient extends Emitter {
6795
6789
  constraints: {
6796
6790
  // Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
6797
6791
  audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
6798
- video: screenSharing ? (isDesktop ? ({ mandatory: { chromeMediaSource: 'desktop' } }) : { cursor: 'always' })
6792
+ video: screenSharing ? (isDesktop
6793
+ ? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
6799
6794
  : this._getVideoConstraints(enableVideo),
6800
6795
  screen: screenSharing,
6801
6796
  desktop: isDesktop,
@@ -7130,11 +7125,14 @@ class WebRTCClient extends Emitter {
7130
7125
 
7131
7126
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
7132
7127
 
7133
- pc.oniceconnectionstatechange = () => {
7134
- if (pc.iceConnectionState === 'disconnected') {
7135
- this.eventEmitter.emit(ON_DISCONNECTED);
7136
- }
7137
- };
7128
+ if (pc) {
7129
+ pc.oniceconnectionstatechange = () => {
7130
+ logger.info('on ice connection state changed', { state: pc.iceConnectionState });
7131
+ if (pc.iceConnectionState === 'disconnected') {
7132
+ this.eventEmitter.emit(ON_DISCONNECTED);
7133
+ }
7134
+ };
7135
+ }
7138
7136
 
7139
7137
  if (withEvent) {
7140
7138
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
@@ -7344,13 +7342,17 @@ class WebRTCClient extends Emitter {
7344
7342
  const nbStats = this.sessionNetworkStats[sessionId].length;
7345
7343
  const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
7346
7344
  const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
7345
+ const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
7347
7346
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
7348
7347
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
7348
+ const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
7349
7349
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
7350
7350
  const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
7351
7351
  const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
7352
- let audioBytesSent = 0;
7353
- let audioBytesReceived = 0;
7352
+ let audioBytesSent = 0; // content + header
7353
+ let audioBytesReceived = 0; // content + header
7354
+ let audioContentSent = 0; // useful to detect blank call
7355
+ let audioContentReceived = 0;
7354
7356
  let videoBytesSent = 0;
7355
7357
  let videoBytesReceived = 0;
7356
7358
  let transportSent = 0;
@@ -7359,25 +7361,27 @@ class WebRTCClient extends Emitter {
7359
7361
 
7360
7362
  stats.forEach(report => {
7361
7363
  if (report.type === 'outbound-rtp' && report.kind === 'audio') {
7362
- audioBytesSent += report.bytesSent + report.headerBytesSent;
7364
+ audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
7365
+ audioContentSent += Number(report.bytesSent);
7363
7366
  }
7364
7367
  if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
7365
- audioBytesSent += report.bytesSent;
7368
+ audioBytesSent += Number(report.bytesSent);
7366
7369
  }
7367
7370
  if (report.type === 'outbound-rtp' && report.kind === 'video') {
7368
- videoBytesSent += report.bytesSent + report.headerBytesSent;
7371
+ videoBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
7369
7372
  }
7370
7373
  if (report.type === 'inbound-rtp' && report.kind === 'audio') {
7371
- packetsLost += report.packetsLost;
7372
- networkStats.packetsReceived = report.packetsReceived;
7373
- audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
7374
+ packetsLost += Number(report.packetsLost);
7375
+ networkStats.packetsReceived = Number(report.packetsReceived);
7376
+ audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
7377
+ audioContentReceived += Number(report.bytesReceived);
7374
7378
  }
7375
7379
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
7376
- videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
7380
+ videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
7377
7381
  }
7378
7382
  if (report.type === 'outbound-rtp' && report.kind === 'video') {
7379
7383
  if ('framesPerSecond' in report) {
7380
- networkStats.framesPerSecond = report.framesPerSecond;
7384
+ networkStats.framesPerSecond = Number(report.framesPerSecond);
7381
7385
  }
7382
7386
  if ('framerateMean' in report) {
7383
7387
  // framerateMean is only available in FF
@@ -7385,24 +7389,31 @@ class WebRTCClient extends Emitter {
7385
7389
  }
7386
7390
  }
7387
7391
  if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
7388
- packetsLost += report.packetsLost;
7389
- networkStats.roundTripTime = report.roundTripTime;
7390
- networkStats.jitter = report.jitter;
7392
+ packetsLost += Number(report.packetsLost);
7393
+ networkStats.roundTripTime = Number(report.roundTripTime);
7394
+ networkStats.jitter = Number(report.jitter);
7391
7395
  }
7392
7396
  if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
7393
- packetsLost += report.packetsLost;
7397
+ packetsLost += Number(report.packetsLost);
7394
7398
  }
7395
7399
  if (report.type === 'transport') {
7396
- transportSent += report.bytesSent;
7397
- transportReceived += report.bytesReceived;
7400
+ transportSent += Number(report.bytesSent);
7401
+ transportReceived += Number(report.bytesReceived);
7398
7402
  }
7399
7403
  });
7400
7404
 
7401
7405
  networkStats.packetsLost = packetsLost;
7406
+
7402
7407
  networkStats.totalAudioBytesSent = audioBytesSent;
7403
7408
  networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
7404
7409
  networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
7405
7410
  networkStats.audioBytesReceived = audioBytesReceived;
7411
+
7412
+ networkStats.totalAudioContentSent = audioContentSent;
7413
+ networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
7414
+ networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
7415
+ networkStats.audioContentReceived = audioContentReceived;
7416
+
7406
7417
  networkStats.totalVideoBytesSent = videoBytesSent;
7407
7418
  networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
7408
7419
  networkStats.totalVideoBytesReceived = videoBytesReceived;