@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
@@ -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
  //
@@ -6635,7 +6673,7 @@ const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
6635
6673
  const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
6636
6674
  class CanceledCallError extends Error {}
6637
6675
 
6638
- const MAX_REGISTER_TRIES = 10;
6676
+ const MAX_REGISTER_TRIES = 5;
6639
6677
 
6640
6678
 
6641
6679
 
@@ -6689,6 +6727,7 @@ class WebRTCClient extends Emitter {
6689
6727
 
6690
6728
 
6691
6729
 
6730
+
6692
6731
 
6693
6732
  // sugar
6694
6733
 
@@ -6751,6 +6790,7 @@ class WebRTCClient extends Emitter {
6751
6790
  this.conferences = {};
6752
6791
  this.networkMonitoringInterval = {};
6753
6792
  this.sessionNetworkStats = {};
6793
+ this.forceClosed = false;
6754
6794
 
6755
6795
  this._boundOnHeartbeat = this._onHeartbeat.bind(this);
6756
6796
  this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
@@ -6872,6 +6912,8 @@ class WebRTCClient extends Emitter {
6872
6912
  skipRegister: this.skipRegister,
6873
6913
  };
6874
6914
 
6915
+ this.forceClosed = false;
6916
+
6875
6917
  if (this.skipRegister) {
6876
6918
  logger$8.info('sdk webrtc skip register...', logInfo);
6877
6919
  return Promise.resolve();
@@ -6896,7 +6938,15 @@ class WebRTCClient extends Emitter {
6896
6938
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6897
6939
 
6898
6940
  const onRegisterFailed = () => {
6899
- logger$8.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6941
+ logger$8.info('sdk webrtc registering failed', {
6942
+ tries,
6943
+ registerer: !!this.registerer,
6944
+ forceClosed: this.forceClosed,
6945
+ });
6946
+ if (this.forceClosed) {
6947
+ return;
6948
+ }
6949
+
6900
6950
  this.connectionPromise = null;
6901
6951
  if (this.registerer && this.registerer.waiting) {
6902
6952
  this.registerer.waitingToggle(false);
@@ -7174,8 +7224,9 @@ class WebRTCClient extends Emitter {
7174
7224
  }
7175
7225
  }
7176
7226
 
7177
- async close() {
7178
- logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
7227
+ async close(force = false) {
7228
+ logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
7229
+ this.forceClosed = force;
7179
7230
  this._cleanupMedia();
7180
7231
  this.connectionPromise = null;
7181
7232
 
@@ -7194,7 +7245,7 @@ class WebRTCClient extends Emitter {
7194
7245
  this.userAgent.delegate = null;
7195
7246
  this.userAgent.stateChange.removeAllListeners();
7196
7247
 
7197
- await this._disconnectTransport();
7248
+ await this._disconnectTransport(force);
7198
7249
 
7199
7250
  this._cleanupRegister();
7200
7251
 
@@ -8630,7 +8681,15 @@ class WebRTCClient extends Emitter {
8630
8681
  return userAgent.UserAgent.makeURI(`sip:${target}@${this.config.host}`);
8631
8682
  }
8632
8683
 
8633
- async _disconnectTransport() {
8684
+ async _disconnectTransport(force = false) {
8685
+ if (force) {
8686
+ // Bypass sip.js state machine that prevent to close WS with the state `Connecting`
8687
+ this.userAgent.transport.disconnectResolve = () => {};
8688
+ // eslint-disable-next-line
8689
+ this.userAgent.transport._ws.close(1000);
8690
+ return;
8691
+ }
8692
+
8634
8693
  // Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
8635
8694
  if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
8636
8695
  try {
@@ -9367,6 +9426,7 @@ class WebRTCPhone extends Emitter {
9367
9426
  }
9368
9427
 
9369
9428
  callSession.answerTime = new Date();
9429
+ this._updateCallSession(callSession);
9370
9430
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9371
9431
 
9372
9432
  return callSession;
@@ -9576,6 +9636,12 @@ class WebRTCPhone extends Emitter {
9576
9636
  return Promise.resolve(null);
9577
9637
  }
9578
9638
 
9639
+ const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
9640
+ if (sipSessionId && !(sipSessionId in this.callSessions)) {
9641
+ logger$7.warn('Call session already ended or not found, can\'t accept it.', { sipSessionId });
9642
+ return Promise.resolve(null);
9643
+ }
9644
+
9579
9645
  if (callSession.getId() in this.acceptedSessions) {
9580
9646
  logger$7.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
9581
9647
  return Promise.resolve(callSession.sipCallId);
@@ -9583,6 +9649,7 @@ class WebRTCPhone extends Emitter {
9583
9649
 
9584
9650
  this.shouldSendReinvite = false;
9585
9651
  callSession.answerTime = new Date();
9652
+ this._updateCallSession(callSession);
9586
9653
  this.acceptedSessions[callSession.getId()] = true;
9587
9654
 
9588
9655
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9682,7 +9749,7 @@ class WebRTCPhone extends Emitter {
9682
9749
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
9683
9750
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
9684
9751
  logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9685
- this.holdSipSession(this.currentSipSession, callSession);
9752
+ this.holdSipSession(this.currentSipSession, this.currentCallSession);
9686
9753
  }
9687
9754
 
9688
9755
  const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
@@ -9893,6 +9960,7 @@ class WebRTCPhone extends Emitter {
9893
9960
  }
9894
9961
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9895
9962
  callSession.creationTime = new Date();
9963
+ this._updateCallSession(callSession);
9896
9964
 
9897
9965
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9898
9966
 
@@ -10034,7 +10102,7 @@ class WebRTCPhone extends Emitter {
10034
10102
  return this.client && this.client.isConference(callSession.sipCallId);
10035
10103
  }
10036
10104
 
10037
- async close() {
10105
+ async close(force = false) {
10038
10106
  logger$7.info('WebRTC close');
10039
10107
 
10040
10108
  try {
@@ -10046,7 +10114,7 @@ class WebRTCPhone extends Emitter {
10046
10114
  logger$7.error('WebRTC close, unregister error', e);
10047
10115
  }
10048
10116
 
10049
- this.client.close();
10117
+ this.client.close(force);
10050
10118
  this.unbind();
10051
10119
 
10052
10120
  this.incomingSessions = [];
@@ -10172,6 +10240,8 @@ class WebRTCPhone extends Emitter {
10172
10240
  }
10173
10241
 
10174
10242
  callSession.creationTime = new Date();
10243
+ this._updateCallSession(callSession);
10244
+
10175
10245
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
10176
10246
  });
10177
10247
 
@@ -10196,9 +10266,17 @@ class WebRTCPhone extends Emitter {
10196
10266
  });
10197
10267
 
10198
10268
  this.client.on(this.client.ACCEPTED, (sipSession ) => {
10199
- logger$7.info('WebRTC call accepted', { sipId: sipSession.id });
10269
+ const sessionId = this.getSipSessionId(sipSession);
10270
+ const hasSession = sessionId in this.callSessions;
10200
10271
 
10201
- this._onCallAccepted(sipSession, this.client.hasVideo(this.getSipSessionId(sipSession)));
10272
+ logger$7.info('WebRTC call accepted', { sipId: sessionId, hasSession });
10273
+
10274
+ if (!hasSession) {
10275
+ logger$7.warn('Call accepted ignored, session is no longer present in the WebRtcPhone', { sessionId });
10276
+ return;
10277
+ }
10278
+
10279
+ this._onCallAccepted(sipSession, this.client.hasVideo(sessionId));
10202
10280
 
10203
10281
  if (this.audioOutputDeviceId) {
10204
10282
  this.client.changeAudioOutputDevice(this.audioOutputDeviceId);
@@ -10215,6 +10293,8 @@ class WebRTCPhone extends Emitter {
10215
10293
  logger$7.info('WebRTC call rejected', session.id);
10216
10294
  const callSession = this._createCallSession(session);
10217
10295
  callSession.endTime = new Date();
10296
+ this._updateCallSession(callSession);
10297
+
10218
10298
  this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
10219
10299
  });
10220
10300
 
@@ -10332,9 +10412,14 @@ class WebRTCPhone extends Emitter {
10332
10412
  return this.client.getSipSessionId(sipSession);
10333
10413
  }
10334
10414
 
10335
- _updateCallSession(callSession ) {
10415
+ getSipSessionIdFromCallSession(callSession ) {
10336
10416
  const sipSession = this.findSipSession(callSession);
10337
- const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
10417
+
10418
+ return sipSession ? this.getSipSessionId(sipSession) : null;
10419
+ }
10420
+
10421
+ _updateCallSession(callSession ) {
10422
+ const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
10338
10423
 
10339
10424
  if (sipSessionId) {
10340
10425
  this.callSessions[sipSessionId] = callSession;
@@ -10439,6 +10524,7 @@ class WebRTCPhone extends Emitter {
10439
10524
  displayName: identity ? identity.displayName || number : number,
10440
10525
  startTime: fromSession ? fromSession.startTime : new Date(),
10441
10526
  creationTime: fromSession ? fromSession.creationTime : null,
10527
+ answerTime: fromSession ? fromSession.answerTime : null,
10442
10528
  endTime: fromSession ? fromSession.endTime : null,
10443
10529
  answered: state === sessionState.SessionState.Established,
10444
10530
  paused: this.client.isCallHeld(sipSession),
@@ -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
  //
@@ -6637,7 +6675,7 @@ const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
6637
6675
  const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
6638
6676
  class CanceledCallError extends Error {}
6639
6677
 
6640
- const MAX_REGISTER_TRIES = 10;
6678
+ const MAX_REGISTER_TRIES = 5;
6641
6679
 
6642
6680
 
6643
6681
 
@@ -6691,6 +6729,7 @@ class WebRTCClient extends Emitter {
6691
6729
 
6692
6730
 
6693
6731
 
6732
+
6694
6733
 
6695
6734
  // sugar
6696
6735
 
@@ -6753,6 +6792,7 @@ class WebRTCClient extends Emitter {
6753
6792
  this.conferences = {};
6754
6793
  this.networkMonitoringInterval = {};
6755
6794
  this.sessionNetworkStats = {};
6795
+ this.forceClosed = false;
6756
6796
 
6757
6797
  this._boundOnHeartbeat = this._onHeartbeat.bind(this);
6758
6798
  this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
@@ -6874,6 +6914,8 @@ class WebRTCClient extends Emitter {
6874
6914
  skipRegister: this.skipRegister,
6875
6915
  };
6876
6916
 
6917
+ this.forceClosed = false;
6918
+
6877
6919
  if (this.skipRegister) {
6878
6920
  logger$8.info('sdk webrtc skip register...', logInfo);
6879
6921
  return Promise.resolve();
@@ -6898,7 +6940,15 @@ class WebRTCClient extends Emitter {
6898
6940
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
6899
6941
 
6900
6942
  const onRegisterFailed = () => {
6901
- logger$8.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
6943
+ logger$8.info('sdk webrtc registering failed', {
6944
+ tries,
6945
+ registerer: !!this.registerer,
6946
+ forceClosed: this.forceClosed,
6947
+ });
6948
+ if (this.forceClosed) {
6949
+ return;
6950
+ }
6951
+
6902
6952
  this.connectionPromise = null;
6903
6953
  if (this.registerer && this.registerer.waiting) {
6904
6954
  this.registerer.waitingToggle(false);
@@ -7176,8 +7226,9 @@ class WebRTCClient extends Emitter {
7176
7226
  }
7177
7227
  }
7178
7228
 
7179
- async close() {
7180
- logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
7229
+ async close(force = false) {
7230
+ logger$8.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
7231
+ this.forceClosed = force;
7181
7232
  this._cleanupMedia();
7182
7233
  this.connectionPromise = null;
7183
7234
 
@@ -7196,7 +7247,7 @@ class WebRTCClient extends Emitter {
7196
7247
  this.userAgent.delegate = null;
7197
7248
  this.userAgent.stateChange.removeAllListeners();
7198
7249
 
7199
- await this._disconnectTransport();
7250
+ await this._disconnectTransport(force);
7200
7251
 
7201
7252
  this._cleanupRegister();
7202
7253
 
@@ -8632,7 +8683,15 @@ class WebRTCClient extends Emitter {
8632
8683
  return userAgent.UserAgent.makeURI(`sip:${target}@${this.config.host}`);
8633
8684
  }
8634
8685
 
8635
- async _disconnectTransport() {
8686
+ async _disconnectTransport(force = false) {
8687
+ if (force) {
8688
+ // Bypass sip.js state machine that prevent to close WS with the state `Connecting`
8689
+ this.userAgent.transport.disconnectResolve = () => {};
8690
+ // eslint-disable-next-line
8691
+ this.userAgent.transport._ws.close(1000);
8692
+ return;
8693
+ }
8694
+
8636
8695
  // Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
8637
8696
  if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
8638
8697
  try {
@@ -9369,6 +9428,7 @@ class WebRTCPhone extends Emitter {
9369
9428
  }
9370
9429
 
9371
9430
  callSession.answerTime = new Date();
9431
+ this._updateCallSession(callSession);
9372
9432
  this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
9373
9433
 
9374
9434
  return callSession;
@@ -9578,6 +9638,12 @@ class WebRTCPhone extends Emitter {
9578
9638
  return Promise.resolve(null);
9579
9639
  }
9580
9640
 
9641
+ const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
9642
+ if (sipSessionId && !(sipSessionId in this.callSessions)) {
9643
+ logger$7.warn('Call session already ended or not found, can\'t accept it.', { sipSessionId });
9644
+ return Promise.resolve(null);
9645
+ }
9646
+
9581
9647
  if (callSession.getId() in this.acceptedSessions) {
9582
9648
  logger$7.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
9583
9649
  return Promise.resolve(callSession.sipCallId);
@@ -9585,6 +9651,7 @@ class WebRTCPhone extends Emitter {
9585
9651
 
9586
9652
  this.shouldSendReinvite = false;
9587
9653
  callSession.answerTime = new Date();
9654
+ this._updateCallSession(callSession);
9588
9655
  this.acceptedSessions[callSession.getId()] = true;
9589
9656
 
9590
9657
  this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
@@ -9684,7 +9751,7 @@ class WebRTCPhone extends Emitter {
9684
9751
  // Hold current session if different from the current one (we don't want 2 sessions active at the same time).
9685
9752
  if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
9686
9753
  logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
9687
- this.holdSipSession(this.currentSipSession, callSession);
9754
+ this.holdSipSession(this.currentSipSession, this.currentCallSession);
9688
9755
  }
9689
9756
 
9690
9757
  const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
@@ -9895,6 +9962,7 @@ class WebRTCPhone extends Emitter {
9895
9962
  }
9896
9963
  const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
9897
9964
  callSession.creationTime = new Date();
9965
+ this._updateCallSession(callSession);
9898
9966
 
9899
9967
  this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
9900
9968
 
@@ -10036,7 +10104,7 @@ class WebRTCPhone extends Emitter {
10036
10104
  return this.client && this.client.isConference(callSession.sipCallId);
10037
10105
  }
10038
10106
 
10039
- async close() {
10107
+ async close(force = false) {
10040
10108
  logger$7.info('WebRTC close');
10041
10109
 
10042
10110
  try {
@@ -10048,7 +10116,7 @@ class WebRTCPhone extends Emitter {
10048
10116
  logger$7.error('WebRTC close, unregister error', e);
10049
10117
  }
10050
10118
 
10051
- this.client.close();
10119
+ this.client.close(force);
10052
10120
  this.unbind();
10053
10121
 
10054
10122
  this.incomingSessions = [];
@@ -10174,6 +10242,8 @@ class WebRTCPhone extends Emitter {
10174
10242
  }
10175
10243
 
10176
10244
  callSession.creationTime = new Date();
10245
+ this._updateCallSession(callSession);
10246
+
10177
10247
  this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
10178
10248
  });
10179
10249
 
@@ -10198,9 +10268,17 @@ class WebRTCPhone extends Emitter {
10198
10268
  });
10199
10269
 
10200
10270
  this.client.on(this.client.ACCEPTED, (sipSession ) => {
10201
- logger$7.info('WebRTC call accepted', { sipId: sipSession.id });
10271
+ const sessionId = this.getSipSessionId(sipSession);
10272
+ const hasSession = sessionId in this.callSessions;
10202
10273
 
10203
- this._onCallAccepted(sipSession, this.client.hasVideo(this.getSipSessionId(sipSession)));
10274
+ logger$7.info('WebRTC call accepted', { sipId: sessionId, hasSession });
10275
+
10276
+ if (!hasSession) {
10277
+ logger$7.warn('Call accepted ignored, session is no longer present in the WebRtcPhone', { sessionId });
10278
+ return;
10279
+ }
10280
+
10281
+ this._onCallAccepted(sipSession, this.client.hasVideo(sessionId));
10204
10282
 
10205
10283
  if (this.audioOutputDeviceId) {
10206
10284
  this.client.changeAudioOutputDevice(this.audioOutputDeviceId);
@@ -10217,6 +10295,8 @@ class WebRTCPhone extends Emitter {
10217
10295
  logger$7.info('WebRTC call rejected', session.id);
10218
10296
  const callSession = this._createCallSession(session);
10219
10297
  callSession.endTime = new Date();
10298
+ this._updateCallSession(callSession);
10299
+
10220
10300
  this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
10221
10301
  });
10222
10302
 
@@ -10334,9 +10414,14 @@ class WebRTCPhone extends Emitter {
10334
10414
  return this.client.getSipSessionId(sipSession);
10335
10415
  }
10336
10416
 
10337
- _updateCallSession(callSession ) {
10417
+ getSipSessionIdFromCallSession(callSession ) {
10338
10418
  const sipSession = this.findSipSession(callSession);
10339
- const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
10419
+
10420
+ return sipSession ? this.getSipSessionId(sipSession) : null;
10421
+ }
10422
+
10423
+ _updateCallSession(callSession ) {
10424
+ const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
10340
10425
 
10341
10426
  if (sipSessionId) {
10342
10427
  this.callSessions[sipSessionId] = callSession;
@@ -10441,6 +10526,7 @@ class WebRTCPhone extends Emitter {
10441
10526
  displayName: identity ? identity.displayName || number : number,
10442
10527
  startTime: fromSession ? fromSession.startTime : new Date(),
10443
10528
  creationTime: fromSession ? fromSession.creationTime : null,
10529
+ answerTime: fromSession ? fromSession.answerTime : null,
10444
10530
  endTime: fromSession ? fromSession.endTime : null,
10445
10531
  answered: state === sessionState.SessionState.Established,
10446
10532
  paused: this.client.isCallHeld(sipSession),
@@ -4590,6 +4590,34 @@ var chatdMethods = (client , baseUrl ) => ({
4590
4590
  client.get(`${baseUrl}/users/me/rooms/messages`, options),
4591
4591
  });
4592
4592
 
4593
+ //
4594
+
4595
+
4596
+
4597
+
4598
+
4599
+ class MeetingStatus {
4600
+
4601
+
4602
+
4603
+
4604
+ constructor({
4605
+ full,
4606
+ } = {}) {
4607
+ this.full = full;
4608
+
4609
+ // Useful to compare instead of instanceof with minified code
4610
+ this.type = 'MeetingStatus';
4611
+ }
4612
+
4613
+ static parse(plain ) {
4614
+ return new MeetingStatus({
4615
+ full: plain.full,
4616
+ });
4617
+ }
4618
+
4619
+ }
4620
+
4593
4621
  /* */
4594
4622
 
4595
4623
 
@@ -4784,6 +4812,8 @@ var calldMethods = (client , baseUrl ) => ({
4784
4812
  client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
4785
4813
  ApiRequester.successResponseParser),
4786
4814
 
4815
+ guestGetMeetingStatus: (meetingUuid ) =>
4816
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
4787
4817
  });
4788
4818
 
4789
4819
  //
@@ -5346,7 +5376,7 @@ const events = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
5346
5376
  const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
5347
5377
  class CanceledCallError extends Error {}
5348
5378
 
5349
- const MAX_REGISTER_TRIES = 10;
5379
+ const MAX_REGISTER_TRIES = 5;
5350
5380
 
5351
5381
 
5352
5382
 
@@ -5400,6 +5430,7 @@ class WebRTCClient extends Emitter {
5400
5430
 
5401
5431
 
5402
5432
 
5433
+
5403
5434
 
5404
5435
  // sugar
5405
5436
 
@@ -5462,6 +5493,7 @@ class WebRTCClient extends Emitter {
5462
5493
  this.conferences = {};
5463
5494
  this.networkMonitoringInterval = {};
5464
5495
  this.sessionNetworkStats = {};
5496
+ this.forceClosed = false;
5465
5497
 
5466
5498
  this._boundOnHeartbeat = this._onHeartbeat.bind(this);
5467
5499
  this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
@@ -5583,6 +5615,8 @@ class WebRTCClient extends Emitter {
5583
5615
  skipRegister: this.skipRegister,
5584
5616
  };
5585
5617
 
5618
+ this.forceClosed = false;
5619
+
5586
5620
  if (this.skipRegister) {
5587
5621
  logger.info('sdk webrtc skip register...', logInfo);
5588
5622
  return Promise.resolve();
@@ -5607,7 +5641,15 @@ class WebRTCClient extends Emitter {
5607
5641
  const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
5608
5642
 
5609
5643
  const onRegisterFailed = () => {
5610
- logger.info('sdk webrtc registering failed', { tries, registerer: !!this.registerer });
5644
+ logger.info('sdk webrtc registering failed', {
5645
+ tries,
5646
+ registerer: !!this.registerer,
5647
+ forceClosed: this.forceClosed,
5648
+ });
5649
+ if (this.forceClosed) {
5650
+ return;
5651
+ }
5652
+
5611
5653
  this.connectionPromise = null;
5612
5654
  if (this.registerer && this.registerer.waiting) {
5613
5655
  this.registerer.waitingToggle(false);
@@ -5885,8 +5927,9 @@ class WebRTCClient extends Emitter {
5885
5927
  }
5886
5928
  }
5887
5929
 
5888
- async close() {
5889
- logger.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
5930
+ async close(force = false) {
5931
+ logger.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
5932
+ this.forceClosed = force;
5890
5933
  this._cleanupMedia();
5891
5934
  this.connectionPromise = null;
5892
5935
 
@@ -5905,7 +5948,7 @@ class WebRTCClient extends Emitter {
5905
5948
  this.userAgent.delegate = null;
5906
5949
  this.userAgent.stateChange.removeAllListeners();
5907
5950
 
5908
- await this._disconnectTransport();
5951
+ await this._disconnectTransport(force);
5909
5952
 
5910
5953
  this._cleanupRegister();
5911
5954
 
@@ -7341,7 +7384,15 @@ class WebRTCClient extends Emitter {
7341
7384
  return userAgent.UserAgent.makeURI(`sip:${target}@${this.config.host}`);
7342
7385
  }
7343
7386
 
7344
- async _disconnectTransport() {
7387
+ async _disconnectTransport(force = false) {
7388
+ if (force) {
7389
+ // Bypass sip.js state machine that prevent to close WS with the state `Connecting`
7390
+ this.userAgent.transport.disconnectResolve = () => {};
7391
+ // eslint-disable-next-line
7392
+ this.userAgent.transport._ws.close(1000);
7393
+ return;
7394
+ }
7395
+
7345
7396
  // Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
7346
7397
  if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
7347
7398
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wazo/sdk",
3
- "version": "0.37.30",
3
+ "version": "0.37.34",
4
4
  "description": "Wazo's JavaScript Software Development Kit.",
5
5
  "main": "dist/wazo-sdk.js",
6
6
  "author": "Wazo (http://wazo.io)",