@wazo/sdk 0.37.30 → 0.37.34
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/dist/wazo-sdk.js +4 -4
- package/esm/__tests__/api-client.test.js +30 -0
- package/esm/__tests__/web-rtc-client.test.js +57 -6
- package/esm/api/calld.js +30 -0
- package/esm/api-client.js +30 -0
- package/esm/checker/Checker.js +57 -6
- package/esm/checker/checks/aor.js +30 -0
- package/esm/checker/checks/api.js +30 -0
- package/esm/checker/checks/index.js +57 -6
- package/esm/checker/checks/webrtc-transport.js +57 -6
- package/esm/checker/checks/webrtc.js +57 -6
- package/esm/domain/AdHocAPIConference.js +30 -0
- package/esm/domain/CallSession.js +9 -1
- package/esm/domain/Features.js +30 -0
- package/esm/domain/MeetingStatus.js +29 -0
- package/esm/domain/Phone/CTIPhone.js +39 -1
- package/esm/domain/Phone/WebRTCPhone.js +43 -8
- package/esm/domain/__tests__/CallSession.test.js +41 -5
- package/esm/domain/__tests__/IndirectTransfer.test.js +9 -1
- package/esm/domain/__tests__/Room.test.js +9 -1
- package/esm/index.js +100 -14
- package/esm/service/CallApi.js +30 -0
- package/esm/service/getApiClient.js +30 -0
- package/esm/simple/Auth.js +100 -14
- package/esm/simple/Configuration.js +100 -14
- package/esm/simple/Directory.js +30 -0
- package/esm/simple/Phone.js +100 -14
- package/esm/simple/index.js +100 -14
- package/esm/simple/room/LocalParticipant.js +100 -14
- package/esm/simple/room/Participant.js +100 -14
- package/esm/simple/room/RemoteParticipant.js +100 -14
- package/esm/simple/room/Room.js +100 -14
- package/esm/simple/room/SipRoom.js +100 -14
- package/esm/simple/room/Stream.js +100 -14
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +100 -14
- package/esm/simple/utils.js +100 -14
- package/esm/web-rtc-client.js +57 -6
- package/lib/__tests__/api-client.test.js +30 -0
- package/lib/__tests__/web-rtc-client.test.js +57 -6
- package/lib/api/calld.js +30 -0
- package/lib/api-client.js +30 -0
- package/lib/checker/Checker.js +57 -6
- package/lib/checker/checks/aor.js +30 -0
- package/lib/checker/checks/api.js +30 -0
- package/lib/checker/checks/index.js +57 -6
- package/lib/checker/checks/webrtc-transport.js +57 -6
- package/lib/checker/checks/webrtc.js +57 -6
- package/lib/domain/AdHocAPIConference.js +30 -0
- package/lib/domain/CallSession.js +9 -1
- package/lib/domain/Features.js +30 -0
- package/lib/domain/MeetingStatus.js +31 -0
- package/lib/domain/Phone/CTIPhone.js +39 -1
- package/lib/domain/Phone/WebRTCPhone.js +43 -8
- package/lib/domain/__tests__/CallSession.test.js +41 -5
- package/lib/domain/__tests__/IndirectTransfer.test.js +9 -1
- package/lib/domain/__tests__/Room.test.js +9 -1
- package/lib/index.js +100 -14
- package/lib/service/CallApi.js +30 -0
- package/lib/service/getApiClient.js +30 -0
- package/lib/simple/Auth.js +100 -14
- package/lib/simple/Configuration.js +100 -14
- package/lib/simple/Directory.js +30 -0
- package/lib/simple/Phone.js +100 -14
- package/lib/simple/index.js +100 -14
- package/lib/simple/room/LocalParticipant.js +100 -14
- package/lib/simple/room/Participant.js +100 -14
- package/lib/simple/room/RemoteParticipant.js +100 -14
- package/lib/simple/room/Room.js +100 -14
- package/lib/simple/room/SipRoom.js +100 -14
- package/lib/simple/room/Stream.js +100 -14
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +100 -14
- package/lib/simple/utils.js +100 -14
- package/lib/web-rtc-client.js +57 -6
- package/package.json +1 -1
- package/src/api/calld.js +3 -0
- package/src/domain/CallSession.js +9 -1
- package/src/domain/MeetingStatus.js +27 -0
- package/src/domain/Phone/WebRTCPhone.js +34 -7
- package/src/domain/__tests__/CallSession.test.js +32 -4
- package/src/web-rtc-client.js +27 -6
package/lib/domain/Features.js
CHANGED
|
@@ -4024,6 +4024,34 @@ var chatdMethods = (client , baseUrl ) => ({
|
|
|
4024
4024
|
client.get(`${baseUrl}/users/me/rooms/messages`, options),
|
|
4025
4025
|
});
|
|
4026
4026
|
|
|
4027
|
+
//
|
|
4028
|
+
|
|
4029
|
+
|
|
4030
|
+
|
|
4031
|
+
|
|
4032
|
+
|
|
4033
|
+
class MeetingStatus {
|
|
4034
|
+
|
|
4035
|
+
|
|
4036
|
+
|
|
4037
|
+
|
|
4038
|
+
constructor({
|
|
4039
|
+
full,
|
|
4040
|
+
} = {}) {
|
|
4041
|
+
this.full = full;
|
|
4042
|
+
|
|
4043
|
+
// Useful to compare instead of instanceof with minified code
|
|
4044
|
+
this.type = 'MeetingStatus';
|
|
4045
|
+
}
|
|
4046
|
+
|
|
4047
|
+
static parse(plain ) {
|
|
4048
|
+
return new MeetingStatus({
|
|
4049
|
+
full: plain.full,
|
|
4050
|
+
});
|
|
4051
|
+
}
|
|
4052
|
+
|
|
4053
|
+
}
|
|
4054
|
+
|
|
4027
4055
|
/* */
|
|
4028
4056
|
|
|
4029
4057
|
|
|
@@ -4218,6 +4246,8 @@ var calldMethods = (client , baseUrl ) => ({
|
|
|
4218
4246
|
client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
|
|
4219
4247
|
ApiRequester.successResponseParser),
|
|
4220
4248
|
|
|
4249
|
+
guestGetMeetingStatus: (meetingUuid ) =>
|
|
4250
|
+
client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
|
|
4221
4251
|
});
|
|
4222
4252
|
|
|
4223
4253
|
//
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class MeetingStatus {
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
constructor({
|
|
15
|
+
full,
|
|
16
|
+
} = {}) {
|
|
17
|
+
this.full = full;
|
|
18
|
+
|
|
19
|
+
// Useful to compare instead of instanceof with minified code
|
|
20
|
+
this.type = 'MeetingStatus';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static parse(plain ) {
|
|
24
|
+
return new MeetingStatus({
|
|
25
|
+
full: plain.full,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = MeetingStatus;
|
|
@@ -2051,13 +2051,21 @@ class CallSession {
|
|
|
2051
2051
|
|
|
2052
2052
|
// Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
|
|
2053
2053
|
set answered(value ) {
|
|
2054
|
-
this.answerTime = value ? new Date() : null;
|
|
2054
|
+
this.answerTime = value ? this.answerTime || new Date() : null;
|
|
2055
2055
|
}
|
|
2056
2056
|
|
|
2057
2057
|
get answered() {
|
|
2058
2058
|
return !!this.answerTime;
|
|
2059
2059
|
}
|
|
2060
2060
|
|
|
2061
|
+
toJSON() {
|
|
2062
|
+
const jsonObj = { ...this };
|
|
2063
|
+
// $FlowFixMe
|
|
2064
|
+
jsonObj.answered = this.answered;
|
|
2065
|
+
|
|
2066
|
+
return jsonObj;
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2061
2069
|
static parseCall(call ) {
|
|
2062
2070
|
return new CallSession({
|
|
2063
2071
|
callId: call.id,
|
|
@@ -4416,6 +4424,34 @@ class IndirectTransfer {
|
|
|
4416
4424
|
}
|
|
4417
4425
|
}
|
|
4418
4426
|
|
|
4427
|
+
//
|
|
4428
|
+
|
|
4429
|
+
|
|
4430
|
+
|
|
4431
|
+
|
|
4432
|
+
|
|
4433
|
+
class MeetingStatus {
|
|
4434
|
+
|
|
4435
|
+
|
|
4436
|
+
|
|
4437
|
+
|
|
4438
|
+
constructor({
|
|
4439
|
+
full,
|
|
4440
|
+
} = {}) {
|
|
4441
|
+
this.full = full;
|
|
4442
|
+
|
|
4443
|
+
// Useful to compare instead of instanceof with minified code
|
|
4444
|
+
this.type = 'MeetingStatus';
|
|
4445
|
+
}
|
|
4446
|
+
|
|
4447
|
+
static parse(plain ) {
|
|
4448
|
+
return new MeetingStatus({
|
|
4449
|
+
full: plain.full,
|
|
4450
|
+
});
|
|
4451
|
+
}
|
|
4452
|
+
|
|
4453
|
+
}
|
|
4454
|
+
|
|
4419
4455
|
/* */
|
|
4420
4456
|
|
|
4421
4457
|
|
|
@@ -4610,6 +4646,8 @@ var calldMethods = (client , baseUrl ) => ({
|
|
|
4610
4646
|
client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
|
|
4611
4647
|
ApiRequester.successResponseParser),
|
|
4612
4648
|
|
|
4649
|
+
guestGetMeetingStatus: (meetingUuid ) =>
|
|
4650
|
+
client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
|
|
4613
4651
|
});
|
|
4614
4652
|
|
|
4615
4653
|
//
|
|
@@ -399,13 +399,21 @@ class CallSession {
|
|
|
399
399
|
|
|
400
400
|
// Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
|
|
401
401
|
set answered(value ) {
|
|
402
|
-
this.answerTime = value ? new Date() : null;
|
|
402
|
+
this.answerTime = value ? this.answerTime || new Date() : null;
|
|
403
403
|
}
|
|
404
404
|
|
|
405
405
|
get answered() {
|
|
406
406
|
return !!this.answerTime;
|
|
407
407
|
}
|
|
408
408
|
|
|
409
|
+
toJSON() {
|
|
410
|
+
const jsonObj = { ...this };
|
|
411
|
+
// $FlowFixMe
|
|
412
|
+
jsonObj.answered = this.answered;
|
|
413
|
+
|
|
414
|
+
return jsonObj;
|
|
415
|
+
}
|
|
416
|
+
|
|
409
417
|
static parseCall(call ) {
|
|
410
418
|
return new CallSession({
|
|
411
419
|
callId: call.id,
|
|
@@ -1513,6 +1521,7 @@ class WebRTCPhone extends Emitter {
|
|
|
1513
1521
|
}
|
|
1514
1522
|
|
|
1515
1523
|
callSession.answerTime = new Date();
|
|
1524
|
+
this._updateCallSession(callSession);
|
|
1516
1525
|
this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
|
|
1517
1526
|
|
|
1518
1527
|
return callSession;
|
|
@@ -1722,6 +1731,12 @@ class WebRTCPhone extends Emitter {
|
|
|
1722
1731
|
return Promise.resolve(null);
|
|
1723
1732
|
}
|
|
1724
1733
|
|
|
1734
|
+
const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
|
|
1735
|
+
if (sipSessionId && !(sipSessionId in this.callSessions)) {
|
|
1736
|
+
logger.warn('Call session already ended or not found, can\'t accept it.', { sipSessionId });
|
|
1737
|
+
return Promise.resolve(null);
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1725
1740
|
if (callSession.getId() in this.acceptedSessions) {
|
|
1726
1741
|
logger.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
|
|
1727
1742
|
return Promise.resolve(callSession.sipCallId);
|
|
@@ -1729,6 +1744,7 @@ class WebRTCPhone extends Emitter {
|
|
|
1729
1744
|
|
|
1730
1745
|
this.shouldSendReinvite = false;
|
|
1731
1746
|
callSession.answerTime = new Date();
|
|
1747
|
+
this._updateCallSession(callSession);
|
|
1732
1748
|
this.acceptedSessions[callSession.getId()] = true;
|
|
1733
1749
|
|
|
1734
1750
|
this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
|
|
@@ -1828,7 +1844,7 @@ class WebRTCPhone extends Emitter {
|
|
|
1828
1844
|
// Hold current session if different from the current one (we don't want 2 sessions active at the same time).
|
|
1829
1845
|
if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
|
|
1830
1846
|
logger.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
|
|
1831
|
-
this.holdSipSession(this.currentSipSession,
|
|
1847
|
+
this.holdSipSession(this.currentSipSession, this.currentCallSession);
|
|
1832
1848
|
}
|
|
1833
1849
|
|
|
1834
1850
|
const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
|
|
@@ -2039,6 +2055,7 @@ class WebRTCPhone extends Emitter {
|
|
|
2039
2055
|
}
|
|
2040
2056
|
const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
|
|
2041
2057
|
callSession.creationTime = new Date();
|
|
2058
|
+
this._updateCallSession(callSession);
|
|
2042
2059
|
|
|
2043
2060
|
this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
|
|
2044
2061
|
|
|
@@ -2180,7 +2197,7 @@ class WebRTCPhone extends Emitter {
|
|
|
2180
2197
|
return this.client && this.client.isConference(callSession.sipCallId);
|
|
2181
2198
|
}
|
|
2182
2199
|
|
|
2183
|
-
async close() {
|
|
2200
|
+
async close(force = false) {
|
|
2184
2201
|
logger.info('WebRTC close');
|
|
2185
2202
|
|
|
2186
2203
|
try {
|
|
@@ -2192,7 +2209,7 @@ class WebRTCPhone extends Emitter {
|
|
|
2192
2209
|
logger.error('WebRTC close, unregister error', e);
|
|
2193
2210
|
}
|
|
2194
2211
|
|
|
2195
|
-
this.client.close();
|
|
2212
|
+
this.client.close(force);
|
|
2196
2213
|
this.unbind();
|
|
2197
2214
|
|
|
2198
2215
|
this.incomingSessions = [];
|
|
@@ -2318,6 +2335,8 @@ class WebRTCPhone extends Emitter {
|
|
|
2318
2335
|
}
|
|
2319
2336
|
|
|
2320
2337
|
callSession.creationTime = new Date();
|
|
2338
|
+
this._updateCallSession(callSession);
|
|
2339
|
+
|
|
2321
2340
|
this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
|
|
2322
2341
|
});
|
|
2323
2342
|
|
|
@@ -2342,9 +2361,17 @@ class WebRTCPhone extends Emitter {
|
|
|
2342
2361
|
});
|
|
2343
2362
|
|
|
2344
2363
|
this.client.on(this.client.ACCEPTED, (sipSession ) => {
|
|
2345
|
-
|
|
2364
|
+
const sessionId = this.getSipSessionId(sipSession);
|
|
2365
|
+
const hasSession = sessionId in this.callSessions;
|
|
2346
2366
|
|
|
2347
|
-
|
|
2367
|
+
logger.info('WebRTC call accepted', { sipId: sessionId, hasSession });
|
|
2368
|
+
|
|
2369
|
+
if (!hasSession) {
|
|
2370
|
+
logger.warn('Call accepted ignored, session is no longer present in the WebRtcPhone', { sessionId });
|
|
2371
|
+
return;
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
this._onCallAccepted(sipSession, this.client.hasVideo(sessionId));
|
|
2348
2375
|
|
|
2349
2376
|
if (this.audioOutputDeviceId) {
|
|
2350
2377
|
this.client.changeAudioOutputDevice(this.audioOutputDeviceId);
|
|
@@ -2361,6 +2388,8 @@ class WebRTCPhone extends Emitter {
|
|
|
2361
2388
|
logger.info('WebRTC call rejected', session.id);
|
|
2362
2389
|
const callSession = this._createCallSession(session);
|
|
2363
2390
|
callSession.endTime = new Date();
|
|
2391
|
+
this._updateCallSession(callSession);
|
|
2392
|
+
|
|
2364
2393
|
this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
|
|
2365
2394
|
});
|
|
2366
2395
|
|
|
@@ -2478,9 +2507,14 @@ class WebRTCPhone extends Emitter {
|
|
|
2478
2507
|
return this.client.getSipSessionId(sipSession);
|
|
2479
2508
|
}
|
|
2480
2509
|
|
|
2481
|
-
|
|
2510
|
+
getSipSessionIdFromCallSession(callSession ) {
|
|
2482
2511
|
const sipSession = this.findSipSession(callSession);
|
|
2483
|
-
|
|
2512
|
+
|
|
2513
|
+
return sipSession ? this.getSipSessionId(sipSession) : null;
|
|
2514
|
+
}
|
|
2515
|
+
|
|
2516
|
+
_updateCallSession(callSession ) {
|
|
2517
|
+
const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
|
|
2484
2518
|
|
|
2485
2519
|
if (sipSessionId) {
|
|
2486
2520
|
this.callSessions[sipSessionId] = callSession;
|
|
@@ -2585,6 +2619,7 @@ class WebRTCPhone extends Emitter {
|
|
|
2585
2619
|
displayName: identity ? identity.displayName || number : number,
|
|
2586
2620
|
startTime: fromSession ? fromSession.startTime : new Date(),
|
|
2587
2621
|
creationTime: fromSession ? fromSession.creationTime : null,
|
|
2622
|
+
answerTime: fromSession ? fromSession.answerTime : null,
|
|
2588
2623
|
endTime: fromSession ? fromSession.endTime : null,
|
|
2589
2624
|
answered: state === sessionState.SessionState.Established,
|
|
2590
2625
|
paused: this.client.isCallHeld(sipSession),
|
|
@@ -370,13 +370,21 @@ class CallSession {
|
|
|
370
370
|
|
|
371
371
|
// Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
|
|
372
372
|
set answered(value ) {
|
|
373
|
-
this.answerTime = value ? new Date() : null;
|
|
373
|
+
this.answerTime = value ? this.answerTime || new Date() : null;
|
|
374
374
|
}
|
|
375
375
|
|
|
376
376
|
get answered() {
|
|
377
377
|
return !!this.answerTime;
|
|
378
378
|
}
|
|
379
379
|
|
|
380
|
+
toJSON() {
|
|
381
|
+
const jsonObj = { ...this };
|
|
382
|
+
// $FlowFixMe
|
|
383
|
+
jsonObj.answered = this.answered;
|
|
384
|
+
|
|
385
|
+
return jsonObj;
|
|
386
|
+
}
|
|
387
|
+
|
|
380
388
|
static parseCall(call ) {
|
|
381
389
|
return new CallSession({
|
|
382
390
|
callId: call.id,
|
|
@@ -402,6 +410,8 @@ class CallSession {
|
|
|
402
410
|
}
|
|
403
411
|
}
|
|
404
412
|
|
|
413
|
+
const stringify = cs => JSON.parse(JSON.stringify(cs));
|
|
414
|
+
|
|
405
415
|
describe('CallSession domain', () => {
|
|
406
416
|
it('should update from another CallSession without data loss', () => {
|
|
407
417
|
const callSession = new CallSession({
|
|
@@ -440,7 +450,7 @@ describe('CallSession domain', () => {
|
|
|
440
450
|
expect(cs2.is(cs1)).toBeTruthy();
|
|
441
451
|
});
|
|
442
452
|
|
|
443
|
-
it('should set answerTime when setting answered', () => {
|
|
453
|
+
it('should set answerTime when setting answered to true', () => {
|
|
444
454
|
const cs1 = new CallSession({});
|
|
445
455
|
cs1.answered = true;
|
|
446
456
|
|
|
@@ -449,11 +459,37 @@ describe('CallSession domain', () => {
|
|
|
449
459
|
|
|
450
460
|
const cs3 = new CallSession({ answered: true });
|
|
451
461
|
|
|
452
|
-
expect(cs1.answered).
|
|
462
|
+
expect(cs1.answered).toEqual(true);
|
|
453
463
|
expect(cs1.answerTime).not.toBeNull();
|
|
454
|
-
expect(cs2.answered).
|
|
464
|
+
expect(cs2.answered).toEqual(true);
|
|
455
465
|
expect(cs2.answerTime).not.toBeNull();
|
|
456
|
-
expect(cs3.answered).
|
|
466
|
+
expect(cs3.answered).toEqual(true);
|
|
457
467
|
expect(cs3.answerTime).not.toBeNull();
|
|
468
|
+
|
|
469
|
+
const cs4 = stringify(cs1);
|
|
470
|
+
const cs5 = stringify(cs2);
|
|
471
|
+
const cs6 = stringify(cs3);
|
|
472
|
+
|
|
473
|
+
expect(cs4.answered).toEqual(true);
|
|
474
|
+
expect(cs5.answered).toEqual(true);
|
|
475
|
+
expect(cs6.answered).toEqual(true);
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
it('should reset answerTime when setting answered to false', () => {
|
|
479
|
+
const cs1 = new CallSession({});
|
|
480
|
+
cs1.answered = false;
|
|
481
|
+
|
|
482
|
+
const cs2 = new CallSession({ answered: false });
|
|
483
|
+
|
|
484
|
+
expect(cs1.answered).toEqual(false);
|
|
485
|
+
expect(cs1.answerTime).toBeNull();
|
|
486
|
+
expect(cs2.answered).toEqual(false);
|
|
487
|
+
expect(cs2.answerTime).toBeNull();
|
|
488
|
+
|
|
489
|
+
const cs4 = stringify(cs1);
|
|
490
|
+
const cs5 = stringify(cs2);
|
|
491
|
+
|
|
492
|
+
expect(cs4.answered).toEqual(false);
|
|
493
|
+
expect(cs5.answered).toEqual(false);
|
|
458
494
|
});
|
|
459
495
|
});
|
|
@@ -370,13 +370,21 @@ class CallSession {
|
|
|
370
370
|
|
|
371
371
|
// Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
|
|
372
372
|
set answered(value ) {
|
|
373
|
-
this.answerTime = value ? new Date() : null;
|
|
373
|
+
this.answerTime = value ? this.answerTime || new Date() : null;
|
|
374
374
|
}
|
|
375
375
|
|
|
376
376
|
get answered() {
|
|
377
377
|
return !!this.answerTime;
|
|
378
378
|
}
|
|
379
379
|
|
|
380
|
+
toJSON() {
|
|
381
|
+
const jsonObj = { ...this };
|
|
382
|
+
// $FlowFixMe
|
|
383
|
+
jsonObj.answered = this.answered;
|
|
384
|
+
|
|
385
|
+
return jsonObj;
|
|
386
|
+
}
|
|
387
|
+
|
|
380
388
|
static parseCall(call ) {
|
|
381
389
|
return new CallSession({
|
|
382
390
|
callId: call.id,
|
|
@@ -370,13 +370,21 @@ class CallSession {
|
|
|
370
370
|
|
|
371
371
|
// Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
|
|
372
372
|
set answered(value ) {
|
|
373
|
-
this.answerTime = value ? new Date() : null;
|
|
373
|
+
this.answerTime = value ? this.answerTime || new Date() : null;
|
|
374
374
|
}
|
|
375
375
|
|
|
376
376
|
get answered() {
|
|
377
377
|
return !!this.answerTime;
|
|
378
378
|
}
|
|
379
379
|
|
|
380
|
+
toJSON() {
|
|
381
|
+
const jsonObj = { ...this };
|
|
382
|
+
// $FlowFixMe
|
|
383
|
+
jsonObj.answered = this.answered;
|
|
384
|
+
|
|
385
|
+
return jsonObj;
|
|
386
|
+
}
|
|
387
|
+
|
|
380
388
|
static parseCall(call ) {
|
|
381
389
|
return new CallSession({
|
|
382
390
|
callId: call.id,
|
package/lib/index.js
CHANGED
|
@@ -3596,13 +3596,21 @@ class CallSession {
|
|
|
3596
3596
|
|
|
3597
3597
|
// Retro-compatibility: `answered` was a boolean before. We can reproduce the behaviour with a getter/setter
|
|
3598
3598
|
set answered(value ) {
|
|
3599
|
-
this.answerTime = value ? new Date() : null;
|
|
3599
|
+
this.answerTime = value ? this.answerTime || new Date() : null;
|
|
3600
3600
|
}
|
|
3601
3601
|
|
|
3602
3602
|
get answered() {
|
|
3603
3603
|
return !!this.answerTime;
|
|
3604
3604
|
}
|
|
3605
3605
|
|
|
3606
|
+
toJSON() {
|
|
3607
|
+
const jsonObj = { ...this };
|
|
3608
|
+
// $FlowFixMe
|
|
3609
|
+
jsonObj.answered = this.answered;
|
|
3610
|
+
|
|
3611
|
+
return jsonObj;
|
|
3612
|
+
}
|
|
3613
|
+
|
|
3606
3614
|
static parseCall(call ) {
|
|
3607
3615
|
return new CallSession({
|
|
3608
3616
|
callId: call.id,
|
|
@@ -4937,6 +4945,34 @@ var chatdMethods = (client , baseUrl ) => ({
|
|
|
4937
4945
|
client.get(`${baseUrl}/users/me/rooms/messages`, options),
|
|
4938
4946
|
});
|
|
4939
4947
|
|
|
4948
|
+
//
|
|
4949
|
+
|
|
4950
|
+
|
|
4951
|
+
|
|
4952
|
+
|
|
4953
|
+
|
|
4954
|
+
class MeetingStatus {
|
|
4955
|
+
|
|
4956
|
+
|
|
4957
|
+
|
|
4958
|
+
|
|
4959
|
+
constructor({
|
|
4960
|
+
full,
|
|
4961
|
+
} = {}) {
|
|
4962
|
+
this.full = full;
|
|
4963
|
+
|
|
4964
|
+
// Useful to compare instead of instanceof with minified code
|
|
4965
|
+
this.type = 'MeetingStatus';
|
|
4966
|
+
}
|
|
4967
|
+
|
|
4968
|
+
static parse(plain ) {
|
|
4969
|
+
return new MeetingStatus({
|
|
4970
|
+
full: plain.full,
|
|
4971
|
+
});
|
|
4972
|
+
}
|
|
4973
|
+
|
|
4974
|
+
}
|
|
4975
|
+
|
|
4940
4976
|
/* */
|
|
4941
4977
|
|
|
4942
4978
|
|
|
@@ -5131,6 +5167,8 @@ var calldMethods = (client , baseUrl ) => ({
|
|
|
5131
5167
|
client.put(`${baseUrl}/users/me/calls/${callId}/record/resume`, null, null,
|
|
5132
5168
|
ApiRequester.successResponseParser),
|
|
5133
5169
|
|
|
5170
|
+
guestGetMeetingStatus: (meetingUuid ) =>
|
|
5171
|
+
client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}/status`).then(MeetingStatus.parse),
|
|
5134
5172
|
});
|
|
5135
5173
|
|
|
5136
5174
|
//
|
|
@@ -6198,7 +6236,7 @@ const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
|
|
|
6198
6236
|
const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
|
|
6199
6237
|
class CanceledCallError extends Error {}
|
|
6200
6238
|
|
|
6201
|
-
const MAX_REGISTER_TRIES =
|
|
6239
|
+
const MAX_REGISTER_TRIES = 5;
|
|
6202
6240
|
|
|
6203
6241
|
|
|
6204
6242
|
|
|
@@ -6252,6 +6290,7 @@ class WebRTCClient extends Emitter {
|
|
|
6252
6290
|
|
|
6253
6291
|
|
|
6254
6292
|
|
|
6293
|
+
|
|
6255
6294
|
|
|
6256
6295
|
// sugar
|
|
6257
6296
|
|
|
@@ -6314,6 +6353,7 @@ class WebRTCClient extends Emitter {
|
|
|
6314
6353
|
this.conferences = {};
|
|
6315
6354
|
this.networkMonitoringInterval = {};
|
|
6316
6355
|
this.sessionNetworkStats = {};
|
|
6356
|
+
this.forceClosed = false;
|
|
6317
6357
|
|
|
6318
6358
|
this._boundOnHeartbeat = this._onHeartbeat.bind(this);
|
|
6319
6359
|
this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
|
|
@@ -6435,6 +6475,8 @@ class WebRTCClient extends Emitter {
|
|
|
6435
6475
|
skipRegister: this.skipRegister,
|
|
6436
6476
|
};
|
|
6437
6477
|
|
|
6478
|
+
this.forceClosed = false;
|
|
6479
|
+
|
|
6438
6480
|
if (this.skipRegister) {
|
|
6439
6481
|
logger$9.info('sdk webrtc skip register...', logInfo);
|
|
6440
6482
|
return Promise.resolve();
|
|
@@ -6459,7 +6501,15 @@ class WebRTCClient extends Emitter {
|
|
|
6459
6501
|
const registerOptions = this._isWeb() ? {} : { extraContactHeaderParams: ['mobility=mobile'] };
|
|
6460
6502
|
|
|
6461
6503
|
const onRegisterFailed = () => {
|
|
6462
|
-
logger$9.info('sdk webrtc registering failed', {
|
|
6504
|
+
logger$9.info('sdk webrtc registering failed', {
|
|
6505
|
+
tries,
|
|
6506
|
+
registerer: !!this.registerer,
|
|
6507
|
+
forceClosed: this.forceClosed,
|
|
6508
|
+
});
|
|
6509
|
+
if (this.forceClosed) {
|
|
6510
|
+
return;
|
|
6511
|
+
}
|
|
6512
|
+
|
|
6463
6513
|
this.connectionPromise = null;
|
|
6464
6514
|
if (this.registerer && this.registerer.waiting) {
|
|
6465
6515
|
this.registerer.waitingToggle(false);
|
|
@@ -6737,8 +6787,9 @@ class WebRTCClient extends Emitter {
|
|
|
6737
6787
|
}
|
|
6738
6788
|
}
|
|
6739
6789
|
|
|
6740
|
-
async close() {
|
|
6741
|
-
logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent });
|
|
6790
|
+
async close(force = false) {
|
|
6791
|
+
logger$9.info('sdk webrtc closing client', { userAgent: !!this.userAgent, force });
|
|
6792
|
+
this.forceClosed = force;
|
|
6742
6793
|
this._cleanupMedia();
|
|
6743
6794
|
this.connectionPromise = null;
|
|
6744
6795
|
|
|
@@ -6757,7 +6808,7 @@ class WebRTCClient extends Emitter {
|
|
|
6757
6808
|
this.userAgent.delegate = null;
|
|
6758
6809
|
this.userAgent.stateChange.removeAllListeners();
|
|
6759
6810
|
|
|
6760
|
-
await this._disconnectTransport();
|
|
6811
|
+
await this._disconnectTransport(force);
|
|
6761
6812
|
|
|
6762
6813
|
this._cleanupRegister();
|
|
6763
6814
|
|
|
@@ -8193,7 +8244,15 @@ class WebRTCClient extends Emitter {
|
|
|
8193
8244
|
return userAgent.UserAgent.makeURI(`sip:${target}@${this.config.host}`);
|
|
8194
8245
|
}
|
|
8195
8246
|
|
|
8196
|
-
async _disconnectTransport() {
|
|
8247
|
+
async _disconnectTransport(force = false) {
|
|
8248
|
+
if (force) {
|
|
8249
|
+
// Bypass sip.js state machine that prevent to close WS with the state `Connecting`
|
|
8250
|
+
this.userAgent.transport.disconnectResolve = () => {};
|
|
8251
|
+
// eslint-disable-next-line
|
|
8252
|
+
this.userAgent.transport._ws.close(1000);
|
|
8253
|
+
return;
|
|
8254
|
+
}
|
|
8255
|
+
|
|
8197
8256
|
// Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
|
|
8198
8257
|
if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
|
|
8199
8258
|
try {
|
|
@@ -9831,6 +9890,7 @@ class WebRTCPhone extends Emitter {
|
|
|
9831
9890
|
}
|
|
9832
9891
|
|
|
9833
9892
|
callSession.answerTime = new Date();
|
|
9893
|
+
this._updateCallSession(callSession);
|
|
9834
9894
|
this.eventEmitter.emit(ON_CALL_ACCEPTED, callSession, cameraEnabled);
|
|
9835
9895
|
|
|
9836
9896
|
return callSession;
|
|
@@ -10040,6 +10100,12 @@ class WebRTCPhone extends Emitter {
|
|
|
10040
10100
|
return Promise.resolve(null);
|
|
10041
10101
|
}
|
|
10042
10102
|
|
|
10103
|
+
const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
|
|
10104
|
+
if (sipSessionId && !(sipSessionId in this.callSessions)) {
|
|
10105
|
+
logger$7.warn('Call session already ended or not found, can\'t accept it.', { sipSessionId });
|
|
10106
|
+
return Promise.resolve(null);
|
|
10107
|
+
}
|
|
10108
|
+
|
|
10043
10109
|
if (callSession.getId() in this.acceptedSessions) {
|
|
10044
10110
|
logger$7.warn('CallSession already accepted.', { id: callSession ? callSession.getId() : 'n/a' });
|
|
10045
10111
|
return Promise.resolve(callSession.sipCallId);
|
|
@@ -10047,6 +10113,7 @@ class WebRTCPhone extends Emitter {
|
|
|
10047
10113
|
|
|
10048
10114
|
this.shouldSendReinvite = false;
|
|
10049
10115
|
callSession.answerTime = new Date();
|
|
10116
|
+
this._updateCallSession(callSession);
|
|
10050
10117
|
this.acceptedSessions[callSession.getId()] = true;
|
|
10051
10118
|
|
|
10052
10119
|
this.eventEmitter.emit(ON_CALL_ANSWERED, callSession);
|
|
@@ -10146,7 +10213,7 @@ class WebRTCPhone extends Emitter {
|
|
|
10146
10213
|
// Hold current session if different from the current one (we don't want 2 sessions active at the same time).
|
|
10147
10214
|
if (this.currentSipSession && this.currentSipSession.id !== sipSession.id) {
|
|
10148
10215
|
logger$7.info('WebRTC hold call after resume', { id: this.currentSipSession.id });
|
|
10149
|
-
this.holdSipSession(this.currentSipSession,
|
|
10216
|
+
this.holdSipSession(this.currentSipSession, this.currentCallSession);
|
|
10150
10217
|
}
|
|
10151
10218
|
|
|
10152
10219
|
const promise = this.unholdSipSession(sipSession, callSession, withEvent, isConference);
|
|
@@ -10357,6 +10424,7 @@ class WebRTCPhone extends Emitter {
|
|
|
10357
10424
|
}
|
|
10358
10425
|
const callSession = this._createOutgoingCallSession(sipSession, cameraEnabled || false);
|
|
10359
10426
|
callSession.creationTime = new Date();
|
|
10427
|
+
this._updateCallSession(callSession);
|
|
10360
10428
|
|
|
10361
10429
|
this.eventEmitter.emit(ON_PLAY_PROGRESS_SOUND, this.audioOutputDeviceId, this.audioOutputVolume);
|
|
10362
10430
|
|
|
@@ -10498,7 +10566,7 @@ class WebRTCPhone extends Emitter {
|
|
|
10498
10566
|
return this.client && this.client.isConference(callSession.sipCallId);
|
|
10499
10567
|
}
|
|
10500
10568
|
|
|
10501
|
-
async close() {
|
|
10569
|
+
async close(force = false) {
|
|
10502
10570
|
logger$7.info('WebRTC close');
|
|
10503
10571
|
|
|
10504
10572
|
try {
|
|
@@ -10510,7 +10578,7 @@ class WebRTCPhone extends Emitter {
|
|
|
10510
10578
|
logger$7.error('WebRTC close, unregister error', e);
|
|
10511
10579
|
}
|
|
10512
10580
|
|
|
10513
|
-
this.client.close();
|
|
10581
|
+
this.client.close(force);
|
|
10514
10582
|
this.unbind();
|
|
10515
10583
|
|
|
10516
10584
|
this.incomingSessions = [];
|
|
@@ -10636,6 +10704,8 @@ class WebRTCPhone extends Emitter {
|
|
|
10636
10704
|
}
|
|
10637
10705
|
|
|
10638
10706
|
callSession.creationTime = new Date();
|
|
10707
|
+
this._updateCallSession(callSession);
|
|
10708
|
+
|
|
10639
10709
|
this.eventEmitter.emit(ON_CALL_INCOMING, callSession, wantsToDoVideo);
|
|
10640
10710
|
});
|
|
10641
10711
|
|
|
@@ -10660,9 +10730,17 @@ class WebRTCPhone extends Emitter {
|
|
|
10660
10730
|
});
|
|
10661
10731
|
|
|
10662
10732
|
this.client.on(this.client.ACCEPTED, (sipSession ) => {
|
|
10663
|
-
|
|
10733
|
+
const sessionId = this.getSipSessionId(sipSession);
|
|
10734
|
+
const hasSession = sessionId in this.callSessions;
|
|
10664
10735
|
|
|
10665
|
-
|
|
10736
|
+
logger$7.info('WebRTC call accepted', { sipId: sessionId, hasSession });
|
|
10737
|
+
|
|
10738
|
+
if (!hasSession) {
|
|
10739
|
+
logger$7.warn('Call accepted ignored, session is no longer present in the WebRtcPhone', { sessionId });
|
|
10740
|
+
return;
|
|
10741
|
+
}
|
|
10742
|
+
|
|
10743
|
+
this._onCallAccepted(sipSession, this.client.hasVideo(sessionId));
|
|
10666
10744
|
|
|
10667
10745
|
if (this.audioOutputDeviceId) {
|
|
10668
10746
|
this.client.changeAudioOutputDevice(this.audioOutputDeviceId);
|
|
@@ -10679,6 +10757,8 @@ class WebRTCPhone extends Emitter {
|
|
|
10679
10757
|
logger$7.info('WebRTC call rejected', session.id);
|
|
10680
10758
|
const callSession = this._createCallSession(session);
|
|
10681
10759
|
callSession.endTime = new Date();
|
|
10760
|
+
this._updateCallSession(callSession);
|
|
10761
|
+
|
|
10682
10762
|
this.eventEmitter.emit(ON_CALL_REJECTED, callSession);
|
|
10683
10763
|
});
|
|
10684
10764
|
|
|
@@ -10796,9 +10876,14 @@ class WebRTCPhone extends Emitter {
|
|
|
10796
10876
|
return this.client.getSipSessionId(sipSession);
|
|
10797
10877
|
}
|
|
10798
10878
|
|
|
10799
|
-
|
|
10879
|
+
getSipSessionIdFromCallSession(callSession ) {
|
|
10800
10880
|
const sipSession = this.findSipSession(callSession);
|
|
10801
|
-
|
|
10881
|
+
|
|
10882
|
+
return sipSession ? this.getSipSessionId(sipSession) : null;
|
|
10883
|
+
}
|
|
10884
|
+
|
|
10885
|
+
_updateCallSession(callSession ) {
|
|
10886
|
+
const sipSessionId = this.getSipSessionIdFromCallSession(callSession);
|
|
10802
10887
|
|
|
10803
10888
|
if (sipSessionId) {
|
|
10804
10889
|
this.callSessions[sipSessionId] = callSession;
|
|
@@ -10903,6 +10988,7 @@ class WebRTCPhone extends Emitter {
|
|
|
10903
10988
|
displayName: identity ? identity.displayName || number : number,
|
|
10904
10989
|
startTime: fromSession ? fromSession.startTime : new Date(),
|
|
10905
10990
|
creationTime: fromSession ? fromSession.creationTime : null,
|
|
10991
|
+
answerTime: fromSession ? fromSession.answerTime : null,
|
|
10906
10992
|
endTime: fromSession ? fromSession.endTime : null,
|
|
10907
10993
|
answered: state === sessionState.SessionState.Established,
|
|
10908
10994
|
paused: this.client.isCallHeld(sipSession),
|