@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
@@ -3274,6 +3274,7 @@ var updateFrom = (instance , from ) => {
3274
3274
 
3275
3275
 
3276
3276
 
3277
+
3277
3278
 
3278
3279
 
3279
3280
 
@@ -3321,14 +3322,14 @@ class CallSession {
3321
3322
 
3322
3323
 
3323
3324
 
3325
+ // = creationTime
3326
+
3324
3327
 
3325
3328
 
3326
3329
 
3327
3330
 
3328
3331
 
3329
3332
 
3330
-
3331
-
3332
3333
 
3333
3334
 
3334
3335
 
@@ -3392,6 +3393,7 @@ class CallSession {
3392
3393
  recordingPaused,
3393
3394
  videoRemotelyDowngraded,
3394
3395
  sipSession,
3396
+ answerTime,
3395
3397
  } ) {
3396
3398
  this.callId = callId;
3397
3399
  this.sipCallId = sipCallId;
@@ -3419,6 +3421,7 @@ class CallSession {
3419
3421
  this.recordingPaused = recordingPaused || false;
3420
3422
  this.videoRemotelyDowngraded = videoRemotelyDowngraded;
3421
3423
  this.sipSession = sipSession;
3424
+ this.answerTime = answerTime || this.answerTime;
3422
3425
 
3423
3426
  // Useful to compare instead of instanceof with minified code
3424
3427
  this.type = 'CallSession';
@@ -3449,7 +3452,7 @@ class CallSession {
3449
3452
  }
3450
3453
 
3451
3454
  answer() {
3452
- this.answered = true;
3455
+ this.answerTime = new Date();
3453
3456
  }
3454
3457
 
3455
3458
  systemAnswer() {
@@ -3605,6 +3608,15 @@ class CallSession {
3605
3608
  return newFrom(callSession, CallSession);
3606
3609
  }
3607
3610
 
3611
+ // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
3612
+ set answered(value ) {
3613
+ this.answerTime = value ? this.answerTime || new Date() : null;
3614
+ }
3615
+
3616
+ get answered() {
3617
+ return !!this.answerTime;
3618
+ }
3619
+
3608
3620
  static parseCall(call ) {
3609
3621
  return new CallSession({
3610
3622
  callId: call.id,
@@ -4830,6 +4842,34 @@ var chatdMethods = (client , baseUrl ) => ({
4830
4842
  client.get(`${baseUrl}/users/me/rooms/messages`, options),
4831
4843
  });
4832
4844
 
4845
+ //
4846
+
4847
+
4848
+
4849
+
4850
+
4851
+ class MeetingStatus {
4852
+
4853
+
4854
+
4855
+
4856
+ constructor({
4857
+ full,
4858
+ } = {}) {
4859
+ this.full = full;
4860
+
4861
+ // Useful to compare instead of instanceof with minified code
4862
+ this.type = 'MeetingStatus';
4863
+ }
4864
+
4865
+ static parse(plain ) {
4866
+ return new MeetingStatus({
4867
+ full: plain.full,
4868
+ });
4869
+ }
4870
+
4871
+ }
4872
+
4833
4873
  /* */
4834
4874
 
4835
4875
 
@@ -5024,6 +5064,8 @@ var calldMethods = (client , baseUrl ) => ({
5024
5064
  client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
5025
5065
  ApiRequester.successResponseParser),
5026
5066
 
5067
+ guestGetMeetingStatus: (meetingUuid ) =>
5068
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
5027
5069
  });
5028
5070
 
5029
5071
  //
@@ -6625,6 +6667,7 @@ const MAX_REGISTER_TRIES = 10;
6625
6667
 
6626
6668
 
6627
6669
 
6670
+
6628
6671
 
6629
6672
 
6630
6673
 
@@ -6666,6 +6709,7 @@ class WebRTCClient extends Emitter {
6666
6709
 
6667
6710
 
6668
6711
 
6712
+
6669
6713
 
6670
6714
  // sugar
6671
6715
 
@@ -6728,6 +6772,7 @@ class WebRTCClient extends Emitter {
6728
6772
  this.conferences = {};
6729
6773
  this.networkMonitoringInterval = {};
6730
6774
  this.sessionNetworkStats = {};
6775
+ this.forceClosed = false;
6731
6776
 
6732
6777
  this._boundOnHeartbeat = this._onHeartbeat.bind(this);
6733
6778
  this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
@@ -6849,6 +6894,8 @@ class WebRTCClient extends Emitter {
6849
6894
  skipRegister: this.skipRegister,
6850
6895
  };
6851
6896
 
6897
+ this.forceClosed = false;
6898
+
6852
6899
  if (this.skipRegister) {
6853
6900
  logger$8.info('sdk webrtc skip register...', logInfo);
6854
6901
  return Promise.resolve();
@@ -6873,7 +6920,15 @@ class WebRTCClient extends Emitter {
6873
6920
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6874
6921
 
6875
6922
  const onRegisterFailed = () => {
6876
- logger$8.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6923
+ logger$8.info('sdk webrtc registering failed', {
6924
+ tries,
6925
+ registerer: !!this.registerer,
6926
+ forceClosed: this.forceClosed,
6927
+ });
6928
+ if (this.forceClosed) {
6929
+ return;
6930
+ }
6931
+
6877
6932
  this.connectionPromise = null;
6878
6933
  if (this.registerer && this.registerer.waiting) {
6879
6934
  this.registerer.waitingToggle(false);
@@ -7151,8 +7206,9 @@ class WebRTCClient extends Emitter {
7151
7206
  }
7152
7207
  }
7153
7208
 
7154
- async close() {
7155
- logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
7209
+ async close(force = false) {
7210
+ logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
7211
+ this.forceClosed = force;
7156
7212
  this._cleanupMedia();
7157
7213
  this.connectionPromise = null;
7158
7214
 
@@ -7171,7 +7227,7 @@ class WebRTCClient extends Emitter {
7171
7227
  this.userAgent.delegate = null;
7172
7228
  this.userAgent.stateChange.removeAllListeners();
7173
7229
 
7174
- await this._disconnectTransport();
7230
+ await this._disconnectTransport(force);
7175
7231
 
7176
7232
  this._cleanupRegister();
7177
7233
 
@@ -8241,6 +8297,13 @@ class WebRTCClient extends Emitter {
8241
8297
  }
8242
8298
 
8243
8299
  _createWebRTCConfiguration(configOverrides = {}) {
8300
+ let { host } = this.config;
8301
+ let port = this.config.port || 443;
8302
+
8303
+ if (this.config.websocketSip) {
8304
+ [host, port = 443] = this.config.websocketSip.split(':');
8305
+ }
8306
+
8244
8307
  const config = {
8245
8308
  authorizationUsername: this.config.authorizationUser,
8246
8309
  authorizationPassword: this.config.password,
@@ -8276,7 +8339,7 @@ class WebRTCClient extends Emitter {
8276
8339
  },
8277
8340
  transportOptions: {
8278
8341
  traceSip: configOverrides.traceSip || false,
8279
- wsServers: `wss://${this.config.host}:${this.config.port || 443}/api/asterisk/ws`,
8342
+ wsServers: `wss://${host}:${port}/api/asterisk/ws`,
8280
8343
  },
8281
8344
  sessionDescriptionHandlerFactoryOptions: {
8282
8345
  modifiers: [replaceLocalIpModifier],
@@ -8600,7 +8663,15 @@ class WebRTCClient extends Emitter {
8600
8663
  return UserAgent.makeURI(`sip:${target}@${this.config.host}`);
8601
8664
  }
8602
8665
 
8603
- async _disconnectTransport() {
8666
+ async _disconnectTransport(force = false) {
8667
+ if (force) {
8668
+ // Bypass sip.js state machine that prevent to close WS with the state `Connecting`
8669
+ this.userAgent.transport.disconnectResolve = () => {};
8670
+ // eslint-disable-next-line
8671
+ this.userAgent.transport._ws.close(1000);
8672
+ return;
8673
+ }
8674
+
8604
8675
  // Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
8605
8676
  if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
8606
8677
  try {
@@ -9336,6 +9407,8 @@ class WebRTCPhone extends Emitter {
9336
9407
  this.removeIncomingSessions(sipSessionId);
9337
9408
  }
9338
9409
 
9410
+ callSession.answerTime = new Date();
9411
+ this._updateCallSession(callSession);
9339
9412
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9340
9413
 
9341
9414
  return callSession;
@@ -9551,6 +9624,8 @@ class WebRTCPhone extends Emitter {
9551
9624
  }
9552
9625
 
9553
9626
  this.shouldSendReinvite = false;
9627
+ callSession.answerTime = new Date();
9628
+ this._updateCallSession(callSession);
9554
9629
  this.acceptedSessions[callSession.getId()] = true;
9555
9630
 
9556
9631
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9650,7 +9725,7 @@ class WebRTCPhone extends Emitter {
9650
9725
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
9651
9726
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
9652
9727
  logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9653
- this.holdSipSession(this.currentSipSession, callSession);
9728
+ this.holdSipSession(this.currentSipSession, this.currentCallSession);
9654
9729
  }
9655
9730
 
9656
9731
  const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
@@ -9861,6 +9936,7 @@ class WebRTCPhone extends Emitter {
9861
9936
  }
9862
9937
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9863
9938
  callSession.creationTime = new Date();
9939
+ this._updateCallSession(callSession);
9864
9940
 
9865
9941
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9866
9942
 
@@ -10002,7 +10078,7 @@ class WebRTCPhone extends Emitter {
10002
10078
  return this.client && this.client.isConference(callSession.sipCallId);
10003
10079
  }
10004
10080
 
10005
- async close() {
10081
+ async close(force = false) {
10006
10082
  logger$7.info('WebRTC close');
10007
10083
 
10008
10084
  try {
@@ -10014,7 +10090,7 @@ class WebRTCPhone extends Emitter {
10014
10090
  logger$7.error('WebRTC close, unregister error', e);
10015
10091
  }
10016
10092
 
10017
- this.client.close();
10093
+ this.client.close(force);
10018
10094
  this.unbind();
10019
10095
 
10020
10096
  this.incomingSessions = [];
@@ -10140,6 +10216,8 @@ class WebRTCPhone extends Emitter {
10140
10216
  }
10141
10217
 
10142
10218
  callSession.creationTime = new Date();
10219
+ this._updateCallSession(callSession);
10220
+
10143
10221
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
10144
10222
  });
10145
10223
 
@@ -10183,6 +10261,8 @@ class WebRTCPhone extends Emitter {
10183
10261
  logger$7.info('WebRTC call rejected', session.id);
10184
10262
  const callSession = this._createCallSession(session);
10185
10263
  callSession.endTime = new Date();
10264
+ this._updateCallSession(callSession);
10265
+
10186
10266
  this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
10187
10267
  });
10188
10268
 
@@ -10407,6 +10487,7 @@ class WebRTCPhone extends Emitter {
10407
10487
  displayName: identity ? identity.displayName || number : number,
10408
10488
  startTime: fromSession ? fromSession.startTime : new Date(),
10409
10489
  creationTime: fromSession ? fromSession.creationTime : null,
10490
+ answerTime: fromSession ? fromSession.answerTime : null,
10410
10491
  endTime: fromSession ? fromSession.endTime : null,
10411
10492
  answered: state === SessionState.Established,
10412
10493
  paused: this.client.isCallHeld(sipSession),
@@ -3274,6 +3274,7 @@ var updateFrom = (instance , from ) => {
3274
3274
 
3275
3275
 
3276
3276
 
3277
+
3277
3278
 
3278
3279
 
3279
3280
 
@@ -3321,14 +3322,14 @@ class CallSession {
3321
3322
 
3322
3323
 
3323
3324
 
3325
+ // = creationTime
3326
+
3324
3327
 
3325
3328
 
3326
3329
 
3327
3330
 
3328
3331
 
3329
3332
 
3330
-
3331
-
3332
3333
 
3333
3334
 
3334
3335
 
@@ -3392,6 +3393,7 @@ class CallSession {
3392
3393
  recordingPaused,
3393
3394
  videoRemotelyDowngraded,
3394
3395
  sipSession,
3396
+ answerTime,
3395
3397
  } ) {
3396
3398
  this.callId = callId;
3397
3399
  this.sipCallId = sipCallId;
@@ -3419,6 +3421,7 @@ class CallSession {
3419
3421
  this.recordingPaused = recordingPaused || false;
3420
3422
  this.videoRemotelyDowngraded = videoRemotelyDowngraded;
3421
3423
  this.sipSession = sipSession;
3424
+ this.answerTime = answerTime || this.answerTime;
3422
3425
 
3423
3426
  // Useful to compare instead of instanceof with minified code
3424
3427
  this.type = 'CallSession';
@@ -3449,7 +3452,7 @@ class CallSession {
3449
3452
  }
3450
3453
 
3451
3454
  answer() {
3452
- this.answered = true;
3455
+ this.answerTime = new Date();
3453
3456
  }
3454
3457
 
3455
3458
  systemAnswer() {
@@ -3605,6 +3608,15 @@ class CallSession {
3605
3608
  return newFrom(callSession, CallSession);
3606
3609
  }
3607
3610
 
3611
+ // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
3612
+ set answered(value ) {
3613
+ this.answerTime = value ? this.answerTime || new Date() : null;
3614
+ }
3615
+
3616
+ get answered() {
3617
+ return !!this.answerTime;
3618
+ }
3619
+
3608
3620
  static parseCall(call ) {
3609
3621
  return new CallSession({
3610
3622
  callId: call.id,
@@ -4830,6 +4842,34 @@ var chatdMethods = (client , baseUrl ) => ({
4830
4842
  client.get(`${baseUrl}/users/me/rooms/messages`, options),
4831
4843
  });
4832
4844
 
4845
+ //
4846
+
4847
+
4848
+
4849
+
4850
+
4851
+ class MeetingStatus {
4852
+
4853
+
4854
+
4855
+
4856
+ constructor({
4857
+ full,
4858
+ } = {}) {
4859
+ this.full = full;
4860
+
4861
+ // Useful to compare instead of instanceof with minified code
4862
+ this.type = 'MeetingStatus';
4863
+ }
4864
+
4865
+ static parse(plain ) {
4866
+ return new MeetingStatus({
4867
+ full: plain.full,
4868
+ });
4869
+ }
4870
+
4871
+ }
4872
+
4833
4873
  /* */
4834
4874
 
4835
4875
 
@@ -5024,6 +5064,8 @@ var calldMethods = (client , baseUrl ) => ({
5024
5064
  client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
5025
5065
  ApiRequester.successResponseParser),
5026
5066
 
5067
+ guestGetMeetingStatus: (meetingUuid ) =>
5068
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
5027
5069
  });
5028
5070
 
5029
5071
  //
@@ -6625,6 +6667,7 @@ const MAX_REGISTER_TRIES = 10;
6625
6667
 
6626
6668
 
6627
6669
 
6670
+
6628
6671
 
6629
6672
 
6630
6673
 
@@ -6666,6 +6709,7 @@ class WebRTCClient extends Emitter {
6666
6709
 
6667
6710
 
6668
6711
 
6712
+
6669
6713
 
6670
6714
  // sugar
6671
6715
 
@@ -6728,6 +6772,7 @@ class WebRTCClient extends Emitter {
6728
6772
  this.conferences = {};
6729
6773
  this.networkMonitoringInterval = {};
6730
6774
  this.sessionNetworkStats = {};
6775
+ this.forceClosed = false;
6731
6776
 
6732
6777
  this._boundOnHeartbeat = this._onHeartbeat.bind(this);
6733
6778
  this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
@@ -6849,6 +6894,8 @@ class WebRTCClient extends Emitter {
6849
6894
  skipRegister: this.skipRegister,
6850
6895
  };
6851
6896
 
6897
+ this.forceClosed = false;
6898
+
6852
6899
  if (this.skipRegister) {
6853
6900
  logger$8.info('sdk webrtc skip register...', logInfo);
6854
6901
  return Promise.resolve();
@@ -6873,7 +6920,15 @@ class WebRTCClient extends Emitter {
6873
6920
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6874
6921
 
6875
6922
  const onRegisterFailed = () => {
6876
- logger$8.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6923
+ logger$8.info('sdk webrtc registering failed', {
6924
+ tries,
6925
+ registerer: !!this.registerer,
6926
+ forceClosed: this.forceClosed,
6927
+ });
6928
+ if (this.forceClosed) {
6929
+ return;
6930
+ }
6931
+
6877
6932
  this.connectionPromise = null;
6878
6933
  if (this.registerer && this.registerer.waiting) {
6879
6934
  this.registerer.waitingToggle(false);
@@ -7151,8 +7206,9 @@ class WebRTCClient extends Emitter {
7151
7206
  }
7152
7207
  }
7153
7208
 
7154
- async close() {
7155
- logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
7209
+ async close(force = false) {
7210
+ logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
7211
+ this.forceClosed = force;
7156
7212
  this._cleanupMedia();
7157
7213
  this.connectionPromise = null;
7158
7214
 
@@ -7171,7 +7227,7 @@ class WebRTCClient extends Emitter {
7171
7227
  this.userAgent.delegate = null;
7172
7228
  this.userAgent.stateChange.removeAllListeners();
7173
7229
 
7174
- await this._disconnectTransport();
7230
+ await this._disconnectTransport(force);
7175
7231
 
7176
7232
  this._cleanupRegister();
7177
7233
 
@@ -8241,6 +8297,13 @@ class WebRTCClient extends Emitter {
8241
8297
  }
8242
8298
 
8243
8299
  _createWebRTCConfiguration(configOverrides = {}) {
8300
+ let { host } = this.config;
8301
+ let port = this.config.port || 443;
8302
+
8303
+ if (this.config.websocketSip) {
8304
+ [host, port = 443] = this.config.websocketSip.split(':');
8305
+ }
8306
+
8244
8307
  const config = {
8245
8308
  authorizationUsername: this.config.authorizationUser,
8246
8309
  authorizationPassword: this.config.password,
@@ -8276,7 +8339,7 @@ class WebRTCClient extends Emitter {
8276
8339
  },
8277
8340
  transportOptions: {
8278
8341
  traceSip: configOverrides.traceSip || false,
8279
- wsServers: `wss://${this.config.host}:${this.config.port || 443}/api/asterisk/ws`,
8342
+ wsServers: `wss://${host}:${port}/api/asterisk/ws`,
8280
8343
  },
8281
8344
  sessionDescriptionHandlerFactoryOptions: {
8282
8345
  modifiers: [replaceLocalIpModifier],
@@ -8600,7 +8663,15 @@ class WebRTCClient extends Emitter {
8600
8663
  return UserAgent.makeURI(`sip:${target}@${this.config.host}`);
8601
8664
  }
8602
8665
 
8603
- async _disconnectTransport() {
8666
+ async _disconnectTransport(force = false) {
8667
+ if (force) {
8668
+ // Bypass sip.js state machine that prevent to close WS with the state `Connecting`
8669
+ this.userAgent.transport.disconnectResolve = () => {};
8670
+ // eslint-disable-next-line
8671
+ this.userAgent.transport._ws.close(1000);
8672
+ return;
8673
+ }
8674
+
8604
8675
  // Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
8605
8676
  if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
8606
8677
  try {
@@ -9336,6 +9407,8 @@ class WebRTCPhone extends Emitter {
9336
9407
  this.removeIncomingSessions(sipSessionId);
9337
9408
  }
9338
9409
 
9410
+ callSession.answerTime = new Date();
9411
+ this._updateCallSession(callSession);
9339
9412
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9340
9413
 
9341
9414
  return callSession;
@@ -9551,6 +9624,8 @@ class WebRTCPhone extends Emitter {
9551
9624
  }
9552
9625
 
9553
9626
  this.shouldSendReinvite = false;
9627
+ callSession.answerTime = new Date();
9628
+ this._updateCallSession(callSession);
9554
9629
  this.acceptedSessions[callSession.getId()] = true;
9555
9630
 
9556
9631
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9650,7 +9725,7 @@ class WebRTCPhone extends Emitter {
9650
9725
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
9651
9726
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
9652
9727
  logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9653
- this.holdSipSession(this.currentSipSession, callSession);
9728
+ this.holdSipSession(this.currentSipSession, this.currentCallSession);
9654
9729
  }
9655
9730
 
9656
9731
  const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
@@ -9861,6 +9936,7 @@ class WebRTCPhone extends Emitter {
9861
9936
  }
9862
9937
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9863
9938
  callSession.creationTime = new Date();
9939
+ this._updateCallSession(callSession);
9864
9940
 
9865
9941
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9866
9942
 
@@ -10002,7 +10078,7 @@ class WebRTCPhone extends Emitter {
10002
10078
  return this.client && this.client.isConference(callSession.sipCallId);
10003
10079
  }
10004
10080
 
10005
- async close() {
10081
+ async close(force = false) {
10006
10082
  logger$7.info('WebRTC close');
10007
10083
 
10008
10084
  try {
@@ -10014,7 +10090,7 @@ class WebRTCPhone extends Emitter {
10014
10090
  logger$7.error('WebRTC close, unregister error', e);
10015
10091
  }
10016
10092
 
10017
- this.client.close();
10093
+ this.client.close(force);
10018
10094
  this.unbind();
10019
10095
 
10020
10096
  this.incomingSessions = [];
@@ -10140,6 +10216,8 @@ class WebRTCPhone extends Emitter {
10140
10216
  }
10141
10217
 
10142
10218
  callSession.creationTime = new Date();
10219
+ this._updateCallSession(callSession);
10220
+
10143
10221
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
10144
10222
  });
10145
10223
 
@@ -10183,6 +10261,8 @@ class WebRTCPhone extends Emitter {
10183
10261
  logger$7.info('WebRTC call rejected', session.id);
10184
10262
  const callSession = this._createCallSession(session);
10185
10263
  callSession.endTime = new Date();
10264
+ this._updateCallSession(callSession);
10265
+
10186
10266
  this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
10187
10267
  });
10188
10268
 
@@ -10407,6 +10487,7 @@ class WebRTCPhone extends Emitter {
10407
10487
  displayName: identity ? identity.displayName || number : number,
10408
10488
  startTime: fromSession ? fromSession.startTime : new Date(),
10409
10489
  creationTime: fromSession ? fromSession.creationTime : null,
10490
+ answerTime: fromSession ? fromSession.answerTime : null,
10410
10491
  endTime: fromSession ? fromSession.endTime : null,
10411
10492
  answered: state === SessionState.Established,
10412
10493
  paused: this.client.isCallHeld(sipSession),