@wazo/sdk 1.0.0-alpha.1 → 1.0.0-alpha.11

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 (148) hide show
  1. package/README.md +16 -7
  2. package/dist/wazo-sdk.js +6 -6
  3. package/esm/__tests__/__voice__/call.test.js +57 -2
  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 +64 -63
  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 +6 -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 +2 -2
  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/softphone-state-machine.d.ts +1 -2
  45. package/esm/types/state-machine/softphone-state-machine.d.ts.map +1 -1
  46. package/esm/types/state-machine/utils.d.ts +2 -2
  47. package/esm/types/state-machine/utils.d.ts.map +1 -1
  48. package/esm/types/utils/sdp.d.ts +3 -2
  49. package/esm/types/utils/sdp.d.ts.map +1 -1
  50. package/esm/types/utils/webrtc.d.ts +1 -0
  51. package/esm/types/utils/webrtc.d.ts.map +1 -1
  52. package/esm/types/voice/call.d.ts +30 -12
  53. package/esm/types/voice/call.d.ts.map +1 -1
  54. package/esm/types/voice/softphone.d.ts +25 -13
  55. package/esm/types/voice/softphone.d.ts.map +1 -1
  56. package/esm/types/web-rtc-client.d.ts +39 -38
  57. package/esm/types/web-rtc-client.d.ts.map +1 -1
  58. package/esm/utils/sdp.js +22 -9
  59. package/esm/utils/webrtc.js +23 -3
  60. package/esm/voice/call.js +131 -38
  61. package/esm/voice/softphone.js +145 -35
  62. package/esm/web-rtc-client.js +61 -58
  63. package/lib/__tests__/__voice__/call.test.js +56 -1
  64. package/lib/api/auth.js +3 -0
  65. package/lib/checker/checks/webrtc.js +1 -1
  66. package/lib/domain/CallLog.js +2 -3
  67. package/lib/domain/Phone/CTIPhone.js +2 -2
  68. package/lib/domain/Phone/WebRTCPhone.js +63 -62
  69. package/lib/index.js +7 -3
  70. package/lib/service/CallApi.js +2 -2
  71. package/lib/simple/Auth.js +15 -3
  72. package/lib/simple/Phone.js +3 -2
  73. package/lib/simple/index.js +2 -1
  74. package/lib/simple/room/Room.js +1 -1
  75. package/lib/simple/room/SipRoom.js +1 -1
  76. package/lib/state-machine/call-state-machine.js +2 -2
  77. package/lib/state-machine/softphone-state-machine.js +1 -2
  78. package/lib/state-machine/utils.js +10 -4
  79. package/lib/types/api/auth.d.ts +3 -0
  80. package/lib/types/api/auth.d.ts.map +1 -1
  81. package/lib/types/checker/checks/index.d.ts +1 -1
  82. package/lib/types/checker/checks/webrtc-transport.d.ts +2 -2
  83. package/lib/types/checker/checks/webrtc-transport.d.ts.map +1 -1
  84. package/lib/types/domain/CallLog.d.ts.map +1 -1
  85. package/lib/types/domain/CallSession.d.ts +3 -3
  86. package/lib/types/domain/CallSession.d.ts.map +1 -1
  87. package/lib/types/domain/Phone/CTIPhone.d.ts.map +1 -1
  88. package/lib/types/domain/Phone/WebRTCPhone.d.ts +22 -22
  89. package/lib/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
  90. package/lib/types/domain/types.d.ts +0 -4
  91. package/lib/types/domain/types.d.ts.map +1 -1
  92. package/lib/types/index.d.ts +3 -1
  93. package/lib/types/index.d.ts.map +1 -1
  94. package/lib/types/lib/WazoSessionDescriptionHandler.d.ts +3 -3
  95. package/lib/types/lib/WazoSessionDescriptionHandler.d.ts.map +1 -1
  96. package/lib/types/service/CallApi.d.ts +5 -5
  97. package/lib/types/service/CallApi.d.ts.map +1 -1
  98. package/lib/types/simple/Auth.d.ts +6 -1
  99. package/lib/types/simple/Auth.d.ts.map +1 -1
  100. package/lib/types/simple/Phone.d.ts +8 -8
  101. package/lib/types/simple/Phone.d.ts.map +1 -1
  102. package/lib/types/simple/index.d.ts +3 -1
  103. package/lib/types/simple/index.d.ts.map +1 -1
  104. package/lib/types/state-machine/softphone-state-machine.d.ts +1 -2
  105. package/lib/types/state-machine/softphone-state-machine.d.ts.map +1 -1
  106. package/lib/types/state-machine/utils.d.ts +2 -2
  107. package/lib/types/state-machine/utils.d.ts.map +1 -1
  108. package/lib/types/utils/sdp.d.ts +3 -2
  109. package/lib/types/utils/sdp.d.ts.map +1 -1
  110. package/lib/types/utils/webrtc.d.ts +1 -0
  111. package/lib/types/utils/webrtc.d.ts.map +1 -1
  112. package/lib/types/voice/call.d.ts +30 -12
  113. package/lib/types/voice/call.d.ts.map +1 -1
  114. package/lib/types/voice/softphone.d.ts +25 -13
  115. package/lib/types/voice/softphone.d.ts.map +1 -1
  116. package/lib/types/web-rtc-client.d.ts +39 -38
  117. package/lib/types/web-rtc-client.d.ts.map +1 -1
  118. package/lib/utils/sdp.js +25 -10
  119. package/lib/utils/webrtc.js +24 -3
  120. package/lib/voice/call.js +132 -36
  121. package/lib/voice/softphone.js +150 -35
  122. package/lib/web-rtc-client.js +59 -57
  123. package/package.json +1 -1
  124. package/src/__tests__/__voice__/call.test.ts +63 -2
  125. package/src/api/auth.ts +5 -0
  126. package/src/checker/checks/webrtc-transport.ts +2 -2
  127. package/src/checker/checks/webrtc.ts +2 -2
  128. package/src/domain/CallLog.ts +2 -3
  129. package/src/domain/CallSession.ts +3 -3
  130. package/src/domain/Phone/CTIPhone.ts +3 -2
  131. package/src/domain/Phone/WebRTCPhone.ts +95 -93
  132. package/src/domain/types.ts +0 -5
  133. package/src/index.ts +4 -1
  134. package/src/lib/WazoSessionDescriptionHandler.ts +3 -3
  135. package/src/service/CallApi.ts +7 -7
  136. package/src/simple/Auth.ts +15 -3
  137. package/src/simple/Phone.ts +12 -11
  138. package/src/simple/index.ts +2 -1
  139. package/src/simple/room/Room.ts +3 -3
  140. package/src/simple/room/SipRoom.ts +3 -3
  141. package/src/state-machine/call-state-machine.ts +2 -2
  142. package/src/state-machine/softphone-state-machine.ts +1 -2
  143. package/src/state-machine/utils.ts +14 -6
  144. package/src/utils/sdp.ts +26 -11
  145. package/src/utils/webrtc.ts +26 -4
  146. package/src/voice/call.ts +170 -50
  147. package/src/voice/softphone.ts +180 -41
  148. package/src/web-rtc-client.ts +106 -99
