@wazo/sdk 1.0.0-alpha.2 → 1.0.0-alpha.20

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 (158) hide show
  1. package/README.md +16 -7
  2. package/dist/wazo-sdk.js +2 -2
  3. package/esm/__tests__/__voice__/call.test.js +52 -3
  4. package/esm/api/auth.js +3 -0
  5. package/esm/checker/checks/webrtc.js +2 -2
  6. package/esm/domain/CallLog.js +2 -3
  7. package/esm/domain/Phone/CTIPhone.js +2 -2
  8. package/esm/domain/Phone/WebRTCPhone.js +59 -57
  9. package/esm/index.js +3 -1
  10. package/esm/service/CallApi.js +4 -4
  11. package/esm/simple/Auth.js +13 -3
  12. package/esm/simple/Phone.js +5 -5
  13. package/esm/simple/index.js +2 -1
  14. package/esm/simple/room/Room.js +2 -2
  15. package/esm/simple/room/SipRoom.js +2 -2
  16. package/esm/state-machine/call-state-machine.js +34 -19
  17. package/esm/state-machine/softphone-state-machine.js +1 -2
  18. package/esm/state-machine/utils.js +10 -4
  19. package/esm/types/api/auth.d.ts +3 -0
  20. package/esm/types/api/auth.d.ts.map +1 -1
  21. package/esm/types/checker/checks/index.d.ts +1 -1
  22. package/esm/types/checker/checks/webrtc-transport.d.ts +2 -2
  23. package/esm/types/checker/checks/webrtc-transport.d.ts.map +1 -1
  24. package/esm/types/domain/CallLog.d.ts.map +1 -1
  25. package/esm/types/domain/CallSession.d.ts +3 -3
  26. package/esm/types/domain/CallSession.d.ts.map +1 -1
  27. package/esm/types/domain/Phone/CTIPhone.d.ts.map +1 -1
  28. package/esm/types/domain/Phone/WebRTCPhone.d.ts +22 -22
  29. package/esm/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
  30. package/esm/types/domain/types.d.ts +0 -4
  31. package/esm/types/domain/types.d.ts.map +1 -1
  32. package/esm/types/index.d.ts +3 -1
  33. package/esm/types/index.d.ts.map +1 -1
  34. package/esm/types/lib/WazoSessionDescriptionHandler.d.ts +3 -3
  35. package/esm/types/lib/WazoSessionDescriptionHandler.d.ts.map +1 -1
  36. package/esm/types/service/CallApi.d.ts +5 -5
  37. package/esm/types/service/CallApi.d.ts.map +1 -1
  38. package/esm/types/simple/Auth.d.ts +6 -1
  39. package/esm/types/simple/Auth.d.ts.map +1 -1
  40. package/esm/types/simple/Phone.d.ts +8 -8
  41. package/esm/types/simple/Phone.d.ts.map +1 -1
  42. package/esm/types/simple/index.d.ts +3 -1
  43. package/esm/types/simple/index.d.ts.map +1 -1
  44. package/esm/types/state-machine/call-state-machine.d.ts +12 -1
  45. package/esm/types/state-machine/call-state-machine.d.ts.map +1 -1
  46. package/esm/types/state-machine/softphone-state-machine.d.ts +1 -2
  47. package/esm/types/state-machine/softphone-state-machine.d.ts.map +1 -1
  48. package/esm/types/state-machine/utils.d.ts +1 -1
  49. package/esm/types/state-machine/utils.d.ts.map +1 -1
  50. package/esm/types/utils/sdp.d.ts +1 -2
  51. package/esm/types/utils/sdp.d.ts.map +1 -1
  52. package/esm/types/utils/update-from.d.ts +1 -1
  53. package/esm/types/utils/update-from.d.ts.map +1 -1
  54. package/esm/types/utils/webrtc.d.ts.map +1 -1
  55. package/esm/types/voice/call.d.ts +15 -3
  56. package/esm/types/voice/call.d.ts.map +1 -1
  57. package/esm/types/voice/softphone.d.ts +7 -0
  58. package/esm/types/voice/softphone.d.ts.map +1 -1
  59. package/esm/types/web-rtc-client.d.ts +39 -38
  60. package/esm/types/web-rtc-client.d.ts.map +1 -1
  61. package/esm/utils/sdp.js +16 -9
  62. package/esm/utils/update-from.js +2 -2
  63. package/esm/utils/webrtc.js +10 -4
  64. package/esm/voice/call.js +86 -28
  65. package/esm/voice/softphone.js +58 -17
  66. package/esm/web-rtc-client.js +67 -58
  67. package/lib/__tests__/__voice__/call.test.js +51 -2
  68. package/lib/api/auth.js +3 -0
  69. package/lib/checker/checks/webrtc.js +1 -1
  70. package/lib/domain/CallLog.js +2 -3
  71. package/lib/domain/Phone/CTIPhone.js +2 -2
  72. package/lib/domain/Phone/WebRTCPhone.js +58 -56
  73. package/lib/index.js +7 -3
  74. package/lib/service/CallApi.js +2 -2
  75. package/lib/simple/Auth.js +15 -3
  76. package/lib/simple/Phone.js +2 -2
  77. package/lib/simple/index.js +2 -1
  78. package/lib/simple/room/Room.js +1 -1
  79. package/lib/simple/room/SipRoom.js +1 -1
  80. package/lib/state-machine/call-state-machine.js +35 -20
  81. package/lib/state-machine/softphone-state-machine.js +1 -2
  82. package/lib/state-machine/utils.js +10 -4
  83. package/lib/types/api/auth.d.ts +3 -0
  84. package/lib/types/api/auth.d.ts.map +1 -1
  85. package/lib/types/checker/checks/index.d.ts +1 -1
  86. package/lib/types/checker/checks/webrtc-transport.d.ts +2 -2
  87. package/lib/types/checker/checks/webrtc-transport.d.ts.map +1 -1
  88. package/lib/types/domain/CallLog.d.ts.map +1 -1
  89. package/lib/types/domain/CallSession.d.ts +3 -3
  90. package/lib/types/domain/CallSession.d.ts.map +1 -1
  91. package/lib/types/domain/Phone/CTIPhone.d.ts.map +1 -1
  92. package/lib/types/domain/Phone/WebRTCPhone.d.ts +22 -22
  93. package/lib/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
  94. package/lib/types/domain/types.d.ts +0 -4
  95. package/lib/types/domain/types.d.ts.map +1 -1
  96. package/lib/types/index.d.ts +3 -1
  97. package/lib/types/index.d.ts.map +1 -1
  98. package/lib/types/lib/WazoSessionDescriptionHandler.d.ts +3 -3
  99. package/lib/types/lib/WazoSessionDescriptionHandler.d.ts.map +1 -1
  100. package/lib/types/service/CallApi.d.ts +5 -5
  101. package/lib/types/service/CallApi.d.ts.map +1 -1
  102. package/lib/types/simple/Auth.d.ts +6 -1
  103. package/lib/types/simple/Auth.d.ts.map +1 -1
  104. package/lib/types/simple/Phone.d.ts +8 -8
  105. package/lib/types/simple/Phone.d.ts.map +1 -1
  106. package/lib/types/simple/index.d.ts +3 -1
  107. package/lib/types/simple/index.d.ts.map +1 -1
  108. package/lib/types/state-machine/call-state-machine.d.ts +12 -1
  109. package/lib/types/state-machine/call-state-machine.d.ts.map +1 -1
  110. package/lib/types/state-machine/softphone-state-machine.d.ts +1 -2
  111. package/lib/types/state-machine/softphone-state-machine.d.ts.map +1 -1
  112. package/lib/types/state-machine/utils.d.ts +1 -1
  113. package/lib/types/state-machine/utils.d.ts.map +1 -1
  114. package/lib/types/utils/sdp.d.ts +1 -2
  115. package/lib/types/utils/sdp.d.ts.map +1 -1
  116. package/lib/types/utils/update-from.d.ts +1 -1
  117. package/lib/types/utils/update-from.d.ts.map +1 -1
  118. package/lib/types/utils/webrtc.d.ts.map +1 -1
  119. package/lib/types/voice/call.d.ts +15 -3
  120. package/lib/types/voice/call.d.ts.map +1 -1
  121. package/lib/types/voice/softphone.d.ts +7 -0
  122. package/lib/types/voice/softphone.d.ts.map +1 -1
  123. package/lib/types/web-rtc-client.d.ts +39 -38
  124. package/lib/types/web-rtc-client.d.ts.map +1 -1
  125. package/lib/utils/sdp.js +17 -10
  126. package/lib/utils/update-from.js +2 -2
  127. package/lib/utils/webrtc.js +11 -4
  128. package/lib/voice/call.js +89 -27
  129. package/lib/voice/softphone.js +62 -17
  130. package/lib/web-rtc-client.js +66 -57
  131. package/package.json +1 -1
  132. package/src/__tests__/__voice__/call.test.ts +61 -3
  133. package/src/api/auth.ts +5 -0
  134. package/src/checker/checks/webrtc-transport.ts +2 -2
  135. package/src/checker/checks/webrtc.ts +2 -2
  136. package/src/domain/CallLog.ts +2 -3
  137. package/src/domain/CallSession.ts +3 -3
  138. package/src/domain/Phone/CTIPhone.ts +3 -2
  139. package/src/domain/Phone/WebRTCPhone.ts +87 -85
  140. package/src/domain/__tests__/CallSession.test.ts +4 -0
  141. package/src/domain/types.ts +0 -5
  142. package/src/index.ts +4 -1
  143. package/src/lib/WazoSessionDescriptionHandler.ts +3 -3
  144. package/src/service/CallApi.ts +7 -7
  145. package/src/simple/Auth.ts +15 -3
  146. package/src/simple/Phone.ts +11 -11
  147. package/src/simple/index.ts +2 -1
  148. package/src/simple/room/Room.ts +3 -3
  149. package/src/simple/room/SipRoom.ts +3 -3
  150. package/src/state-machine/call-state-machine.ts +38 -19
  151. package/src/state-machine/softphone-state-machine.ts +1 -2
  152. package/src/state-machine/utils.ts +12 -4
  153. package/src/utils/sdp.ts +18 -11
  154. package/src/utils/update-from.ts +2 -2
  155. package/src/utils/webrtc.ts +11 -4
  156. package/src/voice/call.ts +109 -36
  157. package/src/voice/softphone.ts +75 -18
  158. package/src/web-rtc-client.ts +112 -98
