@wazo/sdk 0.37.30 → 0.37.34

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 (80) hide show
  1. package/dist/wazo-sdk.js +4 -4
  2. package/esm/__tests__/api-client.test.js +30 -0
  3. package/esm/__tests__/web-rtc-client.test.js +57 -6
  4. package/esm/api/calld.js +30 -0
  5. package/esm/api-client.js +30 -0
  6. package/esm/checker/Checker.js +57 -6
  7. package/esm/checker/checks/aor.js +30 -0
  8. package/esm/checker/checks/api.js +30 -0
  9. package/esm/checker/checks/index.js +57 -6
  10. package/esm/checker/checks/webrtc-transport.js +57 -6
  11. package/esm/checker/checks/webrtc.js +57 -6
  12. package/esm/domain/AdHocAPIConference.js +30 -0
  13. package/esm/domain/CallSession.js +9 -1
  14. package/esm/domain/Features.js +30 -0
  15. package/esm/domain/MeetingStatus.js +29 -0
  16. package/esm/domain/Phone/CTIPhone.js +39 -1
  17. package/esm/domain/Phone/WebRTCPhone.js +43 -8
  18. package/esm/domain/__tests__/CallSession.test.js +41 -5
  19. package/esm/domain/__tests__/IndirectTransfer.test.js +9 -1
  20. package/esm/domain/__tests__/Room.test.js +9 -1
  21. package/esm/index.js +100 -14
  22. package/esm/service/CallApi.js +30 -0
  23. package/esm/service/getApiClient.js +30 -0
  24. package/esm/simple/Auth.js +100 -14
  25. package/esm/simple/Configuration.js +100 -14
  26. package/esm/simple/Directory.js +30 -0
  27. package/esm/simple/Phone.js +100 -14
  28. package/esm/simple/index.js +100 -14
  29. package/esm/simple/room/LocalParticipant.js +100 -14
  30. package/esm/simple/room/Participant.js +100 -14
  31. package/esm/simple/room/RemoteParticipant.js +100 -14
  32. package/esm/simple/room/Room.js +100 -14
  33. package/esm/simple/room/SipRoom.js +100 -14
  34. package/esm/simple/room/Stream.js +100 -14
  35. package/esm/simple/room/__tests__/RemoteParticipant.test.js +100 -14
  36. package/esm/simple/utils.js +100 -14
  37. package/esm/web-rtc-client.js +57 -6
  38. package/lib/__tests__/api-client.test.js +30 -0
  39. package/lib/__tests__/web-rtc-client.test.js +57 -6
  40. package/lib/api/calld.js +30 -0
  41. package/lib/api-client.js +30 -0
  42. package/lib/checker/Checker.js +57 -6
  43. package/lib/checker/checks/aor.js +30 -0
  44. package/lib/checker/checks/api.js +30 -0
  45. package/lib/checker/checks/index.js +57 -6
  46. package/lib/checker/checks/webrtc-transport.js +57 -6
  47. package/lib/checker/checks/webrtc.js +57 -6
  48. package/lib/domain/AdHocAPIConference.js +30 -0
  49. package/lib/domain/CallSession.js +9 -1
  50. package/lib/domain/Features.js +30 -0
  51. package/lib/domain/MeetingStatus.js +31 -0
  52. package/lib/domain/Phone/CTIPhone.js +39 -1
  53. package/lib/domain/Phone/WebRTCPhone.js +43 -8
  54. package/lib/domain/__tests__/CallSession.test.js +41 -5
  55. package/lib/domain/__tests__/IndirectTransfer.test.js +9 -1
  56. package/lib/domain/__tests__/Room.test.js +9 -1
  57. package/lib/index.js +100 -14
  58. package/lib/service/CallApi.js +30 -0
  59. package/lib/service/getApiClient.js +30 -0
  60. package/lib/simple/Auth.js +100 -14
  61. package/lib/simple/Configuration.js +100 -14
  62. package/lib/simple/Directory.js +30 -0
  63. package/lib/simple/Phone.js +100 -14
  64. package/lib/simple/index.js +100 -14
  65. package/lib/simple/room/LocalParticipant.js +100 -14
  66. package/lib/simple/room/Participant.js +100 -14
  67. package/lib/simple/room/RemoteParticipant.js +100 -14
  68. package/lib/simple/room/Room.js +100 -14
  69. package/lib/simple/room/SipRoom.js +100 -14
  70. package/lib/simple/room/Stream.js +100 -14
  71. package/lib/simple/room/__tests__/RemoteParticipant.test.js +100 -14
  72. package/lib/simple/utils.js +100 -14
  73. package/lib/web-rtc-client.js +57 -6
  74. package/package.json +1 -1
  75. package/src/api/calld.js +3 -0
  76. package/src/domain/CallSession.js +9 -1
  77. package/src/domain/MeetingStatus.js +27 -0
  78. package/src/domain/Phone/WebRTCPhone.js +34 -7
  79. package/src/domain/__tests__/CallSession.test.js +32 -4
  80. package/src/web-rtc-client.js +27 -6
