@wazo/sdk 0.37.28 → 0.37.32

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 (81) hide show
  1. package/README.md +2 -1
  2. package/dist/wazo-sdk.js +4 -4
  3. package/esm/__tests__/api-client.test.js +30 -0
  4. package/esm/__tests__/web-rtc-client.test.js +65 -6
  5. package/esm/api/calld.js +30 -0
  6. package/esm/api-client.js +30 -0
  7. package/esm/checker/Checker.js +65 -6
  8. package/esm/checker/checks/aor.js +30 -0
  9. package/esm/checker/checks/api.js +30 -0
  10. package/esm/checker/checks/index.js +65 -6
  11. package/esm/checker/checks/webrtc-transport.js +65 -6
  12. package/esm/checker/checks/webrtc.js +65 -6
  13. package/esm/domain/AdHocAPIConference.js +30 -0
  14. package/esm/domain/CallSession.js +15 -3
  15. package/esm/domain/Features.js +30 -0
  16. package/esm/domain/MeetingStatus.js +29 -0
  17. package/esm/domain/Phone/CTIPhone.js +45 -3
  18. package/esm/domain/Phone/WebRTCPhone.js +28 -6
  19. package/esm/domain/__tests__/CallSession.test.js +32 -3
  20. package/esm/domain/__tests__/IndirectTransfer.test.js +15 -3
  21. package/esm/domain/__tests__/Room.test.js +15 -3
  22. package/esm/index.js +93 -12
  23. package/esm/service/CallApi.js +30 -0
  24. package/esm/service/getApiClient.js +30 -0
  25. package/esm/simple/Auth.js +93 -12
  26. package/esm/simple/Configuration.js +93 -12
  27. package/esm/simple/Directory.js +30 -0
  28. package/esm/simple/Phone.js +93 -12
  29. package/esm/simple/index.js +93 -12
  30. package/esm/simple/room/LocalParticipant.js +93 -12
  31. package/esm/simple/room/Participant.js +93 -12
  32. package/esm/simple/room/RemoteParticipant.js +93 -12
  33. package/esm/simple/room/Room.js +93 -12
  34. package/esm/simple/room/SipRoom.js +93 -12
  35. package/esm/simple/room/Stream.js +93 -12
  36. package/esm/simple/room/__tests__/RemoteParticipant.test.js +93 -12
  37. package/esm/simple/utils.js +93 -12
  38. package/esm/web-rtc-client.js +65 -6
  39. package/lib/__tests__/api-client.test.js +30 -0
  40. package/lib/__tests__/web-rtc-client.test.js +65 -6
  41. package/lib/api/calld.js +30 -0
  42. package/lib/api-client.js +30 -0
  43. package/lib/checker/Checker.js +65 -6
  44. package/lib/checker/checks/aor.js +30 -0
  45. package/lib/checker/checks/api.js +30 -0
  46. package/lib/checker/checks/index.js +65 -6
  47. package/lib/checker/checks/webrtc-transport.js +65 -6
  48. package/lib/checker/checks/webrtc.js +65 -6
  49. package/lib/domain/AdHocAPIConference.js +30 -0
  50. package/lib/domain/CallSession.js +15 -3
  51. package/lib/domain/Features.js +30 -0
  52. package/lib/domain/MeetingStatus.js +31 -0
  53. package/lib/domain/Phone/CTIPhone.js +45 -3
  54. package/lib/domain/Phone/WebRTCPhone.js +28 -6
  55. package/lib/domain/__tests__/CallSession.test.js +32 -3
  56. package/lib/domain/__tests__/IndirectTransfer.test.js +15 -3
  57. package/lib/domain/__tests__/Room.test.js +15 -3
  58. package/lib/index.js +93 -12
  59. package/lib/service/CallApi.js +30 -0
  60. package/lib/service/getApiClient.js +30 -0
  61. package/lib/simple/Auth.js +93 -12
  62. package/lib/simple/Configuration.js +93 -12
  63. package/lib/simple/Directory.js +30 -0
  64. package/lib/simple/Phone.js +93 -12
  65. package/lib/simple/index.js +93 -12
  66. package/lib/simple/room/LocalParticipant.js +93 -12
  67. package/lib/simple/room/Participant.js +93 -12
  68. package/lib/simple/room/RemoteParticipant.js +93 -12
  69. package/lib/simple/room/Room.js +93 -12
  70. package/lib/simple/room/SipRoom.js +93 -12
  71. package/lib/simple/room/Stream.js +93 -12
  72. package/lib/simple/room/__tests__/RemoteParticipant.test.js +93 -12
  73. package/lib/simple/utils.js +93 -12
  74. package/lib/web-rtc-client.js +65 -6
  75. package/package.json +1 -1
  76. package/src/api/calld.js +3 -0
  77. package/src/domain/CallSession.js +16 -4
  78. package/src/domain/MeetingStatus.js +27 -0
  79. package/src/domain/Phone/WebRTCPhone.js +13 -3
  80. package/src/domain/__tests__/CallSession.test.js +17 -0
  81. package/src/web-rtc-client.js +35 -6