@@ -51,6 +51,7 @@ const logger = IssueReporter_1.default ? IssueReporter_1.default.loggerFor('webr
51
51
  const statsLogger = IssueReporter_1.default ? IssueReporter_1.default.loggerFor('webrtc-stats') : console;
52
52
  // events
53
53
  const REGISTERED = 'registered';
54
+ const REGISTERING = 'registering';
54
55
  const UNREGISTERED = 'unregistered';
55
56
  const REGISTRATION_FAILED = 'registrationFailed';
56
57
  const INVITE = 'invite';
@@ -68,7 +69,7 @@ const ON_ERROR = 'onError';
68
69
  const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
69
70
  const ON_NETWORK_STATS = 'onNetworkStats';
70
71
  const ON_DISCONNECTED = 'onDisconnected';
71
- exports.events = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
72
+ exports.events = [REGISTERED, REGISTERING, UNREGISTERED, REGISTRATION_FAILED, INVITE];
72
73
  exports.transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
73
74
  class CanceledCallError extends Error {
74
75
  }
@@ -85,7 +86,9 @@ class WebRTCClient extends Emitter_1.default {
85
86
  this.skipRegister = config.skipRegister;
86
87
  this._buildConfig(config, session).then((newConfig) => {
87
88
  this.config = newConfig;
88
- this.userAgent = this.createUserAgent(uaConfigOverrides);
89
+ if (!this.userAgent) {
90
+ this.userAgent = this.createUserAgent(uaConfigOverrides);
91
+ }
89
92
  });
90
93
  this.audioOutputDeviceId = config.audioDeviceOutput;
91
94
  this.audioOutputVolume = config.audioOutputVolume || 1;
@@ -110,6 +113,7 @@ class WebRTCClient extends Emitter_1.default {
110
113
  this.heartbeat.setOnHeartbeatTimeout(this._onHeartbeatTimeout.bind(this));
111
114
  // sugar
112
115
  this.REGISTERED = REGISTERED;
116
+ this.REGISTERING = REGISTERING;
113
117
  this.UNREGISTERED = UNREGISTERED;
114
118
  this.REGISTRATION_FAILED = REGISTRATION_FAILED;
115
119
  this.INVITE = INVITE;
@@ -151,7 +155,7 @@ class WebRTCClient extends Emitter_1.default {
151
155
  logger.info('sdk webrtc on invite', {
152
156
  method: 'delegate.onInvite',
153
157
  clientId: this.clientId,
154
- id: invitation.id,
158
+ id: (0, sdp_1.getSipCallId)(invitation),
155
159
  remoteURI: invitation.remoteURI,
156
160
  });
157
161
  this._setupSession(invitation);
@@ -218,7 +222,7 @@ class WebRTCClient extends Emitter_1.default {
218
222
  // @ts-ignore: private
219
223
  this.registerer.waitingToggle(false);
220
224
  }
221
- this.eventEmitter.emit(UNREGISTERED);
225
+ this.eventEmitter.emit(UNREGISTERED, error);
222
226
  }
223
227
  });
224
228
  }
