@wazo/sdk 0.37.26 → 0.37.30

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 (121) hide show
  1. package/README.md +98 -59
  2. package/dist/wazo-sdk.js +3 -3
  3. package/esm/__tests__/api-client.test.js +1 -1
  4. package/esm/__tests__/web-rtc-client.test.js +18 -5
  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 +1 -1
  13. package/esm/api/ctid-ng.js +1 -1
  14. package/esm/api/dird.js +1 -1
  15. package/esm/api/webhookd.js +1 -1
  16. package/esm/api-client.js +1 -1
  17. package/esm/checker/Checker.js +18 -5
  18. package/esm/checker/checks/aor.js +1 -1
  19. package/esm/checker/checks/api.js +1 -1
  20. package/esm/checker/checks/index.js +18 -5
  21. package/esm/checker/checks/wazo-websocket.js +1 -1
  22. package/esm/checker/checks/webrtc-transport.js +18 -5
  23. package/esm/checker/checks/webrtc.js +18 -5
  24. package/esm/domain/AdHocAPIConference.js +1 -1
  25. package/esm/domain/CallSession.js +29 -2
  26. package/esm/domain/Features.js +1 -1
  27. package/esm/domain/Phone/CTIPhone.js +30 -3
  28. package/esm/domain/Phone/WebRTCPhone.js +55 -6
  29. package/esm/domain/SFUNotAvailableError.js +9 -0
  30. package/esm/domain/__tests__/CallSession.test.js +46 -2
  31. package/esm/domain/__tests__/IndirectTransfer.test.js +29 -2
  32. package/esm/domain/__tests__/Room.test.js +29 -2
  33. package/esm/index.js +83 -10
  34. package/esm/lib/WazoSessionDescriptionHandler.js +9 -4
  35. package/esm/service/CallApi.js +1 -1
  36. package/esm/service/IssueReporter.js +1 -1
  37. package/esm/service/__tests__/IssueReporter.test.js +1 -1
  38. package/esm/service/getApiClient.js +1 -1
  39. package/esm/simple/Auth.js +82 -10
  40. package/esm/simple/Configuration.js +82 -10
  41. package/esm/simple/Directory.js +1 -1
  42. package/esm/simple/Phone.js +82 -10
  43. package/esm/simple/Websocket.js +1 -1
  44. package/esm/simple/index.js +82 -10
  45. package/esm/simple/room/LocalParticipant.js +82 -10
  46. package/esm/simple/room/Participant.js +82 -10
  47. package/esm/simple/room/RemoteParticipant.js +82 -10
  48. package/esm/simple/room/Room.js +82 -10
  49. package/esm/simple/room/SipRoom.js +82 -10
  50. package/esm/simple/room/Stream.js +82 -10
  51. package/esm/simple/room/__tests__/RemoteParticipant.test.js +82 -10
  52. package/esm/simple/utils.js +82 -10
  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 +18 -5
  56. package/esm/websocket-client.js +1 -1
  57. package/lib/__tests__/api-client.test.js +1 -1
  58. package/lib/__tests__/web-rtc-client.test.js +18 -5
  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 +1 -1
  67. package/lib/api/ctid-ng.js +1 -1
  68. package/lib/api/dird.js +1 -1
  69. package/lib/api/webhookd.js +1 -1
  70. package/lib/api-client.js +1 -1
  71. package/lib/checker/Checker.js +18 -5
  72. package/lib/checker/checks/aor.js +1 -1
  73. package/lib/checker/checks/api.js +1 -1
  74. package/lib/checker/checks/index.js +18 -5
  75. package/lib/checker/checks/wazo-websocket.js +1 -1
  76. package/lib/checker/checks/webrtc-transport.js +18 -5
  77. package/lib/checker/checks/webrtc.js +18 -5
  78. package/lib/domain/AdHocAPIConference.js +1 -1
  79. package/lib/domain/CallSession.js +29 -2
  80. package/lib/domain/Features.js +1 -1
  81. package/lib/domain/Phone/CTIPhone.js +30 -3
  82. package/lib/domain/Phone/WebRTCPhone.js +55 -5
  83. package/lib/domain/SFUNotAvailableError.js +11 -0
  84. package/lib/domain/__tests__/CallSession.test.js +46 -2
  85. package/lib/domain/__tests__/IndirectTransfer.test.js +29 -2
  86. package/lib/domain/__tests__/Room.test.js +29 -2
  87. package/lib/index.js +83 -10
  88. package/lib/lib/WazoSessionDescriptionHandler.js +9 -4
  89. package/lib/service/CallApi.js +1 -1
  90. package/lib/service/IssueReporter.js +1 -1
  91. package/lib/service/__tests__/IssueReporter.test.js +1 -1
  92. package/lib/service/getApiClient.js +1 -1
  93. package/lib/simple/Auth.js +82 -10
  94. package/lib/simple/Configuration.js +82 -10
  95. package/lib/simple/Directory.js +1 -1
  96. package/lib/simple/Phone.js +82 -10
  97. package/lib/simple/Websocket.js +1 -1
  98. package/lib/simple/index.js +82 -10
  99. package/lib/simple/room/LocalParticipant.js +82 -10
  100. package/lib/simple/room/Participant.js +82 -10
  101. package/lib/simple/room/RemoteParticipant.js +82 -10
  102. package/lib/simple/room/Room.js +82 -10
  103. package/lib/simple/room/SipRoom.js +82 -10
  104. package/lib/simple/room/Stream.js +82 -10
  105. package/lib/simple/room/__tests__/RemoteParticipant.test.js +82 -10
  106. package/lib/simple/utils.js +82 -10
  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 +18 -5
  110. package/lib/websocket-client.js +1 -1
  111. package/package.json +1 -1
  112. package/src/domain/CallSession.js +32 -4
  113. package/src/domain/Phone/WebRTCPhone.js +24 -2
  114. package/src/domain/SFUNotAvailableError.js +7 -0
  115. package/src/domain/__tests__/CallSession.test.js +17 -0
  116. package/src/index.js +2 -0
  117. package/src/lib/WazoSessionDescriptionHandler.js +8 -3
  118. package/src/simple/Phone.js +2 -1
  119. package/src/simple/index.js +2 -0
  120. package/src/utils/api-requester.js +1 -1
  121. package/src/web-rtc-client.js +9 -1
