@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
package/lib/index.js CHANGED
@@ -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,
@@ -4925,6 +4937,34 @@ var chatdMethods = (client , baseUrl ) => ({
4925
4937
  client.get(`${baseUrl}/users/me/rooms/messages`, options),
4926
4938
  });
4927
4939
 
4940
+ //
4941
+
4942
+
4943
+
4944
+
4945
+
4946
+ class MeetingStatus {
4947
+
4948
+
4949
+
4950
+
4951
+ constructor({
4952
+ full,
4953
+ } = {}) {
4954
+ this.full = full;
4955
+
4956
+ // Useful to compare instead of instanceof with minified code
4957
+ this.type = 'MeetingStatus';
4958
+ }
4959
+
4960
+ static parse(plain ) {
4961
+ return new MeetingStatus({
4962
+ full: plain.full,
4963
+ });
4964
+ }
4965
+
4966
+ }
4967
+
4928
4968
  /* */
4929
4969
 
4930
4970
 
@@ -5119,6 +5159,8 @@ var calldMethods = (client , baseUrl ) => ({
5119
5159
  client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
5120
5160
  ApiRequester.successResponseParser),
5121
5161
 
5162
+ guestGetMeetingStatus: (meetingUuid ) =>
5163
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
5122
5164
  });
5123
5165
 
5124
5166
  //
@@ -6198,6 +6240,7 @@ const MAX_REGISTER_TRIES = 10;
6198
6240
 
6199
6241
 
6200
6242
 
6243
+
6201
6244
 
6202
6245
 
6203
6246
 