@@ -368,13 +368,21 @@ class CallSession {
368
368
 
369
369
  // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
370
370
  set answered(value ) {
371
- this.answerTime = value ? new Date() : null;
371
+ this.answerTime = value ? this.answerTime || new Date() : null;
372
372
  }
373
373
 
374
374
  get answered() {
375
375
  return !!this.answerTime;
376
376
  }
377
377
 
378
+ toJSON() {
379
+ const jsonObj = { ...this };
380
+ // $FlowFixMe
381
+ jsonObj.answered = this.answered;
382
+
383
+ return jsonObj;
384
+ }
385
+
378
386
  static parseCall(call ) {
379
387
  return new CallSession({
380
388
  callId: call.id,
@@ -368,13 +368,21 @@ class CallSession {
368
368
 
369
369
  // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
370
370
  set answered(value ) {
371
- this.answerTime = value ? new Date() : null;
371
+ this.answerTime = value ? this.answerTime || new Date() : null;
372
372
  }
373
373
 
374
374
  get answered() {
375
375
  return !!this.answerTime;
376
376
  }
377
377
 
378
+ toJSON() {
379
+ const jsonObj = { ...this };
380
+ // $FlowFixMe
381
+ jsonObj.answered = this.answered;
382
+
383
+ return jsonObj;
384
+ }
385
+
378
386
  static parseCall(call ) {
379
387
  return new CallSession({
380
388
  callId: call.id,
package/esm/index.js CHANGED
@@ -3585,13 +3585,21 @@ class CallSession {
3585
3585
 
3586
3586
  // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
3587
3587
  set answered(value ) {
3588
- this.answerTime = value ? new Date() : null;
3588
+ this.answerTime = value ? this.answerTime || new Date() : null;
3589
3589
  }
3590
3590
 
3591
3591
  get answered() {
3592
3592
  return !!this.answerTime;
3593
3593
  }
3594
3594
 
3595
+ toJSON() {
3596
+ const jsonObj = { ...this };
3597
+ // $FlowFixMe
3598
+ jsonObj.answered = this.answered;
3599
+
3600
+ return jsonObj;
3601
+ }
3602
+
3595
3603
  static parseCall(call ) {
3596
3604
  return new CallSession({
3597
3605
  callId: call.id,
@@ -4926,6 +4934,34 @@ var chatdMethods = (client , baseUrl ) => ({
4926
4934
  client.get(`${baseUrl}/users/me/rooms/messages`, options),
4927
4935
  });
4928
4936
 
4937
+ //
4938
+
4939
+
4940
+
4941
+
4942
+
4943
+ class MeetingStatus {
4944
+
4945
+
4946
+
4947
+
4948
+ constructor({
4949
+ full,
4950
+ } = {}) {
4951
+ this.full = full;
4952
+
4953
+ // Useful to compare instead of instanceof with minified code
4954
+ this.type = 'MeetingStatus';
4955
+ }
4956
+
4957
+ static parse(plain ) {
4958
+ return new MeetingStatus({
4959
+ full: plain.full,
4960
+ });
4961
+ }
4962
+
4963
+ }
4964
+
4929
4965
  /* */
4930
4966
 
4931
4967
 
@@ -5120,6 +5156,8 @@ var calldMethods = (client , baseUrl ) => ({
5120
5156
  client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
5121
5157
  ApiRequester.successResponseParser),
5122
5158
 
5159
+ guestGetMeetingStatus: (meetingUuid ) =>
5160
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
5123
5161
  });
5124
5162
 
5125
5163
  //
@@ -6187,7 +6225,7 @@ const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
6187
6225
  const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
6188
6226
  class CanceledCallError extends Error {}
6189
6227
 
6190
- const MAX_REGISTER_TRIES = 10;
6228
+ const MAX_REGISTER_TRIES = 5;
6191
6229
 
6192
6230
 
6193
6231
 
@@ -6241,6 +6279,7 @@ class WebRTCClient extends Emitter {
6241
6279
 
6242
6280
 
6243
6281
 
6282
+
6244
6283
 
6245
6284
  // sugar
6246
6285
 
@@ -6303,6 +6342,7 @@ class WebRTCClient extends Emitter {
6303
6342
  this.conferences = {};
6304
6343
  this.networkMonitoringInterval = {};
6305
6344
  this.sessionNetworkStats = {};
6345
+ this.forceClosed = false;
6306
6346
 
6307
6347
  this._boundOnHeartbeat = this._onHeartbeat.bind(this);
6308
6348
  this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
@@ -6424,6 +6464,8 @@ class WebRTCClient extends Emitter {
6424
6464
  skipRegister: this.skipRegister,
6425
6465
  };
6426
6466
 
6467
+ this.forceClosed = false;
6468
+
6427
6469
  if (this.skipRegister) {
6428
6470
  logger$9.info('sdk webrtc skip register...', logInfo);
6429
6471
  return Promise.resolve();
@@ -6448,7 +6490,15 @@ class WebRTCClient extends Emitter {
6448
6490
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6449
6491
 
6450
6492
  const onRegisterFailed = () => {
6451
- logger$9.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6493
+ logger$9.info('sdk webrtc registering failed', {
6494
+ tries,
6495
+ registerer: !!this.registerer,
6496
+ forceClosed: this.forceClosed,
6497
+ });
6498
+ if (this.forceClosed) {
6499
+ return;
6500
+ }
6501
+
6452
6502
  this.connectionPromise = null;
6453
6503
  if (this.registerer && this.registerer.waiting) {
6454
6504
  this.registerer.waitingToggle(false);
@@ -6726,8 +6776,9 @@ class WebRTCClient extends Emitter {
6726
6776
  }
6727
6777
  }
6728
6778
 
6729
- async close() {
6730
- logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6779
+ async close(force = false) {
6780
+ logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
6781
+ this.forceClosed = force;
6731
6782
  this._cleanupMedia();
6732
6783
  this.connectionPromise = null;
6733
6784
 
@@ -6746,7 +6797,7 @@ class WebRTCClient extends Emitter {
6746
6797
  this.userAgent.delegate = null;
6747
6798
  this.userAgent.stateChange.removeAllListeners();
6748
6799
 
6749
- await this._disconnectTransport();
6800
+ await this._disconnectTransport(force);
6750
6801
 
6751
6802
  this._cleanupRegister();
6752
6803
 
@@ -8182,7 +8233,15 @@ class WebRTCClient extends Emitter {
8182
8233
  return UserAgent.makeURI(`sip:${target}@${this.config.host}`);
8183
8234
  }
8184
8235
 
8185
- async _disconnectTransport() {
8236
+ async _disconnectTransport(force = false) {
8237
+ if (force) {
8238
+ // Bypass sip.js state machine that prevent to close WS with the state `Connecting`
8239
+ this.userAgent.transport.disconnectResolve = () => {};
8240
+ // eslint-disable-next-line
8241
+ this.userAgent.transport._ws.close(1000);
8242
+ return;
8243
+ }
8244
+
8186
8245
  // Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
8187
8246
  if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
8188
8247
  try {
@@ -9820,6 +9879,7 @@ class WebRTCPhone extends Emitter {
9820
9879
  }
9821
9880
 
9822
9881
  callSession.answerTime = new Date();
9882
+ this._updateCallSession(callSession);
9823
9883
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9824
9884
 
9825
9885
  return callSession;
@@ -10029,6 +10089,12 @@ class WebRTCPhone extends Emitter {
10029
10089
  return Promise.resolve(null);
10030
10090
  }
10031
10091
 
10092
+ const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
10093
+ if (sipSessionId && !(sipSessionId in this.callSessions)) {
10094
+ logger$7.warn('Call session already ended or not found, can\'t accept it.', { sipSessionId });
10095
+ return Promise.resolve(null);
10096
+ }
10097
+
10032
10098
  if (callSession.getId() in this.acceptedSessions) {
10033
10099
  logger$7.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
10034
10100
  return Promise.resolve(callSession.sipCallId);
@@ -10036,6 +10102,7 @@ class WebRTCPhone extends Emitter {
10036
10102
 
10037
10103
  this.shouldSendReinvite = false;
10038
10104
  callSession.answerTime = new Date();
10105
+ this._updateCallSession(callSession);
10039
10106
  this.acceptedSessions[callSession.getId()] = true;
10040
10107
 
10041
10108
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -10135,7 +10202,7 @@ class WebRTCPhone extends Emitter {
10135
10202
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
10136
10203
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
10137
10204
  logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
10138
- this.holdSipSession(this.currentSipSession, callSession);
10205
+ this.holdSipSession(this.currentSipSession, this.currentCallSession);
10139
10206
  }
10140
10207
 
10141
10208
  const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
@@ -10346,6 +10413,7 @@ class WebRTCPhone extends Emitter {
10346
10413
  }
10347
10414
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
10348
10415
  callSession.creationTime = new Date();
10416
+ this._updateCallSession(callSession);
10349
10417
 
10350
10418
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
10351
10419
 
@@ -10487,7 +10555,7 @@ class WebRTCPhone extends Emitter {
10487
10555
  return this.client && this.client.isConference(callSession.sipCallId);
10488
10556
  }
10489
10557
 
10490
- async close() {
10558
+ async close(force = false) {
10491
10559
  logger$7.info('WebRTC close');
10492
10560
 
10493
10561
  try {
@@ -10499,7 +10567,7 @@ class WebRTCPhone extends Emitter {
10499
10567
  logger$7.error('WebRTC close, unregister error', e);
10500
10568
  }
10501
10569
 
10502
- this.client.close();
10570
+ this.client.close(force);
10503
10571
  this.unbind();
10504
10572
 
10505
10573
  this.incomingSessions = [];
@@ -10625,6 +10693,8 @@ class WebRTCPhone extends Emitter {
10625
10693
  }
10626
10694
 
10627
10695
  callSession.creationTime = new Date();
10696
+ this._updateCallSession(callSession);
10697
+
10628
10698
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
10629
10699
  });
10630
10700
 
@@ -10649,9 +10719,17 @@ class WebRTCPhone extends Emitter {
10649
10719
  });
10650
10720
 
10651
10721
  this.client.on(this.client.ACCEPTED, (sipSession ) => {
10652
- logger$7.info('WebRTC call accepted', { sipId: sipSession.id });
10722
+ const sessionId = this.getSipSessionId(sipSession);
10723
+ const hasSession = sessionId in this.callSessions;
10653
10724
 
10654
- this._onCallAccepted(sipSession, this.client.hasVideo(this.getSipSessionId(sipSession)));
10725
+ logger$7.info('WebRTC call accepted', { sipId: sessionId, hasSession });
10726
+
10727
+ if (!hasSession) {
10728
+ logger$7.warn('Call accepted ignored, session is no longer present in the WebRtcPhone', { sessionId });
10729
+ return;
10730
+ }
10731
+
10732
+ this._onCallAccepted(sipSession, this.client.hasVideo(sessionId));
10655
10733
 
10656
10734
  if (this.audioOutputDeviceId) {
10657
10735
  this.client.changeAudioOutputDevice(this.audioOutputDeviceId);
@@ -10668,6 +10746,8 @@ class WebRTCPhone extends Emitter {
10668
10746
  logger$7.info('WebRTC call rejected', session.id);
10669
10747
  const callSession = this._createCallSession(session);
10670
10748
  callSession.endTime = new Date();
10749
+ this._updateCallSession(callSession);
10750
+
10671
10751
  this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
10672
10752
  });
10673
10753
 
@@ -10785,9 +10865,14 @@ class WebRTCPhone extends Emitter {
10785
10865
  return this.client.getSipSessionId(sipSession);
10786
10866
  }
10787
10867
 
10788
- _updateCallSession(callSession ) {
10868
+ getSipSessionIdFromCallSession(callSession ) {
10789
10869
  const sipSession = this.findSipSession(callSession);
10790
- const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
10870
+
10871
+ return sipSession ? this.getSipSessionId(sipSession) : null;
10872
+ }
10873
+
10874
+ _updateCallSession(callSession ) {
10875
+ const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
10791
10876
 
10792
10877
  if (sipSessionId) {
10793
10878
  this.callSessions[sipSessionId] = callSession;
@@ -10892,6 +10977,7 @@ class WebRTCPhone extends Emitter {
10892
10977
  displayName: identity ? identity.displayName || number : number,
10893
10978
  startTime: fromSession ? fromSession.startTime : new Date(),
10894
10979
  creationTime: fromSession ? fromSession.creationTime : null,
10980
+ answerTime: fromSession ? fromSession.answerTime : null,
10895
10981
  endTime: fromSession ? fromSession.endTime : null,
10896
10982
  answered: state === SessionState.Established,
10897
10983
  paused: this.client.isCallHeld(sipSession),
@@ -4016,6 +4016,34 @@ class IndirectTransfer {
4016
4016
  }
4017
4017
  }
4018
4018
 
4019
+ //
4020
+
4021
+
4022
+
4023
+
4024
+
4025
+ class MeetingStatus {
4026
+
4027
+
4028
+
4029
+
4030
+ constructor({
4031
+ full,
4032
+ } = {}) {
4033
+ this.full = full;
4034
+
4035
+ // Useful to compare instead of instanceof with minified code
4036
+ this.type = 'MeetingStatus';
4037
+ }
4038
+
4039
+ static parse(plain ) {
4040
+ return new MeetingStatus({
4041
+ full: plain.full,
4042
+ });
4043
+ }
4044
+
4045
+ }
4046
+
4019
4047
  /* */
4020
4048
 
4021
4049
 
@@ -4210,6 +4238,8 @@ var calldMethods = (client , baseUrl ) => ({
4210
4238
  client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
4211
4239
  ApiRequester.successResponseParser),
4212
4240
 
4241
+ guestGetMeetingStatus: (meetingUuid ) =>
4242
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
4213
4243
  });
4214
4244
 
4215
4245
  //
@@ -4016,6 +4016,34 @@ var chatdMethods = (client , baseUrl ) => ({
4016
4016
  client.get(`${baseUrl}/users/me/rooms/messages`, options),
4017
4017
  });
4018
4018
 
4019
+ //
4020
+
4021
+
4022
+
4023
+
4024
+
4025
+ class MeetingStatus {
4026
+
4027
+
4028
+
4029
+
4030
+ constructor({
4031
+ full,
4032
+ } = {}) {
4033
+ this.full = full;
4034
+
4035
+ // Useful to compare instead of instanceof with minified code
4036
+ this.type = 'MeetingStatus';
4037
+ }
4038
+
4039
+ static parse(plain ) {
4040
+ return new MeetingStatus({
4041
+ full: plain.full,
4042
+ });
4043
+ }
4044
+
4045
+ }
4046
+
4019
4047
  /* */
4020
4048
 
4021
4049
 
@@ -4210,6 +4238,8 @@ var calldMethods = (client , baseUrl ) => ({
4210
4238
  client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
4211
4239
  ApiRequester.successResponseParser),
4212
4240
 
4241
+ guestGetMeetingStatus: (meetingUuid ) =>
4242
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
4213
4243
  });
4214
4244
 
4215
4245
  //
@@ -3584,13 +3584,21 @@ class CallSession {
3584
3584
 
3585
3585
  // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
3586
3586
  set answered(value ) {
3587
- this.answerTime = value ? new Date() : null;
3587
+ this.answerTime = value ? this.answerTime || new Date() : null;
3588
3588
  }
3589
3589
 
3590
3590
  get answered() {
3591
3591
  return !!this.answerTime;
3592
3592
  }
3593
3593
 
3594
+ toJSON() {
3595
+ const jsonObj = { ...this };
3596
+ // $FlowFixMe
3597
+ jsonObj.answered = this.answered;
3598
+
3599
+ return jsonObj;
3600
+ }
3601
+
3594
3602
  static parseCall(call ) {
3595
3603
  return new CallSession({
3596
3604
  callId: call.id,
@@ -4842,6 +4850,34 @@ var chatdMethods = (client , baseUrl ) => ({
4842
4850
  client.get(`${baseUrl}/users/me/rooms/messages`, options),
4843
4851
  });
4844
4852
 
4853
+ //
4854
+
4855
+
4856
+
4857
+
4858
+
4859
+ class MeetingStatus {
4860
+
4861
+
4862
+
4863
+
4864
+ constructor({
4865
+ full,
4866
+ } = {}) {
4867
+ this.full = full;
4868
+
4869
+ // Useful to compare instead of instanceof with minified code
4870
+ this.type = 'MeetingStatus';
4871
+ }
4872
+
4873
+ static parse(plain ) {
4874
+ return new MeetingStatus({
4875
+ full: plain.full,
4876
+ });
4877
+ }
4878
+
4879
+ }
4880
+
4845
4881
  /* */
4846
4882
 
4847
4883
 
@@ -5036,6 +5072,8 @@ var calldMethods = (client , baseUrl ) => ({
5036
5072
  client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
5037
5073
  ApiRequester.successResponseParser),
5038
5074
 
5075
+ guestGetMeetingStatus: (meetingUuid ) =>
5076
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
5039
5077
  });
5040
5078
 
5041
5079
  //
@@ -6361,7 +6399,7 @@ const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
6361
6399
  const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
6362
6400
  class CanceledCallError extends Error {}
6363
6401
 
6364
- const MAX_REGISTER_TRIES = 10;
6402
+ const MAX_REGISTER_TRIES = 5;
6365
6403
 
6366
6404
 
6367
6405
 
@@ -6415,6 +6453,7 @@ class WebRTCClient extends Emitter {
6415
6453
 
6416
6454
 
6417
6455
 
6456
+
6418
6457
 
6419
6458
  // sugar
6420
6459
 
@@ -6477,6 +6516,7 @@ class WebRTCClient extends Emitter {
6477
6516
  this.conferences = {};
6478
6517
  this.networkMonitoringInterval = {};
6479
6518
  this.sessionNetworkStats = {};
6519
+ this.forceClosed = false;
6480
6520
 
6481
6521
  this._boundOnHeartbeat = this._onHeartbeat.bind(this);
6482
6522
  this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
@@ -6598,6 +6638,8 @@ class WebRTCClient extends Emitter {
6598
6638
  skipRegister: this.skipRegister,
6599
6639
  };
6600
6640
 
6641
+ this.forceClosed = false;
6642
+
6601
6643
  if (this.skipRegister) {
6602
6644
  logger$9.info('sdk webrtc skip register...', logInfo);
6603
6645
  return Promise.resolve();
@@ -6622,7 +6664,15 @@ class WebRTCClient extends Emitter {
6622
6664
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6623
6665
 
6624
6666
  const onRegisterFailed = () => {
6625
- logger$9.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6667
+ logger$9.info('sdk webrtc registering failed', {
6668
+ tries,
6669
+ registerer: !!this.registerer,
6670
+ forceClosed: this.forceClosed,
6671
+ });
6672
+ if (this.forceClosed) {
6673
+ return;
6674
+ }
6675
+
6626
6676
  this.connectionPromise = null;
6627
6677
  if (this.registerer && this.registerer.waiting) {
6628
6678
  this.registerer.waitingToggle(false);
@@ -6900,8 +6950,9 @@ class WebRTCClient extends Emitter {
6900
6950
  }
6901
6951
  }
6902
6952
 
6903
- async close() {
6904
- logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6953
+ async close(force = false) {
6954
+ logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
6955
+ this.forceClosed = force;
6905
6956
  this._cleanupMedia();
6906
6957
  this.connectionPromise = null;
6907
6958
 
@@ -6920,7 +6971,7 @@ class WebRTCClient extends Emitter {
6920
6971
  this.userAgent.delegate = null;
6921
6972
  this.userAgent.stateChange.removeAllListeners();
6922
6973
 
6923
- await this._disconnectTransport();
6974
+ await this._disconnectTransport(force);
6924
6975
 
6925
6976
  this._cleanupRegister();
6926
6977
 
@@ -8356,7 +8407,15 @@ class WebRTCClient extends Emitter {
8356
8407
  return UserAgent.makeURI(`sip:${target}@${this.config.host}`);
8357
8408
  }
8358
8409
 
8359
- async _disconnectTransport() {
8410
+ async _disconnectTransport(force = false) {
8411
+ if (force) {
8412
+ // Bypass sip.js state machine that prevent to close WS with the state `Connecting`
8413
+ this.userAgent.transport.disconnectResolve = () => {};
8414
+ // eslint-disable-next-line
8415
+ this.userAgent.transport._ws.close(1000);
8416
+ return;
8417
+ }
8418
+
8360
8419
  // Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
8361
8420
  if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
8362
8421
  try {
@@ -9093,6 +9152,7 @@ class WebRTCPhone extends Emitter {
9093
9152
  }
9094
9153
 
9095
9154
  callSession.answerTime = new Date();
9155
+ this._updateCallSession(callSession);
9096
9156
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9097
9157
 
9098
9158
  return callSession;
@@ -9302,6 +9362,12 @@ class WebRTCPhone extends Emitter {
9302
9362
  return Promise.resolve(null);
9303
9363
  }
9304
9364
 
9365
+ const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
9366
+ if (sipSessionId && !(sipSessionId in this.callSessions)) {
9367
+ logger$8.warn('Call session already ended or not found, can\'t accept it.', { sipSessionId });
9368
+ return Promise.resolve(null);
9369
+ }
9370
+
9305
9371
  if (callSession.getId() in this.acceptedSessions) {
9306
9372
  logger$8.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
9307
9373
  return Promise.resolve(callSession.sipCallId);
@@ -9309,6 +9375,7 @@ class WebRTCPhone extends Emitter {
9309
9375
 
9310
9376
  this.shouldSendReinvite = false;
9311
9377
  callSession.answerTime = new Date();
9378
+ this._updateCallSession(callSession);
9312
9379
  this.acceptedSessions[callSession.getId()] = true;
9313
9380
 
9314
9381
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9408,7 +9475,7 @@ class WebRTCPhone extends Emitter {
9408
9475
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
9409
9476
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
9410
9477
  logger$8.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9411
- this.holdSipSession(this.currentSipSession, callSession);
9478
+ this.holdSipSession(this.currentSipSession, this.currentCallSession);
9412
9479
  }
9413
9480
 
9414
9481
  const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
@@ -9619,6 +9686,7 @@ class WebRTCPhone extends Emitter {
9619
9686
  }
9620
9687
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9621
9688
  callSession.creationTime = new Date();
9689
+ this._updateCallSession(callSession);
9622
9690
 
9623
9691
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9624
9692
 
@@ -9760,7 +9828,7 @@ class WebRTCPhone extends Emitter {
9760
9828
  return this.client && this.client.isConference(callSession.sipCallId);
9761
9829
  }
9762
9830
 
9763
- async close() {
9831
+ async close(force = false) {
9764
9832
  logger$8.info('WebRTC close');
9765
9833
 
9766
9834
  try {
@@ -9772,7 +9840,7 @@ class WebRTCPhone extends Emitter {
9772
9840
  logger$8.error('WebRTC close, unregister error', e);
9773
9841
  }
9774
9842
 
9775
- this.client.close();
9843
+ this.client.close(force);
9776
9844
  this.unbind();
9777
9845
 
9778
9846
  this.incomingSessions = [];
@@ -9898,6 +9966,8 @@ class WebRTCPhone extends Emitter {
9898
9966
  }
9899
9967
 
9900
9968
  callSession.creationTime = new Date();
9969
+ this._updateCallSession(callSession);
9970
+
9901
9971
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
9902
9972
  });
9903
9973
 
@@ -9922,9 +9992,17 @@ class WebRTCPhone extends Emitter {
9922
9992
  });
9923
9993
 
9924
9994
  this.client.on(this.client.ACCEPTED, (sipSession ) => {
9925
- logger$8.info('WebRTC call accepted', { sipId: sipSession.id });
9995
+ const sessionId = this.getSipSessionId(sipSession);
9996
+ const hasSession = sessionId in this.callSessions;
9926
9997
 
9927
- this._onCallAccepted(sipSession, this.client.hasVideo(this.getSipSessionId(sipSession)));
9998
+ logger$8.info('WebRTC call accepted', { sipId: sessionId, hasSession });
9999
+
10000
+ if (!hasSession) {
10001
+ logger$8.warn('Call accepted ignored, session is no longer present in the WebRtcPhone', { sessionId });
10002
+ return;
10003
+ }
10004
+
10005
+ this._onCallAccepted(sipSession, this.client.hasVideo(sessionId));
9928
10006
 
9929
10007
  if (this.audioOutputDeviceId) {
9930
10008
  this.client.changeAudioOutputDevice(this.audioOutputDeviceId);
@@ -9941,6 +10019,8 @@ class WebRTCPhone extends Emitter {
9941
10019
  logger$8.info('WebRTC call rejected', session.id);
9942
10020
  const callSession = this._createCallSession(session);
9943
10021
  callSession.endTime = new Date();
10022
+ this._updateCallSession(callSession);
10023
+
9944
10024
  this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
9945
10025
  });
9946
10026
 
@@ -10058,9 +10138,14 @@ class WebRTCPhone extends Emitter {
10058
10138
  return this.client.getSipSessionId(sipSession);
10059
10139
  }
10060
10140
 
10061
- _updateCallSession(callSession ) {
10141
+ getSipSessionIdFromCallSession(callSession ) {
10062
10142
  const sipSession = this.findSipSession(callSession);
10063
- const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
10143
+
10144
+ return sipSession ? this.getSipSessionId(sipSession) : null;
10145
+ }
10146
+
10147
+ _updateCallSession(callSession ) {
10148
+ const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
10064
10149
 
10065
10150
  if (sipSessionId) {
10066
10151
  this.callSessions[sipSessionId] = callSession;
@@ -10165,6 +10250,7 @@ class WebRTCPhone extends Emitter {
10165
10250
  displayName: identity ? identity.displayName || number : number,
10166
10251
  startTime: fromSession ? fromSession.startTime : new Date(),
10167
10252
  creationTime: fromSession ? fromSession.creationTime : null,
10253
+ answerTime: fromSession ? fromSession.answerTime : null,
10168
10254
  endTime: fromSession ? fromSession.endTime : null,
10169
10255
  answered: state === SessionState.Established,
10170
10256
  paused: this.client.isCallHeld(sipSession),