@wazo/sdk 1.0.0-alpha.0 → 1.0.0-alpha.10
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.
- package/README.md +16 -7
- package/dist/wazo-sdk.js +6 -6
- package/esm/__tests__/__voice__/call.test.js +57 -2
- package/esm/__tests__/api-client.test.js +20 -1
- package/esm/api/auth.js +16 -2
- package/esm/checker/checks/webrtc.js +2 -2
- package/esm/domain/CallLog.js +2 -3
- package/esm/domain/Phone/CTIPhone.js +2 -2
- package/esm/domain/Phone/WebRTCPhone.js +64 -63
- package/esm/index.js +5 -1
- package/esm/service/CallApi.js +4 -4
- package/esm/simple/Auth.js +19 -15
- package/esm/simple/Phone.js +6 -5
- package/esm/simple/__tests__/Auth.test.js +8 -64
- package/esm/simple/index.js +2 -1
- package/esm/simple/room/Room.js +2 -2
- package/esm/simple/room/SipRoom.js +2 -2
- package/esm/state-machine/call-state-machine.js +2 -2
- package/esm/state-machine/softphone-state-machine.js +1 -2
- package/esm/state-machine/utils.js +8 -3
- package/esm/types/api/auth.d.ts +3 -0
- package/esm/types/api/auth.d.ts.map +1 -1
- package/esm/types/checker/checks/index.d.ts +1 -1
- package/esm/types/checker/checks/webrtc-transport.d.ts +2 -2
- package/esm/types/checker/checks/webrtc-transport.d.ts.map +1 -1
- package/esm/types/domain/CallLog.d.ts.map +1 -1
- package/esm/types/domain/CallSession.d.ts +3 -3
- package/esm/types/domain/CallSession.d.ts.map +1 -1
- package/esm/types/domain/Phone/CTIPhone.d.ts.map +1 -1
- package/esm/types/domain/Phone/WebRTCPhone.d.ts +22 -22
- package/esm/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
- package/esm/types/domain/types.d.ts +0 -4
- package/esm/types/domain/types.d.ts.map +1 -1
- package/esm/types/index.d.ts +5 -1
- package/esm/types/index.d.ts.map +1 -1
- package/esm/types/lib/WazoSessionDescriptionHandler.d.ts +3 -3
- package/esm/types/lib/WazoSessionDescriptionHandler.d.ts.map +1 -1
- package/esm/types/service/CallApi.d.ts +5 -5
- package/esm/types/service/CallApi.d.ts.map +1 -1
- package/esm/types/simple/Auth.d.ts +6 -1
- package/esm/types/simple/Auth.d.ts.map +1 -1
- package/esm/types/simple/Phone.d.ts +8 -8
- package/esm/types/simple/Phone.d.ts.map +1 -1
- package/esm/types/simple/index.d.ts +3 -1
- package/esm/types/simple/index.d.ts.map +1 -1
- package/esm/types/state-machine/softphone-state-machine.d.ts +1 -2
- package/esm/types/state-machine/softphone-state-machine.d.ts.map +1 -1
- package/esm/types/state-machine/utils.d.ts +2 -2
- package/esm/types/state-machine/utils.d.ts.map +1 -1
- package/esm/types/utils/api-requester.d.ts.map +1 -1
- package/esm/types/utils/sdp.d.ts +3 -2
- package/esm/types/utils/sdp.d.ts.map +1 -1
- package/esm/types/utils/webrtc.d.ts +1 -0
- package/esm/types/utils/webrtc.d.ts.map +1 -1
- package/esm/types/voice/call.d.ts +30 -12
- package/esm/types/voice/call.d.ts.map +1 -1
- package/esm/types/voice/softphone.d.ts +25 -13
- package/esm/types/voice/softphone.d.ts.map +1 -1
- package/esm/types/web-rtc-client.d.ts +39 -38
- package/esm/types/web-rtc-client.d.ts.map +1 -1
- package/esm/utils/__tests__/api-requester.test.js +17 -0
- package/esm/utils/api-requester.js +9 -1
- package/esm/utils/sdp.js +22 -9
- package/esm/utils/webrtc.js +24 -4
- package/esm/voice/call.js +130 -38
- package/esm/voice/softphone.js +145 -35
- package/esm/web-rtc-client.js +61 -58
- package/lib/__tests__/__voice__/call.test.js +56 -1
- package/lib/__tests__/api-client.test.js +20 -1
- package/lib/api/auth.js +16 -2
- package/lib/checker/checks/webrtc.js +1 -1
- package/lib/domain/CallLog.js +2 -3
- package/lib/domain/Phone/CTIPhone.js +2 -2
- package/lib/domain/Phone/WebRTCPhone.js +63 -62
- package/lib/index.js +11 -3
- package/lib/service/CallApi.js +2 -2
- package/lib/simple/Auth.js +21 -15
- package/lib/simple/Phone.js +3 -2
- package/lib/simple/__tests__/Auth.test.js +11 -64
- package/lib/simple/index.js +2 -1
- package/lib/simple/room/Room.js +1 -1
- package/lib/simple/room/SipRoom.js +1 -1
- package/lib/state-machine/call-state-machine.js +2 -2
- package/lib/state-machine/softphone-state-machine.js +1 -2
- package/lib/state-machine/utils.js +8 -3
- package/lib/types/api/auth.d.ts +3 -0
- package/lib/types/api/auth.d.ts.map +1 -1
- package/lib/types/checker/checks/index.d.ts +1 -1
- package/lib/types/checker/checks/webrtc-transport.d.ts +2 -2
- package/lib/types/checker/checks/webrtc-transport.d.ts.map +1 -1
- package/lib/types/domain/CallLog.d.ts.map +1 -1
- package/lib/types/domain/CallSession.d.ts +3 -3
- package/lib/types/domain/CallSession.d.ts.map +1 -1
- package/lib/types/domain/Phone/CTIPhone.d.ts.map +1 -1
- package/lib/types/domain/Phone/WebRTCPhone.d.ts +22 -22
- package/lib/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
- package/lib/types/domain/types.d.ts +0 -4
- package/lib/types/domain/types.d.ts.map +1 -1
- package/lib/types/index.d.ts +5 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/lib/WazoSessionDescriptionHandler.d.ts +3 -3
- package/lib/types/lib/WazoSessionDescriptionHandler.d.ts.map +1 -1
- package/lib/types/service/CallApi.d.ts +5 -5
- package/lib/types/service/CallApi.d.ts.map +1 -1
- package/lib/types/simple/Auth.d.ts +6 -1
- package/lib/types/simple/Auth.d.ts.map +1 -1
- package/lib/types/simple/Phone.d.ts +8 -8
- package/lib/types/simple/Phone.d.ts.map +1 -1
- package/lib/types/simple/index.d.ts +3 -1
- package/lib/types/simple/index.d.ts.map +1 -1
- package/lib/types/state-machine/softphone-state-machine.d.ts +1 -2
- package/lib/types/state-machine/softphone-state-machine.d.ts.map +1 -1
- package/lib/types/state-machine/utils.d.ts +2 -2
- package/lib/types/state-machine/utils.d.ts.map +1 -1
- package/lib/types/utils/api-requester.d.ts.map +1 -1
- package/lib/types/utils/sdp.d.ts +3 -2
- package/lib/types/utils/sdp.d.ts.map +1 -1
- package/lib/types/utils/webrtc.d.ts +1 -0
- package/lib/types/utils/webrtc.d.ts.map +1 -1
- package/lib/types/voice/call.d.ts +30 -12
- package/lib/types/voice/call.d.ts.map +1 -1
- package/lib/types/voice/softphone.d.ts +25 -13
- package/lib/types/voice/softphone.d.ts.map +1 -1
- package/lib/types/web-rtc-client.d.ts +39 -38
- package/lib/types/web-rtc-client.d.ts.map +1 -1
- package/lib/utils/__tests__/api-requester.test.js +17 -0
- package/lib/utils/api-requester.js +9 -1
- package/lib/utils/sdp.js +25 -10
- package/lib/utils/webrtc.js +25 -4
- package/lib/voice/call.js +131 -36
- package/lib/voice/softphone.js +150 -35
- package/lib/web-rtc-client.js +59 -57
- package/package.json +1 -1
- package/src/__tests__/__voice__/call.test.ts +63 -2
- package/src/__tests__/api-client.test.ts +22 -1
- package/src/api/auth.ts +30 -3
- package/src/checker/checks/webrtc-transport.ts +2 -2
- package/src/checker/checks/webrtc.ts +2 -2
- package/src/domain/CallLog.ts +2 -3
- package/src/domain/CallSession.ts +3 -3
- package/src/domain/Phone/CTIPhone.ts +3 -2
- package/src/domain/Phone/WebRTCPhone.ts +95 -93
- package/src/domain/types.ts +0 -5
- package/src/index.ts +6 -1
- package/src/lib/WazoSessionDescriptionHandler.ts +3 -3
- package/src/service/CallApi.ts +7 -7
- package/src/simple/Auth.ts +21 -16
- package/src/simple/Phone.ts +12 -11
- package/src/simple/__tests__/Auth.test.ts +9 -87
- package/src/simple/index.ts +2 -1
- package/src/simple/room/Room.ts +3 -3
- package/src/simple/room/SipRoom.ts +3 -3
- package/src/state-machine/call-state-machine.ts +2 -2
- package/src/state-machine/softphone-state-machine.ts +1 -2
- package/src/state-machine/utils.ts +12 -5
- package/src/utils/__tests__/api-requester.test.ts +20 -0
- package/src/utils/api-requester.ts +9 -1
- package/src/utils/sdp.ts +26 -11
- package/src/utils/webrtc.ts +27 -5
- package/src/voice/call.ts +169 -50
- package/src/voice/softphone.ts +180 -41
- package/src/web-rtc-client.ts +106 -99
package/esm/voice/softphone.js
CHANGED
|
@@ -4,19 +4,24 @@ import { createActor } from 'xstate';
|
|
|
4
4
|
import InvalidState from '../domain/InvalidState';
|
|
5
5
|
import Wazo from '..';
|
|
6
6
|
import softphoneStateMachine, { Actions, States } from '../state-machine/softphone-state-machine';
|
|
7
|
-
import { Actions as CallActions } from '../state-machine/call-state-machine';
|
|
8
7
|
import WazoWebRTCClient from '../web-rtc-client';
|
|
9
8
|
import IssueReporter from '../service/IssueReporter';
|
|
10
9
|
import configureLogger from '../utils/sip-logger';
|
|
11
10
|
import Call from './call';
|
|
12
11
|
import { assertCan, can, getState, waitUntilState } from '../state-machine/utils';
|
|
12
|
+
import { getSipCallId } from '../utils/sdp';
|
|
13
13
|
export const EVENT_INCOMING = 'incoming';
|
|
14
|
+
export const EVENT_OUTGOING = 'outgoing';
|
|
14
15
|
export const EVENT_HEARTBEAT = 'heartbeat';
|
|
15
16
|
export const EVENT_HEARTBEAT_TIMEOUT = 'heartbeatTimeout';
|
|
16
17
|
export const EVENT_REGISTERED = 'registered';
|
|
17
18
|
export const EVENT_UNREGISTERED = 'unregistered';
|
|
18
19
|
export const EVENT_DISCONNECTED = 'disconnected';
|
|
19
20
|
export const EVENT_VIDEO_INPUT_CHANGE = 'videoInputChange';
|
|
21
|
+
export const EVENT_TERMINATE_SOUND = 'terminateSound';
|
|
22
|
+
export const EVENT_PLAY_HANGUP_SOUND = 'playHangupSound';
|
|
23
|
+
export const EVENT_PLAY_RING_SOUND = 'playRingSound';
|
|
24
|
+
export const EVENT_PLAY_INBOUND_CALL_SOUND = 'playInboundCallSound';
|
|
20
25
|
export const EVENT_ON_MESSAGE = 'message';
|
|
21
26
|
export const EVENT_ON_CHAT = 'phone/ON_CHAT';
|
|
22
27
|
export const EVENT_ON_SIGNAL = 'phone/ON_SIGNAL';
|
|
@@ -28,7 +33,6 @@ export class Softphone extends EventEmitter {
|
|
|
28
33
|
audioRingDeviceId;
|
|
29
34
|
audioOutputVolume;
|
|
30
35
|
audioRingVolume;
|
|
31
|
-
eventEmitter;
|
|
32
36
|
calls;
|
|
33
37
|
client;
|
|
34
38
|
session;
|
|
@@ -36,6 +40,7 @@ export class Softphone extends EventEmitter {
|
|
|
36
40
|
softphoneActor;
|
|
37
41
|
options;
|
|
38
42
|
shouldSendReinvite;
|
|
43
|
+
ringingEnabled = true;
|
|
39
44
|
constructor() {
|
|
40
45
|
super();
|
|
41
46
|
this.calls = [];
|
|
@@ -49,6 +54,7 @@ export class Softphone extends EventEmitter {
|
|
|
49
54
|
this.audioRingVolume = 1;
|
|
50
55
|
const server = Wazo.Auth.getHost();
|
|
51
56
|
const session = Wazo.Auth.getSession();
|
|
57
|
+
logger.info('softphone - connect', { server, session: !!session });
|
|
52
58
|
if (!server || !session) {
|
|
53
59
|
throw new Error('Please connect to the server using `Wazo.Auth.logIn` or `Wazo.Auth.authenticate` before using Room.connect().');
|
|
54
60
|
}
|
|
@@ -60,13 +66,17 @@ export class Softphone extends EventEmitter {
|
|
|
60
66
|
this.options.userUuid = session.uuid || '';
|
|
61
67
|
return this.connectWithCredentials(server, this.sipLine, session.displayName(), options);
|
|
62
68
|
}
|
|
69
|
+
async hangupAllCalls() {
|
|
70
|
+
return Promise.all(this.calls.map(call => call.hangup()));
|
|
71
|
+
}
|
|
63
72
|
async disconnect() {
|
|
64
73
|
assertCan(this.softphoneActor, Actions.UNREGISTER);
|
|
65
74
|
if (!this.client) {
|
|
75
|
+
logger.info('softphone - disconnect, not client to disconnect, bailing');
|
|
66
76
|
return null;
|
|
67
77
|
}
|
|
68
78
|
// Terminate all calls
|
|
69
|
-
await
|
|
79
|
+
await this.hangupAllCalls();
|
|
70
80
|
return this.client.unregister();
|
|
71
81
|
}
|
|
72
82
|
getPrimaryWebRtcLine() {
|
|
@@ -74,7 +84,8 @@ export class Softphone extends EventEmitter {
|
|
|
74
84
|
}
|
|
75
85
|
async connectWithCredentials(server, sipLine, displayName, rawOptions = {}) {
|
|
76
86
|
assertCan(this.softphoneActor, Actions.REGISTER);
|
|
77
|
-
|
|
87
|
+
logger.info('softphone - connect with credentials', { server, username: sipLine.username, displayName, options: rawOptions });
|
|
88
|
+
this._sendAction(Actions.REGISTER);
|
|
78
89
|
const [host, port = 443] = server.split(':');
|
|
79
90
|
let options = { ...rawOptions };
|
|
80
91
|
options.media = options.media || {
|
|
@@ -114,19 +125,22 @@ export class Softphone extends EventEmitter {
|
|
|
114
125
|
logger.warn('softphone - calling with empty number, bailing.');
|
|
115
126
|
return Promise.resolve(null);
|
|
116
127
|
}
|
|
117
|
-
if (this.
|
|
118
|
-
throw new InvalidState(`Invalid state ${States.UNREGISTERED}`, States.UNREGISTERED);
|
|
119
|
-
}
|
|
120
|
-
if (this.getState() !== States.REGISTERING) {
|
|
128
|
+
if (this.state === States.REGISTERING) {
|
|
121
129
|
logger.info('softphone - calling when registering, waiting for Softphone to be registered ...');
|
|
122
130
|
await waitUntilState(this.softphoneActor, States.REGISTERED);
|
|
123
131
|
}
|
|
132
|
+
if (this.state !== States.REGISTERED) {
|
|
133
|
+
throw new InvalidState(`Invalid state ${States.UNREGISTERED}`, States.UNREGISTERED);
|
|
134
|
+
}
|
|
124
135
|
// Hold other calls
|
|
125
136
|
this.holdAllCalls();
|
|
126
137
|
let sipCall;
|
|
127
138
|
try {
|
|
128
139
|
sipCall = this.client.call(options.params.To, options.withCamera, options.audioOnly, options.conference, options);
|
|
129
140
|
const call = new Call(sipCall, this);
|
|
141
|
+
call.onMakeCall();
|
|
142
|
+
this.calls.push(call);
|
|
143
|
+
this.emit(EVENT_OUTGOING, call);
|
|
130
144
|
return call;
|
|
131
145
|
}
|
|
132
146
|
catch (error) {
|
|
@@ -137,11 +151,64 @@ export class Softphone extends EventEmitter {
|
|
|
137
151
|
removeCall(callToRemove) {
|
|
138
152
|
this.calls = this.calls.filter((call) => call.id !== callToRemove.id);
|
|
139
153
|
}
|
|
154
|
+
onCallTerminated(call) {
|
|
155
|
+
logger.info('softphone - on call terminated', { id: call.id });
|
|
156
|
+
const currentCall = this.getCurrentCall();
|
|
157
|
+
const isCurrentCall = currentCall?.id === call.id;
|
|
158
|
+
const isRinging = call.isRinging();
|
|
159
|
+
const isCurrentIncomingCall = isCurrentCall && isRinging;
|
|
160
|
+
const incomingCalls = this.getIncomingCalls();
|
|
161
|
+
const nbIncomingCalls = incomingCalls.length;
|
|
162
|
+
// Send an event to terminate ringing sound
|
|
163
|
+
if (isCurrentIncomingCall) {
|
|
164
|
+
setTimeout(() => {
|
|
165
|
+
// Avoid race condition when the other is calling and hanging up immediately
|
|
166
|
+
this.emit(EVENT_TERMINATE_SOUND, call, 'call terminated');
|
|
167
|
+
}, 5);
|
|
168
|
+
}
|
|
169
|
+
// If the terminated call was an incoming call, we have to re-trigger if it's was the first incoming call
|
|
170
|
+
// Otherwise, we have to re-trigger an incoming call event if another call is incoming
|
|
171
|
+
const shouldRetrigger = isCurrentCall ? nbIncomingCalls : isCurrentIncomingCall;
|
|
172
|
+
// Re-trigger incoming call event for remaining incoming calls
|
|
173
|
+
logger.info('Softphone - check to re-trigger incoming call', { shouldRetrigger, nbIncomingCalls });
|
|
174
|
+
if (shouldRetrigger && nbIncomingCalls > 1) {
|
|
175
|
+
const nextCall = incomingCalls.find(c => c.id !== call.id);
|
|
176
|
+
// Avoid race condition
|
|
177
|
+
setTimeout(() => {
|
|
178
|
+
if (this.ringingEnabled) {
|
|
179
|
+
if (currentCall) {
|
|
180
|
+
this.emit(EVENT_PLAY_RING_SOUND, this.audioRingDeviceId, this.audioRingVolume, nextCall);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
this.emit(EVENT_PLAY_INBOUND_CALL_SOUND, this.audioOutputDeviceId, this.audioOutputVolume, nextCall);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
this.emit(EVENT_INCOMING, nextCall);
|
|
187
|
+
}, 100);
|
|
188
|
+
}
|
|
189
|
+
// @ts-ignore: does not exist
|
|
190
|
+
if (!call.sipCall.isCanceled) {
|
|
191
|
+
setTimeout(() => {
|
|
192
|
+
this.emit(EVENT_PLAY_HANGUP_SOUND, this.audioOutputDeviceId, this.audioOutputVolume, call);
|
|
193
|
+
}, 10);
|
|
194
|
+
}
|
|
195
|
+
this.client.onCallEnded(call.sipCall);
|
|
196
|
+
this.removeCall(call);
|
|
197
|
+
}
|
|
198
|
+
enableRinging() {
|
|
199
|
+
logger.info('softphone - enable ringing');
|
|
200
|
+
this.ringingEnabled = true;
|
|
201
|
+
}
|
|
202
|
+
disableRinging() {
|
|
203
|
+
logger.info('softphone - disable ringing');
|
|
204
|
+
this.ringingEnabled = false;
|
|
205
|
+
}
|
|
140
206
|
holdAllCalls(exceptCall = null) {
|
|
141
|
-
|
|
207
|
+
logger.info('softphone - hold all calls', { exceptId: exceptCall?.id, ids: this.calls.map(call => call.id) });
|
|
208
|
+
this.calls.filter(call => !call.isHeld() && call.id !== exceptCall?.id).forEach(call => call.hold());
|
|
142
209
|
}
|
|
143
210
|
startHeartbeat() {
|
|
144
|
-
logger.info('softphone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client
|
|
211
|
+
logger.info('softphone - start heartbeat', { client: !!this.client, hasHeartbeat: this.client?.hasHeartbeat() });
|
|
145
212
|
if (!this.client || this.client.hasHeartbeat()) {
|
|
146
213
|
return;
|
|
147
214
|
}
|
|
@@ -190,28 +257,52 @@ export class Softphone extends EventEmitter {
|
|
|
190
257
|
logger.info('softphone - changing ring volume', { volume });
|
|
191
258
|
this.audioRingVolume = volume;
|
|
192
259
|
}
|
|
193
|
-
getCalls() {
|
|
194
|
-
return this.calls;
|
|
195
|
-
}
|
|
196
260
|
getCurrentCall() {
|
|
197
|
-
return this.
|
|
261
|
+
return this.getActiveCalls()[0];
|
|
262
|
+
}
|
|
263
|
+
getActiveCalls() {
|
|
264
|
+
return this.calls.filter(call => call.isEstablished());
|
|
198
265
|
}
|
|
199
|
-
|
|
200
|
-
return this.
|
|
266
|
+
getIncomingCalls() {
|
|
267
|
+
return this.calls.filter(call => call.isRinging());
|
|
268
|
+
}
|
|
269
|
+
get state() {
|
|
270
|
+
return getState(this.softphoneActor);
|
|
271
|
+
}
|
|
272
|
+
get user() {
|
|
273
|
+
return this.client?.userAgent?.contact?.uri?.user;
|
|
201
274
|
}
|
|
202
275
|
getUserAgent() {
|
|
203
276
|
return this.client?.config?.userAgentString || 'softphone';
|
|
204
277
|
}
|
|
278
|
+
isRegistering() {
|
|
279
|
+
return this.state === States.REGISTERING;
|
|
280
|
+
}
|
|
281
|
+
isRegistered() {
|
|
282
|
+
return this.state === States.REGISTERED;
|
|
283
|
+
}
|
|
284
|
+
isUnRegistered() {
|
|
285
|
+
return this.state === States.UNREGISTERED;
|
|
286
|
+
}
|
|
205
287
|
_bindEvents() {
|
|
206
288
|
this.client.on(this.client.INVITE, (sipSession) => {
|
|
207
289
|
const call = new Call(sipSession, this);
|
|
208
|
-
|
|
290
|
+
logger.info('softphone - on invite', { callId: call.id, number: call.number });
|
|
291
|
+
call.onCallIncoming();
|
|
209
292
|
this.calls.push(call);
|
|
210
|
-
this.
|
|
293
|
+
this.emit(EVENT_INCOMING, call);
|
|
294
|
+
if (!this.getCurrentCall()) {
|
|
295
|
+
if (this.ringingEnabled) {
|
|
296
|
+
this.emit(EVENT_PLAY_RING_SOUND, this.audioRingDeviceId, this.audioRingVolume, call);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
this.emit(EVENT_PLAY_INBOUND_CALL_SOUND, this.audioOutputDeviceId, this.audioOutputVolume, call);
|
|
301
|
+
}
|
|
211
302
|
});
|
|
212
303
|
this.client.on(this.client.ON_REINVITE, (sipCall, request, updatedCalleeName, updatedNumber, hadRemoteVideo) => {
|
|
213
304
|
logger.info('softphone - on reinvite', {
|
|
214
|
-
callId: sipCall
|
|
305
|
+
callId: getSipCallId(sipCall),
|
|
215
306
|
inviteId: request.callId,
|
|
216
307
|
updatedCalleeName,
|
|
217
308
|
updatedNumber,
|
|
@@ -220,6 +311,8 @@ export class Softphone extends EventEmitter {
|
|
|
220
311
|
this._onCallEvent(sipCall, 'onReinvite', request, updatedCalleeName, updatedNumber, hadRemoteVideo);
|
|
221
312
|
});
|
|
222
313
|
this.client.on(this.client.ACCEPTED, async (sipCall) => {
|
|
314
|
+
const call = this._getCall(sipCall);
|
|
315
|
+
this.emit(EVENT_TERMINATE_SOUND, call, 'call accepted');
|
|
223
316
|
this._onCallEvent(sipCall, 'onAccepted');
|
|
224
317
|
if (this.audioOutputDeviceId) {
|
|
225
318
|
await this.client.changeAudioOutputDevice(this.audioOutputDeviceId);
|
|
@@ -249,23 +342,31 @@ export class Softphone extends EventEmitter {
|
|
|
249
342
|
});
|
|
250
343
|
this.client.on(this.client.UNREGISTERED, () => {
|
|
251
344
|
logger.info('softphone - unregistered');
|
|
252
|
-
this.
|
|
253
|
-
|
|
345
|
+
if (!can(this.softphoneActor, Actions.UNREGISTER)) {
|
|
346
|
+
logger.warn('softphone - cannot unregister', { state: this.state });
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
this._sendAction(Actions.UNREGISTER);
|
|
350
|
+
this.emit(EVENT_UNREGISTERED);
|
|
254
351
|
});
|
|
255
352
|
this.client.on(this.client.ON_DISCONNECTED, () => {
|
|
256
353
|
logger.info('softphone - disconnected');
|
|
257
|
-
this.
|
|
354
|
+
if (!can(this.softphoneActor, Actions.TRANSPORT_CLOSED)) {
|
|
355
|
+
logger.warn('softphone - cannot disconnected', { state: this.state });
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
258
358
|
this._sendAction(Actions.TRANSPORT_CLOSED);
|
|
359
|
+
this.emit(EVENT_DISCONNECTED);
|
|
259
360
|
});
|
|
260
361
|
this.client.on(this.client.REGISTERED, () => {
|
|
261
362
|
logger.info('softphone - registered', { state: getState(this.softphoneActor) });
|
|
262
363
|
if (!can(this.softphoneActor, Actions.REGISTER_DONE)) {
|
|
263
|
-
logger.warn('softphone - registered but not in REGISTERING state', { state:
|
|
364
|
+
logger.warn('softphone - registered but not in REGISTERING state', { state: this.state });
|
|
264
365
|
return;
|
|
265
366
|
}
|
|
266
367
|
this.stopHeartbeat();
|
|
267
368
|
this._sendAction(Actions.REGISTER_DONE);
|
|
268
|
-
this.
|
|
369
|
+
this.emit(EVENT_REGISTERED);
|
|
269
370
|
// If the phone registered with a current callSession (eg: when switching network):
|
|
270
371
|
// send a reinvite to renegociate ICE with new IP
|
|
271
372
|
if (this.shouldSendReinvite) {
|
|
@@ -276,12 +377,16 @@ export class Softphone extends EventEmitter {
|
|
|
276
377
|
}
|
|
277
378
|
});
|
|
278
379
|
this.client.on(this.client.CONNECTED, () => {
|
|
279
|
-
logger.info('softphone - connected');
|
|
380
|
+
logger.info('softphone - connected', { state: this.state });
|
|
280
381
|
this.stopHeartbeat();
|
|
281
382
|
});
|
|
383
|
+
this.client.on(this.client.REGISTERING, () => {
|
|
384
|
+
logger.info('softphone - registering', { state: this.state });
|
|
385
|
+
this._sendAction(Actions.REGISTER);
|
|
386
|
+
});
|
|
282
387
|
this.client.on(this.client.DISCONNECTED, () => {
|
|
283
388
|
logger.info('softphone - disconnected');
|
|
284
|
-
this.
|
|
389
|
+
this.emit(EVENT_DISCONNECTED);
|
|
285
390
|
// Do not trigger heartbeat if already running
|
|
286
391
|
if (!this.client.hasHeartbeat()) {
|
|
287
392
|
this.startHeartbeat();
|
|
@@ -290,30 +395,35 @@ export class Softphone extends EventEmitter {
|
|
|
290
395
|
this.shouldSendReinvite = this.calls.length > 0;
|
|
291
396
|
});
|
|
292
397
|
this.client.on('onVideoInputChange', stream => {
|
|
293
|
-
this.
|
|
398
|
+
this.emit(EVENT_VIDEO_INPUT_CHANGE, stream);
|
|
294
399
|
});
|
|
295
400
|
this.client.on(this.client.MESSAGE, (message) => {
|
|
296
401
|
this._onMessage(message);
|
|
297
|
-
this.
|
|
402
|
+
this.emit(EVENT_ON_MESSAGE, message);
|
|
298
403
|
});
|
|
299
404
|
this.client.setOnHeartbeatTimeout(() => {
|
|
300
|
-
this.
|
|
405
|
+
this.emit(EVENT_HEARTBEAT_TIMEOUT);
|
|
301
406
|
});
|
|
302
407
|
this.client.setOnHeartbeatCallback(() => {
|
|
303
|
-
this.
|
|
408
|
+
this.emit(EVENT_HEARTBEAT);
|
|
304
409
|
});
|
|
305
410
|
}
|
|
306
411
|
_sendAction(action) {
|
|
412
|
+
const was = this.state;
|
|
307
413
|
this.softphoneActor.send({ type: action });
|
|
414
|
+
logger.trace('softphone - send action', { action, was, state: this.state });
|
|
308
415
|
}
|
|
309
416
|
_getCall(sipCall) {
|
|
310
|
-
return this.calls.find(call => call.id === sipCall
|
|
417
|
+
return this.calls.find(call => call.id === getSipCallId(sipCall));
|
|
418
|
+
}
|
|
419
|
+
_getCallIds() {
|
|
420
|
+
return this.calls.map(call => call.id);
|
|
311
421
|
}
|
|
312
422
|
_onCallEvent(sipCall, eventName, ...args) {
|
|
313
|
-
logger.
|
|
423
|
+
logger.info('softphone - received call event', { eventName, sipId: getSipCallId(sipCall) });
|
|
314
424
|
const call = this._getCall(sipCall);
|
|
315
425
|
if (!call) {
|
|
316
|
-
logger.warn('softphone - no call found to send the event', { eventName, sipId: sipCall.
|
|
426
|
+
logger.warn('softphone - no call found to send the event', { eventName, sipId: getSipCallId(sipCall), ids: this._getCallIds() });
|
|
317
427
|
return;
|
|
318
428
|
}
|
|
319
429
|
// @ts-ignore
|
|
@@ -333,11 +443,11 @@ export class Softphone extends EventEmitter {
|
|
|
333
443
|
const { type, content, } = body;
|
|
334
444
|
switch (type) {
|
|
335
445
|
case MESSAGE_TYPE_CHAT:
|
|
336
|
-
this.
|
|
446
|
+
this.emit(EVENT_ON_CHAT, content);
|
|
337
447
|
break;
|
|
338
448
|
case MESSAGE_TYPE_SIGNAL:
|
|
339
449
|
{
|
|
340
|
-
this.
|
|
450
|
+
this.emit(EVENT_ON_SIGNAL, content);
|
|
341
451
|
break;
|
|
342
452
|
}
|
|
343
453
|
default:
|