@@ -264,11 +264,6 @@ export type PeerConnection = RTCPeerConnection & {
264
264
  addStream: (stream: MediaStream) => void;
265
265
  sfu: any;
266
266
  };
267
- // @TODO, rename it to SipCall
268
- export type WazoSession = (Invitation | Inviter) & {
269
- remoteTag?: any;
270
- callId?: string;
271
- };
272
267
 
273
268
  export type SipCall = (Invitation | Inviter) & {
274
269
  remoteTag?: any;
package/src/index.ts CHANGED
@@ -7,7 +7,7 @@ export { default as ServerError } from './domain/ServerError';
7
7
  export { default as InvalidStateTransition } from './domain/InvalidStateTransition';
8
8
  export { default as InvalidState } from './domain/InvalidState';
9
9
  export { default as SFUNotAvailableError } from './domain/SFUNotAvailableError';
10
- export { default as Call } from './domain/Call';
10
+ export { default as ApiCall } from './domain/Call';
11
11
  export { default as CallLog } from './domain/CallLog';
12
12
  export { default as Recording } from './domain/Recording';
13
13
  export { default as ChatMessage } from './domain/ChatMessage';
@@ -53,6 +53,9 @@ export { default as WazoApiClient } from './api-client';
53
53
  export { default as Agent, AgentResponse, AgentArguments } from './domain/Agent';
54
54
  export { default as ExternalApp } from './domain/ExternalApp';
55
55
  export { default as SessionDescriptionHandler } from './lib/WazoSessionDescriptionHandler';
56
+ export { default as Call } from './voice/call';
57
+ export { Softphone } from './voice/softphone';
58
+
56
59
  export * from './types/WebSocketMessage';
57
60
  export * from './utils/PhoneNumberUtil';
58
61
  export * from './utils/string';
@@ -5,7 +5,7 @@ import type { MediaStreamFactory } from 'sip.js/lib/platform/web/session-descrip
5
5
  import type { SessionDescriptionHandlerConfiguration } from 'sip.js/lib/platform/web/session-description-handler/session-description-handler-configuration';
6
6
  import { SessionDescriptionHandler } from 'sip.js/lib/platform/web/session-description-handler/session-description-handler';
7
7
  import { SessionDescriptionHandlerOptions } from 'sip.js/lib/platform/web/session-description-handler/session-description-handler-options';
8
- import { PeerConnection, WazoSession } from '../domain/types';
8
+ import { PeerConnection, SipCall } from '../domain/types';
9
9
  import IssueReporter from '../service/IssueReporter';
10
10
  import { type Candidate, addIcesInAllBundles, fixSdp, parseCandidate } from '../utils/sdp';
11
11
 
@@ -36,10 +36,10 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
36
36
 
37
37
  isWeb: boolean;
38
38
 
39
- session: WazoSession;
39
+ session: SipCall;
40
40
 
41
41
  // eslint-disable-next-line @typescript-eslint/default-param-last
42
- constructor(logger: Logger, mediaStreamFactory: MediaStreamFactory, sessionDescriptionHandlerConfiguration: SessionDescriptionHandlerConfiguration, isWeb: boolean, session: WazoSession) {
42
+ constructor(logger: Logger, mediaStreamFactory: MediaStreamFactory, sessionDescriptionHandlerConfiguration: SessionDescriptionHandlerConfiguration, isWeb: boolean, session: SipCall) {
43
43
  super(logger, mediaStreamFactory, sessionDescriptionHandlerConfiguration);
44
44
  this.eventEmitter = new EventEmitter();
45
45
  this.isWeb = isWeb;
@@ -1,9 +1,9 @@
1
- import Call from '../domain/Call';
1
+ import ApiCall from '../domain/Call';
2
+ import Call from '../voice/call';
2
3
  import CallLog from '../domain/CallLog';
3
4
  import Line from '../domain/Line';
4
5
  import Session from '../domain/Session';
5
6
  import Relocation from '../domain/Relocation';
6
- import CallSession from '../domain/CallSession';
7
7
  import getApiClient from './getApiClient';
8
8
  import Transfer from '../domain/IndirectTransfer';
9
9
 
@@ -16,7 +16,7 @@ export default class CallApi {
16
16
  return getApiClient().callLogd.listDistinctCallLogs(offset, limit, distinct);
17
17
  }
18
18
 
19
- static async fetchActiveCalls(): Promise<Call[]> {
19
+ static async fetchActiveCalls(): Promise<ApiCall[]> {
20
20
  return getApiClient().calld.listCalls();
21
21
  }
22
22
 
@@ -37,14 +37,14 @@ export default class CallApi {
37
37
  return getApiClient().confd.getUserLineSip(session.uuid as string, lineToUse ? <unknown>lineToUse.id as string : '');
38
38
  }
39
39
 
40
- static async cancelCall(callSession: CallSession): Promise<boolean> {
41
- return getApiClient().calld.cancelCall(callSession.callId);
40
+ static async cancelCall(call: Call): Promise<boolean> {
41
+ return getApiClient().calld.cancelCall(call.apiId || '');
42
42
  }
43
43
 
44
- static async makeCall(callFromLine: Line, extension: string, isMobile = false, callbackAllLines = false): Promise<Call | null | undefined> {
44
+ static async makeCall(callFromLine: Line, extension: string, isMobile = false, callbackAllLines = false): Promise<ApiCall | null | undefined> {
45
45
  const lineId = callFromLine ? callFromLine.id : null;
46
46
  const response = await getApiClient().calld.makeCall(extension, isMobile, lineId, callbackAllLines);
47
- return Call.parse(response);
47
+ return ApiCall.parse(response);
48
48
  }
49
49
 
50
50
  static async relocateCall(callId: string, line: number, contactIdentifier?: string): Promise<Relocation> {
@@ -167,6 +167,10 @@ export class Auth {
167
167
  return this._onAuthenticated(rawSession as Session);
168
168
  }
169
169
 
170
+ async samlLogOut(): Promise<void | { location: string }> {
171
+ return await this.logout(false, true);
172
+ }
173
+
170
174
  async initiateIdpAuthentication(domain: string, redirectUrl: string): Promise<{ location: string, saml_session_id: string } | undefined> {
171
175
  try {
172
176
  return await getApiClient().auth.initiateIdpAuthentication(domain, redirectUrl);
@@ -218,20 +222,26 @@ export class Auth {
218
222
  return getApiClient().auth.refreshToken(refreshToken, '', this.expiration);
219
223
  }
220
224
 
221
- async logout(deleteRefreshToken = true): Promise<void> {
225
+ async logout(deleteRefreshToken = true, saml = false): Promise<void | { location: string }> {
222
226
  try {
223
227
  Wazo.Websocket.close(true);
224
228
 
225
- if (this.clientId && deleteRefreshToken) {
229
+ if (!saml && this.clientId && deleteRefreshToken) {
226
230
  await getApiClient().auth.deleteRefreshToken(this.clientId);
227
231
  }
228
232
  } catch (e: any) {
229
233
  // Nothing to
230
234
  }
231
235
 
236
+ let response;
237
+
232
238
  try {
233
239
  if (this.session?.token) {
234
- await getApiClient().auth.logOut(this.session.token);
240
+ if (saml) {
241
+ response = await getApiClient().auth.samlLogOut();
242
+ } else {
243
+ await getApiClient().auth.logOut(this.session.token);
244
+ }
235
245
  }
236
246
  } catch (e: any) {
237
247
  // Nothing to
@@ -243,6 +253,8 @@ export class Auth {
243
253
  this.authenticated = false;
244
254
  this.usingEdgeServer = undefined;
245
255
  setFetchOptions({});
256
+
257
+ return response;
246
258
  }
247
259
 
248
260
  setOnHostFromHeaders(callback: (hostFromHeaders: string) => void) {
@@ -6,21 +6,22 @@ import type CallSession from '../domain/CallSession';
6
6
  import AdHocAPIConference from '../domain/AdHocAPIConference';
7
7
  import WebRTCPhone, * as PHONE_EVENTS from '../domain/Phone/WebRTCPhone';
8
8
  import { MESSAGE_TYPE_CHAT, MESSAGE_TYPE_SIGNAL } from '../domain/Phone/WebRTCPhone';
9
- import WazoWebRTCClient, { events as clientEvents, transportEvents } from '../web-rtc-client';
9
+ import WebRTCClient, { events as clientEvents, transportEvents } from '../web-rtc-client';
10
10
  import IssueReporter from '../service/IssueReporter';
11
11
  import Emitter from '../utils/Emitter';
12
12
  import Wazo from './index';
13
13
  import SFUNotAvailableError from '../domain/SFUNotAvailableError';
14
- import { WazoSession, WebRtcConfig } from '../domain/types';
15
- import { getSipSessionId } from '../utils/sdp';
14
+ import { SipCall, WebRtcConfig } from '../domain/types';
15
+ import { getSipCallId } from '../utils/sdp';
16
16
 
17
17
  const logger = IssueReporter.loggerFor('simple-phone');
18
18
  const sipLogger = IssueReporter.loggerFor('sip.js');
19
19
  const protocolLogger = IssueReporter.loggerFor('sip');
20
20
  const protocolDebugMessages = ['Received WebSocket text message:', 'Sending WebSocket message:'];
21
21
 
22
+ // @deprecated: Use Wazo.Voice.Softphone instead
22
23
  export class Phone extends Emitter {
23
- client: WazoWebRTCClient;
24
+ client: WebRTCClient;
24
25
 
25
26
  phone: WebRTCPhone | null | undefined;
26
27
 
@@ -187,7 +188,7 @@ export class Phone extends Emitter {
187
188
  options.log.connector = this._logConnector;
188
189
  }
189
190
 
190
- this.client = new WazoWebRTCClient({
191
+ this.client = new WebRTCClient({
191
192
  host,
192
193
  port: typeof port === 'string' ? parseInt(port, 10) : port,
193
194
  displayName,
@@ -329,14 +330,14 @@ export class Phone extends Emitter {
329
330
  return this.phone ? this.phone.stopNetworkMonitoring(callSession) : null;
330
331
  }
331
332
 
332
- getSipSessionId(sipSession: WazoSession): string | null | undefined {
333
+ getSipCallId(sipSession: SipCall): string | null | undefined {
333
334
  if (!sipSession || !this.phone) {
334
335
  return null;
335
336
  }
336
- return getSipSessionId(sipSession);
337
+ return getSipCallId(sipSession);
337
338
  }
338
339
 
339
- sendMessage(body: string, sipSession?: WazoSession, contentType = 'text/plain'): void {
340
+ sendMessage(body: string, sipSession?: SipCall, contentType = 'text/plain'): void {
340
341
  const toSipSession = sipSession || this.getCurrentSipSession();
341
342
 
342
343
  if (!toSipSession || !this.phone) {
@@ -346,14 +347,14 @@ export class Phone extends Emitter {
346
347
  this.phone.sendMessage(toSipSession, body, contentType);
347
348
  }
348
349
 
349
- sendChat(content: string, sipSession?: WazoSession): void {
350
+ sendChat(content: string, sipSession?: SipCall): void {
350
351
  this.sendMessage(JSON.stringify({
351
352
  type: MESSAGE_TYPE_CHAT,
352
353
  content,
353
354
  }), sipSession, 'application/json');
354
355
  }
355
356
 
356
- sendSignal(content: any, sipSession?: WazoSession): void {
357
+ sendSignal(content: any, sipSession?: SipCall): void {
357
358
  this.sendMessage(JSON.stringify({
358
359
  type: MESSAGE_TYPE_SIGNAL,
359
360
  content,
@@ -446,7 +447,7 @@ export class Phone extends Emitter {
446
447
  return this.phone ? this.phone.hasAVideoTrack(callSession) : false;
447
448
  }
448
449
 
449
- getCurrentSipSession(): WazoSession | null {
450
+ getCurrentSipSession(): SipCall | null {
450
451
  return this.phone?.currentSipSession || null;
451
452
  }
452
453
 
@@ -41,7 +41,7 @@ import Features from '../domain/Features';
41
41
  import Meeting from '../domain/Meeting';
42
42
  import Checker from '../checker/Checker';
43
43
 
44
- import Softphone from '../voice/softphone';
44
+ import Softphone, { Softphone as SoftphoneClass } from '../voice/softphone';
45
45
  import Call from '../voice/call';
46
46
 
47
47
  const Wazo = {
@@ -91,6 +91,7 @@ const Wazo = {
91
91
  SwitchboardCall,
92
92
  WebRTCPhone,
93
93
  Meeting,
94
+ SoftphoneClass,
94
95
  },
95
96
 
96
97
  // Api
@@ -9,8 +9,8 @@ import Participant, { RawParticipant } from './Participant';
9
9
  import RemoteParticipant from './RemoteParticipant';
10
10
  import IssueReporter from '../../service/IssueReporter';
11
11
  import LocalParticipant from './LocalParticipant';
12
- import { PeerConnection, WazoSession } from '../../domain/types';
13
- import { getSipSessionId } from '../../utils/sdp';
12
+ import { PeerConnection, SipCall } from '../../domain/types';
13
+ import { getSipCallId } from '../../utils/sdp';
14
14
 
15
15
  export const SIGNAL_TYPE_PARTICIPANT_UPDATE = 'signal/PARTICIPANT_UPDATE';
16
16
  export const SIGNAL_TYPE_PARTICIPANT_REQUEST = 'signal/PARTICIPANT_REQUEST';
@@ -498,7 +498,7 @@ class Room extends Emitter {
498
498
  this.audioStream = stream;
499
499
 
500
500
  if (!this.roomAudioElement) {
501
- const sessionId = getSipSessionId(Wazo.Phone.phone?.currentSipSession as WazoSession);
501
+ const sessionId = getSipCallId(Wazo.Phone.phone?.currentSipSession as SipCall);
502
502
  this.roomAudioElement = await Wazo.Phone.phone?.createAudioElementFor(sessionId as string) as HTMLAudioElement;
503
503
  this.roomAudioElement.srcObject = stream;
504
504
  } else {
@@ -3,8 +3,8 @@ import CallSession from '../../domain/CallSession';
3
3
  import IssueReporter from '../../service/IssueReporter';
4
4
  import Wazo from '../index';
5
5
  import Room from './Room';
6
- import { WazoSession } from '../../domain/types';
7
- import { getSipSessionId } from '../../utils/sdp';
6
+ import { SipCall } from '../../domain/types';
7
+ import { getSipCallId } from '../../utils/sdp';
8
8
 
9
9
  const logger = IssueReporter.loggerFor('sdk-sip-room');
10
10
 
@@ -157,7 +157,7 @@ class SipRoom extends Room {
157
157
  }
158
158
 
159
159
  _getCurrentSipCallIs() {
160
- return getSipSessionId(Wazo.Phone.phone?.currentSipSession as WazoSession);
160
+ return getSipCallId(Wazo.Phone.phone?.currentSipSession as SipCall);
161
161
  }
162
162
 
163
163
  }
@@ -43,7 +43,7 @@ export type EstablishedActionTypes = typeof EstablishedActions[keyof typeof Esta
43
43
 
44
44
  const callMachine = setup({
45
45
  guards: {
46
- isRegistered: () => softphone.getState() === SoftphoneStates.REGISTERED,
46
+ isRegistered: () => softphone.state === SoftphoneStates.REGISTERED,
47
47
  },
48
48
  }).createMachine({
49
49
  id: 'call',
@@ -53,7 +53,7 @@ const callMachine = setup({
53
53
  [States.IDLE]: {
54
54
  on: {
55
55
  [Actions.INCOMING_CALL]: {
56
- // guard: 'isRegistered',
56
+ guard: 'isRegistered',
57
57
  target: States.RINGING,
58
58
  },
59
59
  [Actions.MAKE_CALL]: {
@@ -12,7 +12,6 @@ export const Actions = {
12
12
  REGISTER: 'register',
13
13
  REGISTER_DONE: 'registerDone',
14
14
  UNREGISTER: 'unregister',
15
- UNREGISTERED: 'unregistered',
16
15
  TRANSPORT_CLOSED: 'transportClosed',
17
16
  } as const;
18
17
 
@@ -32,7 +31,7 @@ const softphoneMachine = setup({}).createMachine({
32
31
  on: {
33
32
  [Actions.REGISTER_DONE]: States.REGISTERED,
34
33
  [Actions.TRANSPORT_CLOSED]: States.UNREGISTERED,
35
- [Actions.UNREGISTERED]: States.UNREGISTERED,
34
+ [Actions.UNREGISTER]: States.UNREGISTERED,
36
35
  },
37
36
  },
38
37
  [States.REGISTERED]: {
@@ -8,16 +8,23 @@ import IssueReporter from '../service/IssueReporter';
8
8
 
9
9
  const logger = IssueReporter.loggerFor('state-machine');
10
10
 
11
- export const getState = (actor: SoftphoneActorRef | CallActorRef): SoftphoneStates | CallStates | EstablishedStateTypes => {
12
- return actor.getSnapshot().value as SoftphoneStates | CallStates | EstablishedStateTypes;
11
+ export const getState = (actor: SoftphoneActorRef | CallActorRef): SoftphoneStates | CallStates | EstablishedStateTypes | Record<CallStates, EstablishedStateTypes> => {
12
+ return actor.getSnapshot().value as SoftphoneStates | CallStates | EstablishedStateTypes | Record<CallStates, EstablishedStateTypes>;
13
13
  };
14
14
 
15
15
  export const can = (actor: SoftphoneActorRef | CallActorRef, action: SoftphoneActions | CallActions | EstablishedCallActions): boolean => {
16
16
  return actor.getSnapshot().can({ type: action });
17
17
  };
18
18
 
19
- export const hasState = (actor: SoftphoneActorRef | CallActorRef, state: SoftphoneStates | CallStates): boolean => {
20
- return getState(actor) === state;
19
+ export const hasState = (actor: SoftphoneActorRef | CallActorRef, state: SoftphoneStates | CallStates, innerState?: EstablishedStateTypes): boolean => {
20
+ const currentState = getState(actor);
21
+
22
+ // When using nested states, we'll have an object here
23
+ if (typeof currentState === 'object') {
24
+ return innerState ? state in currentState && currentState[state as CallStates] === innerState : state in currentState;
25
+ }
26
+
27
+ return currentState === state;
21
28
  };
22
29
 
23
30
  export const waitUntilState = (actor: SoftphoneActorRef | CallActorRef, state: SoftphoneStates | CallStates, timeout = 5000): Promise<unknown> => {
@@ -36,7 +43,8 @@ export const waitUntilState = (actor: SoftphoneActorRef | CallActorRef, state: S
36
43
  export const assertCan = (actor: SoftphoneActorRef | CallActorRef, action: SoftphoneActions | CallActions | EstablishedCallActions): void => {
37
44
  if (!can(actor, action)) {
38
45
  const currentState = actor.getSnapshot().value;
39
- const message = `Invalid state transition from ${currentState} with action ${action}`;
46
+ const currentStateString = typeof currentState === 'object' ? JSON.stringify(currentState) : currentState;
47
+ const message = `Invalid state transition from ${currentStateString} with action ${action}`;
40
48
  logger.warn(message);
41
49
 
42
50
  throw new InvalidStateTransition(message, action, currentState as string);
@@ -45,7 +53,7 @@ export const assertCan = (actor: SoftphoneActorRef | CallActorRef, action: Softp
45
53
 
46
54
  export const assertState = (actor: SoftphoneActorRef | CallActorRef, state: SoftphoneStates | CallStates): void => {
47
55
  if (!hasState(actor, state)) {
48
- const message = `Invalid state ${state}`;
56
+ const message = `Invalid state ${state}, has state ${getState(actor)}`;
49
57
  logger.warn(message);
50
58
 
51
59
  throw new InvalidState(message, state);
package/src/utils/sdp.ts CHANGED
@@ -1,12 +1,11 @@
1
+ /* eslint-disable no-underscore-dangle */
1
2
  import sdpParser from 'sdp-transform';
2
3
  import { UserAgent } from 'sip.js/lib/api/user-agent';
3
- import { Inviter } from 'sip.js/lib/api';
4
+ import { Inviter, Invitation } from 'sip.js/lib/api';
4
5
  import { URI } from 'sip.js/lib/grammar/uri';
5
6
 
6
7
  import type { SipCall } from '../domain/types';
7
8
 
8
- export const SIP_ID_LENGTH = 36;
9
-
10
9
  export type Candidate = {
11
10
  foundation: string;
12
11
  component: number;
@@ -146,25 +145,26 @@ export const addIcesInAllBundles = (sdp: string) => {
146
145
  return sdpParser.write(parsedSdp);
147
146
  };
148
147
 
149
- export const getSipSessionId = (sipSession: SipCall | null | undefined): string => {
148
+ export const getSipCallId = (sipSession: SipCall | null | undefined): string => {
150
149
  if (!sipSession) {
151
150
  return '';
152
151
  }
153
152
 
154
- const message = sipSession.message as Partial<{ callId?: string }>;
155
- if (message?.callId) {
156
- return message.callId.substring(0, SIP_ID_LENGTH);
157
- }
158
-
159
153
  // For Inviter
160
154
  // @ts-ignore: private
161
155
  if (sipSession instanceof Inviter && sipSession.outgoingRequestMessage) {
162
156
  // @ts-ignore: private
163
- return sipSession.outgoingRequestMessage.callId.substring(0, SIP_ID_LENGTH);
157
+ return sipSession.outgoingRequestMessage.callId;
164
158
  }
165
159
 
166
160
  // For Invitation
167
- return (sipSession.id || '').substring(0, SIP_ID_LENGTH);
161
+ // @ts-ignore: private
162
+ if (sipSession instanceof Invitation && sipSession.incomingInviteRequest.message) {
163
+ // @ts-ignore: private
164
+ return sipSession.incomingInviteRequest.message.callId;
165
+ }
166
+
167
+ return sipSession.id;
168
168
  };
169
169
 
170
170
  // We need to replace 0.0.0.0 to 127.0.0.1 in the sdp to avoid MOH during a createOffer.
@@ -174,3 +174,18 @@ export const replaceLocalIpModifier = (description: Record<string, any>) => Prom
174
174
  });
175
175
 
176
176
  export const makeURI = (target: string, host: string): URI | undefined => UserAgent.makeURI(`sip:${target}@${host}`);
177
+
178
+ export const getCallNumber = (sipCall: SipCall): string => {
179
+ // eslint-disable-next-line
180
+ const identity = sipCall ? sipCall.remoteIdentity || sipCall.assertedIdentity : null;
181
+ // @ts-ignore: private
182
+ return identity ? identity.uri._normal.user : null;
183
+ };
184
+
185
+ export const getCallDisplayName = (sipCall: SipCall): string => {
186
+ // eslint-disable-next-line
187
+ const identity = sipCall ? sipCall.remoteIdentity || sipCall.assertedIdentity : null;
188
+ const number = getCallNumber(sipCall);
189
+
190
+ return identity ? identity.displayName || number : number;
191
+ };
@@ -1,4 +1,4 @@
1
- /* eslint-disable no-underscore-dangle, no-param-reassign */
1
+ /* eslint-disable no-underscore-dangle, no-param-reassign, no-restricted-syntax */
2
2
  import type { SessionDescriptionHandler } from 'sip.js/lib/platform/web/session-description-handler/session-description-handler';
3
3
  import type { SessionDescriptionHandlerFactoryOptions } from 'sip.js/lib/platform/web/session-description-handler/session-description-handler-factory-options';
4
4
  import type { SessionDescriptionHandlerConfiguration } from 'sip.js/lib/platform/web/session-description-handler/session-description-handler-configuration';
@@ -7,7 +7,7 @@ import { stripVideo } from 'sip.js/lib/platform/web';
7
7
 
8
8
  import WazoSessionDescriptionHandler, { wazoMediaStreamFactory } from '../lib/WazoSessionDescriptionHandler';
9
9
  import { SipCall, PeerConnection, UserAgentOptions, WebRtcConfig, UserAgentConfigOverrides } from '../domain/types';
10
- import { getVideoDirection, hasAnActiveVideo, makeURI, replaceLocalIpModifier } from './sdp';
10
+ import { getSipCallId, getVideoDirection, hasAnActiveVideo, makeURI, replaceLocalIpModifier } from './sdp';
11
11
  import IssueReporter from '../service/IssueReporter';
12
12
  import { lastIndexOf } from './array';
13
13
 
@@ -246,13 +246,35 @@ export const toggleVideo = (sipCall: SipCall, muteCamera: boolean): void => {
246
246
  }
247
247
  };
248
248
 
249
+ export const isVideoMuted = (sipCall: SipCall): boolean => {
250
+ const sdh = sipCall.sessionDescriptionHandler as SessionDescriptionHandler;
251
+ const pc = sdh?.peerConnection as PeerConnection;
252
+
253
+ if (pc?.getSenders) {
254
+ for (const sender of pc.getSenders()) {
255
+ if (sender && sender.track && sender.track.kind === 'video') {
256
+ return !sender.track.enabled;
257
+ }
258
+ }
259
+ } else {
260
+ for (const stream of pc.getLocalStreams()) {
261
+ // eslint-disable-next-line no-unreachable-loop
262
+ for (const track of stream.getVideoTracks()) {
263
+ return !track.enabled;
264
+ }
265
+ }
266
+ }
267
+
268
+ return true;
269
+ };
270
+
249
271
  export const cleanupStream = (stream: MediaStream): void => {
250
272
  stream.getTracks().filter(track => track.enabled).forEach(track => track.stop());
251
273
  };
252
274
 
253
275
  export const setLocalMediaStream = (sipCall: SipCall, newStream: MediaStream): void => {
254
276
  logger.info('setting local media stream', {
255
- id: sipCall.id,
277
+ id: getSipCallId(sipCall),
256
278
  tracks: newStream ? newStream.getTracks() : null,
257
279
  });
258
280
 
@@ -268,7 +290,7 @@ export const updateRemoteStream = (sipCall: SipCall, allTracks = true): void =>
268
290
  const pc = getPeerConnection(sipCall);
269
291
 
270
292
  logger.info('Updating remote stream', {
271
- id: sipCall.id,
293
+ id: getSipCallId(sipCall),
272
294
  tracks: remoteStream ? remoteStream.getTracks() : null,
273
295
  receiverTracks: pc && pc.getReceivers ? pc.getReceivers().map((receiver) => receiver.track) : null,
274
296
  });