@wazo/sdk 0.43.6 → 1.0.0-alpha.0

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/dist/wazo-sdk.js +3 -3
  2. package/esm/__tests__/__voice__/call.test.js +72 -0
  3. package/esm/__tests__/__voice__/softphone.test.js +66 -0
  4. package/esm/__tests__/api-client.test.js +1 -20
  5. package/esm/api/auth.js +2 -13
  6. package/esm/checker/checks/webrtc.js +2 -1
  7. package/esm/domain/InvalidState.js +8 -0
  8. package/esm/domain/InvalidStateTransition.js +10 -0
  9. package/esm/domain/Phone/WebRTCPhone.js +33 -35
  10. package/esm/simple/Auth.js +12 -6
  11. package/esm/simple/Phone.js +2 -1
  12. package/esm/simple/__tests__/Auth.test.js +64 -8
  13. package/esm/simple/index.js +8 -2
  14. package/esm/simple/room/Room.js +2 -1
  15. package/esm/simple/room/SipRoom.js +2 -1
  16. package/esm/state-machine/call-state-machine.js +114 -0
  17. package/esm/state-machine/softphone-state-machine.js +39 -0
  18. package/esm/state-machine/utils.js +40 -0
  19. package/esm/types/__tests__/__voice__/call.test.d.ts +2 -0
  20. package/esm/types/__tests__/__voice__/call.test.d.ts.map +1 -0
  21. package/esm/types/__tests__/__voice__/softphone.test.d.ts +2 -0
  22. package/esm/types/__tests__/__voice__/softphone.test.d.ts.map +1 -0
  23. package/esm/types/api/auth.d.ts.map +1 -1
  24. package/esm/types/checker/checks/webrtc.d.ts.map +1 -1
  25. package/esm/types/domain/InvalidState.d.ts +6 -0
  26. package/esm/types/domain/InvalidState.d.ts.map +1 -0
  27. package/esm/types/domain/InvalidStateTransition.d.ts +7 -0
  28. package/esm/types/domain/InvalidStateTransition.d.ts.map +1 -0
  29. package/esm/types/domain/Phone/WebRTCPhone.d.ts +0 -1
  30. package/esm/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
  31. package/esm/types/domain/types.d.ts +4 -0
  32. package/esm/types/domain/types.d.ts.map +1 -1
  33. package/esm/types/simple/Auth.d.ts.map +1 -1
  34. package/esm/types/simple/Phone.d.ts.map +1 -1
  35. package/esm/types/simple/index.d.ts +7 -2
  36. package/esm/types/simple/index.d.ts.map +1 -1
  37. package/esm/types/simple/room/Room.d.ts.map +1 -1
  38. package/esm/types/simple/room/SipRoom.d.ts +1 -1
  39. package/esm/types/simple/room/SipRoom.d.ts.map +1 -1
  40. package/esm/types/state-machine/call-state-machine.d.ts +43 -0
  41. package/esm/types/state-machine/call-state-machine.d.ts.map +1 -0
  42. package/esm/types/state-machine/softphone-state-machine.d.ts +19 -0
  43. package/esm/types/state-machine/softphone-state-machine.d.ts.map +1 -0
  44. package/esm/types/state-machine/utils.d.ts +9 -0
  45. package/esm/types/state-machine/utils.d.ts.map +1 -0
  46. package/esm/types/utils/api-requester.d.ts.map +1 -1
  47. package/esm/types/utils/sdp.d.ts +6 -0
  48. package/esm/types/utils/sdp.d.ts.map +1 -1
  49. package/esm/types/utils/sip-logger.d.ts +4 -0
  50. package/esm/types/utils/sip-logger.d.ts.map +1 -0
  51. package/esm/types/utils/webrtc.d.ts +40 -0
  52. package/esm/types/utils/webrtc.d.ts.map +1 -1
  53. package/esm/types/voice/call.d.ts +110 -0
  54. package/esm/types/voice/call.d.ts.map +1 -0
  55. package/esm/types/voice/softphone.d.ts +77 -0
  56. package/esm/types/voice/softphone.d.ts.map +1 -0
  57. package/esm/types/web-rtc-client.d.ts +1 -36
  58. package/esm/types/web-rtc-client.d.ts.map +1 -1
  59. package/esm/utils/__tests__/api-requester.test.js +0 -17
  60. package/esm/utils/api-requester.js +1 -9
  61. package/esm/utils/sdp.js +26 -0
  62. package/esm/utils/sip-logger.js +32 -0
  63. package/esm/utils/webrtc.js +465 -0
  64. package/esm/voice/call.js +527 -0
  65. package/esm/voice/softphone.js +347 -0
  66. package/esm/web-rtc-client.js +86 -584
  67. package/lib/__tests__/__voice__/call.test.js +86 -0
  68. package/lib/__tests__/__voice__/softphone.test.js +80 -0
  69. package/lib/__tests__/api-client.test.js +1 -20
  70. package/lib/api/auth.js +2 -13
  71. package/lib/checker/checks/webrtc.js +2 -1
  72. package/lib/domain/InvalidState.js +9 -0
  73. package/lib/domain/InvalidStateTransition.js +10 -0
  74. package/lib/domain/Phone/WebRTCPhone.js +33 -35
  75. package/lib/simple/Auth.js +12 -6
  76. package/lib/simple/Phone.js +2 -1
  77. package/lib/simple/__tests__/Auth.test.js +64 -11
  78. package/lib/simple/index.js +6 -0
  79. package/lib/simple/room/Room.js +4 -3
  80. package/lib/simple/room/SipRoom.js +2 -1
  81. package/lib/state-machine/call-state-machine.js +120 -0
  82. package/lib/state-machine/softphone-state-machine.js +42 -0
  83. package/lib/state-machine/utils.js +52 -0
  84. package/lib/types/__tests__/__voice__/call.test.d.ts +2 -0
  85. package/lib/types/__tests__/__voice__/call.test.d.ts.map +1 -0
  86. package/lib/types/__tests__/__voice__/softphone.test.d.ts +2 -0
  87. package/lib/types/__tests__/__voice__/softphone.test.d.ts.map +1 -0
  88. package/lib/types/api/auth.d.ts.map +1 -1
  89. package/lib/types/checker/checks/webrtc.d.ts.map +1 -1
  90. package/lib/types/domain/InvalidState.d.ts +6 -0
  91. package/lib/types/domain/InvalidState.d.ts.map +1 -0
  92. package/lib/types/domain/InvalidStateTransition.d.ts +7 -0
  93. package/lib/types/domain/InvalidStateTransition.d.ts.map +1 -0
  94. package/lib/types/domain/Phone/WebRTCPhone.d.ts +0 -1
  95. package/lib/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
  96. package/lib/types/domain/types.d.ts +4 -0
  97. package/lib/types/domain/types.d.ts.map +1 -1
  98. package/lib/types/simple/Auth.d.ts.map +1 -1
  99. package/lib/types/simple/Phone.d.ts.map +1 -1
  100. package/lib/types/simple/index.d.ts +7 -2
  101. package/lib/types/simple/index.d.ts.map +1 -1
  102. package/lib/types/simple/room/Room.d.ts.map +1 -1
  103. package/lib/types/simple/room/SipRoom.d.ts +1 -1
  104. package/lib/types/simple/room/SipRoom.d.ts.map +1 -1
  105. package/lib/types/state-machine/call-state-machine.d.ts +43 -0
  106. package/lib/types/state-machine/call-state-machine.d.ts.map +1 -0
  107. package/lib/types/state-machine/softphone-state-machine.d.ts +19 -0
  108. package/lib/types/state-machine/softphone-state-machine.d.ts.map +1 -0
  109. package/lib/types/state-machine/utils.d.ts +9 -0
  110. package/lib/types/state-machine/utils.d.ts.map +1 -0
  111. package/lib/types/utils/api-requester.d.ts.map +1 -1
  112. package/lib/types/utils/sdp.d.ts +6 -0
  113. package/lib/types/utils/sdp.d.ts.map +1 -1
  114. package/lib/types/utils/sip-logger.d.ts +4 -0
  115. package/lib/types/utils/sip-logger.d.ts.map +1 -0
  116. package/lib/types/utils/webrtc.d.ts +40 -0
  117. package/lib/types/utils/webrtc.d.ts.map +1 -1
  118. package/lib/types/voice/call.d.ts +110 -0
  119. package/lib/types/voice/call.d.ts.map +1 -0
  120. package/lib/types/voice/softphone.d.ts +77 -0
  121. package/lib/types/voice/softphone.d.ts.map +1 -0
  122. package/lib/types/web-rtc-client.d.ts +1 -36
  123. package/lib/types/web-rtc-client.d.ts.map +1 -1
  124. package/lib/utils/__tests__/api-requester.test.js +0 -17
  125. package/lib/utils/api-requester.js +1 -9
  126. package/lib/utils/sdp.js +27 -1
  127. package/lib/utils/sip-logger.js +37 -0
  128. package/lib/utils/webrtc.js +521 -1
  129. package/lib/voice/call.js +577 -0
  130. package/lib/voice/softphone.js +375 -0
  131. package/lib/web-rtc-client.js +89 -601
  132. package/package.json +3 -2
  133. package/src/__tests__/__voice__/call.test.ts +90 -0
  134. package/src/__tests__/__voice__/softphone.test.ts +82 -0
  135. package/src/__tests__/api-client.test.ts +1 -22
  136. package/src/api/auth.ts +3 -25
  137. package/src/checker/checks/webrtc.ts +2 -1
  138. package/src/domain/InvalidState.ts +13 -0
  139. package/src/domain/InvalidStateTransition.ts +17 -0
  140. package/src/domain/Phone/WebRTCPhone.ts +34 -36
  141. package/src/domain/types.ts +6 -1
  142. package/src/simple/Auth.ts +13 -6
  143. package/src/simple/Phone.ts +2 -1
  144. package/src/simple/__tests__/Auth.test.ts +87 -9
  145. package/src/simple/index.ts +9 -2
  146. package/src/simple/room/Room.ts +2 -1
  147. package/src/simple/room/SipRoom.ts +2 -1
  148. package/src/state-machine/call-state-machine.ts +131 -0
  149. package/src/state-machine/softphone-state-machine.ts +49 -0
  150. package/src/state-machine/utils.ts +53 -0
  151. package/src/utils/__tests__/api-requester.test.ts +0 -20
  152. package/src/utils/api-requester.ts +1 -9
  153. package/src/utils/sdp.ts +36 -0
  154. package/src/utils/sip-logger.ts +40 -0
  155. package/src/utils/webrtc.ts +571 -0
  156. package/src/voice/call.ts +713 -0
  157. package/src/voice/softphone.ts +485 -0
  158. package/src/web-rtc-client.ts +90 -690
