@wazo/sdk 0.37.0-rc.5 → 0.37.2
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 +5 -5
- package/esm/__tests__/api-client.test.js +93 -16
- package/esm/__tests__/web-rtc-client.test.js +153 -54
- package/esm/api/agentd.js +24 -3
- package/esm/api/amid.js +7 -1
- package/esm/api/application.js +24 -3
- package/esm/api/auth.js +24 -3
- package/esm/api/call-logd.js +78 -20
- package/esm/api/calld.js +24 -20
- package/esm/api/chatd.js +24 -3
- package/esm/api/confd.js +24 -3
- package/esm/api/ctid-ng.js +24 -3
- package/esm/api/dird.js +27 -6
- package/esm/api/webhookd.js +7 -1
- package/esm/api-client.js +93 -16
- package/esm/checker/Checker.js +156 -54
- package/esm/checker/checks/aor.js +95 -16
- package/esm/checker/checks/api.js +94 -16
- package/esm/checker/checks/index.js +156 -54
- package/esm/checker/checks/wazo-websocket.js +7 -1
- package/esm/checker/checks/webrtc-transport.js +153 -54
- package/esm/checker/checks/webrtc.js +153 -54
- package/esm/domain/AdHocAPIConference.js +1717 -1640
- package/esm/domain/CallLog.js +71 -19
- package/esm/domain/CallSession.js +1 -18
- package/esm/domain/Contact.js +3 -3
- package/esm/domain/Features.js +93 -16
- package/esm/domain/IndirectTransfer.js +0 -17
- package/esm/domain/Phone/CTIPhone.js +100 -19
- package/esm/domain/Phone/Phone.js +0 -17
- package/esm/domain/Phone/WebRTCPhone.js +51 -36
- package/esm/domain/Recording.js +51 -0
- package/esm/domain/Room.js +0 -17
- package/esm/domain/SwitchboardCall.js +0 -17
- package/esm/domain/__tests__/CallLog.test.js +89 -19
- package/esm/domain/__tests__/CallSession.test.js +1 -18
- package/esm/domain/__tests__/Contact.test.js +3 -3
- package/esm/domain/__tests__/IndirectTransfer.test.js +1 -18
- package/esm/domain/__tests__/Room.test.js +1 -18
- package/esm/domain/__tests__/Session.test.js +7 -0
- package/esm/index.js +3436 -2911
- package/esm/lib/WazoSessionDescriptionHandler.js +28 -10
- package/esm/service/CallApi.js +93 -16
- package/esm/service/IssueReporter.js +7 -1
- package/esm/service/__tests__/IssueReporter.test.js +26 -2
- package/esm/service/getApiClient.js +93 -16
- package/esm/simple/Auth.js +619 -97
- package/esm/simple/Configuration.js +619 -97
- package/esm/simple/Directory.js +93 -16
- package/esm/simple/Phone.js +3261 -2739
- package/esm/simple/Websocket.js +7 -1
- package/esm/simple/index.js +619 -97
- package/esm/simple/room/LocalParticipant.js +619 -97
- package/esm/simple/room/Participant.js +619 -97
- package/esm/simple/room/RemoteParticipant.js +619 -97
- package/esm/simple/room/Room.js +619 -97
- package/esm/simple/room/Stream.js +619 -97
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +619 -97
- package/esm/simple/utils.js +619 -97
- package/esm/utils/__tests__/api-requester.test.js +32 -6
- package/esm/utils/api-requester.js +24 -3
- package/esm/web-rtc-client.js +153 -54
- package/esm/websocket-client.js +7 -1
- package/lib/__tests__/api-client.test.js +93 -16
- package/lib/__tests__/web-rtc-client.test.js +154 -55
- package/lib/api/agentd.js +24 -3
- package/lib/api/amid.js +7 -1
- package/lib/api/application.js +24 -3
- package/lib/api/auth.js +24 -3
- package/lib/api/call-logd.js +78 -20
- package/lib/api/calld.js +24 -20
- package/lib/api/chatd.js +24 -3
- package/lib/api/confd.js +24 -3
- package/lib/api/ctid-ng.js +24 -3
- package/lib/api/dird.js +27 -6
- package/lib/api/webhookd.js +7 -1
- package/lib/api-client.js +93 -16
- package/lib/checker/Checker.js +157 -55
- package/lib/checker/checks/aor.js +95 -16
- package/lib/checker/checks/api.js +94 -16
- package/lib/checker/checks/index.js +157 -55
- package/lib/checker/checks/wazo-websocket.js +7 -1
- package/lib/checker/checks/webrtc-transport.js +154 -55
- package/lib/checker/checks/webrtc.js +154 -55
- package/lib/domain/AdHocAPIConference.js +1717 -1640
- package/lib/domain/CallLog.js +71 -19
- package/lib/domain/CallSession.js +1 -18
- package/lib/domain/Contact.js +3 -3
- package/lib/domain/Features.js +93 -16
- package/lib/domain/IndirectTransfer.js +0 -17
- package/lib/domain/Phone/CTIPhone.js +100 -19
- package/lib/domain/Phone/Phone.js +0 -16
- package/lib/domain/Phone/WebRTCPhone.js +51 -36
- package/lib/domain/Recording.js +57 -0
- package/lib/domain/Room.js +0 -17
- package/lib/domain/SwitchboardCall.js +0 -17
- package/lib/domain/__tests__/CallLog.test.js +89 -19
- package/lib/domain/__tests__/CallSession.test.js +1 -18
- package/lib/domain/__tests__/Contact.test.js +3 -3
- package/lib/domain/__tests__/IndirectTransfer.test.js +1 -18
- package/lib/domain/__tests__/Room.test.js +1 -18
- package/lib/domain/__tests__/Session.test.js +7 -0
- package/lib/index.js +3437 -2912
- package/lib/lib/WazoSessionDescriptionHandler.js +28 -10
- package/lib/service/CallApi.js +93 -16
- package/lib/service/IssueReporter.js +7 -1
- package/lib/service/__tests__/IssueReporter.test.js +26 -2
- package/lib/service/getApiClient.js +93 -16
- package/lib/simple/Auth.js +620 -98
- package/lib/simple/Configuration.js +620 -98
- package/lib/simple/Directory.js +93 -16
- package/lib/simple/Phone.js +3262 -2740
- package/lib/simple/Websocket.js +7 -1
- package/lib/simple/index.js +620 -98
- package/lib/simple/room/LocalParticipant.js +620 -98
- package/lib/simple/room/Participant.js +620 -98
- package/lib/simple/room/RemoteParticipant.js +620 -98
- package/lib/simple/room/Room.js +620 -98
- package/lib/simple/room/Stream.js +620 -98
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +620 -98
- package/lib/simple/utils.js +620 -98
- package/lib/utils/__tests__/api-requester.test.js +32 -6
- package/lib/utils/api-requester.js +24 -3
- package/lib/web-rtc-client.js +154 -55
- package/lib/websocket-client.js +7 -1
- package/package.json +1 -1
- package/src/api-client.js +4 -0
- package/src/checker/checks/aor.js +2 -0
- package/src/checker/checks/api.js +1 -0
- package/src/domain/CallLog.js +18 -11
- package/src/domain/CallSession.js +1 -2
- package/src/domain/Contact.js +3 -3
- package/src/domain/Phone/CTIPhone.js +6 -2
- package/src/domain/Phone/Phone.js +2 -0
- package/src/domain/Phone/WebRTCPhone.js +26 -16
- package/src/domain/Recording.js +48 -0
- package/src/domain/__tests__/CallLog.test.js +19 -0
- package/src/domain/__tests__/Session.test.js +7 -0
- package/src/index.js +6 -0
- package/src/lib/WazoSessionDescriptionHandler.js +21 -9
- package/src/service/IssueReporter.js +7 -1
- package/src/service/__tests__/IssueReporter.test.js +20 -1
- package/src/simple/Phone.js +5 -1
- package/src/simple/index.js +6 -0
- package/src/simple/room/Room.js +18 -15
- package/src/simple/room/Stream.js +1 -4
- package/src/utils/__tests__/api-requester.test.js +9 -4
- package/src/utils/api-requester.js +17 -2
- package/src/web-rtc-client.js +40 -13
|
@@ -305,7 +305,13 @@ class IssueReporter {
|
|
|
305
305
|
}
|
|
306
306
|
|
|
307
307
|
_isLevelAbove(level1 , level2 ) {
|
|
308
|
-
|
|
308
|
+
const index1 = LOG_LEVELS.indexOf(level1);
|
|
309
|
+
const index2 = LOG_LEVELS.indexOf(level2);
|
|
310
|
+
if (index1 === -1 || index2 === -1) {
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return index1 > index2;
|
|
309
315
|
}
|
|
310
316
|
|
|
311
317
|
_makeCategory(category ) {
|
|
@@ -363,6 +369,7 @@ class ApiRequester {
|
|
|
363
369
|
|
|
364
370
|
|
|
365
371
|
|
|
372
|
+
|
|
366
373
|
|
|
367
374
|
|
|
368
375
|
|
|
@@ -402,6 +409,8 @@ class ApiRequester {
|
|
|
402
409
|
this.token = token;
|
|
403
410
|
}
|
|
404
411
|
|
|
412
|
+
this.shouldLogErrors = true;
|
|
413
|
+
|
|
405
414
|
methods.forEach(method => {
|
|
406
415
|
// $FlowFixMe
|
|
407
416
|
ApiRequester.prototype[method] = function sugar(...args) {
|
|
@@ -425,6 +434,14 @@ class ApiRequester {
|
|
|
425
434
|
this.fetchOptions = options;
|
|
426
435
|
}
|
|
427
436
|
|
|
437
|
+
disableErrorLogging() {
|
|
438
|
+
this.shouldLogErrors = false;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
enableErrorLogging() {
|
|
442
|
+
this.shouldLogErrors = true;
|
|
443
|
+
}
|
|
444
|
+
|
|
428
445
|
async call(
|
|
429
446
|
path ,
|
|
430
447
|
method = 'get',
|
|
@@ -485,7 +502,9 @@ class ApiRequester {
|
|
|
485
502
|
? exceptionClass.fromText(err, response.status)
|
|
486
503
|
: exceptionClass.fromResponse(err, response.status);
|
|
487
504
|
|
|
488
|
-
|
|
505
|
+
if (this.shouldLogErrors) {
|
|
506
|
+
logger.error('API error', error);
|
|
507
|
+
}
|
|
489
508
|
|
|
490
509
|
throw error;
|
|
491
510
|
});
|
|
@@ -493,7 +512,9 @@ class ApiRequester {
|
|
|
493
512
|
|
|
494
513
|
return newParse(response, isJson);
|
|
495
514
|
}).catch(error => {
|
|
496
|
-
|
|
515
|
+
if (this.shouldLogErrors) {
|
|
516
|
+
logger.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
|
|
517
|
+
}
|
|
497
518
|
|
|
498
519
|
throw error;
|
|
499
520
|
});
|
|
@@ -615,11 +636,16 @@ describe('Retrieving headers', () => {
|
|
|
615
636
|
});
|
|
616
637
|
|
|
617
638
|
describe('Calling fetch', () => {
|
|
618
|
-
it('should call fetch without body but query string in get method', () => {
|
|
639
|
+
it('should call fetch without body but query string in get method', async () => {
|
|
619
640
|
jest.mock('node-fetch/lib/index', () => {});
|
|
620
|
-
global.fetch = jest.fn(() => Promise.resolve({
|
|
641
|
+
global.fetch = jest.fn(() => Promise.resolve({
|
|
642
|
+
json: () => Promise.resolve({}),
|
|
643
|
+
headers: {
|
|
644
|
+
get: () => '',
|
|
645
|
+
},
|
|
646
|
+
}));
|
|
621
647
|
|
|
622
|
-
new ApiRequester({ server }).call(path, method, body, {});
|
|
648
|
+
await new ApiRequester({ server }).call(path, method, body, {});
|
|
623
649
|
expect(global.fetch).toBeCalledWith(url, { method: 'get', body: null, headers: {}, agent: null });
|
|
624
650
|
});
|
|
625
651
|
});
|
|
@@ -305,7 +305,13 @@ class IssueReporter {
|
|
|
305
305
|
}
|
|
306
306
|
|
|
307
307
|
_isLevelAbove(level1 , level2 ) {
|
|
308
|
-
|
|
308
|
+
const index1 = LOG_LEVELS.indexOf(level1);
|
|
309
|
+
const index2 = LOG_LEVELS.indexOf(level2);
|
|
310
|
+
if (index1 === -1 || index2 === -1) {
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return index1 > index2;
|
|
309
315
|
}
|
|
310
316
|
|
|
311
317
|
_makeCategory(category ) {
|
|
@@ -363,6 +369,7 @@ class ApiRequester {
|
|
|
363
369
|
|
|
364
370
|
|
|
365
371
|
|
|
372
|
+
|
|
366
373
|
|
|
367
374
|
|
|
368
375
|
|
|
@@ -402,6 +409,8 @@ class ApiRequester {
|
|
|
402
409
|
this.token = token;
|
|
403
410
|
}
|
|
404
411
|
|
|
412
|
+
this.shouldLogErrors = true;
|
|
413
|
+
|
|
405
414
|
methods.forEach(method => {
|
|
406
415
|
// $FlowFixMe
|
|
407
416
|
ApiRequester.prototype[method] = function sugar(...args) {
|
|
@@ -425,6 +434,14 @@ class ApiRequester {
|
|
|
425
434
|
this.fetchOptions = options;
|
|
426
435
|
}
|
|
427
436
|
|
|
437
|
+
disableErrorLogging() {
|
|
438
|
+
this.shouldLogErrors = false;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
enableErrorLogging() {
|
|
442
|
+
this.shouldLogErrors = true;
|
|
443
|
+
}
|
|
444
|
+
|
|
428
445
|
async call(
|
|
429
446
|
path ,
|
|
430
447
|
method = 'get',
|
|
@@ -485,7 +502,9 @@ class ApiRequester {
|
|
|
485
502
|
? exceptionClass.fromText(err, response.status)
|
|
486
503
|
: exceptionClass.fromResponse(err, response.status);
|
|
487
504
|
|
|
488
|
-
|
|
505
|
+
if (this.shouldLogErrors) {
|
|
506
|
+
logger.error('API error', error);
|
|
507
|
+
}
|
|
489
508
|
|
|
490
509
|
throw error;
|
|
491
510
|
});
|
|
@@ -493,7 +512,9 @@ class ApiRequester {
|
|
|
493
512
|
|
|
494
513
|
return newParse(response, isJson);
|
|
495
514
|
}).catch(error => {
|
|
496
|
-
|
|
515
|
+
if (this.shouldLogErrors) {
|
|
516
|
+
logger.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
|
|
517
|
+
}
|
|
497
518
|
|
|
498
519
|
throw error;
|
|
499
520
|
});
|
package/esm/web-rtc-client.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import 'webrtc-adapter';
|
|
2
2
|
import { UserAgentState } from 'sip.js/lib/api/user-agent-state';
|
|
3
|
-
import 'sip.js/lib/api/message';
|
|
4
3
|
import { Parser } from 'sip.js/lib/core/messages/parser';
|
|
5
4
|
import { C } from 'sip.js/lib/core/messages/methods/constants';
|
|
6
5
|
import { URI } from 'sip.js/lib/grammar/uri';
|
|
7
6
|
import { UserAgent } from 'sip.js/lib/api/user-agent';
|
|
8
|
-
import { holdModifier } from 'sip.js/lib/platform/web/modifiers/modifiers';
|
|
7
|
+
import { stripVideo, holdModifier } from 'sip.js/lib/platform/web/modifiers/modifiers';
|
|
9
8
|
import { Registerer } from 'sip.js/lib/api/registerer';
|
|
10
9
|
import { Inviter } from 'sip.js/lib/api/inviter';
|
|
11
10
|
import { Messager } from 'sip.js/lib/api/messager';
|
|
@@ -136,6 +135,7 @@ class ApiRequester {
|
|
|
136
135
|
|
|
137
136
|
|
|
138
137
|
|
|
138
|
+
|
|
139
139
|
|
|
140
140
|
|
|
141
141
|
|
|
@@ -175,6 +175,8 @@ class ApiRequester {
|
|
|
175
175
|
this.token = token;
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
+
this.shouldLogErrors = true;
|
|
179
|
+
|
|
178
180
|
methods.forEach(method => {
|
|
179
181
|
// $FlowFixMe
|
|
180
182
|
ApiRequester.prototype[method] = function sugar(...args) {
|
|
@@ -198,6 +200,14 @@ class ApiRequester {
|
|
|
198
200
|
this.fetchOptions = options;
|
|
199
201
|
}
|
|
200
202
|
|
|
203
|
+
disableErrorLogging() {
|
|
204
|
+
this.shouldLogErrors = false;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
enableErrorLogging() {
|
|
208
|
+
this.shouldLogErrors = true;
|
|
209
|
+
}
|
|
210
|
+
|
|
201
211
|
async call(
|
|
202
212
|
path ,
|
|
203
213
|
method = 'get',
|
|
@@ -258,7 +268,9 @@ class ApiRequester {
|
|
|
258
268
|
? exceptionClass.fromText(err, response.status)
|
|
259
269
|
: exceptionClass.fromResponse(err, response.status);
|
|
260
270
|
|
|
261
|
-
|
|
271
|
+
if (this.shouldLogErrors) {
|
|
272
|
+
logger$2.error('API error', error);
|
|
273
|
+
}
|
|
262
274
|
|
|
263
275
|
throw error;
|
|
264
276
|
});
|
|
@@ -266,7 +278,9 @@ class ApiRequester {
|
|
|
266
278
|
|
|
267
279
|
return newParse(response, isJson);
|
|
268
280
|
}).catch(error => {
|
|
269
|
-
|
|
281
|
+
if (this.shouldLogErrors) {
|
|
282
|
+
logger$2.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
|
|
283
|
+
}
|
|
270
284
|
|
|
271
285
|
throw error;
|
|
272
286
|
});
|
|
@@ -577,7 +591,13 @@ class IssueReporter {
|
|
|
577
591
|
}
|
|
578
592
|
|
|
579
593
|
_isLevelAbove(level1 , level2 ) {
|
|
580
|
-
|
|
594
|
+
const index1 = LOG_LEVELS.indexOf(level1);
|
|
595
|
+
const index2 = LOG_LEVELS.indexOf(level2);
|
|
596
|
+
if (index1 === -1 || index2 === -1) {
|
|
597
|
+
return false;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
return index1 > index2;
|
|
581
601
|
}
|
|
582
602
|
|
|
583
603
|
_makeCategory(category ) {
|
|
@@ -606,23 +626,6 @@ const areCandidateValid = (candidates ) =>
|
|
|
606
626
|
getSrflxOrRelay(candidates)
|
|
607
627
|
.length > 0;
|
|
608
628
|
|
|
609
|
-
const toggleVideoDirection = (sdp , direction ) => {
|
|
610
|
-
const parsedSdp = sdpParser.parse(sdp);
|
|
611
|
-
parsedSdp.media = parsedSdp.media.map(media => ({
|
|
612
|
-
...media,
|
|
613
|
-
...(media.type === 'video' ? { direction } : {}),
|
|
614
|
-
}));
|
|
615
|
-
|
|
616
|
-
return sdpParser.write(parsedSdp);
|
|
617
|
-
};
|
|
618
|
-
|
|
619
|
-
const deactivateVideoModifier = (rawDescription ) => {
|
|
620
|
-
const description = rawDescription;
|
|
621
|
-
description.sdp = toggleVideoDirection(description.sdp, 'inactive');
|
|
622
|
-
|
|
623
|
-
return Promise.resolve(description);
|
|
624
|
-
};
|
|
625
|
-
|
|
626
629
|
const hasAnActiveVideo = (sdp ) => {
|
|
627
630
|
if (!sdp) {
|
|
628
631
|
return false;
|
|
@@ -734,6 +737,7 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
734
737
|
const iceRestart = options.offerOptions ? options.offerOptions.iceRestart : false;
|
|
735
738
|
|
|
736
739
|
const isConference = options ? !!options.conference : false;
|
|
740
|
+
const audioOnly = options ? !!options.audioOnly : false;
|
|
737
741
|
|
|
738
742
|
// We should wait for ice when iceRestart (reinvite) or for the first invite
|
|
739
743
|
// We shouldn't wait for ice when holding or resuming the call
|
|
@@ -760,16 +764,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
760
764
|
};
|
|
761
765
|
|
|
762
766
|
return this.getLocalMediaStream(options)
|
|
763
|
-
.then(() => this.updateDirection(options, isConference))
|
|
767
|
+
.then(() => this.updateDirection(options, isConference, audioOnly))
|
|
764
768
|
.then(() => this.createDataChannel(options))
|
|
765
769
|
.then(() => {
|
|
766
|
-
if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options)) {
|
|
770
|
+
if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
|
|
767
771
|
// Add a video an empty bundle to be able to replaceTrack when joining a conference without video
|
|
768
772
|
this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
|
|
769
773
|
}
|
|
770
774
|
})
|
|
771
775
|
.then(() => this.createLocalOfferOrAnswer(options))
|
|
772
|
-
.then(
|
|
776
|
+
.then(sessionDescription => this.setLocalSessionDescription(sessionDescription))
|
|
773
777
|
.then(() => this.waitForIceGatheringComplete(iceRestart, iceTimeout))
|
|
774
778
|
.then(() => this.getLocalSessionDescription())
|
|
775
779
|
.then(description => {
|
|
@@ -892,7 +896,8 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
892
896
|
}
|
|
893
897
|
|
|
894
898
|
// Overridden to send `inactive` in conference
|
|
895
|
-
updateDirection(options , isConference = false
|
|
899
|
+
updateDirection(options , isConference = false,
|
|
900
|
+
audioOnly = false) {
|
|
896
901
|
if (this._peerConnection === undefined) {
|
|
897
902
|
return Promise.reject(new Error('Peer connection closed.'));
|
|
898
903
|
}
|
|
@@ -907,14 +912,17 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
907
912
|
// if we are stable, assume we are creating a local offer
|
|
908
913
|
this.logger.debug('SessionDescriptionHandler.updateDirection - setting offer direction');
|
|
909
914
|
// determine the direction to offer given the current direction and hold state
|
|
910
|
-
const directionToOffer = (currentDirection ) => {
|
|
915
|
+
const directionToOffer = (currentDirection , transceiver /* RTCRtpTransceiver */) => {
|
|
911
916
|
if (isConference) {
|
|
917
|
+
if (audioOnly && transceiver.receiver.track && transceiver.receiver.track.kind === 'video') {
|
|
918
|
+
return 'sendonly';
|
|
919
|
+
}
|
|
912
920
|
return options && options.hold ? 'sendonly' : 'sendrecv';
|
|
913
921
|
}
|
|
914
922
|
|
|
915
923
|
switch (currentDirection) {
|
|
916
924
|
case 'inactive':
|
|
917
|
-
return options && options.hold ? 'inactive' : 'recvonly';
|
|
925
|
+
return options && options.hold ? 'inactive' : (isConference && !audioOnly ? 'sendrecv' : 'recvonly');
|
|
918
926
|
case 'recvonly':
|
|
919
927
|
return options && options.hold ? 'inactive' : 'recvonly';
|
|
920
928
|
case 'sendonly':
|
|
@@ -930,7 +938,7 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
930
938
|
// set the transceiver direction to the offer direction
|
|
931
939
|
this._peerConnection.getTransceivers().forEach((transceiver) => {
|
|
932
940
|
if (transceiver.direction /* guarding, but should always be true */) {
|
|
933
|
-
const offerDirection = directionToOffer(transceiver.direction);
|
|
941
|
+
const offerDirection = directionToOffer(transceiver.direction, transceiver);
|
|
934
942
|
if (transceiver.direction !== offerDirection) {
|
|
935
943
|
// eslint-disable-next-line no-param-reassign
|
|
936
944
|
transceiver.direction = offerDirection;
|
|
@@ -989,6 +997,13 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
989
997
|
// set the transceiver direction to the answer direction
|
|
990
998
|
this._peerConnection.getTransceivers().forEach((transceiver) => {
|
|
991
999
|
if (transceiver.direction /* guarding, but should always be true */) {
|
|
1000
|
+
const { receiver } = transceiver;
|
|
1001
|
+
if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
|
|
1002
|
+
// eslint-disable-next-line no-param-reassign
|
|
1003
|
+
transceiver.direction = 'inactive';
|
|
1004
|
+
return;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
992
1007
|
if (transceiver.direction !== 'stopped' && transceiver.direction !== answerDirection) {
|
|
993
1008
|
// eslint-disable-next-line no-param-reassign
|
|
994
1009
|
transceiver.direction = answerDirection;
|
|
@@ -1027,8 +1042,8 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
1027
1042
|
}
|
|
1028
1043
|
const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
|
|
1029
1044
|
|
|
1030
|
-
// Do not reuse sender tracks in SFU
|
|
1031
|
-
if (sender && !sfu) {
|
|
1045
|
+
// Do not reuse sender video tracks in SFU
|
|
1046
|
+
if (sender && (!sfu || newTrack.kind === 'audio')) {
|
|
1032
1047
|
trackUpdates.push(
|
|
1033
1048
|
new Promise((resolve) => {
|
|
1034
1049
|
this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
|
|
@@ -2094,7 +2109,7 @@ class Contact {
|
|
|
2094
2109
|
|
|
2095
2110
|
return new Contact({
|
|
2096
2111
|
sourceId: single.id || '',
|
|
2097
|
-
name: single.displayName,
|
|
2112
|
+
name: single.displayName || '',
|
|
2098
2113
|
number: numbers.length ? numbers[0].number : '',
|
|
2099
2114
|
numbers,
|
|
2100
2115
|
emails,
|
|
@@ -2125,7 +2140,7 @@ class Contact {
|
|
|
2125
2140
|
|
|
2126
2141
|
return new Contact({
|
|
2127
2142
|
sourceId: single.id || '',
|
|
2128
|
-
name: single.name,
|
|
2143
|
+
name: single.name || '',
|
|
2129
2144
|
number: numbers.length ? numbers[0].number : '',
|
|
2130
2145
|
numbers,
|
|
2131
2146
|
emails,
|
|
@@ -2226,7 +2241,7 @@ class Contact {
|
|
|
2226
2241
|
} = {}) {
|
|
2227
2242
|
this.id = id;
|
|
2228
2243
|
this.uuid = uuid;
|
|
2229
|
-
this.name = name;
|
|
2244
|
+
this.name = name || '';
|
|
2230
2245
|
this.number = number;
|
|
2231
2246
|
this.numbers = numbers;
|
|
2232
2247
|
this.email = email;
|
|
@@ -3535,17 +3550,66 @@ var updateFrom = (instance , from ) => {
|
|
|
3535
3550
|
|
|
3536
3551
|
//
|
|
3537
3552
|
|
|
3553
|
+
|
|
3554
|
+
|
|
3555
|
+
|
|
3556
|
+
|
|
3557
|
+
|
|
3558
|
+
|
|
3559
|
+
|
|
3560
|
+
|
|
3561
|
+
|
|
3562
|
+
|
|
3563
|
+
|
|
3564
|
+
|
|
3565
|
+
|
|
3566
|
+
|
|
3567
|
+
|
|
3568
|
+
|
|
3569
|
+
class Recording {
|
|
3570
|
+
|
|
3571
|
+
|
|
3572
|
+
|
|
3573
|
+
|
|
3574
|
+
|
|
3575
|
+
|
|
3576
|
+
static parseMany(recordings ) {
|
|
3577
|
+
return recordings.map(item => Recording.parse(item));
|
|
3578
|
+
}
|
|
3579
|
+
|
|
3580
|
+
static parse(plain ) {
|
|
3581
|
+
return new Recording({
|
|
3582
|
+
deleted: plain.deleted,
|
|
3583
|
+
fileName: plain.filename,
|
|
3584
|
+
end: plain.end_time ? moment(plain.end_time).toDate() : null,
|
|
3585
|
+
start: moment(plain.start_time).toDate(),
|
|
3586
|
+
uuid: plain.uuid,
|
|
3587
|
+
});
|
|
3588
|
+
}
|
|
3589
|
+
|
|
3590
|
+
constructor({ deleted, end, fileName, start, uuid } ) {
|
|
3591
|
+
this.deleted = deleted;
|
|
3592
|
+
this.end = end;
|
|
3593
|
+
this.fileName = fileName;
|
|
3594
|
+
this.start = start;
|
|
3595
|
+
this.uuid = uuid;
|
|
3596
|
+
}
|
|
3597
|
+
}
|
|
3598
|
+
|
|
3599
|
+
//
|
|
3600
|
+
|
|
3538
3601
|
|
|
3539
|
-
|
|
3602
|
+
|
|
3540
3603
|
|
|
3541
3604
|
|
|
3542
3605
|
|
|
3543
3606
|
|
|
3544
3607
|
|
|
3545
|
-
|
|
3608
|
+
|
|
3546
3609
|
|
|
3547
3610
|
|
|
3548
3611
|
|
|
3612
|
+
|
|
3549
3613
|
|
|
3550
3614
|
|
|
3551
3615
|
|
|
@@ -3558,7 +3622,7 @@ var updateFrom = (instance , from ) => {
|
|
|
3558
3622
|
|
|
3559
3623
|
|
|
3560
3624
|
|
|
3561
|
-
|
|
3625
|
+
|
|
3562
3626
|
|
|
3563
3627
|
|
|
3564
3628
|
|
|
@@ -3573,13 +3637,14 @@ var updateFrom = (instance , from ) => {
|
|
|
3573
3637
|
|
|
3574
3638
|
|
|
3575
3639
|
|
|
3576
|
-
|
|
3640
|
+
|
|
3641
|
+
|
|
3577
3642
|
|
|
3578
3643
|
|
|
3579
3644
|
class CallLog {
|
|
3580
3645
|
|
|
3581
3646
|
|
|
3582
|
-
|
|
3647
|
+
|
|
3583
3648
|
|
|
3584
3649
|
|
|
3585
3650
|
|
|
@@ -3596,7 +3661,7 @@ class CallLog {
|
|
|
3596
3661
|
|
|
3597
3662
|
|
|
3598
3663
|
|
|
3599
|
-
|
|
3664
|
+
|
|
3600
3665
|
|
|
3601
3666
|
static merge(current , toMerge ) {
|
|
3602
3667
|
const onlyUnique = (value, index, self) => self.indexOf(value) === index;
|
|
@@ -3613,7 +3678,7 @@ class CallLog {
|
|
|
3613
3678
|
|
|
3614
3679
|
static parse(plain ) {
|
|
3615
3680
|
return new CallLog({
|
|
3616
|
-
answer: moment(plain.answer).toDate(),
|
|
3681
|
+
answer: plain.answer ? moment(plain.answer).toDate() : null,
|
|
3617
3682
|
answered: plain.answered,
|
|
3618
3683
|
callDirection: plain.call_direction,
|
|
3619
3684
|
destination: {
|
|
@@ -3627,13 +3692,14 @@ class CallLog {
|
|
|
3627
3692
|
id: plain.id,
|
|
3628
3693
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3629
3694
|
start: moment(plain.start).toDate(),
|
|
3630
|
-
end: moment(plain.end).toDate(),
|
|
3695
|
+
end: plain.end ? moment(plain.end).toDate() : null,
|
|
3696
|
+
recordings: Recording.parseMany(plain.recordings),
|
|
3631
3697
|
});
|
|
3632
3698
|
}
|
|
3633
3699
|
|
|
3634
3700
|
static parseNew(plain , session ) {
|
|
3635
3701
|
return new CallLog({
|
|
3636
|
-
answer: moment(plain.answer).toDate(),
|
|
3702
|
+
answer: plain.answer ? moment(plain.answer).toDate() : null,
|
|
3637
3703
|
answered: plain.answered,
|
|
3638
3704
|
callDirection: plain.call_direction,
|
|
3639
3705
|
destination: {
|
|
@@ -3647,7 +3713,8 @@ class CallLog {
|
|
|
3647
3713
|
id: plain.id,
|
|
3648
3714
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3649
3715
|
start: moment(plain.start).toDate(),
|
|
3650
|
-
end: moment(plain.end).toDate(),
|
|
3716
|
+
end: plain.end ? moment(plain.end).toDate() : null,
|
|
3717
|
+
recordings: Recording.parseMany(plain.recordings),
|
|
3651
3718
|
// @TODO: FIXME add verification declined vs missed call
|
|
3652
3719
|
newMissedCall: session
|
|
3653
3720
|
&& session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
|
|
@@ -4883,6 +4950,10 @@ class ApiClient {
|
|
|
4883
4950
|
this.fetchOptions = fetchOptions;
|
|
4884
4951
|
this.client.setFetchOptions(fetchOptions);
|
|
4885
4952
|
}
|
|
4953
|
+
|
|
4954
|
+
disableErrorLogging() {
|
|
4955
|
+
this.client.disableErrorLogging();
|
|
4956
|
+
}
|
|
4886
4957
|
}
|
|
4887
4958
|
|
|
4888
4959
|
//
|
|
@@ -5375,9 +5446,15 @@ class WebRTCClient extends Emitter {
|
|
|
5375
5446
|
|
|
5376
5447
|
call(number , enableVideo , audioOnly = false, conference = false) {
|
|
5377
5448
|
logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
|
|
5378
|
-
const inviterOptions
|
|
5449
|
+
const inviterOptions = {
|
|
5450
|
+
sessionDescriptionHandlerOptionsReInvite: {
|
|
5451
|
+
conference,
|
|
5452
|
+
audioOnly,
|
|
5453
|
+
},
|
|
5454
|
+
};
|
|
5455
|
+
|
|
5379
5456
|
if (audioOnly) {
|
|
5380
|
-
inviterOptions.sessionDescriptionHandlerModifiersReInvite = [
|
|
5457
|
+
inviterOptions.sessionDescriptionHandlerModifiersReInvite = [stripVideo];
|
|
5381
5458
|
}
|
|
5382
5459
|
|
|
5383
5460
|
const session = new Inviter(this.userAgent, this._makeURI(number), inviterOptions);
|
|
@@ -5406,10 +5483,11 @@ class WebRTCClient extends Emitter {
|
|
|
5406
5483
|
sessionDescriptionHandlerOptions: this.getMediaConfiguration(enableVideo || false, conference),
|
|
5407
5484
|
};
|
|
5408
5485
|
|
|
5409
|
-
inviteOptions.
|
|
5486
|
+
inviteOptions.sessionDescriptionHandlerOptions.audioOnly = audioOnly;
|
|
5410
5487
|
|
|
5488
|
+
inviteOptions.sessionDescriptionHandlerModifiers = [replaceLocalIpModifier];
|
|
5411
5489
|
if (audioOnly) {
|
|
5412
|
-
inviteOptions.sessionDescriptionHandlerModifiers.push(
|
|
5490
|
+
inviteOptions.sessionDescriptionHandlerModifiers.push(stripVideo);
|
|
5413
5491
|
}
|
|
5414
5492
|
|
|
5415
5493
|
// Do not await invite here or we'll miss the Establishing state transition
|
|
@@ -5623,6 +5701,9 @@ class WebRTCClient extends Emitter {
|
|
|
5623
5701
|
if (!this._isWeb()) {
|
|
5624
5702
|
options.sessionDescriptionHandlerModifiers = [holdModifier];
|
|
5625
5703
|
}
|
|
5704
|
+
options.sessionDescriptionHandlerOptions = {
|
|
5705
|
+
constraints: options.constraints,
|
|
5706
|
+
};
|
|
5626
5707
|
|
|
5627
5708
|
// Send re-INVITE
|
|
5628
5709
|
return session.invite(options);
|
|
@@ -5662,6 +5743,9 @@ class WebRTCClient extends Emitter {
|
|
|
5662
5743
|
// (eg: holdModifier)
|
|
5663
5744
|
options.sessionDescriptionHandlerModifiers = [];
|
|
5664
5745
|
}
|
|
5746
|
+
options.sessionDescriptionHandlerOptions = {
|
|
5747
|
+
constraints: options.constraints,
|
|
5748
|
+
};
|
|
5665
5749
|
|
|
5666
5750
|
// Send re-INVITE
|
|
5667
5751
|
return session.invite(options);
|
|
@@ -5891,7 +5975,8 @@ class WebRTCClient extends Emitter {
|
|
|
5891
5975
|
? this.video.deviceId.exact : undefined;
|
|
5892
5976
|
}
|
|
5893
5977
|
|
|
5894
|
-
reinvite(sipSession , newConstraints = null, conference = false
|
|
5978
|
+
reinvite(sipSession , newConstraints = null, conference = false,
|
|
5979
|
+
audioOnly = false) {
|
|
5895
5980
|
if (!sipSession) {
|
|
5896
5981
|
return false;
|
|
5897
5982
|
}
|
|
@@ -5901,16 +5986,17 @@ class WebRTCClient extends Emitter {
|
|
|
5901
5986
|
}
|
|
5902
5987
|
|
|
5903
5988
|
const wasMuted = this.isAudioMuted(sipSession);
|
|
5904
|
-
// When upgrading to video, remove the `
|
|
5989
|
+
// When upgrading to video, remove the `stripVideo` modifiers
|
|
5905
5990
|
if (newConstraints && newConstraints.video) {
|
|
5906
5991
|
const modifiers = sipSession.sessionDescriptionHandlerModifiersReInvite;
|
|
5907
5992
|
sipSession.sessionDescriptionHandlerModifiersReInvite = modifiers.filter(modifier =>
|
|
5908
|
-
modifier !==
|
|
5993
|
+
modifier !== stripVideo);
|
|
5909
5994
|
}
|
|
5910
5995
|
|
|
5911
5996
|
sipSession.sessionDescriptionHandlerOptionsReInvite = {
|
|
5912
5997
|
...sipSession.sessionDescriptionHandlerOptionsReInvite,
|
|
5913
5998
|
conference,
|
|
5999
|
+
audioOnly,
|
|
5914
6000
|
};
|
|
5915
6001
|
|
|
5916
6002
|
const shouldDoVideo = newConstraints ? newConstraints.video : this.sessionWantsToDoVideo(sipSession);
|
|
@@ -5950,6 +6036,8 @@ class WebRTCClient extends Emitter {
|
|
|
5950
6036
|
},
|
|
5951
6037
|
sessionDescriptionHandlerOptions: {
|
|
5952
6038
|
constraints,
|
|
6039
|
+
conference,
|
|
6040
|
+
audioOnly,
|
|
5953
6041
|
offerOptions: {
|
|
5954
6042
|
iceRestart: false,
|
|
5955
6043
|
},
|
|
@@ -6409,6 +6497,8 @@ class WebRTCClient extends Emitter {
|
|
|
6409
6497
|
|
|
6410
6498
|
// Invitation and Inviter extends Session
|
|
6411
6499
|
_setupSession(session ) {
|
|
6500
|
+
const sipSessionId = this.getSipSessionId(session);
|
|
6501
|
+
|
|
6412
6502
|
// When receiving an Invitation, the delegate is not defined.
|
|
6413
6503
|
if (!session.delegate) {
|
|
6414
6504
|
session.delegate = {};
|
|
@@ -6432,8 +6522,18 @@ class WebRTCClient extends Emitter {
|
|
|
6432
6522
|
};
|
|
6433
6523
|
};
|
|
6434
6524
|
|
|
6525
|
+
const oldInviteRequest = session.onInviteRequest.bind(session);
|
|
6526
|
+
let hadRemoteVideo = false;
|
|
6527
|
+
|
|
6528
|
+
// Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
|
|
6529
|
+
// Becase when `onInvite` is called we already got the video track
|
|
6530
|
+
session.onInviteRequest = (request) => {
|
|
6531
|
+
hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
|
|
6532
|
+
|
|
6533
|
+
oldInviteRequest(request);
|
|
6534
|
+
};
|
|
6535
|
+
|
|
6435
6536
|
session.delegate.onInvite = (request ) => {
|
|
6436
|
-
const sipSessionId = this.getSipSessionId(session);
|
|
6437
6537
|
let updatedCalleeName = null;
|
|
6438
6538
|
let updatedNumber = null;
|
|
6439
6539
|
if (session.assertedIdentity) {
|
|
@@ -6443,7 +6543,6 @@ class WebRTCClient extends Emitter {
|
|
|
6443
6543
|
logger.info('re-invite received', { updatedCalleeName, updatedNumber });
|
|
6444
6544
|
|
|
6445
6545
|
// Useful to know if it's a video upgrade or an unhold from a remote peer with a video stream
|
|
6446
|
-
const hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
|
|
6447
6546
|
|
|
6448
6547
|
// Update SDP
|
|
6449
6548
|
// Remote video is handled by the `track` event. Here we're dealing with video stream removal.
|
|
@@ -6493,7 +6592,7 @@ class WebRTCClient extends Emitter {
|
|
|
6493
6592
|
}
|
|
6494
6593
|
|
|
6495
6594
|
_isAudioOnly(session ) {
|
|
6496
|
-
return session.sessionDescriptionHandlerModifiersReInvite.find(modifier => modifier ===
|
|
6595
|
+
return session.sessionDescriptionHandlerModifiersReInvite.find(modifier => modifier === stripVideo);
|
|
6497
6596
|
}
|
|
6498
6597
|
|
|
6499
6598
|
_setupMedias(session , newStream ) {
|
package/esm/websocket-client.js
CHANGED
|
@@ -300,7 +300,13 @@ class IssueReporter {
|
|
|
300
300
|
}
|
|
301
301
|
|
|
302
302
|
_isLevelAbove(level1 , level2 ) {
|
|
303
|
-
|
|
303
|
+
const index1 = LOG_LEVELS.indexOf(level1);
|
|
304
|
+
const index2 = LOG_LEVELS.indexOf(level2);
|
|
305
|
+
if (index1 === -1 || index2 === -1) {
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return index1 > index2;
|
|
304
310
|
}
|
|
305
311
|
|
|
306
312
|
_makeCategory(category ) {
|