@@ -142,7 +142,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
142
142
 
143
143
  // Use a function here to be able to mock it in tests
144
144
  const realFetch = () => {
145
- if (typeof document !== 'undefined') {
145
+ if (typeof document !== 'undefined' && window.fetch) {
146
146
  // Browser
147
147
  return window.fetch;
148
148
  }
@@ -3284,13 +3284,16 @@ var updateFrom = (instance , from ) => {
3284
3284
 
3285
3285
 
3286
3286
 
3287
+
3287
3288
 
3288
3289
 
3289
3290
 
3290
3291
 
3291
3292
 
3293
+
3292
3294
 
3293
3295
 
3296
+
3294
3297
 
3295
3298
 
3296
3299
 
@@ -3307,6 +3310,7 @@ var updateFrom = (instance , from ) => {
3307
3310
 
3308
3311
 
3309
3312
 
3313
+
3310
3314
 
3311
3315
 
3312
3316
  class CallSession {
@@ -3326,10 +3330,14 @@ class CallSession {
3326
3330
 
3327
3331
 
3328
3332
 
3329
-
3333
+
3334
+
3335
+ // = creationTime
3330
3336
 
3331
3337
 
3332
3338
 
3339
+
3340
+
3333
3341
 
3334
3342
 
3335
3343
 
@@ -3365,6 +3373,8 @@ class CallSession {
3365
3373
 
3366
3374
 
3367
3375
 
3376
+
3377
+
3368
3378
 
3369
3379
  constructor({
3370
3380
  answered,
@@ -3378,6 +3388,8 @@ class CallSession {
3378
3388
  paused,
3379
3389
  ringing,
3380
3390
  startTime,
3391
+ creationTime,
3392
+ endTime,
3381
3393
  cameraEnabled,
3382
3394
  dialedExtension,
3383
3395
  sipCallId,
@@ -3390,12 +3402,16 @@ class CallSession {
3390
3402
  recording,
3391
3403
  recordingPaused,
3392
3404
  videoRemotelyDowngraded,
3405
+ sipSession,
3406
+ answerTime,
3393
3407
  } ) {
3394
3408
  this.callId = callId;
3395
3409
  this.sipCallId = sipCallId;
3396
3410
  this.displayName = displayName;
3397
3411
  this.number = number;
3412
+ this.creationTime = creationTime;
3398
3413
  this.startTime = startTime;
3414
+ this.endTime = endTime;
3399
3415
  this.isCaller = isCaller;
3400
3416
  this.answered = answered;
3401
3417
  this.answeredBySystem = answeredBySystem;
@@ -3414,6 +3430,8 @@ class CallSession {
3414
3430
  this.recording = recording || false;
3415
3431
  this.recordingPaused = recordingPaused || false;
3416
3432
  this.videoRemotelyDowngraded = videoRemotelyDowngraded;
3433
+ this.sipSession = sipSession;
3434
+ this.answerTime = answerTime || this.answerTime;
3417
3435
 
3418
3436
  // Useful to compare instead of instanceof with minified code
3419
3437
  this.type = 'CallSession';
@@ -3444,7 +3462,7 @@ class CallSession {
3444
3462
  }
3445
3463
 
3446
3464
  answer() {
3447
- this.answered = true;
3465
+ this.answerTime = new Date();
3448
3466
  }
3449
3467
 
3450
3468
  systemAnswer() {
@@ -3600,6 +3618,15 @@ class CallSession {
3600
3618
  return newFrom(callSession, CallSession);
3601
3619
  }
3602
3620
 
3621
+ // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
3622
+ set answered(value ) {
3623
+ this.answerTime = value ? new Date() : null;
3624
+ }
3625
+
3626
+ get answered() {
3627
+ return !!this.answerTime;
3628
+ }
3629
+
3603
3630
  static parseCall(call ) {
3604
3631
  return new CallSession({
3605
3632
  callId: call.id,
@@ -6072,11 +6099,16 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
6072
6099
 
6073
6100
  // $FlowFixMe
6074
6101
  setRemoteSessionDescription(sessionDescription ) {
6075
- const result = super.setRemoteSessionDescription(sessionDescription);
6102
+ try {
6103
+ const result = super.setRemoteSessionDescription(sessionDescription);
6076
6104
 
6077
- this.eventEmitter.emit('setDescription', sessionDescription);
6105
+ this.eventEmitter.emit('setDescription', sessionDescription);
6078
6106
 
6079
- return result;
6107
+ return result;
6108
+ } catch (error) {
6109
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
6110
+ throw error;
6111
+ }
6080
6112
  }
6081
6113
 
6082
6114
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -6615,6 +6647,7 @@ const MAX_REGISTER_TRIES = 10;
6615
6647
 
6616
6648
 
6617
6649
 
6650
+
6618
6651
 
6619
6652
 
6620
6653
 
@@ -8231,6 +8264,13 @@ class WebRTCClient extends Emitter {
8231
8264
  }
8232
8265
 
8233
8266
  _createWebRTCConfiguration(configOverrides = {}) {
8267
+ let { host } = this.config;
8268
+ let port = this.config.port || 443;
8269
+
8270
+ if (this.config.websocketSip) {
8271
+ [host, port = 443] = this.config.websocketSip.split(':');
8272
+ }
8273
+
8234
8274
  const config = {
8235
8275
  authorizationUsername: this.config.authorizationUser,
8236
8276
  authorizationPassword: this.config.password,
@@ -8266,7 +8306,7 @@ class WebRTCClient extends Emitter {
8266
8306
  },
8267
8307
  transportOptions: {
8268
8308
  traceSip: configOverrides.traceSip || false,
8269
- wsServers: `wss://${this.config.host}:${this.config.port || 443}/api/asterisk/ws`,
8309
+ wsServers: `wss://${host}:${port}/api/asterisk/ws`,
8270
8310
  },
8271
8311
  sessionDescriptionHandlerFactoryOptions: {
8272
8312
  modifiers: [replaceLocalIpModifier],
@@ -8728,6 +8768,7 @@ const ON_CAMERA_DISABLED = 'onCameraDisabled';
8728
8768
  const ON_CAMERA_RESUMED = 'onCameraResumed';
8729
8769
  const ON_CALL_CANCELED = 'onCallCanceled';
8730
8770
  const ON_CALL_FAILED = 'onCallFailed';
8771
+ const ON_CALL_REJECTED = 'onCallRejected';
8731
8772
  const ON_CALL_ENDED = 'onCallEnded';
8732
8773
  const ON_CALL_ENDING = 'onCallEnding';
8733
8774
  const ON_MESSAGE = 'onMessage';
@@ -8772,6 +8813,7 @@ const events = [
8772
8813
  ON_CAMERA_DISABLED,
8773
8814
  ON_CALL_FAILED,
8774
8815
  ON_CALL_ENDED,
8816
+ ON_CALL_REJECTED,
8775
8817
  ON_MESSAGE,
8776
8818
  ON_REINVITE,
8777
8819
  ON_TRACK,
@@ -9128,6 +9170,7 @@ class WebRTCPhone extends Emitter {
9128
9170
 
9129
9171
  // Should be called before `_onCallTerminated` or the callCount will not decrement...
9130
9172
  const callSession = this._createCallSession(sipSession);
9173
+ callSession.endTime = new Date();
9131
9174
  const wasCurrentSession = this._onCallTerminated(sipSession);
9132
9175
 
9133
9176
  return this.eventEmitter.emit(ON_CALL_ENDED, callSession, wasCurrentSession);
@@ -9323,6 +9366,7 @@ class WebRTCPhone extends Emitter {
9323
9366
  this.removeIncomingSessions(sipSessionId);
9324
9367
  }
9325
9368
 
9369
+ callSession.answerTime = new Date();
9326
9370
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9327
9371
 
9328
9372
  return callSession;
@@ -9380,6 +9424,7 @@ class WebRTCPhone extends Emitter {
9380
9424
  _onCallTerminated(sipSession ) {
9381
9425
  logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
9382
9426
 
9427
+ const sipSessionId = this.getSipSessionId(sipSession);
9383
9428
  const callSession = this._createCallSession(sipSession);
9384
9429
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
9385
9430
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -9397,7 +9442,6 @@ class WebRTCPhone extends Emitter {
9397
9442
  }, 5);
9398
9443
  }
9399
9444
 
9400
- const sipSessionId = this.getSipSessionId(sipSession);
9401
9445
  if (sipSessionId) {
9402
9446
  this.removeIncomingSessions(sipSessionId);
9403
9447
  }
@@ -9538,6 +9582,7 @@ class WebRTCPhone extends Emitter {
9538
9582
  }
9539
9583
 
9540
9584
  this.shouldSendReinvite = false;
9585
+ callSession.answerTime = new Date();
9541
9586
  this.acceptedSessions[callSession.getId()] = true;
9542
9587
 
9543
9588
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9847,6 +9892,7 @@ class WebRTCPhone extends Emitter {
9847
9892
  return Promise.resolve(null);
9848
9893
  }
9849
9894
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9895
+ callSession.creationTime = new Date();
9850
9896
 
9851
9897
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9852
9898
 
@@ -10042,8 +10088,12 @@ class WebRTCPhone extends Emitter {
10042
10088
  }
10043
10089
 
10044
10090
  const sessionId = this.incomingSessions[0];
10091
+ const sipSession = this.client.getSipSession(sessionId);
10092
+ if (!sipSession) {
10093
+ return null;
10094
+ }
10045
10095
 
10046
- return this._createCallSession(this.client.getSipSession(sessionId));
10096
+ return this._createCallSession(sipSession);
10047
10097
  }
10048
10098
 
10049
10099
  sendMessage(sipSession = null, body , contentType = 'text/plain') {
@@ -10121,6 +10171,7 @@ class WebRTCPhone extends Emitter {
10121
10171
  callSession);
10122
10172
  }
10123
10173
 
10174
+ callSession.creationTime = new Date();
10124
10175
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
10125
10176
  });
10126
10177
 
@@ -10160,6 +10211,13 @@ class WebRTCPhone extends Emitter {
10160
10211
  this.eventEmitter.emit(ON_CALL_ERROR, e);
10161
10212
  });
10162
10213
 
10214
+ this.client.on(this.client.REJECTED, session => {
10215
+ logger$7.info('WebRTC call rejected', session.id);
10216
+ const callSession = this._createCallSession(session);
10217
+ callSession.endTime = new Date();
10218
+ this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
10219
+ });
10220
+
10163
10221
  this.client.on(this.client.UNREGISTERED, () => {
10164
10222
  logger$7.info('WebRTC unregistered');
10165
10223
  this.eventEmitter.emit(ON_UNREGISTERED);
@@ -10372,6 +10430,7 @@ class WebRTCPhone extends Emitter {
10372
10430
  const number = identity ? identity.uri._normal.user : null;
10373
10431
  const { state } = sipSession || {};
10374
10432
  const sessionId = this.getSipSessionId(sipSession);
10433
+ fromSession = fromSession || this.callSessions[sessionId];
10375
10434
 
10376
10435
  const callSession = new CallSession({
10377
10436
  callId: fromSession && fromSession.callId,
@@ -10379,6 +10438,8 @@ class WebRTCPhone extends Emitter {
10379
10438
  sipStatus: state,
10380
10439
  displayName: identity ? identity.displayName || number : number,
10381
10440
  startTime: fromSession ? fromSession.startTime : new Date(),
10441
+ creationTime: fromSession ? fromSession.creationTime : null,
10442
+ endTime: fromSession ? fromSession.endTime : null,
10382
10443
  answered: state === sessionState.SessionState.Established,
10383
10444
  paused: this.client.isCallHeld(sipSession),
10384
10445
  isCaller: 'incoming' in extra ? !extra.incoming : false,
@@ -10389,6 +10450,7 @@ class WebRTCPhone extends Emitter {
10389
10450
  videoMuted: fromSession ? fromSession.isVideoMuted() : false,
10390
10451
  recording: fromSession ? fromSession.isRecording() : false,
10391
10452
  recordingPaused: false, // @TODO
10453
+ sipSession,
10392
10454
  ...extra,
10393
10455
  });
10394
10456
 
@@ -10417,6 +10479,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10417
10479
  ON_CAMERA_RESUMED: ON_CAMERA_RESUMED,
10418
10480
  ON_CALL_CANCELED: ON_CALL_CANCELED,
10419
10481
  ON_CALL_FAILED: ON_CALL_FAILED,
10482
+ ON_CALL_REJECTED: ON_CALL_REJECTED,
10420
10483
  ON_CALL_ENDED: ON_CALL_ENDED,
10421
10484
  ON_CALL_ENDING: ON_CALL_ENDING,
10422
10485
  ON_MESSAGE: ON_MESSAGE,
@@ -10446,6 +10509,14 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10446
10509
  'default': WebRTCPhone
10447
10510
  });
10448
10511
 
10512
+ /* */
10513
+ class SFUNotAvailableError extends Error {
10514
+ constructor(message = 'Sorry your user is not configured to support video conference') {
10515
+ super(message);
10516
+ this.name = 'SFUNotAvailableError';
10517
+ }
10518
+ }
10519
+
10449
10520
  //
10450
10521
 
10451
10522
  const logger$6 = IssueReporter$1.loggerFor('simple-phone');
@@ -10830,7 +10901,7 @@ class Phone extends Emitter {
10830
10901
 
10831
10902
  checkSfu() {
10832
10903
  if (!this.hasSfu()) {
10833
- throw new Error('Sorry your user is not configured to support video conference');
10904
+ throw new SFUNotAvailableError();
10834
10905
  }
10835
10906
  }
10836
10907
 
@@ -12612,6 +12683,7 @@ const Wazo = {
12612
12683
  InvalidSubscription,
12613
12684
  InvalidAuthorization,
12614
12685
  CanceledCallError,
12686
+ SFUNotAvailableError,
12615
12687
  };
12616
12688
 
12617
12689
  if (window) {
@@ -142,7 +142,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
142
142
 
143
143
  // Use a function here to be able to mock it in tests
144
144
  const realFetch = () => {
145
- if (typeof document !== 'undefined') {
145
+ if (typeof document !== 'undefined' && window.fetch) {
146
146
  // Browser
147
147
  return window.fetch;
148
148
  }
@@ -3284,13 +3284,16 @@ var updateFrom = (instance , from ) => {
3284
3284
 
3285
3285
 
3286
3286
 
3287
+
3287
3288
 
3288
3289
 
3289
3290
 
3290
3291
 
3291
3292
 
3293
+
3292
3294
 
3293
3295
 
3296
+
3294
3297
 
3295
3298
 
3296
3299
 
@@ -3307,6 +3310,7 @@ var updateFrom = (instance , from ) => {
3307
3310
 
3308
3311
 
3309
3312
 
3313
+
3310
3314
 
3311
3315
 
3312
3316
  class CallSession {
@@ -3326,10 +3330,14 @@ class CallSession {
3326
3330
 
3327
3331
 
3328
3332
 
3329
-
3333
+
3334
+
3335
+ // = creationTime
3330
3336
 
3331
3337
 
3332
3338
 
3339
+
3340
+
3333
3341
 
3334
3342
 
3335
3343
 
@@ -3365,6 +3373,8 @@ class CallSession {
3365
3373
 
3366
3374
 
3367
3375
 
3376
+
3377
+
3368
3378
 
3369
3379
  constructor({
3370
3380
  answered,
@@ -3378,6 +3388,8 @@ class CallSession {
3378
3388
  paused,
3379
3389
  ringing,
3380
3390
  startTime,
3391
+ creationTime,
3392
+ endTime,
3381
3393
  cameraEnabled,
3382
3394
  dialedExtension,
3383
3395
  sipCallId,
@@ -3390,12 +3402,16 @@ class CallSession {
3390
3402
  recording,
3391
3403
  recordingPaused,
3392
3404
  videoRemotelyDowngraded,
3405
+ sipSession,
3406
+ answerTime,
3393
3407
  } ) {
3394
3408
  this.callId = callId;
3395
3409
  this.sipCallId = sipCallId;
3396
3410
  this.displayName = displayName;
3397
3411
  this.number = number;
3412
+ this.creationTime = creationTime;
3398
3413
  this.startTime = startTime;
3414
+ this.endTime = endTime;
3399
3415
  this.isCaller = isCaller;
3400
3416
  this.answered = answered;
3401
3417
  this.answeredBySystem = answeredBySystem;
@@ -3414,6 +3430,8 @@ class CallSession {
3414
3430
  this.recording = recording || false;
3415
3431
  this.recordingPaused = recordingPaused || false;
3416
3432
  this.videoRemotelyDowngraded = videoRemotelyDowngraded;
3433
+ this.sipSession = sipSession;
3434
+ this.answerTime = answerTime || this.answerTime;
3417
3435
 
3418
3436
  // Useful to compare instead of instanceof with minified code
3419
3437
  this.type = 'CallSession';
@@ -3444,7 +3462,7 @@ class CallSession {
3444
3462
  }
3445
3463
 
3446
3464
  answer() {
3447
- this.answered = true;
3465
+ this.answerTime = new Date();
3448
3466
  }
3449
3467
 
3450
3468
  systemAnswer() {
@@ -3600,6 +3618,15 @@ class CallSession {
3600
3618
  return newFrom(callSession, CallSession);
3601
3619
  }
3602
3620
 
3621
+ // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
3622
+ set answered(value ) {
3623
+ this.answerTime = value ? new Date() : null;
3624
+ }
3625
+
3626
+ get answered() {
3627
+ return !!this.answerTime;
3628
+ }
3629
+
3603
3630
  static parseCall(call ) {
3604
3631
  return new CallSession({
3605
3632
  callId: call.id,
@@ -6072,11 +6099,16 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
6072
6099
 
6073
6100
  // $FlowFixMe
6074
6101
  setRemoteSessionDescription(sessionDescription ) {
6075
- const result = super.setRemoteSessionDescription(sessionDescription);
6102
+ try {
6103
+ const result = super.setRemoteSessionDescription(sessionDescription);
6076
6104
 
6077
- this.eventEmitter.emit('setDescription', sessionDescription);
6105
+ this.eventEmitter.emit('setDescription', sessionDescription);
6078
6106
 
6079
- return result;
6107
+ return result;
6108
+ } catch (error) {
6109
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
6110
+ throw error;
6111
+ }
6080
6112
  }
6081
6113
 
6082
6114
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -6615,6 +6647,7 @@ const MAX_REGISTER_TRIES = 10;
6615
6647
 
6616
6648
 
6617
6649
 
6650
+
6618
6651
 
6619
6652
 
6620
6653
 
@@ -8231,6 +8264,13 @@ class WebRTCClient extends Emitter {
8231
8264
  }
8232
8265
 
8233
8266
  _createWebRTCConfiguration(configOverrides = {}) {
8267
+ let { host } = this.config;
8268
+ let port = this.config.port || 443;
8269
+
8270
+ if (this.config.websocketSip) {
8271
+ [host, port = 443] = this.config.websocketSip.split(':');
8272
+ }
8273
+
8234
8274
  const config = {
8235
8275
  authorizationUsername: this.config.authorizationUser,
8236
8276
  authorizationPassword: this.config.password,
@@ -8266,7 +8306,7 @@ class WebRTCClient extends Emitter {
8266
8306
  },
8267
8307
  transportOptions: {
8268
8308
  traceSip: configOverrides.traceSip || false,
8269
- wsServers: `wss://${this.config.host}:${this.config.port || 443}/api/asterisk/ws`,
8309
+ wsServers: `wss://${host}:${port}/api/asterisk/ws`,
8270
8310
  },
8271
8311
  sessionDescriptionHandlerFactoryOptions: {
8272
8312
  modifiers: [replaceLocalIpModifier],
@@ -8728,6 +8768,7 @@ const ON_CAMERA_DISABLED = 'onCameraDisabled';
8728
8768
  const ON_CAMERA_RESUMED = 'onCameraResumed';
8729
8769
  const ON_CALL_CANCELED = 'onCallCanceled';
8730
8770
  const ON_CALL_FAILED = 'onCallFailed';
8771
+ const ON_CALL_REJECTED = 'onCallRejected';
8731
8772
  const ON_CALL_ENDED = 'onCallEnded';
8732
8773
  const ON_CALL_ENDING = 'onCallEnding';
8733
8774
  const ON_MESSAGE = 'onMessage';
@@ -8772,6 +8813,7 @@ const events = [
8772
8813
  ON_CAMERA_DISABLED,
8773
8814
  ON_CALL_FAILED,
8774
8815
  ON_CALL_ENDED,
8816
+ ON_CALL_REJECTED,
8775
8817
  ON_MESSAGE,
8776
8818
  ON_REINVITE,
8777
8819
  ON_TRACK,
@@ -9128,6 +9170,7 @@ class WebRTCPhone extends Emitter {
9128
9170
 
9129
9171
  // Should be called before `_onCallTerminated` or the callCount will not decrement...
9130
9172
  const callSession = this._createCallSession(sipSession);
9173
+ callSession.endTime = new Date();
9131
9174
  const wasCurrentSession = this._onCallTerminated(sipSession);
9132
9175
 
9133
9176
  return this.eventEmitter.emit(ON_CALL_ENDED, callSession, wasCurrentSession);
@@ -9323,6 +9366,7 @@ class WebRTCPhone extends Emitter {
9323
9366
  this.removeIncomingSessions(sipSessionId);
9324
9367
  }
9325
9368
 
9369
+ callSession.answerTime = new Date();
9326
9370
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9327
9371
 
9328
9372
  return callSession;
@@ -9380,6 +9424,7 @@ class WebRTCPhone extends Emitter {
9380
9424
  _onCallTerminated(sipSession ) {
9381
9425
  logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
9382
9426
 
9427
+ const sipSessionId = this.getSipSessionId(sipSession);
9383
9428
  const callSession = this._createCallSession(sipSession);
9384
9429
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
9385
9430
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -9397,7 +9442,6 @@ class WebRTCPhone extends Emitter {
9397
9442
  }, 5);
9398
9443
  }
9399
9444
 
9400
- const sipSessionId = this.getSipSessionId(sipSession);
9401
9445
  if (sipSessionId) {
9402
9446
  this.removeIncomingSessions(sipSessionId);
9403
9447
  }
@@ -9538,6 +9582,7 @@ class WebRTCPhone extends Emitter {
9538
9582
  }
9539
9583
 
9540
9584
  this.shouldSendReinvite = false;
9585
+ callSession.answerTime = new Date();
9541
9586
  this.acceptedSessions[callSession.getId()] = true;
9542
9587
 
9543
9588
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9847,6 +9892,7 @@ class WebRTCPhone extends Emitter {
9847
9892
  return Promise.resolve(null);
9848
9893
  }
9849
9894
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9895
+ callSession.creationTime = new Date();
9850
9896
 
9851
9897
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9852
9898
 
@@ -10042,8 +10088,12 @@ class WebRTCPhone extends Emitter {
10042
10088
  }
10043
10089
 
10044
10090
  const sessionId = this.incomingSessions[0];
10091
+ const sipSession = this.client.getSipSession(sessionId);
10092
+ if (!sipSession) {
10093
+ return null;
10094
+ }
10045
10095
 
10046
- return this._createCallSession(this.client.getSipSession(sessionId));
10096
+ return this._createCallSession(sipSession);
10047
10097
  }
10048
10098
 
10049
10099
  sendMessage(sipSession = null, body , contentType = 'text/plain') {
@@ -10121,6 +10171,7 @@ class WebRTCPhone extends Emitter {
10121
10171
  callSession);
10122
10172
  }
10123
10173
 
10174
+ callSession.creationTime = new Date();
10124
10175
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
10125
10176
  });
10126
10177
 
@@ -10160,6 +10211,13 @@ class WebRTCPhone extends Emitter {
10160
10211
  this.eventEmitter.emit(ON_CALL_ERROR, e);
10161
10212
  });
10162
10213
 
10214
+ this.client.on(this.client.REJECTED, session => {
10215
+ logger$7.info('WebRTC call rejected', session.id);
10216
+ const callSession = this._createCallSession(session);
10217
+ callSession.endTime = new Date();
10218
+ this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
10219
+ });
10220
+
10163
10221
  this.client.on(this.client.UNREGISTERED, () => {
10164
10222
  logger$7.info('WebRTC unregistered');
10165
10223
  this.eventEmitter.emit(ON_UNREGISTERED);
@@ -10372,6 +10430,7 @@ class WebRTCPhone extends Emitter {
10372
10430
  const number = identity ? identity.uri._normal.user : null;
10373
10431
  const { state } = sipSession || {};
10374
10432
  const sessionId = this.getSipSessionId(sipSession);
10433
+ fromSession = fromSession || this.callSessions[sessionId];
10375
10434
 
10376
10435
  const callSession = new CallSession({
10377
10436
  callId: fromSession && fromSession.callId,
@@ -10379,6 +10438,8 @@ class WebRTCPhone extends Emitter {
10379
10438
  sipStatus: state,
10380
10439
  displayName: identity ? identity.displayName || number : number,
10381
10440
  startTime: fromSession ? fromSession.startTime : new Date(),
10441
+ creationTime: fromSession ? fromSession.creationTime : null,
10442
+ endTime: fromSession ? fromSession.endTime : null,
10382
10443
  answered: state === sessionState.SessionState.Established,
10383
10444
  paused: this.client.isCallHeld(sipSession),
10384
10445
  isCaller: 'incoming' in extra ? !extra.incoming : false,
@@ -10389,6 +10450,7 @@ class WebRTCPhone extends Emitter {
10389
10450
  videoMuted: fromSession ? fromSession.isVideoMuted() : false,
10390
10451
  recording: fromSession ? fromSession.isRecording() : false,
10391
10452
  recordingPaused: false, // @TODO
10453
+ sipSession,
10392
10454
  ...extra,
10393
10455
  });
10394
10456
 
@@ -10417,6 +10479,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10417
10479
  ON_CAMERA_RESUMED: ON_CAMERA_RESUMED,
10418
10480
  ON_CALL_CANCELED: ON_CALL_CANCELED,
10419
10481
  ON_CALL_FAILED: ON_CALL_FAILED,
10482
+ ON_CALL_REJECTED: ON_CALL_REJECTED,
10420
10483
  ON_CALL_ENDED: ON_CALL_ENDED,
10421
10484
  ON_CALL_ENDING: ON_CALL_ENDING,
10422
10485
  ON_MESSAGE: ON_MESSAGE,
@@ -10446,6 +10509,14 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
10446
10509
  'default': WebRTCPhone
10447
10510
  });
10448
10511
 
10512
+ /* */
10513
+ class SFUNotAvailableError extends Error {
10514
+ constructor(message = 'Sorry your user is not configured to support video conference') {
10515
+ super(message);
10516
+ this.name = 'SFUNotAvailableError';
10517
+ }
10518
+ }
10519
+
10449
10520
  //
10450
10521
 
10451
10522
  const logger$6 = IssueReporter$1.loggerFor('simple-phone');
@@ -10830,7 +10901,7 @@ class Phone extends Emitter {
10830
10901
 
10831
10902
  checkSfu() {
10832
10903
  if (!this.hasSfu()) {
10833
- throw new Error('Sorry your user is not configured to support video conference');
10904
+ throw new SFUNotAvailableError();
10834
10905
  }
10835
10906
  }
10836
10907
 
@@ -12617,6 +12688,7 @@ const Wazo = {
12617
12688
  InvalidSubscription,
12618
12689
  InvalidAuthorization,
12619
12690
  CanceledCallError,
12691
+ SFUNotAvailableError,
12620
12692
  };
12621
12693
 
12622
12694
  if (window) {