@@ -0,0 +1,347 @@
1
+ /* eslint-disable no-underscore-dangle */
2
+ import { EventEmitter } from 'events';
3
+ import { createActor } from 'xstate';
4
+ import InvalidState from '../domain/InvalidState';
5
+ import Wazo from '..';
6
+ import softphoneStateMachine, { Actions, States } from '../state-machine/softphone-state-machine';
7
+ import { Actions as CallActions } from '../state-machine/call-state-machine';
8
+ import WazoWebRTCClient from '../web-rtc-client';
9
+ import IssueReporter from '../service/IssueReporter';
10
+ import configureLogger from '../utils/sip-logger';
11
+ import Call from './call';
12
+ import { assertCan, can, getState, waitUntilState } from '../state-machine/utils';
13
+ export const EVENT_INCOMING = 'incoming';
14
+ export const EVENT_HEARTBEAT = 'heartbeat';
15
+ export const EVENT_HEARTBEAT_TIMEOUT = 'heartbeatTimeout';
16
+ export const EVENT_REGISTERED = 'registered';
17
+ export const EVENT_UNREGISTERED = 'unregistered';
18
+ export const EVENT_DISCONNECTED = 'disconnected';
19
+ export const EVENT_VIDEO_INPUT_CHANGE = 'videoInputChange';
20
+ export const EVENT_ON_MESSAGE = 'message';
21
+ export const EVENT_ON_CHAT = 'phone/ON_CHAT';
22
+ export const EVENT_ON_SIGNAL = 'phone/ON_SIGNAL';
23
+ export const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
24
+ export const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
25
+ const logger = IssueReporter.loggerFor('softphone');
26
+ export class Softphone extends EventEmitter {
27
+ audioOutputDeviceId;
28
+ audioRingDeviceId;
29
+ audioOutputVolume;
30
+ audioRingVolume;
31
+ eventEmitter;
32
+ calls;
33
+ client;
34
+ session;
35
+ sipLine;
36
+ softphoneActor;
37
+ options;
38
+ shouldSendReinvite;
39
+ constructor() {
40
+ super();
41
+ this.calls = [];
42
+ this.softphoneActor = createActor(softphoneStateMachine);
43
+ this.softphoneActor.start();
44
+ }
45
+ connect(options = {}) {
46
+ this.calls = [];
47
+ this.options = options;
48
+ this.audioOutputVolume = 1;
49
+ this.audioRingVolume = 1;
50
+ const server = Wazo.Auth.getHost();
51
+ const session = Wazo.Auth.getSession();
52
+ if (!server || !session) {
53
+ throw new Error('Please connect to the server using `Wazo.Auth.logIn` or `Wazo.Auth.authenticate` before using Room.connect().');
54
+ }
55
+ this.session = session;
56
+ this.sipLine = this.getPrimaryWebRtcLine();
57
+ if (!this.sipLine) {
58
+ throw new Error('Sorry, no sip lines found for this user');
59
+ }
60
+ this.options.userUuid = session.uuid || '';
61
+ return this.connectWithCredentials(server, this.sipLine, session.displayName(), options);
62
+ }
63
+ async disconnect() {
64
+ assertCan(this.softphoneActor, Actions.UNREGISTER);
65
+ if (!this.client) {
66
+ return null;
67
+ }
68
+ // Terminate all calls
69
+ await Promise.all(this.calls.map(call => call.hangup()));
70
+ return this.client.unregister();
71
+ }
72
+ getPrimaryWebRtcLine() {
73
+ return this.session?.primaryWebRtcLine() || null;
74
+ }
75
+ async connectWithCredentials(server, sipLine, displayName, rawOptions = {}) {
76
+ assertCan(this.softphoneActor, Actions.REGISTER);
77
+ this.softphoneActor.send({ type: Actions.REGISTER });
78
+ const [host, port = 443] = server.split(':');
79
+ let options = { ...rawOptions };
80
+ options.media = options.media || {
81
+ audio: true,
82
+ video: false,
83
+ };
84
+ options.uaConfigOverrides = options.uaConfigOverrides || {};
85
+ if (IssueReporter.enabled) {
86
+ options = configureLogger(options);
87
+ }
88
+ this.client = new WazoWebRTCClient({
89
+ host,
90
+ port: typeof port === 'string' ? parseInt(port, 10) : port,
91
+ displayName,
92
+ authorizationUser: sipLine.username,
93
+ password: sipLine.secret,
94
+ uri: `${sipLine.username}@${server}`,
95
+ ...options,
96
+ }, undefined, options.uaConfigOverrides);
97
+ this._bindEvents();
98
+ return this.client.register().catch(error => {
99
+ // Avoid exception on `t.server.scheme` in sip transport when losing the webrtc socket connection
100
+ logger.error('softphone - register error', { message: error.message, stack: error.stack });
101
+ this._sendAction(Actions.UNREGISTER);
102
+ });
103
+ }
104
+ reconnect() {
105
+ logger.info('softphone - reconnect', { client: !!this.client });
106
+ if (!this.client) {
107
+ return;
108
+ }
109
+ this.client.attemptReconnection();
110
+ }
111
+ async call(options) {
112
+ logger.info('softphone - call', options);
113
+ if (!options.params.To) {
114
+ logger.warn('softphone - calling with empty number, bailing.');
115
+ return Promise.resolve(null);
116
+ }
117
+ if (this.getState() !== States.UNREGISTERED) {
118
+ throw new InvalidState(`Invalid state ${States.UNREGISTERED}`, States.UNREGISTERED);
119
+ }
120
+ if (this.getState() !== States.REGISTERING) {
121
+ logger.info('softphone - calling when registering, waiting for Softphone to be registered ...');
122
+ await waitUntilState(this.softphoneActor, States.REGISTERED);
123
+ }
124
+ // Hold other calls
125
+ this.holdAllCalls();
126
+ let sipCall;
127
+ try {
128
+ sipCall = this.client.call(options.params.To, options.withCamera, options.audioOnly, options.conference, options);
129
+ const call = new Call(sipCall, this);
130
+ return call;
131
+ }
132
+ catch (error) {
133
+ logger.warn('softphone - call, error', { message: error.message, stack: error.stack });
134
+ return Promise.resolve(null);
135
+ }
136
+ }
137
+ removeCall(callToRemove) {
138
+ this.calls = this.calls.filter((call) => call.id !== callToRemove.id);
139
+ }
140
+ holdAllCalls(exceptCall = null) {
141
+ this.calls.filter(call => !call.isHeld() && call.id === exceptCall?.id).forEach(call => call.hold());
142
+ }
143
+ startHeartbeat() {
144
+ logger.info('softphone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client.hasHeartbeat() });
145
+ if (!this.client || this.client.hasHeartbeat()) {
146
+ return;
147
+ }
148
+ this.client.startHeartbeat();
149
+ }
150
+ stopHeartbeat() {
151
+ logger.info('softphone - stop heartbeat', { client: !!this.client });
152
+ if (!this.client) {
153
+ return;
154
+ }
155
+ this.client.stopHeartbeat();
156
+ }
157
+ setMediaConstraints(media) {
158
+ this.client.setMediaConstraints(media);
159
+ }
160
+ changeAudioOutputDevice(id) {
161
+ logger.info('softphone - change audio device', { deviceId: id });
162
+ this.audioOutputDeviceId = id;
163
+ return this.client.changeAudioOutputDevice(id);
164
+ }
165
+ changeAudioInputDevice(id, force) {
166
+ logger.info('softphone - changeAudio input device', { deviceId: id });
167
+ const currentCall = this.getCurrentCall();
168
+ return this.client.changeAudioInputDevice(id, currentCall?.sipCall, force);
169
+ }
170
+ changeVideoInputDevice(id) {
171
+ logger.info('softphone - change video input device', { deviceId: id });
172
+ const currentCall = this.getCurrentCall();
173
+ return this.client.changeVideoInputDevice(id, currentCall?.sipCall);
174
+ }
175
+ changeRingDevice(id) {
176
+ logger.info('softphone - changing ring device', { id });
177
+ this.audioRingDeviceId = id;
178
+ }
179
+ hasSfu() {
180
+ return this.sipLine?.hasVideoConference() || false;
181
+ }
182
+ // volume is a value between 0 and 1
183
+ changeAudioVolume(volume) {
184
+ logger.info('softphone - changing audio volume', { volume });
185
+ this.audioOutputVolume = volume;
186
+ this.client.changeAudioOutputVolume(volume);
187
+ }
188
+ // volume is a value between 0 and 1
189
+ changeRingVolume(volume) {
190
+ logger.info('softphone - changing ring volume', { volume });
191
+ this.audioRingVolume = volume;
192
+ }
193
+ getCalls() {
194
+ return this.calls;
195
+ }
196
+ getCurrentCall() {
197
+ return this.calls.find(call => call.isEstablished());
198
+ }
199
+ getState() {
200
+ return this.softphoneActor.getSnapshot().value;
201
+ }
202
+ getUserAgent() {
203
+ return this.client?.config?.userAgentString || 'softphone';
204
+ }
205
+ _bindEvents() {
206
+ this.client.on(this.client.INVITE, (sipSession) => {
207
+ const call = new Call(sipSession, this);
208
+ call._sendAction(CallActions.INCOMING_CALL);
209
+ this.calls.push(call);
210
+ this.eventEmitter.emit(EVENT_INCOMING, call);
211
+ });
212
+ this.client.on(this.client.ON_REINVITE, (sipCall, request, updatedCalleeName, updatedNumber, hadRemoteVideo) => {
213
+ logger.info('softphone - on reinvite', {
214
+ callId: sipCall.id,
215
+ inviteId: request.callId,
216
+ updatedCalleeName,
217
+ updatedNumber,
218
+ hadRemoteVideo,
219
+ });
220
+ this._onCallEvent(sipCall, 'onReinvite', request, updatedCalleeName, updatedNumber, hadRemoteVideo);
221
+ });
222
+ this.client.on(this.client.ACCEPTED, async (sipCall) => {
223
+ this._onCallEvent(sipCall, 'onAccepted');
224
+ if (this.audioOutputDeviceId) {
225
+ await this.client.changeAudioOutputDevice(this.audioOutputDeviceId);
226
+ }
227
+ });
228
+ this.client.on(this.client.ON_ERROR, (e, sipCall) => {
229
+ this._onCallEvent(sipCall, 'onError', e);
230
+ });
231
+ this.client.on(this.client.REJECTED, (sipCall) => {
232
+ this._onCallEvent(sipCall, 'onRejected');
233
+ });
234
+ this.client.on(this.client.ON_PROGRESS, (sipCall) => {
235
+ this._onCallEvent(sipCall, 'onProgress');
236
+ });
237
+ this.client.on(this.client.ON_EARLY_MEDIA, (sipCall) => {
238
+ this._onCallEvent(sipCall, 'onEarlyMedia');
239
+ });
240
+ this.client.on(this.client.ON_TRACK, (sipCall, event) => {
241
+ this._onCallEvent(sipCall, 'onTrack', event);
242
+ });
243
+ this.client.on(this.client.ON_NETWORK_STATS, (sipCall, stats, previousStats) => {
244
+ this._onCallEvent(sipCall, 'onNetworkStats', stats, previousStats);
245
+ });
246
+ // Used when upgrading directly in screenshare mode
247
+ this.client.on(this.client.ON_SCREEN_SHARING_REINVITE, (sipCall, response, desktop) => {
248
+ this._onCallEvent(sipCall, 'onScreenshareReinvite', response, desktop);
249
+ });
250
+ this.client.on(this.client.UNREGISTERED, () => {
251
+ logger.info('softphone - unregistered');
252
+ this.eventEmitter.emit(EVENT_UNREGISTERED);
253
+ this._sendAction(Actions.UNREGISTERED);
254
+ });
255
+ this.client.on(this.client.ON_DISCONNECTED, () => {
256
+ logger.info('softphone - disconnected');
257
+ this.eventEmitter.emit(EVENT_DISCONNECTED);
258
+ this._sendAction(Actions.TRANSPORT_CLOSED);
259
+ });
260
+ this.client.on(this.client.REGISTERED, () => {
261
+ logger.info('softphone - registered', { state: getState(this.softphoneActor) });
262
+ if (!can(this.softphoneActor, Actions.REGISTER_DONE)) {
263
+ logger.warn('softphone - registered but not in REGISTERING state', { state: getState(this.softphoneActor) });
264
+ return;
265
+ }
266
+ this.stopHeartbeat();
267
+ this._sendAction(Actions.REGISTER_DONE);
268
+ this.eventEmitter.emit(EVENT_REGISTERED);
269
+ // If the phone registered with a current callSession (eg: when switching network):
270
+ // send a reinvite to renegociate ICE with new IP
271
+ if (this.shouldSendReinvite) {
272
+ this.shouldSendReinvite = false;
273
+ // Send reinvite for all active calls
274
+ this.calls.filter(call => call.isEstablished())
275
+ .forEach(call => { call.sendReinvite({ conference: call.isConference(), iceRestart: true }); });
276
+ }
277
+ });
278
+ this.client.on(this.client.CONNECTED, () => {
279
+ logger.info('softphone - connected');
280
+ this.stopHeartbeat();
281
+ });
282
+ this.client.on(this.client.DISCONNECTED, () => {
283
+ logger.info('softphone - disconnected');
284
+ this.eventEmitter.emit(EVENT_DISCONNECTED);
285
+ // Do not trigger heartbeat if already running
286
+ if (!this.client.hasHeartbeat()) {
287
+ this.startHeartbeat();
288
+ }
289
+ // Tell to send reinvite when reconnecting
290
+ this.shouldSendReinvite = this.calls.length > 0;
291
+ });
292
+ this.client.on('onVideoInputChange', stream => {
293
+ this.eventEmitter.emit(EVENT_VIDEO_INPUT_CHANGE, stream);
294
+ });
295
+ this.client.on(this.client.MESSAGE, (message) => {
296
+ this._onMessage(message);
297
+ this.eventEmitter.emit(EVENT_ON_MESSAGE, message);
298
+ });
299
+ this.client.setOnHeartbeatTimeout(() => {
300
+ this.eventEmitter.emit(EVENT_HEARTBEAT_TIMEOUT);
301
+ });
302
+ this.client.setOnHeartbeatCallback(() => {
303
+ this.eventEmitter.emit(EVENT_HEARTBEAT);
304
+ });
305
+ }
306
+ _sendAction(action) {
307
+ this.softphoneActor.send({ type: action });
308
+ }
309
+ _getCall(sipCall) {
310
+ return this.calls.find(call => call.id === sipCall.id);
311
+ }
312
+ _onCallEvent(sipCall, eventName, ...args) {
313
+ logger.warn('softphone - received call event', { eventName, sipId: sipCall.id });
314
+ const call = this._getCall(sipCall);
315
+ if (!call) {
316
+ logger.warn('softphone - no call found to send the event', { eventName, sipId: sipCall.id });
317
+ return;
318
+ }
319
+ // @ts-ignore
320
+ call[eventName](...args);
321
+ }
322
+ _onMessage(message) {
323
+ if (!message || message.method !== 'MESSAGE') {
324
+ return;
325
+ }
326
+ let body;
327
+ try {
328
+ body = JSON.parse(message.body || '');
329
+ }
330
+ catch (e) {
331
+ return;
332
+ }
333
+ const { type, content, } = body;
334
+ switch (type) {
335
+ case MESSAGE_TYPE_CHAT:
336
+ this.eventEmitter.emit(EVENT_ON_CHAT, content);
337
+ break;
338
+ case MESSAGE_TYPE_SIGNAL:
339
+ {
340
+ this.eventEmitter.emit(EVENT_ON_SIGNAL, content);
341
+ break;
342
+ }
343
+ default:
344
+ }
345
+ }
346
+ }
347
+ export default new Softphone();