@@ -242,6 +246,7 @@ class WebRTCClient extends Emitter_1.default {
242
246
  return Promise.resolve();
243
247
  }
244
248
  logger.info('sdk webrtc registering...', logInfo);
249
+ this.eventEmitter.emit(REGISTERING);
245
250
  if (!this.userAgent) {
246
251
  logger.info('sdk webrtc recreating User Agent');
247
252
  this.userAgent = this.createUserAgent(this.uaConfigOverrides);
@@ -346,11 +351,18 @@ class WebRTCClient extends Emitter_1.default {
346
351
  }
347
352
  unregister() {
348
353
  return __awaiter(this, void 0, void 0, function* () {
354
+ var _a;
349
355
  logger.info('sdk webrtc unregistering..', {
350
356
  clientId: this.clientId,
351
357
  userAgent: !!this.userAgent,
352
358
  registerer: !!this.registerer,
353
359
  });
360
+ // @ts-ignore: private
361
+ if ((_a = this.registerer) === null || _a === void 0 ? void 0 : _a.waiting) {
362
+ logger.info('sdk webrtc unregistering, waiting for register to finish...');
363
+ // We have to wait for the register phase to finish
364
+ yield this.waitForRegister();
365
+ }
354
366
  try {
355
367
  return new Promise((resolve, reject) => {
356
368
  if (!this.registerer) {
@@ -425,7 +437,7 @@ class WebRTCClient extends Emitter_1.default {
425
437
  this._setupSession(session);
426
438
  }
427
439
  if (conference) {
428
- this.conferences[(0, sdp_1.getSipSessionId)(session)] = true;
440
+ this.conferences[(0, sdp_1.getSipCallId)(session)] = true;
429
441
  }
430
442
  const inviteOptions = {
431
443
  requestDelegate: {
@@ -441,7 +453,7 @@ class WebRTCClient extends Emitter_1.default {
441
453
  },
442
454
  onReject: (response) => {
443
455
  logger.info('on call rejected', {
444
- id: session === null || session === void 0 ? void 0 : session.id,
456
+ id: (0, sdp_1.getSipCallId)(session),
445
457
  // @ts-ignore: fromTag does not exist
446
458
  fromTag: session === null || session === void 0 ? void 0 : session.fromTag,
447
459
  });
@@ -471,7 +483,7 @@ class WebRTCClient extends Emitter_1.default {
471
483
  answer(session, enableVideo) {
472
484
  logger.info('sdk webrtc answer call', {
473
485
  clientId: this.clientId,
474
- id: session.id,
486
+ id: (0, sdp_1.getSipCallId)(session),
475
487
  enableVideo,
476
488
  });
477
489
  if (!session || !session.accept) {
@@ -487,7 +499,7 @@ class WebRTCClient extends Emitter_1.default {
487
499
  if (session.isCanceled) {
488
500
  const message = 'accepted a canceled session (or was canceled during the accept phase).';
489
501
  logger.error(message, {
490
- id: session.id,
502
+ id: (0, sdp_1.getSipCallId)(session),
491
503
  });
492
504
  this.onCallEnded(session);
493
505
  throw new CanceledCallError(message);
@@ -495,7 +507,7 @@ class WebRTCClient extends Emitter_1.default {
495
507
  logger.info('sdk webrtc answer, accepted.');
496
508
  this._onAccepted(session);
497
509
  }).catch(e => {
498
- logger.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
510
+ logger.error(`answer call error for ${(0, sdp_1.getSipCallId)(session)}`, e);
499
511
  throw e;
500
512
  });
501
513
  }
@@ -506,7 +518,7 @@ class WebRTCClient extends Emitter_1.default {
506
518
  try {
507
519
  this._stopSendingStats(session);
508
520
  this._cleanupMedia(session);
509
- delete this.sipSessions[(0, sdp_1.getSipSessionId)(session)];
521
+ delete this.sipSessions[(0, sdp_1.getSipCallId)(session)];
510
522
  // Check if Invitation or Inviter (Invitation = incoming call)
511
523
  const isInviter = session instanceof api_1.Inviter;
512
524
  // @see github.com/onsip/SIP.js/blob/f11dfd584bc9788ccfc94e03034020672b738975/src/platform/web/simple-user/simple-user.ts#L1004
@@ -529,7 +541,7 @@ class WebRTCClient extends Emitter_1.default {
529
541
  }
530
542
  // Fetch and emit an event at `interval` with session network stats
531
543
  startNetworkMonitoring(session, interval = 1000) {
532
- const sessionId = (0, sdp_1.getSipSessionId)(session);
544
+ const sessionId = (0, sdp_1.getSipCallId)(session);
533
545
  logger.info('starting network inspection', {
534
546
  id: sessionId,
535
547
  clientId: this.clientId,
@@ -538,7 +550,7 @@ class WebRTCClient extends Emitter_1.default {
538
550
  this.networkMonitoringInterval[sessionId] = setInterval(() => this._fetchNetworkStats(sessionId), interval);
539
551
  }
540
552
  stopNetworkMonitoring(session) {
541
- const sessionId = (0, sdp_1.getSipSessionId)(session);
553
+ const sessionId = (0, sdp_1.getSipCallId)(session);
542
554
  const exists = (sessionId in this.networkMonitoringInterval);
543
555
  logger.info('stopping network inspection', {
544
556
  clientId: this.clientId,
@@ -555,7 +567,7 @@ class WebRTCClient extends Emitter_1.default {
555
567
  return __awaiter(this, void 0, void 0, function* () {
556
568
  logger.info('sdk webrtc reject call', {
557
569
  clientId: this.clientId,
558
- id: session.id,
570
+ id: (0, sdp_1.getSipCallId)(session),
559
571
  });
560
572
  try {
561
573
  if (session instanceof api_1.Invitation) {
@@ -612,13 +624,13 @@ class WebRTCClient extends Emitter_1.default {
612
624
  }
613
625
  mute(session) {
614
626
  logger.info('sdk webrtc mute', {
615
- id: session.id,
627
+ id: (0, sdp_1.getSipCallId)(session),
616
628
  });
617
629
  (0, webrtc_1.toggleAudio)(session, true);
618
630
  }
619
631
  unmute(session) {
620
632
  logger.info('sdk webrtc unmute', {
621
- id: session.id,
633
+ id: (0, sdp_1.getSipCallId)(session),
622
634
  });
623
635
  (0, webrtc_1.toggleAudio)(session, false);
624
636
  }
@@ -655,18 +667,18 @@ class WebRTCClient extends Emitter_1.default {
655
667
  }
656
668
  toggleCameraOn(session) {
657
669
  logger.info('sdk webrtc toggle camera on', {
658
- id: session.id,
670
+ id: (0, sdp_1.getSipCallId)(session),
659
671
  });
660
672
  (0, webrtc_1.toggleVideo)(session, false);
661
673
  }
662
674
  toggleCameraOff(session) {
663
675
  logger.info('sdk webrtc toggle camera off', {
664
- id: session.id,
676
+ id: (0, sdp_1.getSipCallId)(session),
665
677
  });
666
678
  (0, webrtc_1.toggleVideo)(session, true);
667
679
  }
668
680
  hold(session, isConference = false, hadVideo = false) {
669
- const sessionId = (0, sdp_1.getSipSessionId)(session);
681
+ const sessionId = (0, sdp_1.getSipCallId)(session);
670
682
  const hasVideo = hadVideo || this.hasLocalVideo(sessionId);
671
683
  logger.info('sdk webrtc hold', {
672
684
  sessionId,
@@ -714,7 +726,7 @@ class WebRTCClient extends Emitter_1.default {
714
726
  });
715
727
  }
716
728
  unhold(session, isConference = false) {
717
- const sessionId = (0, sdp_1.getSipSessionId)(session);
729
+ const sessionId = (0, sdp_1.getSipCallId)(session);
718
730
  const hasVideo = sessionId in this.heldSessions && this.heldSessions[sessionId].hasVideo;
719
731
  logger.info('sdk webrtc unhold', {
720
732
  sessionId,
@@ -729,7 +741,7 @@ class WebRTCClient extends Emitter_1.default {
729
741
  return Promise.resolve();
730
742
  }
731
743
  this.unmute(session);
732
- delete this.heldSessions[(0, sdp_1.getSipSessionId)(session)];
744
+ delete this.heldSessions[(0, sdp_1.getSipCallId)(session)];
733
745
  session.sessionDescriptionHandlerOptionsReInvite = {
734
746
  hold: false,
735
747
  conference: isConference,
@@ -754,7 +766,7 @@ class WebRTCClient extends Emitter_1.default {
754
766
  return this.heldSessions[sessionId];
755
767
  }
756
768
  isCallHeld(session) {
757
- return (0, sdp_1.getSipSessionId)(session) in this.heldSessions;
769
+ return (0, sdp_1.getSipCallId)(session) in this.heldSessions;
758
770
  }
759
771
  isVideoRemotelyHeld(sessionId) {
760
772
  return (0, webrtc_1.isVideoRemotelyHeld)(this.heldSessions[sessionId]);
@@ -764,7 +776,7 @@ class WebRTCClient extends Emitter_1.default {
764
776
  return false;
765
777
  }
766
778
  logger.info('Sending DTMF', {
767
- id: (0, sdp_1.getSipSessionId)(session),
779
+ id: (0, sdp_1.getSipCallId)(session),
768
780
  tone,
769
781
  });
770
782
  return session.sessionDescriptionHandler.sendDtmf(tone);
@@ -781,7 +793,7 @@ class WebRTCClient extends Emitter_1.default {
781
793
  transfer(session, target) {
782
794
  this.hold(session);
783
795
  logger.info('Transfering a session', {
784
- id: (0, sdp_1.getSipSessionId)(session),
796
+ id: (0, sdp_1.getSipCallId)(session),
785
797
  target,
786
798
  });
787
799
  const options = {
@@ -804,21 +816,21 @@ class WebRTCClient extends Emitter_1.default {
804
816
  atxfer(session) {
805
817
  this.hold(session);
806
818
  logger.info('webrtc transfer started', {
807
- id: (0, sdp_1.getSipSessionId)(session),
819
+ id: (0, sdp_1.getSipCallId)(session),
808
820
  });
809
821
  const result = {
810
822
  newSession: null,
811
823
  init: (target) => __awaiter(this, void 0, void 0, function* () {
812
824
  logger.info('webrtc transfer initialized', {
813
- id: (0, sdp_1.getSipSessionId)(session),
825
+ id: (0, sdp_1.getSipCallId)(session),
814
826
  target,
815
827
  });
816
828
  result.newSession = yield this.call(target);
817
829
  }),
818
830
  complete: () => {
819
831
  logger.info('webrtc transfer completed', {
820
- id: (0, sdp_1.getSipSessionId)(session),
821
- referId: (0, sdp_1.getSipSessionId)(result.newSession),
832
+ id: (0, sdp_1.getSipCallId)(session),
833
+ referId: (0, sdp_1.getSipCallId)(result.newSession),
822
834
  });
823
835
  session.refer(result.newSession);
824
836
  },
@@ -835,7 +847,7 @@ class WebRTCClient extends Emitter_1.default {
835
847
  return;
836
848
  }
837
849
  logger.info('send WebRTC message', {
838
- sipId: sipSession.id,
850
+ sipId: (0, sdp_1.getSipCallId)(sipSession),
839
851
  contentType,
840
852
  });
841
853
  try {
@@ -990,7 +1002,7 @@ class WebRTCClient extends Emitter_1.default {
990
1002
  }
991
1003
  const sdh = session.sessionDescriptionHandler;
992
1004
  const pc = sdh.peerConnection;
993
- const sessionId = (0, sdp_1.getSipSessionId)(session);
1005
+ const sessionId = (0, sdp_1.getSipCallId)(session);
994
1006
  const localStream = this.getLocalStream(sessionId);
995
1007
  logger.info('changing video input device', {
996
1008
  id,
@@ -1053,7 +1065,7 @@ class WebRTCClient extends Emitter_1.default {
1053
1065
  const desktop = newConstraints && newConstraints.desktop;
1054
1066
  logger.info('Sending reinvite', {
1055
1067
  clientId: this.clientId,
1056
- id: (0, sdp_1.getSipSessionId)(sipSession),
1068
+ id: (0, sdp_1.getSipCallId)(sipSession),
1057
1069
  newConstraints,
1058
1070
  conference,
1059
1071
  audioOnly,
@@ -1085,7 +1097,7 @@ class WebRTCClient extends Emitter_1.default {
1085
1097
  sipSession.incomingInviteRequest.message.body = response.message.body;
1086
1098
  }
1087
1099
  logger.info('on re-INVITE accepted', {
1088
- id: (0, sdp_1.getSipSessionId)(sipSession),
1100
+ id: (0, sdp_1.getSipCallId)(sipSession),
1089
1101
  wasMuted,
1090
1102
  shouldDoScreenSharing,
1091
1103
  });
@@ -1200,7 +1212,7 @@ class WebRTCClient extends Emitter_1.default {
1200
1212
  }
1201
1213
  onCallEnded(session) {
1202
1214
  this._cleanupMedia(session);
1203
- delete this.sipSessions[(0, sdp_1.getSipSessionId)(session)];
1215
+ delete this.sipSessions[(0, sdp_1.getSipCallId)(session)];
1204
1216
  this._stopSendingStats(session);
1205
1217
  this.stopNetworkMonitoring(session);
1206
1218
  }
@@ -1213,14 +1225,14 @@ class WebRTCClient extends Emitter_1.default {
1213
1225
  this.userAgent.attemptReconnection();
1214
1226
  }
1215
1227
  storeSipSession(session) {
1216
- const id = (0, sdp_1.getSipSessionId)(session);
1228
+ const id = (0, sdp_1.getSipCallId)(session);
1217
1229
  logger.info('storing sip session', { id, clientId: this.clientId });
1218
1230
  this.sipSessions[id] = session;
1219
1231
  }
1220
1232
  getSipSession(id) {
1221
- return id in this.sipSessions ? this.sipSessions[id.substring(0, sdp_1.SIP_ID_LENGTH)] : null;
1233
+ return id in this.sipSessions ? this.sipSessions[id] : null;
1222
1234
  }
1223
- getSipSessionIds() {
1235
+ getSipCallIds() {
1224
1236
  return Object.keys(this.sipSessions);
1225
1237
  }
1226
1238
  updateLocalStream(sipSessionId, newStream) {
@@ -1263,8 +1275,8 @@ class WebRTCClient extends Emitter_1.default {
1263
1275
  return audio;
1264
1276
  });
1265
1277
  }
1266
- _onTransportError() {
1267
- logger.error('on transport error');
1278
+ _onTransportError(reason) {
1279
+ logger.warn('on transport error', { reason });
1268
1280
  this.eventEmitter.emit(TRANSPORT_ERROR);
1269
1281
  this.attemptReconnection();
1270
1282
  }
@@ -1319,7 +1331,7 @@ class WebRTCClient extends Emitter_1.default {
1319
1331
  }
1320
1332
  }
1321
1333
  // We can invoke disconnect() with an error that can be catcher by `onDisconnect`, so we have to trigger it here.
1322
- this._onTransportError();
1334
+ this._onTransportError('heartbeat timeout');
1323
1335
  }
1324
1336
  });
1325
1337
  }
@@ -1377,7 +1389,7 @@ class WebRTCClient extends Emitter_1.default {
1377
1389
  }
1378
1390
  // Invitation and Inviter extends Session
1379
1391
  _setupSession(session) {
1380
- const sipSessionId = (0, sdp_1.getSipSessionId)(session);
1392
+ const sipSessionId = (0, sdp_1.getSipCallId)(session);
1381
1393
  // When receiving an Invitation, the delegate is not defined.
1382
1394
  if (!session.delegate) {
1383
1395
  session.delegate = {};
@@ -1441,19 +1453,16 @@ class WebRTCClient extends Emitter_1.default {
1441
1453
  _onProgress(session_1) {
1442
1454
  return __awaiter(this, arguments, void 0, function* (session, early = false) {
1443
1455
  yield this._setupMedias(session);
1444
- const sessionId = (0, sdp_1.getSipSessionId)(session).substr(0, 20);
1456
+ const sessionId = (0, sdp_1.getSipCallId)(session);
1445
1457
  (0, webrtc_1.updateRemoteStream)(session);
1446
- logger.info('progress received', {
1447
- sessionId,
1448
- early,
1449
- });
1458
+ logger.info('progress received', { sessionId, early });
1450
1459
  this.eventEmitter.emit(early ? ON_EARLY_MEDIA : ON_PROGRESS, session);
1451
1460
  });
1452
1461
  }
1453
1462
  _onAccepted(session_1, sessionDialog_1) {
1454
1463
  return __awaiter(this, arguments, void 0, function* (session, sessionDialog, withEvent = true, initAllTracks = true) {
1455
1464
  logger.info('on call accepted', {
1456
- id: session.id,
1465
+ id: (0, sdp_1.getSipCallId)(session),
1457
1466
  clientId: this.clientId,
1458
1467
  remoteTag: session.remoteTag,
1459
1468
  });
@@ -1499,7 +1508,7 @@ class WebRTCClient extends Emitter_1.default {
1499
1508
  return;
1500
1509
  }
1501
1510
  // Safari hack, because you cannot call .play() from a non user action
1502
- const sessionId = (0, sdp_1.getSipSessionId)(session);
1511
+ const sessionId = (0, sdp_1.getSipCallId)(session);
1503
1512
  const isConference = this.isConference(sessionId);
1504
1513
  if (sessionId in this.audioElements) {
1505
1514
  logger.info('html element already exists for session', {
@@ -1545,7 +1554,7 @@ class WebRTCClient extends Emitter_1.default {
1545
1554
  });
1546
1555
  }
1547
1556
  _cleanupMedia(session) {
1548
- const sessionId = (0, sdp_1.getSipSessionId)(session);
1557
+ const sessionId = (0, sdp_1.getSipCallId)(session);
1549
1558
  const localStream = this.getLocalStream(sessionId);
1550
1559
  if (localStream) {
1551
1560
  (0, webrtc_1.cleanupStream)(localStream);
@@ -1564,7 +1573,7 @@ class WebRTCClient extends Emitter_1.default {
1564
1573
  };
1565
1574
  if (this._hasAudio() && (0, webrtc_1.isWeb)()) {
1566
1575
  if (session) {
1567
- cleanLocalElement((0, sdp_1.getSipSessionId)(session));
1576
+ cleanLocalElement((0, sdp_1.getSipCallId)(session));
1568
1577
  }
1569
1578
  else {
1570
1579
  Object.keys(this.audioElements).forEach(id => cleanLocalElement(id));
@@ -1584,7 +1593,7 @@ class WebRTCClient extends Emitter_1.default {
1584
1593
  if (!pc) {
1585
1594
  return;
1586
1595
  }
1587
- const sessionId = (0, sdp_1.getSipSessionId)(session);
1596
+ const sessionId = (0, sdp_1.getSipCallId)(session);
1588
1597
  (0, getstats_1.default)(pc, (result) => {
1589
1598
  const { results, internal, nomore } = result, stats = __rest(result, ["results", "internal", "nomore"]);
1590
1599
  this.statsIntervals[sessionId] = nomore;
@@ -1592,7 +1601,7 @@ class WebRTCClient extends Emitter_1.default {
1592
1601
  }, SEND_STATS_DELAY);
1593
1602
  }
1594
1603
  _stopSendingStats(session) {
1595
- const sessionId = (0, sdp_1.getSipSessionId)(session);
1604
+ const sessionId = (0, sdp_1.getSipCallId)(session);
1596
1605
  logger.trace('Check for stopping stats', {
1597
1606
  sessionId,
1598
1607
  ids: Object.keys(this.statsIntervals),
@@ -1649,18 +1658,18 @@ class WebRTCClient extends Emitter_1.default {
1649
1658
  return __awaiter(this, arguments, void 0, function* (session, options = {}) {
1650
1659
  if (session.state === session_state_1.SessionState.Terminated || session.state === session_state_1.SessionState.Terminating) {
1651
1660
  const error = 'Trying to accept a terminated sipSession.';
1652
- logger.warn(error, { state: session.state, sessionId: session.id });
1661
+ logger.warn(error, { state: session.state, sessionId: (0, sdp_1.getSipCallId)(session) });
1653
1662
  throw new Error(error);
1654
1663
  }
1655
1664
  if (session.state !== session_state_1.SessionState.Initial) {
1656
1665
  const error = 'Trying to accept a non Initial sipSession.';
1657
- logger.warn(error, { state: session.state, sessionId: session.id });
1666
+ logger.warn(error, { state: session.state, sessionId: (0, sdp_1.getSipCallId)(session) });
1658
1667
  throw new Error(error);
1659
1668
  }
1660
1669
  // @ts-ignore: private
1661
1670
  if (!session.incomingInviteRequest.acceptable) {
1662
1671
  const error = 'Trying to reject a non `acceptable` session';
1663
- logger.warn(error, { state: session.state, sessionId: session.id });
1672
+ logger.warn(error, { state: session.state, sessionId: (0, sdp_1.getSipCallId)(session) });
1664
1673
  throw new Error(error);
1665
1674
  }
1666
1675
  try {
@@ -1674,12 +1683,12 @@ class WebRTCClient extends Emitter_1.default {
1674
1683
  _reject(session_1) {
1675
1684
  return __awaiter(this, arguments, void 0, function* (session, options = {}) {
1676
1685
  if (session.state !== session_state_1.SessionState.Initial && session.state !== session_state_1.SessionState.Establishing) {
1677
- logger.warn('Trying to reject a session in a wrong state', { state: session.state, sessionId: session.id });
1686
+ logger.warn('Trying to reject a session in a wrong state', { state: session.state, sessionId: (0, sdp_1.getSipCallId)(session) });
1678
1687
  return;
1679
1688
  }
1680
1689
  // @ts-ignore: private
1681
1690
  if (!session.incomingInviteRequest.rejectable) {
1682
- logger.warn('Trying to reject a non `rejectable` session', { state: session.state, sessionId: session.id });
1691
+ logger.warn('Trying to reject a non `rejectable` session', { state: session.state, sessionId: (0, sdp_1.getSipCallId)(session) });
1683
1692
  return;
1684
1693
  }
1685
1694
  try {
@@ -1693,7 +1702,7 @@ class WebRTCClient extends Emitter_1.default {
1693
1702
  _cancel(session_1) {
1694
1703
  return __awaiter(this, arguments, void 0, function* (session, options = {}) {
1695
1704
  if (session.state !== session_state_1.SessionState.Initial && session.state !== session_state_1.SessionState.Establishing) {
1696
- logger.warn('Trying to cancel a session in a wrong state', { state: session.state, sessionId: session.id });
1705
+ logger.warn('Trying to cancel a session in a wrong state', { state: session.state, sessionId: (0, sdp_1.getSipCallId)(session) });
1697
1706
  return;
1698
1707
  }
1699
1708
  try {
@@ -1707,7 +1716,7 @@ class WebRTCClient extends Emitter_1.default {
1707
1716
  _bye(session_1) {
1708
1717
  return __awaiter(this, arguments, void 0, function* (session, options = {}) {
1709
1718
  if (session.state !== session_state_1.SessionState.Established) {
1710
- logger.warn('Trying to end a session in a wrong state', { state: session.state, sessionId: session.id });
1719
+ logger.warn('Trying to end a session in a wrong state', { state: session.state, sessionId: (0, sdp_1.getSipCallId)(session) });
1711
1720
  return null;
1712
1721
  }
1713
1722
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wazo/sdk",
3
- "version": "1.0.0-alpha.2",
3
+ "version": "1.0.0-alpha.20",
4
4
  "description": "Wazo's JavaScript Software Development Kit.",
5
5
  "main": "index.js",
6
6
  "types": "lib/types/index.d.ts",
@@ -3,7 +3,7 @@ import { Inviter, UserAgent, type URI } from 'sip.js';
3
3
 
4
4
  import softphone from '../../voice/softphone';
5
5
  import Call from '../../voice/call';
6
- import { Actions, EstablishedStates, States } from '../../state-machine/call-state-machine';
6
+ import { Actions, EstablishedStates, EstablishedSubStates, States } from '../../state-machine/call-state-machine';
7
7
  import { Actions as SoftphoneActions } from '../../state-machine/softphone-state-machine';
8
8
  import ApiCall from '../../domain/Call';
9
9
 
@@ -32,6 +32,9 @@ jest.mock('../..', () => ({
32
32
 
33
33
  jest.mock('../../web-rtc-client', () => jest.fn().mockImplementation(() => ({
34
34
  answer: jest.fn(() => Promise.resolve()),
35
+ mute: jest.fn(() => Promise.resolve()),
36
+ hold: jest.fn(() => Promise.resolve()),
37
+ unhold: jest.fn(() => Promise.resolve()),
35
38
  hangup: jest.fn(() => Promise.resolve()),
36
39
  register: jest.fn(() => Promise.resolve()),
37
40
  onCallEnded: jest.fn(() => Promise.resolve()),
@@ -76,9 +79,17 @@ describe('Call', () => {
76
79
  expect(call.id).toBe(apiCall.sipCallId);
77
80
  expect(call.apiId).toBe(apiCall.id);
78
81
  expect(call.number).toBe(apiCall.calleeNumber);
79
- expect(call.answerTime).toStrictEqual(apiCall.startingTime);
82
+ expect(call.answerTime).toStrictEqual(undefined);
83
+ expect(call.creationTime).toStrictEqual(apiCall.startingTime);
80
84
  expect(call.isMuted()).toBeTruthy();
81
- expect(call.state).toStrictEqual({ [States.ESTABLISHED]: EstablishedStates.MUTED });
85
+ expect(call.state).toStrictEqual({
86
+ [States.ESTABLISHED]: {
87
+ [EstablishedStates.ONGOING]: {},
88
+ [EstablishedSubStates.MUTE]: EstablishedStates.MUTED,
89
+ [EstablishedSubStates.HOLD]: EstablishedStates.UN_HELD,
90
+ },
91
+ });
92
+ expect(call.isEstablished()).toBeTruthy();
82
93
  });
83
94
  });
84
95
 
@@ -132,4 +143,51 @@ describe('Call', () => {
132
143
  expect(softphone.client.hangup).toHaveBeenCalled();
133
144
  });
134
145
  });
146
+
147
+ describe('state propagation', () => {
148
+ it('Should update the call state in events', (done) => {
149
+ const call = new Call(sipCall, softphone);
150
+ // @ts-ignore: private method
151
+ call._sendAction(Actions.MAKE_CALL);
152
+
153
+ call.on('remotelyAccepted', () => {
154
+ expect(call.state).toStrictEqual({
155
+ [States.ESTABLISHED]: {
156
+ [EstablishedStates.ONGOING]: {},
157
+ [EstablishedSubStates.MUTE]: EstablishedStates.UN_MUTED,
158
+ [EstablishedSubStates.HOLD]: EstablishedStates.UN_HELD,
159
+ },
160
+ });
161
+ done();
162
+ });
163
+
164
+ call.onAccepted();
165
+ });
166
+ });
167
+
168
+ describe('Multiple sub state', () => {
169
+ it('Should mute and hold a call', () => {
170
+ const call = new Call(sipCall, softphone);
171
+ // @ts-ignore: private method
172
+ call._sendAction(Actions.MAKE_CALL);
173
+
174
+ expect(call.isMuted()).toBeFalsy();
175
+ expect(call.isHeld()).toBeFalsy();
176
+
177
+ // @ts-ignore: private method
178
+ call._sendAction(Actions.REMOTLY_ACCEPTED);
179
+
180
+ call.mute();
181
+ expect(call.isMuted()).toBeTruthy();
182
+ expect(call.isHeld()).toBeFalsy();
183
+
184
+ call.hold();
185
+ expect(call.isMuted()).toBeTruthy();
186
+ expect(call.isHeld()).toBeTruthy();
187
+
188
+ call.resume();
189
+ expect(call.isMuted()).toBeTruthy();
190
+ expect(call.isHeld()).toBeFalsy();
191
+ });
192
+ });
135
193
  });
package/src/api/auth.ts CHANGED
@@ -33,6 +33,7 @@ export interface AuthD {
33
33
  logIn(params: LoginParams): Promise<Session | null | undefined> ;
34
34
  logOut: (token: Token) => Promise<LogoutResponse>;
35
35
  samlLogIn: (samlSessionId: string) => Promise<Session | null | undefined>;
36
+ samlLogOut: () => Promise<void | { location:string }>;
36
37
  initiateIdpAuthentication(domain: string, redirectUrl: string): Promise<any>;
37
38
  refreshToken: (refreshToken: string, backend: string, expiration: number, isMobile?: boolean, tenantId?: string, domainName?: string) => Promise<Session | null | undefined>;
38
39
  deleteRefreshToken: (clientId: string) => Promise<boolean>;
@@ -139,6 +140,10 @@ export default ((client: ApiRequester, baseUrl: string): AuthD => ({
139
140
  return client.post(`${baseUrl}/token`, body, headers).then(Session.parse);
140
141
  },
141
142
 
143
+ samlLogOut() {
144
+ return client.get(`${baseUrl}/saml/logout`, null, null);
145
+ },
146
+
142
147
  initiateIdpAuthentication: async (domain: string, redirectUrl: string) => {
143
148
  const body = {
144
149
  domain,
@@ -1,9 +1,9 @@
1
1
  import WebRTCClient from '../../web-rtc-client';
2
- import { WazoSession } from '../../domain/types';
2
+ import { SipCall } from '../../domain/types';
3
3
 
4
4
  export default {
5
5
  name: 'WebRTC Transport (WS) ~30s',
6
- check: (server: string, session: WazoSession): Promise<void> => new Promise((resolve, reject) => {
6
+ check: (server: string, session: SipCall): Promise<void> => new Promise((resolve, reject) => {
7
7
  const [host, port = 443] = server.split(':');
8
8
 
9
9
  const client = new WebRTCClient({
@@ -1,5 +1,5 @@
1
1
  /* global MediaStream */
2
- import { getSipSessionId } from '../../utils/sdp';
2
+ import { getSipCallId } from '../../utils/sdp';
3
3
  import WebRTCClient from '../../web-rtc-client';
4
4
 
5
5
  export default {
@@ -36,7 +36,7 @@ export default {
36
36
  client.on(client.REGISTERED, () => {
37
37
  const sipSession = client.call('*10');
38
38
 
39
- if (!sipSession || !getSipSessionId(sipSession)) {
39
+ if (!sipSession || !getSipCallId(sipSession)) {
40
40
  return handleError('Unable to make call through WebRTC');
41
41
  }
42
42
 
@@ -118,8 +118,7 @@ export default class CallLog {
118
118
 
119
119
  static parseNew(plain: CallLogResponse, session: Session): CallLog {
120
120
  const callLog: CallLog = CallLog.parse(plain);
121
- // @TODO: FIXME add verification declined vs missed call
122
- callLog.newMissedCall = session && session.hasExtension((plain.requested_extension || plain.destination_extension) as string) && !plain.answered;
121
+ callLog.newMissedCall = session && plain.destination_user_uuid === session.uuid && !plain.answered;
123
122
  return callLog;
124
123
  }
125
124
 
@@ -203,7 +202,7 @@ export default class CallLog {
203
202
  }
204
203
 
205
204
  isAnOutgoingCall(session: Session): boolean {
206
- console.warn(`@wazo/sdk
205
+ console.warn(`@wazo/sdk
207
206
  CallLog.isAnOutgoingcall(session) method is obsolete.
208
207
  Please use CallLog.isOutgoing(session).
209
208
  `);
@@ -2,7 +2,7 @@ import { SessionState } from 'sip.js/lib/api/session-state';
2
2
  import Call from './Call';
3
3
  import newFrom from '../utils/new-from';
4
4
  import updateFrom from '../utils/update-from';
5
- import { WazoSession } from './types';
5
+ import { SipCall } from './types';
6
6
 
7
7
  type CallSessionArguments = {
8
8
  answered: boolean;
@@ -32,7 +32,7 @@ type CallSessionArguments = {
32
32
  screensharing: boolean;
33
33
  recording: boolean;
34
34
  recordingPaused: boolean;
35
- sipSession?: WazoSession;
35
+ sipSession?: SipCall;
36
36
  conference: boolean;
37
37
  };
38
38
  export default class CallSession {
@@ -96,7 +96,7 @@ export default class CallSession {
96
96
 
97
97
  recordingPaused: boolean;
98
98
 
99
- sipSession: WazoSession | undefined;
99
+ sipSession: SipCall | undefined;
100
100
 
101
101
  conference: boolean;
102
102