@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
@@ -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
  //
@@ -3596,13 +3596,21 @@ class CallSession {
3596
3596
 
3597
3597
  // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
3598
3598
  set answered(value ) {
3599
- this.answerTime = value ? new Date() : null;
3599
+ this.answerTime = value ? this.answerTime || new Date() : null;
3600
3600
  }
3601
3601
 
3602
3602
  get answered() {
3603
3603
  return !!this.answerTime;
3604
3604
  }
3605
3605
 
3606
+ toJSON() {
3607
+ const jsonObj = { ...this };
3608
+ // $FlowFixMe
3609
+ jsonObj.answered = this.answered;
3610
+
3611
+ return jsonObj;
3612
+ }
3613
+
3606
3614
  static parseCall(call ) {
3607
3615
  return new CallSession({
3608
3616
  callId: call.id,
@@ -4854,6 +4862,34 @@ var chatdMethods = (client , baseUrl ) => ({
4854
4862
  client.get(`${baseUrl}/users/me/rooms/messages`, options),
4855
4863
  });
4856
4864
 
4865
+ //
4866
+
4867
+
4868
+
4869
+
4870
+
4871
+ class MeetingStatus {
4872
+
4873
+
4874
+
4875
+
4876
+ constructor({
4877
+ full,
4878
+ } = {}) {
4879
+ this.full = full;
4880
+
4881
+ // Useful to compare instead of instanceof with minified code
4882
+ this.type = 'MeetingStatus';
4883
+ }
4884
+
4885
+ static parse(plain ) {
4886
+ return new MeetingStatus({
4887
+ full: plain.full,
4888
+ });
4889
+ }
4890
+
4891
+ }
4892
+
4857
4893
  /* */
4858
4894
 
4859
4895
 
@@ -5048,6 +5084,8 @@ var calldMethods = (client , baseUrl ) => ({
5048
5084
  client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
5049
5085
  ApiRequester.successResponseParser),
5050
5086
 
5087
+ guestGetMeetingStatus: (meetingUuid ) =>
5088
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
5051
5089
  });
5052
5090
 
5053
5091
  //
@@ -6373,7 +6411,7 @@ const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
6373
6411
  const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
6374
6412
  class CanceledCallError extends Error {}
6375
6413
 
6376
- const MAX_REGISTER_TRIES = 10;
6414
+ const MAX_REGISTER_TRIES = 5;
6377
6415
 
6378
6416
 
6379
6417
 
@@ -6427,6 +6465,7 @@ class WebRTCClient extends Emitter {
6427
6465
 
6428
6466
 
6429
6467
 
6468
+
6430
6469
 
6431
6470
  // sugar
6432
6471
 
@@ -6489,6 +6528,7 @@ class WebRTCClient extends Emitter {
6489
6528
  this.conferences = {};
6490
6529
  this.networkMonitoringInterval = {};
6491
6530
  this.sessionNetworkStats = {};
6531
+ this.forceClosed = false;
6492
6532
 
6493
6533
  this._boundOnHeartbeat = this._onHeartbeat.bind(this);
6494
6534
  this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
@@ -6610,6 +6650,8 @@ class WebRTCClient extends Emitter {
6610
6650
  skipRegister: this.skipRegister,
6611
6651
  };
6612
6652
 
6653
+ this.forceClosed = false;
6654
+
6613
6655
  if (this.skipRegister) {
6614
6656
  logger$9.info('sdk webrtc skip register...', logInfo);
6615
6657
  return Promise.resolve();
@@ -6634,7 +6676,15 @@ class WebRTCClient extends Emitter {
6634
6676
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6635
6677
 
6636
6678
  const onRegisterFailed = () => {
6637
- logger$9.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6679
+ logger$9.info('sdk webrtc registering failed', {
6680
+ tries,
6681
+ registerer: !!this.registerer,
6682
+ forceClosed: this.forceClosed,
6683
+ });
6684
+ if (this.forceClosed) {
6685
+ return;
6686
+ }
6687
+
6638
6688
  this.connectionPromise = null;
6639
6689
  if (this.registerer && this.registerer.waiting) {
6640
6690
  this.registerer.waitingToggle(false);
@@ -6912,8 +6962,9 @@ class WebRTCClient extends Emitter {
6912
6962
  }
6913
6963
  }
6914
6964
 
6915
- async close() {
6916
- logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6965
+ async close(force = false) {
6966
+ logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
6967
+ this.forceClosed = force;
6917
6968
  this._cleanupMedia();
6918
6969
  this.connectionPromise = null;
6919
6970
 
@@ -6932,7 +6983,7 @@ class WebRTCClient extends Emitter {
6932
6983
  this.userAgent.delegate = null;
6933
6984
  this.userAgent.stateChange.removeAllListeners();
6934
6985
 
6935
- await this._disconnectTransport();
6986
+ await this._disconnectTransport(force);
6936
6987
 
6937
6988
  this._cleanupRegister();
6938
6989
 
@@ -8368,7 +8419,15 @@ class WebRTCClient extends Emitter {
8368
8419
  return userAgent.UserAgent.makeURI(`sip:${target}@${this.config.host}`);
8369
8420
  }
8370
8421
 
8371
- async _disconnectTransport() {
8422
+ async _disconnectTransport(force = false) {
8423
+ if (force) {
8424
+ // Bypass sip.js state machine that prevent to close WS with the state `Connecting`
8425
+ this.userAgent.transport.disconnectResolve = () => {};
8426
+ // eslint-disable-next-line
8427
+ this.userAgent.transport._ws.close(1000);
8428
+ return;
8429
+ }
8430
+
8372
8431
  // Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
8373
8432
  if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
8374
8433
  try {
@@ -9105,6 +9164,7 @@ class WebRTCPhone extends Emitter {
9105
9164
  }
9106
9165
 
9107
9166
  callSession.answerTime = new Date();
9167
+ this._updateCallSession(callSession);
9108
9168
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9109
9169
 
9110
9170
  return callSession;
@@ -9314,6 +9374,12 @@ class WebRTCPhone extends Emitter {
9314
9374
  return Promise.resolve(null);
9315
9375
  }
9316
9376
 
9377
+ const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
9378
+ if (sipSessionId && !(sipSessionId in this.callSessions)) {
9379
+ logger$8.warn('Call session already ended or not found, can\'t accept it.', { sipSessionId });
9380
+ return Promise.resolve(null);
9381
+ }
9382
+
9317
9383
  if (callSession.getId() in this.acceptedSessions) {
9318
9384
  logger$8.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
9319
9385
  return Promise.resolve(callSession.sipCallId);
@@ -9321,6 +9387,7 @@ class WebRTCPhone extends Emitter {
9321
9387
 
9322
9388
  this.shouldSendReinvite = false;
9323
9389
  callSession.answerTime = new Date();
9390
+ this._updateCallSession(callSession);
9324
9391
  this.acceptedSessions[callSession.getId()] = true;
9325
9392
 
9326
9393
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9420,7 +9487,7 @@ class WebRTCPhone extends Emitter {
9420
9487
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
9421
9488
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
9422
9489
  logger$8.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9423
- this.holdSipSession(this.currentSipSession, callSession);
9490
+ this.holdSipSession(this.currentSipSession, this.currentCallSession);
9424
9491
  }
9425
9492
 
9426
9493
  const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
@@ -9631,6 +9698,7 @@ class WebRTCPhone extends Emitter {
9631
9698
  }
9632
9699
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9633
9700
  callSession.creationTime = new Date();
9701
+ this._updateCallSession(callSession);
9634
9702
 
9635
9703
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9636
9704
 
@@ -9772,7 +9840,7 @@ class WebRTCPhone extends Emitter {
9772
9840
  return this.client && this.client.isConference(callSession.sipCallId);
9773
9841
  }
9774
9842
 
9775
- async close() {
9843
+ async close(force = false) {
9776
9844
  logger$8.info('WebRTC close');
9777
9845
 
9778
9846
  try {
@@ -9784,7 +9852,7 @@ class WebRTCPhone extends Emitter {
9784
9852
  logger$8.error('WebRTC close, unregister error', e);
9785
9853
  }
9786
9854
 
9787
- this.client.close();
9855
+ this.client.close(force);
9788
9856
  this.unbind();
9789
9857
 
9790
9858
  this.incomingSessions = [];
@@ -9910,6 +9978,8 @@ class WebRTCPhone extends Emitter {
9910
9978
  }
9911
9979
 
9912
9980
  callSession.creationTime = new Date();
9981
+ this._updateCallSession(callSession);
9982
+
9913
9983
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
9914
9984
  });
9915
9985
 
@@ -9934,9 +10004,17 @@ class WebRTCPhone extends Emitter {
9934
10004
  });
9935
10005
 
9936
10006
  this.client.on(this.client.ACCEPTED, (sipSession ) => {
9937
- logger$8.info('WebRTC call accepted', { sipId: sipSession.id });
10007
+ const sessionId = this.getSipSessionId(sipSession);
10008
+ const hasSession = sessionId in this.callSessions;
9938
10009
 
9939
- this._onCallAccepted(sipSession, this.client.hasVideo(this.getSipSessionId(sipSession)));
10010
+ logger$8.info('WebRTC call accepted', { sipId: sessionId, hasSession });
10011
+
10012
+ if (!hasSession) {
10013
+ logger$8.warn('Call accepted ignored, session is no longer present in the WebRtcPhone', { sessionId });
10014
+ return;
10015
+ }
10016
+
10017
+ this._onCallAccepted(sipSession, this.client.hasVideo(sessionId));
9940
10018
 
9941
10019
  if (this.audioOutputDeviceId) {
9942
10020
  this.client.changeAudioOutputDevice(this.audioOutputDeviceId);
@@ -9953,6 +10031,8 @@ class WebRTCPhone extends Emitter {
9953
10031
  logger$8.info('WebRTC call rejected', session.id);
9954
10032
  const callSession = this._createCallSession(session);
9955
10033
  callSession.endTime = new Date();
10034
+ this._updateCallSession(callSession);
10035
+
9956
10036
  this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
9957
10037
  });
9958
10038
 
@@ -10070,9 +10150,14 @@ class WebRTCPhone extends Emitter {
10070
10150
  return this.client.getSipSessionId(sipSession);
10071
10151
  }
10072
10152
 
10073
- _updateCallSession(callSession ) {
10153
+ getSipSessionIdFromCallSession(callSession ) {
10074
10154
  const sipSession = this.findSipSession(callSession);
10075
- const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
10155
+
10156
+ return sipSession ? this.getSipSessionId(sipSession) : null;
10157
+ }
10158
+
10159
+ _updateCallSession(callSession ) {
10160
+ const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
10076
10161
 
10077
10162
  if (sipSessionId) {
10078
10163
  this.callSessions[sipSessionId] = callSession;
@@ -10177,6 +10262,7 @@ class WebRTCPhone extends Emitter {
10177
10262
  displayName: identity ? identity.displayName || number : number,
10178
10263
  startTime: fromSession ? fromSession.startTime : new Date(),
10179
10264
  creationTime: fromSession ? fromSession.creationTime : null,
10265
+ answerTime: fromSession ? fromSession.answerTime : null,
10180
10266
  endTime: fromSession ? fromSession.endTime : null,
10181
10267
  answered: state === sessionState.SessionState.Established,
10182
10268
  paused: this.client.isCallHeld(sipSession),
@@ -3594,13 +3594,21 @@ class CallSession {
3594
3594
 
3595
3595
  // Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
3596
3596
  set answered(value ) {
3597
- this.answerTime = value ? new Date() : null;
3597
+ this.answerTime = value ? this.answerTime || new Date() : null;
3598
3598
  }
3599
3599
 
3600
3600
  get answered() {
3601
3601
  return !!this.answerTime;
3602
3602
  }
3603
3603
 
3604
+ toJSON() {
3605
+ const jsonObj = { ...this };
3606
+ // $FlowFixMe
3607
+ jsonObj.answered = this.answered;
3608
+
3609
+ return jsonObj;
3610
+ }
3611
+
3604
3612
  static parseCall(call ) {
3605
3613
  return new CallSession({
3606
3614
  callId: call.id,
@@ -4852,6 +4860,34 @@ var chatdMethods = (client , baseUrl ) => ({
4852
4860
  client.get(`${baseUrl}/users/me/rooms/messages`, options),
4853
4861
  });
4854
4862
 
4863
+ //
4864
+
4865
+
4866
+
4867
+
4868
+
4869
+ class MeetingStatus {
4870
+
4871
+
4872
+
4873
+
4874
+ constructor({
4875
+ full,
4876
+ } = {}) {
4877
+ this.full = full;
4878
+
4879
+ // Useful to compare instead of instanceof with minified code
4880
+ this.type = 'MeetingStatus';
4881
+ }
4882
+
4883
+ static parse(plain ) {
4884
+ return new MeetingStatus({
4885
+ full: plain.full,
4886
+ });
4887
+ }
4888
+
4889
+ }
4890
+
4855
4891
  /* */
4856
4892
 
4857
4893
 
@@ -5046,6 +5082,8 @@ var calldMethods = (client , baseUrl ) => ({
5046
5082
  client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
5047
5083
  ApiRequester.successResponseParser),
5048
5084
 
5085
+ guestGetMeetingStatus: (meetingUuid ) =>
5086
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
5049
5087
  });
5050
5088
 
5051
5089
  //
@@ -6371,7 +6409,7 @@ const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
6371
6409
  const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
6372
6410
  class CanceledCallError extends Error {}
6373
6411
 
6374
- const MAX_REGISTER_TRIES = 10;
6412
+ const MAX_REGISTER_TRIES = 5;
6375
6413
 
6376
6414
 
6377
6415
 
@@ -6425,6 +6463,7 @@ class WebRTCClient extends Emitter {
6425
6463
 
6426
6464
 
6427
6465
 
6466
+
6428
6467
 
6429
6468
  // sugar
6430
6469
 
@@ -6487,6 +6526,7 @@ class WebRTCClient extends Emitter {
6487
6526
  this.conferences = {};
6488
6527
  this.networkMonitoringInterval = {};
6489
6528
  this.sessionNetworkStats = {};
6529
+ this.forceClosed = false;
6490
6530
 
6491
6531
  this._boundOnHeartbeat = this._onHeartbeat.bind(this);
6492
6532
  this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
@@ -6608,6 +6648,8 @@ class WebRTCClient extends Emitter {
6608
6648
  skipRegister: this.skipRegister,
6609
6649
  };
6610
6650
 
6651
+ this.forceClosed = false;
6652
+
6611
6653
  if (this.skipRegister) {
6612
6654
  logger$9.info('sdk webrtc skip register...', logInfo);
6613
6655
  return Promise.resolve();
@@ -6632,7 +6674,15 @@ class WebRTCClient extends Emitter {
6632
6674
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6633
6675
 
6634
6676
  const onRegisterFailed = () => {
6635
- logger$9.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6677
+ logger$9.info('sdk webrtc registering failed', {
6678
+ tries,
6679
+ registerer: !!this.registerer,
6680
+ forceClosed: this.forceClosed,
6681
+ });
6682
+ if (this.forceClosed) {
6683
+ return;
6684
+ }
6685
+
6636
6686
  this.connectionPromise = null;
6637
6687
  if (this.registerer && this.registerer.waiting) {
6638
6688
  this.registerer.waitingToggle(false);
@@ -6910,8 +6960,9 @@ class WebRTCClient extends Emitter {
6910
6960
  }
6911
6961
  }
6912
6962
 
6913
- async close() {
6914
- logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
6963
+ async close(force = false) {
6964
+ logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
6965
+ this.forceClosed = force;
6915
6966
  this._cleanupMedia();
6916
6967
  this.connectionPromise = null;
6917
6968
 
@@ -6930,7 +6981,7 @@ class WebRTCClient extends Emitter {
6930
6981
  this.userAgent.delegate = null;
6931
6982
  this.userAgent.stateChange.removeAllListeners();
6932
6983
 
6933
- await this._disconnectTransport();
6984
+ await this._disconnectTransport(force);
6934
6985
 
6935
6986
  this._cleanupRegister();
6936
6987
 
@@ -8366,7 +8417,15 @@ class WebRTCClient extends Emitter {
8366
8417
  return userAgent.UserAgent.makeURI(`sip:${target}@${this.config.host}`);
8367
8418
  }
8368
8419
 
8369
- async _disconnectTransport() {
8420
+ async _disconnectTransport(force = false) {
8421
+ if (force) {
8422
+ // Bypass sip.js state machine that prevent to close WS with the state `Connecting`
8423
+ this.userAgent.transport.disconnectResolve = () => {};
8424
+ // eslint-disable-next-line
8425
+ this.userAgent.transport._ws.close(1000);
8426
+ return;
8427
+ }
8428
+
8370
8429
  // Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
8371
8430
  if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
8372
8431
  try {
@@ -9103,6 +9162,7 @@ class WebRTCPhone extends Emitter {
9103
9162
  }
9104
9163
 
9105
9164
  callSession.answerTime = new Date();
9165
+ this._updateCallSession(callSession);
9106
9166
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9107
9167
 
9108
9168
  return callSession;
@@ -9312,6 +9372,12 @@ class WebRTCPhone extends Emitter {
9312
9372
  return Promise.resolve(null);
9313
9373
  }
9314
9374
 
9375
+ const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
9376
+ if (sipSessionId && !(sipSessionId in this.callSessions)) {
9377
+ logger$8.warn('Call session already ended or not found, can\'t accept it.', { sipSessionId });
9378
+ return Promise.resolve(null);
9379
+ }
9380
+
9315
9381
  if (callSession.getId() in this.acceptedSessions) {
9316
9382
  logger$8.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
9317
9383
  return Promise.resolve(callSession.sipCallId);
@@ -9319,6 +9385,7 @@ class WebRTCPhone extends Emitter {
9319
9385
 
9320
9386
  this.shouldSendReinvite = false;
9321
9387
  callSession.answerTime = new Date();
9388
+ this._updateCallSession(callSession);
9322
9389
  this.acceptedSessions[callSession.getId()] = true;
9323
9390
 
9324
9391
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9418,7 +9485,7 @@ class WebRTCPhone extends Emitter {
9418
9485
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
9419
9486
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
9420
9487
  logger$8.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9421
- this.holdSipSession(this.currentSipSession, callSession);
9488
+ this.holdSipSession(this.currentSipSession, this.currentCallSession);
9422
9489
  }
9423
9490
 
9424
9491
  const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
@@ -9629,6 +9696,7 @@ class WebRTCPhone extends Emitter {
9629
9696
  }
9630
9697
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9631
9698
  callSession.creationTime = new Date();
9699
+ this._updateCallSession(callSession);
9632
9700
 
9633
9701
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9634
9702
 
@@ -9770,7 +9838,7 @@ class WebRTCPhone extends Emitter {
9770
9838
  return this.client && this.client.isConference(callSession.sipCallId);
9771
9839
  }
9772
9840
 
9773
- async close() {
9841
+ async close(force = false) {
9774
9842
  logger$8.info('WebRTC close');
9775
9843
 
9776
9844
  try {
@@ -9782,7 +9850,7 @@ class WebRTCPhone extends Emitter {
9782
9850
  logger$8.error('WebRTC close, unregister error', e);
9783
9851
  }
9784
9852
 
9785
- this.client.close();
9853
+ this.client.close(force);
9786
9854
  this.unbind();
9787
9855
 
9788
9856
  this.incomingSessions = [];
@@ -9908,6 +9976,8 @@ class WebRTCPhone extends Emitter {
9908
9976
  }
9909
9977
 
9910
9978
  callSession.creationTime = new Date();
9979
+ this._updateCallSession(callSession);
9980
+
9911
9981
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
9912
9982
  });
9913
9983
 
@@ -9932,9 +10002,17 @@ class WebRTCPhone extends Emitter {
9932
10002
  });
9933
10003
 
9934
10004
  this.client.on(this.client.ACCEPTED, (sipSession ) => {
9935
- logger$8.info('WebRTC call accepted', { sipId: sipSession.id });
10005
+ const sessionId = this.getSipSessionId(sipSession);
10006
+ const hasSession = sessionId in this.callSessions;
9936
10007
 
9937
- this._onCallAccepted(sipSession, this.client.hasVideo(this.getSipSessionId(sipSession)));
10008
+ logger$8.info('WebRTC call accepted', { sipId: sessionId, hasSession });
10009
+
10010
+ if (!hasSession) {
10011
+ logger$8.warn('Call accepted ignored, session is no longer present in the WebRtcPhone', { sessionId });
10012
+ return;
10013
+ }
10014
+
10015
+ this._onCallAccepted(sipSession, this.client.hasVideo(sessionId));
9938
10016
 
9939
10017
  if (this.audioOutputDeviceId) {
9940
10018
  this.client.changeAudioOutputDevice(this.audioOutputDeviceId);
@@ -9951,6 +10029,8 @@ class WebRTCPhone extends Emitter {
9951
10029
  logger$8.info('WebRTC call rejected', session.id);
9952
10030
  const callSession = this._createCallSession(session);
9953
10031
  callSession.endTime = new Date();
10032
+ this._updateCallSession(callSession);
10033
+
9954
10034
  this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
9955
10035
  });
9956
10036
 
@@ -10068,9 +10148,14 @@ class WebRTCPhone extends Emitter {
10068
10148
  return this.client.getSipSessionId(sipSession);
10069
10149
  }
10070
10150
 
10071
- _updateCallSession(callSession ) {
10151
+ getSipSessionIdFromCallSession(callSession ) {
10072
10152
  const sipSession = this.findSipSession(callSession);
10073
- const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
10153
+
10154
+ return sipSession ? this.getSipSessionId(sipSession) : null;
10155
+ }
10156
+
10157
+ _updateCallSession(callSession ) {
10158
+ const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
10074
10159
 
10075
10160
  if (sipSessionId) {
10076
10161
  this.callSessions[sipSessionId] = callSession;
@@ -10175,6 +10260,7 @@ class WebRTCPhone extends Emitter {
10175
10260
  displayName: identity ? identity.displayName || number : number,
10176
10261
  startTime: fromSession ? fromSession.startTime : new Date(),
10177
10262
  creationTime: fromSession ? fromSession.creationTime : null,
10263
+ answerTime: fromSession ? fromSession.answerTime : null,
10178
10264
  endTime: fromSession ? fromSession.endTime : null,
10179
10265
  answered: state === sessionState.SessionState.Established,
10180
10266
  paused: this.client.isCallHeld(sipSession),
@@ -4022,6 +4022,34 @@ var chatdMethods = (client , baseUrl ) => ({
4022
4022
  client.get(`${baseUrl}/users/me/rooms/messages`, options),
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
  //