@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
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,13 +6,13 @@ 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');
@@ -21,7 +21,7 @@ const protocolDebugMessages = ['Received WebSocket text message:', 'Sending WebS
21
21
 
22
22
  // @deprecated: Use Wazo.Voice.Softphone instead
23
23
  export class Phone extends Emitter {
24
- client: WazoWebRTCClient;
24
+ client: WebRTCClient;
25
25
 
26
26
  phone: WebRTCPhone | null | undefined;
27
27
 
@@ -188,7 +188,7 @@ export class Phone extends Emitter {
188
188
  options.log.connector = this._logConnector;
189
189
  }
190
190
 
191
- this.client = new WazoWebRTCClient({
191
+ this.client = new WebRTCClient({
192
192
  host,
193
193
  port: typeof port === 'string' ? parseInt(port, 10) : port,
194
194
  displayName,
@@ -330,14 +330,14 @@ export class Phone extends Emitter {
330
330
  return this.phone ? this.phone.stopNetworkMonitoring(callSession) : null;
331
331
  }
332
332
 
333
- getSipSessionId(sipSession: WazoSession): string | null | undefined {
333
+ getSipCallId(sipSession: SipCall): string | null | undefined {
334
334
  if (!sipSession || !this.phone) {
335
335
  return null;
336
336
  }
337
- return getSipSessionId(sipSession);
337
+ return getSipCallId(sipSession);
338
338
  }
339
339
 
340
- sendMessage(body: string, sipSession?: WazoSession, contentType = 'text/plain'): void {
340
+ sendMessage(body: string, sipSession?: SipCall, contentType = 'text/plain'): void {
341
341
  const toSipSession = sipSession || this.getCurrentSipSession();
342
342
 
343
343
  if (!toSipSession || !this.phone) {
@@ -347,14 +347,14 @@ export class Phone extends Emitter {
347
347
  this.phone.sendMessage(toSipSession, body, contentType);
348
348
  }
349
349
 
350
- sendChat(content: string, sipSession?: WazoSession): void {
350
+ sendChat(content: string, sipSession?: SipCall): void {
351
351
  this.sendMessage(JSON.stringify({
352
352
  type: MESSAGE_TYPE_CHAT,
353
353
  content,
354
354
  }), sipSession, 'application/json');
355
355
  }
356
356
 
357
- sendSignal(content: any, sipSession?: WazoSession): void {
357
+ sendSignal(content: any, sipSession?: SipCall): void {
358
358
  this.sendMessage(JSON.stringify({
359
359
  type: MESSAGE_TYPE_SIGNAL,
360
360
  content,
@@ -447,7 +447,7 @@ export class Phone extends Emitter {
447
447
  return this.phone ? this.phone.hasAVideoTrack(callSession) : false;
448
448
  }
449
449
 
450
- getCurrentSipSession(): WazoSession | null {
450
+ getCurrentSipSession(): SipCall | null {
451
451
  return this.phone?.currentSipSession || null;
452
452
  }
453
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
  }
@@ -15,11 +15,19 @@ export const EstablishedStates = {
15
15
  ONGOING: 'ongoing',
16
16
  HELD: 'held',
17
17
  MUTED: 'muted',
18
+ UN_MUTED: 'unMuted',
19
+ UN_HELD: 'unHeld',
20
+ } as const;
21
+
22
+ export const EstablishedSubStates = {
23
+ MUTE: 'muteState',
24
+ HOLD: 'holdState',
18
25
  } as const;
19
26
 
20
27
  export type StateTypes = typeof States[keyof typeof States];
21
28
 
22
29
  export type EstablishedStateTypes = typeof EstablishedStates[keyof typeof EstablishedStates];
30
+ export type EstablishedSubStateTypes = typeof EstablishedSubStates[keyof typeof EstablishedSubStates];
23
31
 
24
32
  export const Actions = {
25
33
  INCOMING_CALL: 'incomingCall',
@@ -53,7 +61,7 @@ const callMachine = setup({
53
61
  [States.IDLE]: {
54
62
  on: {
55
63
  [Actions.INCOMING_CALL]: {
56
- // guard: 'isRegistered',
64
+ guard: 'isRegistered',
57
65
  target: States.RINGING,
58
66
  },
59
67
  [Actions.MAKE_CALL]: {
@@ -88,35 +96,46 @@ const callMachine = setup({
88
96
  },
89
97
  [States.ESTABLISHED]: {
90
98
  initial: EstablishedStates.ONGOING,
99
+ type: 'parallel',
91
100
  on: {
92
101
  [Actions.HANGUP]: {
93
102
  guard: 'isRegistered',
94
103
  target: States.TERMINATED,
95
104
  },
96
- [EstablishedActions.HOLD]: {
97
- guard: 'isRegistered',
98
- target: `.${EstablishedStates.HELD}`,
99
- },
100
- [EstablishedActions.MUTE]: {
101
- guard: 'isRegistered',
102
- target: `.${EstablishedStates.MUTED}`,
103
- },
104
105
  },
105
106
  states: {
106
107
  [EstablishedStates.ONGOING]: { },
107
- [EstablishedStates.HELD]: {
108
- on: {
109
- [EstablishedActions.RESUME]: {
110
- guard: 'isRegistered',
111
- target: EstablishedStates.ONGOING,
108
+
109
+ // Mute / Unmute
110
+ [EstablishedSubStates.MUTE]: {
111
+ initial: EstablishedStates.UN_MUTED,
112
+ states: {
113
+ [EstablishedStates.MUTED]: {
114
+ on: {
115
+ unMute: EstablishedStates.UN_MUTED,
116
+ },
117
+ },
118
+ [EstablishedStates.UN_MUTED]: {
119
+ on: {
120
+ mute: EstablishedStates.MUTED,
121
+ },
112
122
  },
113
123
  },
114
124
  },
115
- [EstablishedStates.MUTED]: {
116
- on: {
117
- [EstablishedActions.UN_MUTE]: {
118
- guard: 'isRegistered',
119
- target: EstablishedStates.ONGOING,
125
+
126
+ // Hold / Resume
127
+ [EstablishedSubStates.HOLD]: {
128
+ initial: EstablishedStates.UN_HELD,
129
+ states: {
130
+ [EstablishedStates.HELD]: {
131
+ on: {
132
+ [EstablishedActions.RESUME]: EstablishedStates.UN_HELD,
133
+ },
134
+ },
135
+ [EstablishedStates.UN_HELD]: {
136
+ on: {
137
+ [EstablishedActions.HOLD]: EstablishedStates.HELD,
138
+ },
120
139
  },
121
140
  },
122
141
  },
@@ -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]: {
@@ -16,8 +16,15 @@ export const can = (actor: SoftphoneActorRef | CallActorRef, action: SoftphoneAc
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,13 +1,12 @@
1
1
  /* eslint-disable no-underscore-dangle */
2
2
  import sdpParser from 'sdp-transform';
3
3
  import { UserAgent } from 'sip.js/lib/api/user-agent';
4
- import { Inviter } from 'sip.js/lib/api';
4
+ import { Inviter, Invitation } from 'sip.js/lib/api';
5
+ import { SessionDialog } from 'sip.js/lib/core/dialogs/session-dialog';
5
6
  import { URI } from 'sip.js/lib/grammar/uri';
6
7
 
7
8
  import type { SipCall } from '../domain/types';
8
9
 
9
- export const SIP_ID_LENGTH = 36;
10
-
11
10
  export type Candidate = {
12
11
  foundation: string;
13
12
  component: number;
@@ -147,25 +146,33 @@ export const addIcesInAllBundles = (sdp: string) => {
147
146
  return sdpParser.write(parsedSdp);
148
147
  };
149
148
 
150
- export const getSipSessionId = (sipSession: SipCall | null | undefined): string => {
149
+ export const getSipCallId = (sipSession: SipCall | null | undefined): string => {
151
150
  if (!sipSession) {
152
151
  return '';
153
152
  }
154
153
 
155
- const message = sipSession.message as Partial<{ callId?: string }>;
156
- if (message?.callId) {
157
- return message.callId.substring(0, SIP_ID_LENGTH);
158
- }
159
-
160
154
  // For Inviter
161
155
  // @ts-ignore: private
162
156
  if (sipSession instanceof Inviter && sipSession.outgoingRequestMessage) {
163
157
  // @ts-ignore: private
164
- return sipSession.outgoingRequestMessage.callId.substring(0, SIP_ID_LENGTH);
158
+ return sipSession.outgoingRequestMessage.callId;
165
159
  }
166
160
 
167
161
  // For Invitation
168
- return (sipSession.id || '').substring(0, SIP_ID_LENGTH);
162
+ // @ts-ignore: private
163
+ if (sipSession instanceof Invitation && sipSession.incomingInviteRequest.message) {
164
+ // @ts-ignore: private
165
+ return sipSession.incomingInviteRequest.message.callId;
166
+ }
167
+
168
+ // For EarlyMedia
169
+ // @ts-ignore: private
170
+ if (sipSession instanceof SessionDialog) {
171
+ // @ts-ignore: private
172
+ return sipSession.dialogState.callId;
173
+ }
174
+
175
+ return sipSession.id;
169
176
  };
170
177
 
171
178
  // We need to replace 0.0.0.0 to 127.0.0.1 in the sdp to avoid MOH during a createOffer.
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable no-param-reassign */
2
- export default ((instance: any, from: any) => {
3
- Object.keys(from)
2
+ export default ((instance: any, from: any, attributes: string[] | null = null) => {
3
+ (attributes || Object.keys(from))
4
4
  .forEach(key => {
5
5
  if ((!instance[key] && from[key])
6
6
  || (typeof instance[key] !== 'undefined' && typeof from[key] !== 'undefined' && instance[key] !== from[key])
@@ -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
 
@@ -187,6 +187,10 @@ export const sessionWantsToDoVideo = (sipCall: SipCall): boolean => {
187
187
  } = sipCall.request || sipCall;
188
188
  // Sometimes with InviteClientContext the body is in the body attribute ...
189
189
  const sdp = typeof body === 'object' && body ? body.body : body;
190
+ if (!sdp) {
191
+ return (sipCall.sessionDescriptionHandler as any)?.localMediaStreamConstraints?.video;
192
+ }
193
+
190
194
  return hasAnActiveVideo(sdp);
191
195
  };
192
196
 
@@ -249,6 +253,9 @@ export const toggleVideo = (sipCall: SipCall, muteCamera: boolean): void => {
249
253
  export const isVideoMuted = (sipCall: SipCall): boolean => {
250
254
  const sdh = sipCall.sessionDescriptionHandler as SessionDescriptionHandler;
251
255
  const pc = sdh?.peerConnection as PeerConnection;
256
+ if (!pc) {
257
+ return true;
258
+ }
252
259
 
253
260
  if (pc?.getSenders) {
254
261
  for (const sender of pc.getSenders()) {
@@ -274,7 +281,7 @@ export const cleanupStream = (stream: MediaStream): void => {
274
281
 
275
282
  export const setLocalMediaStream = (sipCall: SipCall, newStream: MediaStream): void => {
276
283
  logger.info('setting local media stream', {
277
- id: sipCall.id,
284
+ id: getSipCallId(sipCall),
278
285
  tracks: newStream ? newStream.getTracks() : null,
279
286
  });
280
287
 
@@ -290,7 +297,7 @@ export const updateRemoteStream = (sipCall: SipCall, allTracks = true): void =>
290
297
  const pc = getPeerConnection(sipCall);
291
298
 
292
299
  logger.info('Updating remote stream', {
293
- id: sipCall.id,
300
+ id: getSipCallId(sipCall),
294
301
  tracks: remoteStream ? remoteStream.getTracks() : null,
295
302
  receiverTracks: pc && pc.getReceivers ? pc.getReceivers().map((receiver) => receiver.track) : null,
296
303
  });
@@ -327,7 +334,7 @@ export const getVideoConstraints = (video: Constraint = false): MediaTrackConstr
327
334
  }
328
335
 
329
336
  // @ts-ignore: media constraints
330
- return this.video?.deviceId?.exact ? this.video : true;
337
+ return video?.deviceId?.exact ? video : true;
331
338
  };
332
339
 
333
340
  // eslint-disable-next-line no-unused-vars