@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
@@ -3260,6 +3260,7 @@ var updateFrom = (instance , from ) => {
3260
3260
 
3261
3261
 
3262
3262
 
3263
+
3263
3264
 
3264
3265
 
3265
3266
 
@@ -3307,14 +3308,14 @@ class CallSession {
3307
3308
 
3308
3309
 
3309
3310
 
3311
+ // = creationTime
3312
+
3310
3313
 
3311
3314
 
3312
3315
 
3313
3316
 
3314
3317
 
3315
3318
 
3316
-
3317
-
3318
3319
 
3319
3320
 
3320
3321
 
@@ -3378,6 +3379,7 @@ class CallSession {
3378
3379
  recordingPaused,
3379
3380
  videoRemotelyDowngraded,
3380
3381
  sipSession,
3382
+ answerTime,
3381
3383
  } ) {
3382
3384
  this.callId = callId;
3383
3385
  this.sipCallId = sipCallId;
@@ -3405,6 +3407,7 @@ class CallSession {
3405
3407
  this.recordingPaused = recordingPaused || false;
3406
3408
  this.videoRemotelyDowngraded = videoRemotelyDowngraded;
3407
3409
  this.sipSession = sipSession;
3410
+ this.answerTime = answerTime || this.answerTime;
3408
3411
 
3409
3412
  // Useful to compare instead of instanceof with minified code
3410
3413
  this.type = 'CallSession';
@@ -3435,7 +3438,7 @@ class CallSession {
3435
3438
  }
3436
3439
 
3437
3440
  answer() {
3438
- this.answered = true;
3441
+ this.answerTime = new Date();
3439
3442
  }
3440
3443
 
3441
3444
  systemAnswer() {
@@ -3591,6 +3594,15 @@ class CallSession {
3591
3594
  return newFrom(callSession, CallSession);
3592
3595
  }
3593
3596
 
3597
+ // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
3598
+ set answered(value ) {
3599
+ this.answerTime = value ? this.answerTime || new Date() : null;
3600
+ }
3601
+
3602
+ get answered() {
3603
+ return !!this.answerTime;
3604
+ }
3605
+
3594
3606
  static parseCall(call ) {
3595
3607
  return new CallSession({
3596
3608
  callId: call.id,
@@ -4842,6 +4854,34 @@ var chatdMethods = (client , baseUrl ) => ({
4842
4854
  client.get(`${baseUrl}/users/me/rooms/messages`, options),
4843
4855
  });
4844
4856
 
4857
+ //
4858
+
4859
+
4860
+
4861
+
4862
+
4863
+ class MeetingStatus {
4864
+
4865
+
4866
+
4867
+
4868
+ constructor({
4869
+ full,
4870
+ } = {}) {
4871
+ this.full = full;
4872
+
4873
+ // Useful to compare instead of instanceof with minified code
4874
+ this.type = 'MeetingStatus';
4875
+ }
4876
+
4877
+ static parse(plain ) {
4878
+ return new MeetingStatus({
4879
+ full: plain.full,
4880
+ });
4881
+ }
4882
+
4883
+ }
4884
+
4845
4885
  /* */
4846
4886
 
4847
4887
 
@@ -5036,6 +5076,8 @@ var calldMethods = (client , baseUrl ) => ({
5036
5076
  client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
5037
5077
  ApiRequester.successResponseParser),
5038
5078
 
5079
+ guestGetMeetingStatus: (meetingUuid ) =>
5080
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
5039
5081
  });
5040
5082
 
5041
5083
  //
@@ -6637,6 +6679,7 @@ const MAX_REGISTER_TRIES = 10;
6637
6679
 
6638
6680
 
6639
6681
 
6682
+
6640
6683
 
6641
6684
 
6642
6685
 
@@ -6678,6 +6721,7 @@ class WebRTCClient extends Emitter {
6678
6721
 
6679
6722
 
6680
6723
 
6724
+
6681
6725
 
6682
6726
  // sugar
6683
6727
 
@@ -6740,6 +6784,7 @@ class WebRTCClient extends Emitter {
6740
6784
  this.conferences = {};
6741
6785
  this.networkMonitoringInterval = {};
6742
6786
  this.sessionNetworkStats = {};
6787
+ this.forceClosed = false;
6743
6788
 
6744
6789
  this._boundOnHeartbeat = this._onHeartbeat.bind(this);
6745
6790
  this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
@@ -6861,6 +6906,8 @@ class WebRTCClient extends Emitter {
6861
6906
  skipRegister: this.skipRegister,
6862
6907
  };
6863
6908
 
6909
+ this.forceClosed = false;
6910
+
6864
6911
  if (this.skipRegister) {
6865
6912
  logger$8.info('sdk webrtc skip register...', logInfo);
6866
6913
  return Promise.resolve();
@@ -6885,7 +6932,15 @@ class WebRTCClient extends Emitter {
6885
6932
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6886
6933
 
6887
6934
  const onRegisterFailed = () => {
6888
- logger$8.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6935
+ logger$8.info('sdk webrtc registering failed', {
6936
+ tries,
6937
+ registerer: !!this.registerer,
6938
+ forceClosed: this.forceClosed,
6939
+ });
6940
+ if (this.forceClosed) {
6941
+ return;
6942
+ }
6943
+
6889
6944
  this.connectionPromise = null;
6890
6945
  if (this.registerer && this.registerer.waiting) {
6891
6946
  this.registerer.waitingToggle(false);
@@ -7163,8 +7218,9 @@ class WebRTCClient extends Emitter {
7163
7218
  }
7164
7219
  }
7165
7220
 
7166
- async close() {
7167
- logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
7221
+ async close(force = false) {
7222
+ logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
7223
+ this.forceClosed = force;
7168
7224
  this._cleanupMedia();
7169
7225
  this.connectionPromise = null;
7170
7226
 
@@ -7183,7 +7239,7 @@ class WebRTCClient extends Emitter {
7183
7239
  this.userAgent.delegate = null;
7184
7240
  this.userAgent.stateChange.removeAllListeners();
7185
7241
 
7186
- await this._disconnectTransport();
7242
+ await this._disconnectTransport(force);
7187
7243
 
7188
7244
  this._cleanupRegister();
7189
7245
 
@@ -8253,6 +8309,13 @@ class WebRTCClient extends Emitter {
8253
8309
  }
8254
8310
 
8255
8311
  _createWebRTCConfiguration(configOverrides = {}) {
8312
+ let { host } = this.config;
8313
+ let port = this.config.port || 443;
8314
+
8315
+ if (this.config.websocketSip) {
8316
+ [host, port = 443] = this.config.websocketSip.split(':');
8317
+ }
8318
+
8256
8319
  const config = {
8257
8320
  authorizationUsername: this.config.authorizationUser,
8258
8321
  authorizationPassword: this.config.password,
@@ -8288,7 +8351,7 @@ class WebRTCClient extends Emitter {
8288
8351
  },
8289
8352
  transportOptions: {
8290
8353
  traceSip: configOverrides.traceSip || false,
8291
- wsServers: `wss://${this.config.host}:${this.config.port || 443}/api/asterisk/ws`,
8354
+ wsServers: `wss://${host}:${port}/api/asterisk/ws`,
8292
8355
  },
8293
8356
  sessionDescriptionHandlerFactoryOptions: {
8294
8357
  modifiers: [replaceLocalIpModifier],
@@ -8612,7 +8675,15 @@ class WebRTCClient extends Emitter {
8612
8675
  return userAgent.UserAgent.makeURI(`sip:${target}@${this.config.host}`);
8613
8676
  }
8614
8677
 
8615
- async _disconnectTransport() {
8678
+ async _disconnectTransport(force = false) {
8679
+ if (force) {
8680
+ // Bypass sip.js state machine that prevent to close WS with the state `Connecting`
8681
+ this.userAgent.transport.disconnectResolve = () => {};
8682
+ // eslint-disable-next-line
8683
+ this.userAgent.transport._ws.close(1000);
8684
+ return;
8685
+ }
8686
+
8616
8687
  // Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
8617
8688
  if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
8618
8689
  try {
@@ -9348,6 +9419,8 @@ class WebRTCPhone extends Emitter {
9348
9419
  this.removeIncomingSessions(sipSessionId);
9349
9420
  }
9350
9421
 
9422
+ callSession.answerTime = new Date();
9423
+ this._updateCallSession(callSession);
9351
9424
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9352
9425
 
9353
9426
  return callSession;
@@ -9563,6 +9636,8 @@ class WebRTCPhone extends Emitter {
9563
9636
  }
9564
9637
 
9565
9638
  this.shouldSendReinvite = false;
9639
+ callSession.answerTime = new Date();
9640
+ this._updateCallSession(callSession);
9566
9641
  this.acceptedSessions[callSession.getId()] = true;
9567
9642
 
9568
9643
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9662,7 +9737,7 @@ class WebRTCPhone extends Emitter {
9662
9737
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
9663
9738
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
9664
9739
  logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9665
- this.holdSipSession(this.currentSipSession, callSession);
9740
+ this.holdSipSession(this.currentSipSession, this.currentCallSession);
9666
9741
  }
9667
9742
 
9668
9743
  const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
@@ -9873,6 +9948,7 @@ class WebRTCPhone extends Emitter {
9873
9948
  }
9874
9949
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9875
9950
  callSession.creationTime = new Date();
9951
+ this._updateCallSession(callSession);
9876
9952
 
9877
9953
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9878
9954
 
@@ -10014,7 +10090,7 @@ class WebRTCPhone extends Emitter {
10014
10090
  return this.client && this.client.isConference(callSession.sipCallId);
10015
10091
  }
10016
10092
 
10017
- async close() {
10093
+ async close(force = false) {
10018
10094
  logger$7.info('WebRTC close');
10019
10095
 
10020
10096
  try {
@@ -10026,7 +10102,7 @@ class WebRTCPhone extends Emitter {
10026
10102
  logger$7.error('WebRTC close, unregister error', e);
10027
10103
  }
10028
10104
 
10029
- this.client.close();
10105
+ this.client.close(force);
10030
10106
  this.unbind();
10031
10107
 
10032
10108
  this.incomingSessions = [];
@@ -10152,6 +10228,8 @@ class WebRTCPhone extends Emitter {
10152
10228
  }
10153
10229
 
10154
10230
  callSession.creationTime = new Date();
10231
+ this._updateCallSession(callSession);
10232
+
10155
10233
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
10156
10234
  });
10157
10235
 
@@ -10195,6 +10273,8 @@ class WebRTCPhone extends Emitter {
10195
10273
  logger$7.info('WebRTC call rejected', session.id);
10196
10274
  const callSession = this._createCallSession(session);
10197
10275
  callSession.endTime = new Date();
10276
+ this._updateCallSession(callSession);
10277
+
10198
10278
  this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
10199
10279
  });
10200
10280
 
@@ -10419,6 +10499,7 @@ class WebRTCPhone extends Emitter {
10419
10499
  displayName: identity ? identity.displayName || number : number,
10420
10500
  startTime: fromSession ? fromSession.startTime : new Date(),
10421
10501
  creationTime: fromSession ? fromSession.creationTime : null,
10502
+ answerTime: fromSession ? fromSession.answerTime : null,
10422
10503
  endTime: fromSession ? fromSession.endTime : null,
10423
10504
  answered: state === sessionState.SessionState.Established,
10424
10505
  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),