@@ -6239,6 +6282,7 @@ class WebRTCClient extends Emitter {
6239
6282
 
6240
6283
 
6241
6284
 
6285
+
6242
6286
 
6243
6287
  // sugar
6244
6288
 
@@ -6301,6 +6345,7 @@ class WebRTCClient extends Emitter {
6301
6345
  this.conferences = {};
6302
6346
  this.networkMonitoringInterval = {};
6303
6347
  this.sessionNetworkStats = {};
6348
+ this.forceClosed = false;
6304
6349
 
6305
6350
  this._boundOnHeartbeat = this._onHeartbeat.bind(this);
6306
6351
  this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
@@ -6422,6 +6467,8 @@ class WebRTCClient extends Emitter {
6422
6467
  skipRegister: this.skipRegister,
6423
6468
  };
6424
6469
 
6470
+ this.forceClosed = false;
6471
+
6425
6472
  if (this.skipRegister) {
6426
6473
  logger$9.info('sdk webrtc skip register...', logInfo);
6427
6474
  return Promise.resolve();
@@ -6446,7 +6493,15 @@ class WebRTCClient extends Emitter {
6446
6493
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6447
6494
 
6448
6495
  const onRegisterFailed = () => {
6449
- logger$9.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6496
+ logger$9.info('sdk webrtc registering failed', {
6497
+ tries,
6498
+ registerer: !!this.registerer,
6499
+ forceClosed: this.forceClosed,
6500
+ });
6501
+ if (this.forceClosed) {
6502
+ return;
6503
+ }
6504
+
6450
6505
  this.connectionPromise = null;
6451
6506
  if (this.registerer && this.registerer.waiting) {
6452
6507
  this.registerer.waitingToggle(false);
@@ -6724,8 +6779,9 @@ class WebRTCClient extends Emitter {
6724
6779
  }
6725
6780
  }
6726
6781
 
6727
- async close() {
6728
- logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6782
+ async close(force = false) {
6783
+ logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
6784
+ this.forceClosed = force;
6729
6785
  this._cleanupMedia();
6730
6786
  this.connectionPromise = null;
6731
6787
 
@@ -6744,7 +6800,7 @@ class WebRTCClient extends Emitter {
6744
6800
  this.userAgent.delegate = null;
6745
6801
  this.userAgent.stateChange.removeAllListeners();
6746
6802
 
6747
- await this._disconnectTransport();
6803
+ await this._disconnectTransport(force);
6748
6804
 
6749
6805
  this._cleanupRegister();
6750
6806
 
@@ -7814,6 +7870,13 @@ class WebRTCClient extends Emitter {
7814
7870
  }
7815
7871
 
7816
7872
  _createWebRTCConfiguration(configOverrides = {}) {
7873
+ let { host } = this.config;
7874
+ let port = this.config.port || 443;
7875
+
7876
+ if (this.config.websocketSip) {
7877
+ [host, port = 443] = this.config.websocketSip.split(':');
7878
+ }
7879
+
7817
7880
  const config = {
7818
7881
  authorizationUsername: this.config.authorizationUser,
7819
7882
  authorizationPassword: this.config.password,
@@ -7849,7 +7912,7 @@ class WebRTCClient extends Emitter {
7849
7912
  },
7850
7913
  transportOptions: {
7851
7914
  traceSip: configOverrides.traceSip || false,
7852
- wsServers: `wss://${this.config.host}:${this.config.port || 443}/api/asterisk/ws`,
7915
+ wsServers: `wss://${host}:${port}/api/asterisk/ws`,
7853
7916
  },
7854
7917
  sessionDescriptionHandlerFactoryOptions: {
7855
7918
  modifiers: [replaceLocalIpModifier],
@@ -8173,7 +8236,15 @@ class WebRTCClient extends Emitter {
8173
8236
  return userAgent.UserAgent.makeURI(`sip:${target}@${this.config.host}`);
8174
8237
  }
8175
8238
 
8176
- async _disconnectTransport() {
8239
+ async _disconnectTransport(force = false) {
8240
+ if (force) {
8241
+ // Bypass sip.js state machine that prevent to close WS with the state `Connecting`
8242
+ this.userAgent.transport.disconnectResolve = () => {};
8243
+ // eslint-disable-next-line
8244
+ this.userAgent.transport._ws.close(1000);
8245
+ return;
8246
+ }
8247
+
8177
8248
  // Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
8178
8249
  if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
8179
8250
  try {
@@ -9810,6 +9881,8 @@ class WebRTCPhone extends Emitter {
9810
9881
  this.removeIncomingSessions(sipSessionId);
9811
9882
  }
9812
9883
 
9884
+ callSession.answerTime = new Date();
9885
+ this._updateCallSession(callSession);
9813
9886
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9814
9887
 
9815
9888
  return callSession;
@@ -10025,6 +10098,8 @@ class WebRTCPhone extends Emitter {
10025
10098
  }
10026
10099
 
10027
10100
  this.shouldSendReinvite = false;
10101
+ callSession.answerTime = new Date();
10102
+ this._updateCallSession(callSession);
10028
10103
  this.acceptedSessions[callSession.getId()] = true;
10029
10104
 
10030
10105
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -10124,7 +10199,7 @@ class WebRTCPhone extends Emitter {
10124
10199
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
10125
10200
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
10126
10201
  logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
10127
- this.holdSipSession(this.currentSipSession, callSession);
10202
+ this.holdSipSession(this.currentSipSession, this.currentCallSession);
10128
10203
  }
10129
10204
 
10130
10205
  const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
@@ -10335,6 +10410,7 @@ class WebRTCPhone extends Emitter {
10335
10410
  }
10336
10411
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
10337
10412
  callSession.creationTime = new Date();
10413
+ this._updateCallSession(callSession);
10338
10414
 
10339
10415
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
10340
10416
 
@@ -10476,7 +10552,7 @@ class WebRTCPhone extends Emitter {
10476
10552
  return this.client && this.client.isConference(callSession.sipCallId);
10477
10553
  }
10478
10554
 
10479
- async close() {
10555
+ async close(force = false) {
10480
10556
  logger$7.info('WebRTC close');
10481
10557
 
10482
10558
  try {
@@ -10488,7 +10564,7 @@ class WebRTCPhone extends Emitter {
10488
10564
  logger$7.error('WebRTC close, unregister error', e);
10489
10565
  }
10490
10566
 
10491
- this.client.close();
10567
+ this.client.close(force);
10492
10568
  this.unbind();
10493
10569
 
10494
10570
  this.incomingSessions = [];
@@ -10614,6 +10690,8 @@ class WebRTCPhone extends Emitter {
10614
10690
  }
10615
10691
 
10616
10692
  callSession.creationTime = new Date();
10693
+ this._updateCallSession(callSession);
10694
+
10617
10695
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
10618
10696
  });
10619
10697
 
@@ -10657,6 +10735,8 @@ class WebRTCPhone extends Emitter {
10657
10735
  logger$7.info('WebRTC call rejected', session.id);
10658
10736
  const callSession = this._createCallSession(session);
10659
10737
  callSession.endTime = new Date();
10738
+ this._updateCallSession(callSession);
10739
+
10660
10740
  this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
10661
10741
  });
10662
10742
 
@@ -10881,6 +10961,7 @@ class WebRTCPhone extends Emitter {
10881
10961
  displayName: identity ? identity.displayName || number : number,
10882
10962
  startTime: fromSession ? fromSession.startTime : new Date(),
10883
10963
  creationTime: fromSession ? fromSession.creationTime : null,
10964
+ answerTime: fromSession ? fromSession.answerTime : null,
10884
10965
  endTime: fromSession ? fromSession.endTime : null,
10885
10966
  answered: state === sessionState.SessionState.Established,
10886
10967
  paused: this.client.isCallHeld(sipSession),
@@ -4022,6 +4022,34 @@ class IndirectTransfer {
4022
4022
  }
4023
4023
  }
4024
4024
 
4025
+ //
4026
+
4027
+
4028
+
4029
+
4030
+
4031
+ class MeetingStatus {
4032
+
4033
+
4034
+
4035
+
4036
+ constructor({
4037
+ full,
4038
+ } = {}) {
4039
+ this.full = full;
4040
+
4041
+ // Useful to compare instead of instanceof with minified code
4042
+ this.type = 'MeetingStatus';
4043
+ }
4044
+
4045
+ static parse(plain ) {
4046
+ return new MeetingStatus({
4047
+ full: plain.full,
4048
+ });
4049
+ }
4050
+
4051
+ }
4052
+
4025
4053
  /* */
4026
4054
 
4027
4055
 
@@ -4216,6 +4244,8 @@ var calldMethods = (client , baseUrl ) => ({
4216
4244
  client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
4217
4245
  ApiRequester.successResponseParser),
4218
4246
 
4247
+ guestGetMeetingStatus: (meetingUuid ) =>
4248
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
4219
4249
  });
4220
4250
 
4221
4251
  //
@@ -4024,6 +4024,34 @@ var chatdMethods = (client , baseUrl ) => ({
4024
4024
  client.get(`${baseUrl}/users/me/rooms/messages`, options),
4025
4025
  });
4026
4026
 
4027
+ //
4028
+
4029
+
4030
+
4031
+
4032
+
4033
+ class MeetingStatus {
4034
+
4035
+
4036
+
4037
+
4038
+ constructor({
4039
+ full,
4040
+ } = {}) {
4041
+ this.full = full;
4042
+
4043
+ // Useful to compare instead of instanceof with minified code
4044
+ this.type = 'MeetingStatus';
4045
+ }
4046
+
4047
+ static parse(plain ) {
4048
+ return new MeetingStatus({
4049
+ full: plain.full,
4050
+ });
4051
+ }
4052
+
4053
+ }
4054
+
4027
4055
  /* */
4028
4056
 
4029
4057
 
@@ -4218,6 +4246,8 @@ var calldMethods = (client , baseUrl ) => ({
4218
4246
  client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
4219
4247
  ApiRequester.successResponseParser),
4220
4248
 
4249
+ guestGetMeetingStatus: (meetingUuid ) =>
4250
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
4221
4251
  });
4222
4252
 
4223
4253
  //
@@ -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
  //
@@ -6373,6 +6415,7 @@ const MAX_REGISTER_TRIES = 10;
6373
6415
 
6374
6416
 
6375
6417
 
6418
+
6376
6419
 
6377
6420
 
6378
6421
 
@@ -6414,6 +6457,7 @@ class WebRTCClient extends Emitter {
6414
6457
 
6415
6458
 
6416
6459
 
6460
+
6417
6461
 
6418
6462
  // sugar
6419
6463
 
@@ -6476,6 +6520,7 @@ class WebRTCClient extends Emitter {
6476
6520
  this.conferences = {};
6477
6521
  this.networkMonitoringInterval = {};
6478
6522
  this.sessionNetworkStats = {};
6523
+ this.forceClosed = false;
6479
6524
 
6480
6525
  this._boundOnHeartbeat = this._onHeartbeat.bind(this);
6481
6526
  this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
@@ -6597,6 +6642,8 @@ class WebRTCClient extends Emitter {
6597
6642
  skipRegister: this.skipRegister,
6598
6643
  };
6599
6644
 
6645
+ this.forceClosed = false;
6646
+
6600
6647
  if (this.skipRegister) {
6601
6648
  logger$9.info('sdk webrtc skip register...', logInfo);
6602
6649
  return Promise.resolve();
@@ -6621,7 +6668,15 @@ class WebRTCClient extends Emitter {
6621
6668
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6622
6669
 
6623
6670
  const onRegisterFailed = () => {
6624
- logger$9.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6671
+ logger$9.info('sdk webrtc registering failed', {
6672
+ tries,
6673
+ registerer: !!this.registerer,
6674
+ forceClosed: this.forceClosed,
6675
+ });
6676
+ if (this.forceClosed) {
6677
+ return;
6678
+ }
6679
+
6625
6680
  this.connectionPromise = null;
6626
6681
  if (this.registerer && this.registerer.waiting) {
6627
6682
  this.registerer.waitingToggle(false);
@@ -6899,8 +6954,9 @@ class WebRTCClient extends Emitter {
6899
6954
  }
6900
6955
  }
6901
6956
 
6902
- async close() {
6903
- logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6957
+ async close(force = false) {
6958
+ logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
6959
+ this.forceClosed = force;
6904
6960
  this._cleanupMedia();
6905
6961
  this.connectionPromise = null;
6906
6962
 
@@ -6919,7 +6975,7 @@ class WebRTCClient extends Emitter {
6919
6975
  this.userAgent.delegate = null;
6920
6976
  this.userAgent.stateChange.removeAllListeners();
6921
6977
 
6922
- await this._disconnectTransport();
6978
+ await this._disconnectTransport(force);
6923
6979
 
6924
6980
  this._cleanupRegister();
6925
6981
 
@@ -7989,6 +8045,13 @@ class WebRTCClient extends Emitter {
7989
8045
  }
7990
8046
 
7991
8047
  _createWebRTCConfiguration(configOverrides = {}) {
8048
+ let { host } = this.config;
8049
+ let port = this.config.port || 443;
8050
+
8051
+ if (this.config.websocketSip) {
8052
+ [host, port = 443] = this.config.websocketSip.split(':');
8053
+ }
8054
+
7992
8055
  const config = {
7993
8056
  authorizationUsername: this.config.authorizationUser,
7994
8057
  authorizationPassword: this.config.password,
@@ -8024,7 +8087,7 @@ class WebRTCClient extends Emitter {
8024
8087
  },
8025
8088
  transportOptions: {
8026
8089
  traceSip: configOverrides.traceSip || false,
8027
- wsServers: `wss://${this.config.host}:${this.config.port || 443}/api/asterisk/ws`,
8090
+ wsServers: `wss://${host}:${port}/api/asterisk/ws`,
8028
8091
  },
8029
8092
  sessionDescriptionHandlerFactoryOptions: {
8030
8093
  modifiers: [replaceLocalIpModifier],
@@ -8348,7 +8411,15 @@ class WebRTCClient extends Emitter {
8348
8411
  return userAgent.UserAgent.makeURI(`sip:${target}@${this.config.host}`);
8349
8412
  }
8350
8413
 
8351
- async _disconnectTransport() {
8414
+ async _disconnectTransport(force = false) {
8415
+ if (force) {
8416
+ // Bypass sip.js state machine that prevent to close WS with the state `Connecting`
8417
+ this.userAgent.transport.disconnectResolve = () => {};
8418
+ // eslint-disable-next-line
8419
+ this.userAgent.transport._ws.close(1000);
8420
+ return;
8421
+ }
8422
+
8352
8423
  // Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
8353
8424
  if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
8354
8425
  try {
@@ -9084,6 +9155,8 @@ class WebRTCPhone extends Emitter {
9084
9155
  this.removeIncomingSessions(sipSessionId);
9085
9156
  }
9086
9157
 
9158
+ callSession.answerTime = new Date();
9159
+ this._updateCallSession(callSession);
9087
9160
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9088
9161
 
9089
9162
  return callSession;
@@ -9299,6 +9372,8 @@ class WebRTCPhone extends Emitter {
9299
9372
  }
9300
9373
 
9301
9374
  this.shouldSendReinvite = false;
9375
+ callSession.answerTime = new Date();
9376
+ this._updateCallSession(callSession);
9302
9377
  this.acceptedSessions[callSession.getId()] = true;
9303
9378
 
9304
9379
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9398,7 +9473,7 @@ class WebRTCPhone extends Emitter {
9398
9473
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
9399
9474
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
9400
9475
  logger$8.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9401
- this.holdSipSession(this.currentSipSession, callSession);
9476
+ this.holdSipSession(this.currentSipSession, this.currentCallSession);
9402
9477
  }
9403
9478
 
9404
9479
  const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
@@ -9609,6 +9684,7 @@ class WebRTCPhone extends Emitter {
9609
9684
  }
9610
9685
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9611
9686
  callSession.creationTime = new Date();
9687
+ this._updateCallSession(callSession);
9612
9688
 
9613
9689
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9614
9690
 
@@ -9750,7 +9826,7 @@ class WebRTCPhone extends Emitter {
9750
9826
  return this.client && this.client.isConference(callSession.sipCallId);
9751
9827
  }
9752
9828
 
9753
- async close() {
9829
+ async close(force = false) {
9754
9830
  logger$8.info('WebRTC close');
9755
9831
 
9756
9832
  try {
@@ -9762,7 +9838,7 @@ class WebRTCPhone extends Emitter {
9762
9838
  logger$8.error('WebRTC close, unregister error', e);
9763
9839
  }
9764
9840
 
9765
- this.client.close();
9841
+ this.client.close(force);
9766
9842
  this.unbind();
9767
9843
 
9768
9844
  this.incomingSessions = [];
@@ -9888,6 +9964,8 @@ class WebRTCPhone extends Emitter {
9888
9964
  }
9889
9965
 
9890
9966
  callSession.creationTime = new Date();
9967
+ this._updateCallSession(callSession);
9968
+
9891
9969
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
9892
9970
  });
9893
9971
 
@@ -9931,6 +10009,8 @@ class WebRTCPhone extends Emitter {
9931
10009
  logger$8.info('WebRTC call rejected', session.id);
9932
10010
  const callSession = this._createCallSession(session);
9933
10011
  callSession.endTime = new Date();
10012
+ this._updateCallSession(callSession);
10013
+
9934
10014
  this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
9935
10015
  });
9936
10016
 
@@ -10155,6 +10235,7 @@ class WebRTCPhone extends Emitter {
10155
10235
  displayName: identity ? identity.displayName || number : number,
10156
10236
  startTime: fromSession ? fromSession.startTime : new Date(),
10157
10237
  creationTime: fromSession ? fromSession.creationTime : null,
10238
+ answerTime: fromSession ? fromSession.answerTime : null,
10158
10239
  endTime: fromSession ? fromSession.endTime : null,
10159
10240
  answered: state === sessionState.SessionState.Established,
10160
10241
  paused: this.client.isCallHeld(sipSession),