@@ -3258,6 +3258,7 @@ var updateFrom = (instance , from ) => {
3258
3258
 
3259
3259
 
3260
3260
 
3261
+
3261
3262
 
3262
3263
 
3263
3264
 
@@ -3305,14 +3306,14 @@ class CallSession {
3305
3306
 
3306
3307
 
3307
3308
 
3309
+ // = creationTime
3310
+
3308
3311
 
3309
3312
 
3310
3313
 
3311
3314
 
3312
3315
 
3313
3316
 
3314
-
3315
-
3316
3317
 
3317
3318
 
3318
3319
 
@@ -3376,6 +3377,7 @@ class CallSession {
3376
3377
  recordingPaused,
3377
3378
  videoRemotelyDowngraded,
3378
3379
  sipSession,
3380
+ answerTime,
3379
3381
  } ) {
3380
3382
  this.callId = callId;
3381
3383
  this.sipCallId = sipCallId;
@@ -3403,6 +3405,7 @@ class CallSession {
3403
3405
  this.recordingPaused = recordingPaused || false;
3404
3406
  this.videoRemotelyDowngraded = videoRemotelyDowngraded;
3405
3407
  this.sipSession = sipSession;
3408
+ this.answerTime = answerTime || this.answerTime;
3406
3409
 
3407
3410
  // Useful to compare instead of instanceof with minified code
3408
3411
  this.type = 'CallSession';
@@ -3433,7 +3436,7 @@ class CallSession {
3433
3436
  }
3434
3437
 
3435
3438
  answer() {
3436
- this.answered = true;
3439
+ this.answerTime = new Date();
3437
3440
  }
3438
3441
 
3439
3442
  systemAnswer() {
@@ -3589,6 +3592,15 @@ class CallSession {
3589
3592
  return newFrom(callSession, CallSession);
3590
3593
  }
3591
3594
 
3595
+ // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
3596
+ set answered(value ) {
3597
+ this.answerTime = value ? this.answerTime || new Date() : null;
3598
+ }
3599
+
3600
+ get answered() {
3601
+ return !!this.answerTime;
3602
+ }
3603
+
3592
3604
  static parseCall(call ) {
3593
3605
  return new CallSession({
3594
3606
  callId: call.id,
@@ -4840,6 +4852,34 @@ var chatdMethods = (client , baseUrl ) => ({
4840
4852
  client.get(`${baseUrl}/users/me/rooms/messages`, options),
4841
4853
  });
4842
4854
 
4855
+ //
4856
+
4857
+
4858
+
4859
+
4860
+
4861
+ class MeetingStatus {
4862
+
4863
+
4864
+
4865
+
4866
+ constructor({
4867
+ full,
4868
+ } = {}) {
4869
+ this.full = full;
4870
+
4871
+ // Useful to compare instead of instanceof with minified code
4872
+ this.type = 'MeetingStatus';
4873
+ }
4874
+
4875
+ static parse(plain ) {
4876
+ return new MeetingStatus({
4877
+ full: plain.full,
4878
+ });
4879
+ }
4880
+
4881
+ }
4882
+
4843
4883
  /* */
4844
4884
 
4845
4885
 
@@ -5034,6 +5074,8 @@ var calldMethods = (client , baseUrl ) => ({
5034
5074
  client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
5035
5075
  ApiRequester.successResponseParser),
5036
5076
 
5077
+ guestGetMeetingStatus: (meetingUuid ) =>
5078
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
5037
5079
  });
5038
5080
 
5039
5081
  //
@@ -6635,6 +6677,7 @@ const MAX_REGISTER_TRIES = 10;
6635
6677
 
6636
6678
 
6637
6679
 
6680
+
6638
6681
 
6639
6682
 
6640
6683
 
@@ -6676,6 +6719,7 @@ class WebRTCClient extends Emitter {
6676
6719
 
6677
6720
 
6678
6721
 
6722
+
6679
6723
 
6680
6724
  // sugar
6681
6725
 
@@ -6738,6 +6782,7 @@ class WebRTCClient extends Emitter {
6738
6782
  this.conferences = {};
6739
6783
  this.networkMonitoringInterval = {};
6740
6784
  this.sessionNetworkStats = {};
6785
+ this.forceClosed = false;
6741
6786
 
6742
6787
  this._boundOnHeartbeat = this._onHeartbeat.bind(this);
6743
6788
  this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
@@ -6859,6 +6904,8 @@ class WebRTCClient extends Emitter {
6859
6904
  skipRegister: this.skipRegister,
6860
6905
  };
6861
6906
 
6907
+ this.forceClosed = false;
6908
+
6862
6909
  if (this.skipRegister) {
6863
6910
  logger$8.info('sdk webrtc skip register...', logInfo);
6864
6911
  return Promise.resolve();
@@ -6883,7 +6930,15 @@ class WebRTCClient extends Emitter {
6883
6930
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6884
6931
 
6885
6932
  const onRegisterFailed = () => {
6886
- logger$8.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6933
+ logger$8.info('sdk webrtc registering failed', {
6934
+ tries,
6935
+ registerer: !!this.registerer,
6936
+ forceClosed: this.forceClosed,
6937
+ });
6938
+ if (this.forceClosed) {
6939
+ return;
6940
+ }
6941
+
6887
6942
  this.connectionPromise = null;
6888
6943
  if (this.registerer && this.registerer.waiting) {
6889
6944
  this.registerer.waitingToggle(false);
@@ -7161,8 +7216,9 @@ class WebRTCClient extends Emitter {
7161
7216
  }
7162
7217
  }
7163
7218
 
7164
- async close() {
7165
- logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
7219
+ async close(force = false) {
7220
+ logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
7221
+ this.forceClosed = force;
7166
7222
  this._cleanupMedia();
7167
7223
  this.connectionPromise = null;
7168
7224
 
@@ -7181,7 +7237,7 @@ class WebRTCClient extends Emitter {
7181
7237
  this.userAgent.delegate = null;
7182
7238
  this.userAgent.stateChange.removeAllListeners();
7183
7239
 
7184
- await this._disconnectTransport();
7240
+ await this._disconnectTransport(force);
7185
7241
 
7186
7242
  this._cleanupRegister();
7187
7243
 
@@ -8251,6 +8307,13 @@ class WebRTCClient extends Emitter {
8251
8307
  }
8252
8308
 
8253
8309
  _createWebRTCConfiguration(configOverrides = {}) {
8310
+ let { host } = this.config;
8311
+ let port = this.config.port || 443;
8312
+
8313
+ if (this.config.websocketSip) {
8314
+ [host, port = 443] = this.config.websocketSip.split(':');
8315
+ }
8316
+
8254
8317
  const config = {
8255
8318
  authorizationUsername: this.config.authorizationUser,
8256
8319
  authorizationPassword: this.config.password,
@@ -8286,7 +8349,7 @@ class WebRTCClient extends Emitter {
8286
8349
  },
8287
8350
  transportOptions: {
8288
8351
  traceSip: configOverrides.traceSip || false,
8289
- wsServers: `wss://${this.config.host}:${this.config.port || 443}/api/asterisk/ws`,
8352
+ wsServers: `wss://${host}:${port}/api/asterisk/ws`,
8290
8353
  },
8291
8354
  sessionDescriptionHandlerFactoryOptions: {
8292
8355
  modifiers: [replaceLocalIpModifier],
@@ -8610,7 +8673,15 @@ class WebRTCClient extends Emitter {
8610
8673
  return userAgent.UserAgent.makeURI(`sip:${target}@${this.config.host}`);
8611
8674
  }
8612
8675
 
8613
- async _disconnectTransport() {
8676
+ async _disconnectTransport(force = false) {
8677
+ if (force) {
8678
+ // Bypass sip.js state machine that prevent to close WS with the state `Connecting`
8679
+ this.userAgent.transport.disconnectResolve = () => {};
8680
+ // eslint-disable-next-line
8681
+ this.userAgent.transport._ws.close(1000);
8682
+ return;
8683
+ }
8684
+
8614
8685
  // Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
8615
8686
  if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
8616
8687
  try {
@@ -9346,6 +9417,8 @@ class WebRTCPhone extends Emitter {
9346
9417
  this.removeIncomingSessions(sipSessionId);
9347
9418
  }
9348
9419
 
9420
+ callSession.answerTime = new Date();
9421
+ this._updateCallSession(callSession);
9349
9422
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9350
9423
 
9351
9424
  return callSession;
@@ -9561,6 +9634,8 @@ class WebRTCPhone extends Emitter {
9561
9634
  }
9562
9635
 
9563
9636
  this.shouldSendReinvite = false;
9637
+ callSession.answerTime = new Date();
9638
+ this._updateCallSession(callSession);
9564
9639
  this.acceptedSessions[callSession.getId()] = true;
9565
9640
 
9566
9641
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9660,7 +9735,7 @@ class WebRTCPhone extends Emitter {
9660
9735
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
9661
9736
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
9662
9737
  logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9663
- this.holdSipSession(this.currentSipSession, callSession);
9738
+ this.holdSipSession(this.currentSipSession, this.currentCallSession);
9664
9739
  }
9665
9740
 
9666
9741
  const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
@@ -9871,6 +9946,7 @@ class WebRTCPhone extends Emitter {
9871
9946
  }
9872
9947
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9873
9948
  callSession.creationTime = new Date();
9949
+ this._updateCallSession(callSession);
9874
9950
 
9875
9951
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9876
9952
 
@@ -10012,7 +10088,7 @@ class WebRTCPhone extends Emitter {
10012
10088
  return this.client && this.client.isConference(callSession.sipCallId);
10013
10089
  }
10014
10090
 
10015
- async close() {
10091
+ async close(force = false) {
10016
10092
  logger$7.info('WebRTC close');
10017
10093
 
10018
10094
  try {
@@ -10024,7 +10100,7 @@ class WebRTCPhone extends Emitter {
10024
10100
  logger$7.error('WebRTC close, unregister error', e);
10025
10101
  }
10026
10102
 
10027
- this.client.close();
10103
+ this.client.close(force);
10028
10104
  this.unbind();
10029
10105
 
10030
10106
  this.incomingSessions = [];
@@ -10150,6 +10226,8 @@ class WebRTCPhone extends Emitter {
10150
10226
  }
10151
10227
 
10152
10228
  callSession.creationTime = new Date();
10229
+ this._updateCallSession(callSession);
10230
+
10153
10231
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
10154
10232
  });
10155
10233
 
@@ -10193,6 +10271,8 @@ class WebRTCPhone extends Emitter {
10193
10271
  logger$7.info('WebRTC call rejected', session.id);
10194
10272
  const callSession = this._createCallSession(session);
10195
10273
  callSession.endTime = new Date();
10274
+ this._updateCallSession(callSession);
10275
+
10196
10276
  this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
10197
10277
  });
10198
10278
 
@@ -10417,6 +10497,7 @@ class WebRTCPhone extends Emitter {
10417
10497
  displayName: identity ? identity.displayName || number : number,
10418
10498
  startTime: fromSession ? fromSession.startTime : new Date(),
10419
10499
  creationTime: fromSession ? fromSession.creationTime : null,
10500
+ answerTime: fromSession ? fromSession.answerTime : null,
10420
10501
  endTime: fromSession ? fromSession.endTime : null,
10421
10502
  answered: state === sessionState.SessionState.Established,
10422
10503
  paused: this.client.isCallHeld(sipSession),
@@ -3258,6 +3258,7 @@ var updateFrom = (instance , from ) => {
3258
3258
 
3259
3259
 
3260
3260
 
3261
+
3261
3262
 
3262
3263
 
3263
3264
 
@@ -3305,14 +3306,14 @@ class CallSession {
3305
3306
 
3306
3307
 
3307
3308
 
3309
+ // = creationTime
3310
+
3308
3311
 
3309
3312
 
3310
3313
 
3311
3314
 
3312
3315
 
3313
3316
 
3314
-
3315
-
3316
3317
 
3317
3318
 
3318
3319
 
@@ -3376,6 +3377,7 @@ class CallSession {
3376
3377
  recordingPaused,
3377
3378
  videoRemotelyDowngraded,
3378
3379
  sipSession,
3380
+ answerTime,
3379
3381
  } ) {
3380
3382
  this.callId = callId;
3381
3383
  this.sipCallId = sipCallId;
@@ -3403,6 +3405,7 @@ class CallSession {
3403
3405
  this.recordingPaused = recordingPaused || false;
3404
3406
  this.videoRemotelyDowngraded = videoRemotelyDowngraded;
3405
3407
  this.sipSession = sipSession;
3408
+ this.answerTime = answerTime || this.answerTime;
3406
3409
 
3407
3410
  // Useful to compare instead of instanceof with minified code
3408
3411
  this.type = 'CallSession';
@@ -3433,7 +3436,7 @@ class CallSession {
3433
3436
  }
3434
3437
 
3435
3438
  answer() {
3436
- this.answered = true;
3439
+ this.answerTime = new Date();
3437
3440
  }
3438
3441
 
3439
3442
  systemAnswer() {
@@ -3589,6 +3592,15 @@ class CallSession {
3589
3592
  return newFrom(callSession, CallSession);
3590
3593
  }
3591
3594
 
3595
+ // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
3596
+ set answered(value ) {
3597
+ this.answerTime = value ? this.answerTime || new Date() : null;
3598
+ }
3599
+
3600
+ get answered() {
3601
+ return !!this.answerTime;
3602
+ }
3603
+
3592
3604
  static parseCall(call ) {
3593
3605
  return new CallSession({
3594
3606
  callId: call.id,
@@ -4840,6 +4852,34 @@ var chatdMethods = (client , baseUrl ) => ({
4840
4852
  client.get(`${baseUrl}/users/me/rooms/messages`, options),
4841
4853
  });
4842
4854
 
4855
+ //
4856
+
4857
+
4858
+
4859
+
4860
+
4861
+ class MeetingStatus {
4862
+
4863
+
4864
+
4865
+
4866
+ constructor({
4867
+ full,
4868
+ } = {}) {
4869
+ this.full = full;
4870
+
4871
+ // Useful to compare instead of instanceof with minified code
4872
+ this.type = 'MeetingStatus';
4873
+ }
4874
+
4875
+ static parse(plain ) {
4876
+ return new MeetingStatus({
4877
+ full: plain.full,
4878
+ });
4879
+ }
4880
+
4881
+ }
4882
+
4843
4883
  /* */
4844
4884
 
4845
4885
 
@@ -5034,6 +5074,8 @@ var calldMethods = (client , baseUrl ) => ({
5034
5074
  client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
5035
5075
  ApiRequester.successResponseParser),
5036
5076
 
5077
+ guestGetMeetingStatus: (meetingUuid ) =>
5078
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
5037
5079
  });
5038
5080
 
5039
5081
  //
@@ -6635,6 +6677,7 @@ const MAX_REGISTER_TRIES = 10;
6635
6677
 
6636
6678
 
6637
6679
 
6680
+
6638
6681
 
6639
6682
 
6640
6683
 
@@ -6676,6 +6719,7 @@ class WebRTCClient extends Emitter {
6676
6719
 
6677
6720
 
6678
6721
 
6722
+
6679
6723
 
6680
6724
  // sugar
6681
6725
 
@@ -6738,6 +6782,7 @@ class WebRTCClient extends Emitter {
6738
6782
  this.conferences = {};
6739
6783
  this.networkMonitoringInterval = {};
6740
6784
  this.sessionNetworkStats = {};
6785
+ this.forceClosed = false;
6741
6786
 
6742
6787
  this._boundOnHeartbeat = this._onHeartbeat.bind(this);
6743
6788
  this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
@@ -6859,6 +6904,8 @@ class WebRTCClient extends Emitter {
6859
6904
  skipRegister: this.skipRegister,
6860
6905
  };
6861
6906
 
6907
+ this.forceClosed = false;
6908
+
6862
6909
  if (this.skipRegister) {
6863
6910
  logger$8.info('sdk webrtc skip register...', logInfo);
6864
6911
  return Promise.resolve();
@@ -6883,7 +6930,15 @@ class WebRTCClient extends Emitter {
6883
6930
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6884
6931
 
6885
6932
  const onRegisterFailed = () => {
6886
- logger$8.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6933
+ logger$8.info('sdk webrtc registering failed', {
6934
+ tries,
6935
+ registerer: !!this.registerer,
6936
+ forceClosed: this.forceClosed,
6937
+ });
6938
+ if (this.forceClosed) {
6939
+ return;
6940
+ }
6941
+
6887
6942
  this.connectionPromise = null;
6888
6943
  if (this.registerer && this.registerer.waiting) {
6889
6944
  this.registerer.waitingToggle(false);
@@ -7161,8 +7216,9 @@ class WebRTCClient extends Emitter {
7161
7216
  }
7162
7217
  }
7163
7218
 
7164
- async close() {
7165
- logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
7219
+ async close(force = false) {
7220
+ logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
7221
+ this.forceClosed = force;
7166
7222
  this._cleanupMedia();
7167
7223
  this.connectionPromise = null;
7168
7224
 
@@ -7181,7 +7237,7 @@ class WebRTCClient extends Emitter {
7181
7237
  this.userAgent.delegate = null;
7182
7238
  this.userAgent.stateChange.removeAllListeners();
7183
7239
 
7184
- await this._disconnectTransport();
7240
+ await this._disconnectTransport(force);
7185
7241
 
7186
7242
  this._cleanupRegister();
7187
7243
 
@@ -8251,6 +8307,13 @@ class WebRTCClient extends Emitter {
8251
8307
  }
8252
8308
 
8253
8309
  _createWebRTCConfiguration(configOverrides = {}) {
8310
+ let { host } = this.config;
8311
+ let port = this.config.port || 443;
8312
+
8313
+ if (this.config.websocketSip) {
8314
+ [host, port = 443] = this.config.websocketSip.split(':');
8315
+ }
8316
+
8254
8317
  const config = {
8255
8318
  authorizationUsername: this.config.authorizationUser,
8256
8319
  authorizationPassword: this.config.password,
@@ -8286,7 +8349,7 @@ class WebRTCClient extends Emitter {
8286
8349
  },
8287
8350
  transportOptions: {
8288
8351
  traceSip: configOverrides.traceSip || false,
8289
- wsServers: `wss://${this.config.host}:${this.config.port || 443}/api/asterisk/ws`,
8352
+ wsServers: `wss://${host}:${port}/api/asterisk/ws`,
8290
8353
  },
8291
8354
  sessionDescriptionHandlerFactoryOptions: {
8292
8355
  modifiers: [replaceLocalIpModifier],
@@ -8610,7 +8673,15 @@ class WebRTCClient extends Emitter {
8610
8673
  return userAgent.UserAgent.makeURI(`sip:${target}@${this.config.host}`);
8611
8674
  }
8612
8675
 
8613
- async _disconnectTransport() {
8676
+ async _disconnectTransport(force = false) {
8677
+ if (force) {
8678
+ // Bypass sip.js state machine that prevent to close WS with the state `Connecting`
8679
+ this.userAgent.transport.disconnectResolve = () => {};
8680
+ // eslint-disable-next-line
8681
+ this.userAgent.transport._ws.close(1000);
8682
+ return;
8683
+ }
8684
+
8614
8685
  // Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
8615
8686
  if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
8616
8687
  try {
@@ -9346,6 +9417,8 @@ class WebRTCPhone extends Emitter {
9346
9417
  this.removeIncomingSessions(sipSessionId);
9347
9418
  }
9348
9419
 
9420
+ callSession.answerTime = new Date();
9421
+ this._updateCallSession(callSession);
9349
9422
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9350
9423
 
9351
9424
  return callSession;
@@ -9561,6 +9634,8 @@ class WebRTCPhone extends Emitter {
9561
9634
  }
9562
9635
 
9563
9636
  this.shouldSendReinvite = false;
9637
+ callSession.answerTime = new Date();
9638
+ this._updateCallSession(callSession);
9564
9639
  this.acceptedSessions[callSession.getId()] = true;
9565
9640
 
9566
9641
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9660,7 +9735,7 @@ class WebRTCPhone extends Emitter {
9660
9735
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
9661
9736
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
9662
9737
  logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9663
- this.holdSipSession(this.currentSipSession, callSession);
9738
+ this.holdSipSession(this.currentSipSession, this.currentCallSession);
9664
9739
  }
9665
9740
 
9666
9741
  const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
@@ -9871,6 +9946,7 @@ class WebRTCPhone extends Emitter {
9871
9946
  }
9872
9947
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9873
9948
  callSession.creationTime = new Date();
9949
+ this._updateCallSession(callSession);
9874
9950
 
9875
9951
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9876
9952
 
@@ -10012,7 +10088,7 @@ class WebRTCPhone extends Emitter {
10012
10088
  return this.client && this.client.isConference(callSession.sipCallId);
10013
10089
  }
10014
10090
 
10015
- async close() {
10091
+ async close(force = false) {
10016
10092
  logger$7.info('WebRTC close');
10017
10093
 
10018
10094
  try {
@@ -10024,7 +10100,7 @@ class WebRTCPhone extends Emitter {
10024
10100
  logger$7.error('WebRTC close, unregister error', e);
10025
10101
  }
10026
10102
 
10027
- this.client.close();
10103
+ this.client.close(force);
10028
10104
  this.unbind();
10029
10105
 
10030
10106
  this.incomingSessions = [];
@@ -10150,6 +10226,8 @@ class WebRTCPhone extends Emitter {
10150
10226
  }
10151
10227
 
10152
10228
  callSession.creationTime = new Date();
10229
+ this._updateCallSession(callSession);
10230
+
10153
10231
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
10154
10232
  });
10155
10233
 
@@ -10193,6 +10271,8 @@ class WebRTCPhone extends Emitter {
10193
10271
  logger$7.info('WebRTC call rejected', session.id);
10194
10272
  const callSession = this._createCallSession(session);
10195
10273
  callSession.endTime = new Date();
10274
+ this._updateCallSession(callSession);
10275
+
10196
10276
  this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
10197
10277
  });
10198
10278
 
@@ -10417,6 +10497,7 @@ class WebRTCPhone extends Emitter {
10417
10497
  displayName: identity ? identity.displayName || number : number,
10418
10498
  startTime: fromSession ? fromSession.startTime : new Date(),
10419
10499
  creationTime: fromSession ? fromSession.creationTime : null,
10500
+ answerTime: fromSession ? fromSession.answerTime : null,
10420
10501
  endTime: fromSession ? fromSession.endTime : null,
10421
10502
  answered: state === sessionState.SessionState.Established,
10422
10503
  paused: this.client.isCallHeld(sipSession),