@wazo/sdk 0.37.23 → 0.37.27
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 +95 -57
- package/dist/wazo-sdk.js +3 -3
- package/esm/__tests__/api-client.test.js +12 -7
- package/esm/__tests__/web-rtc-client.test.js +47 -20
- package/esm/api/agentd.js +1 -1
- package/esm/api/amid.js +1 -1
- package/esm/api/application.js +1 -1
- package/esm/api/auth.js +1 -1
- package/esm/api/call-logd.js +1 -1
- package/esm/api/calld.js +1 -1
- package/esm/api/chatd.js +1 -1
- package/esm/api/confd.js +11 -6
- package/esm/api/ctid-ng.js +1 -1
- package/esm/api/dird.js +2 -2
- package/esm/api/webhookd.js +1 -1
- package/esm/api-client.js +12 -7
- package/esm/checker/Checker.js +47 -20
- package/esm/checker/checks/aor.js +12 -7
- package/esm/checker/checks/api.js +12 -7
- package/esm/checker/checks/index.js +47 -20
- package/esm/checker/checks/wazo-websocket.js +1 -1
- package/esm/checker/checks/webrtc-transport.js +47 -20
- package/esm/checker/checks/webrtc.js +47 -20
- package/esm/domain/AdHocAPIConference.js +12 -7
- package/esm/domain/Contact.js +1 -1
- package/esm/domain/Features.js +12 -7
- package/esm/domain/Meeting.js +12 -5
- package/esm/domain/Phone/CTIPhone.js +12 -7
- package/esm/domain/Phone/WebRTCPhone.js +34 -6
- package/esm/domain/__tests__/Contact.test.js +1 -1
- package/esm/domain/__tests__/Meeting.test.js +144 -0
- package/esm/index.js +80 -25
- package/esm/lib/WazoSessionDescriptionHandler.js +9 -4
- package/esm/service/CallApi.js +12 -7
- package/esm/service/IssueReporter.js +1 -1
- package/esm/service/__tests__/IssueReporter.test.js +1 -1
- package/esm/service/getApiClient.js +12 -7
- package/esm/simple/Auth.js +80 -25
- package/esm/simple/Configuration.js +80 -25
- package/esm/simple/Directory.js +12 -7
- package/esm/simple/Phone.js +80 -25
- package/esm/simple/Websocket.js +1 -1
- package/esm/simple/index.js +80 -25
- package/esm/simple/room/LocalParticipant.js +80 -25
- package/esm/simple/room/Participant.js +80 -25
- package/esm/simple/room/RemoteParticipant.js +80 -25
- package/esm/simple/room/Room.js +80 -25
- package/esm/simple/room/SipRoom.js +80 -25
- package/esm/simple/room/Stream.js +80 -25
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +80 -25
- package/esm/simple/utils.js +80 -25
- package/esm/types/WebSocketMessage.js +1 -1
- package/esm/utils/__tests__/api-requester.test.js +1 -1
- package/esm/utils/api-requester.js +1 -1
- package/esm/web-rtc-client.js +47 -20
- package/esm/websocket-client.js +1 -1
- package/lib/__tests__/api-client.test.js +12 -7
- package/lib/__tests__/web-rtc-client.test.js +47 -20
- package/lib/api/agentd.js +1 -1
- package/lib/api/amid.js +1 -1
- package/lib/api/application.js +1 -1
- package/lib/api/auth.js +1 -1
- package/lib/api/call-logd.js +1 -1
- package/lib/api/calld.js +1 -1
- package/lib/api/chatd.js +1 -1
- package/lib/api/confd.js +11 -6
- package/lib/api/ctid-ng.js +1 -1
- package/lib/api/dird.js +2 -2
- package/lib/api/webhookd.js +1 -1
- package/lib/api-client.js +12 -7
- package/lib/checker/Checker.js +47 -20
- package/lib/checker/checks/aor.js +12 -7
- package/lib/checker/checks/api.js +12 -7
- package/lib/checker/checks/index.js +47 -20
- package/lib/checker/checks/wazo-websocket.js +1 -1
- package/lib/checker/checks/webrtc-transport.js +47 -20
- package/lib/checker/checks/webrtc.js +47 -20
- package/lib/domain/AdHocAPIConference.js +12 -7
- package/lib/domain/Contact.js +1 -1
- package/lib/domain/Features.js +12 -7
- package/lib/domain/Meeting.js +16 -5
- package/lib/domain/Phone/CTIPhone.js +12 -7
- package/lib/domain/Phone/WebRTCPhone.js +34 -6
- package/lib/domain/__tests__/Contact.test.js +1 -1
- package/lib/domain/__tests__/Meeting.test.js +150 -0
- package/lib/index.js +80 -25
- package/lib/lib/WazoSessionDescriptionHandler.js +9 -4
- package/lib/service/CallApi.js +12 -7
- package/lib/service/IssueReporter.js +1 -1
- package/lib/service/__tests__/IssueReporter.test.js +1 -1
- package/lib/service/getApiClient.js +12 -7
- package/lib/simple/Auth.js +80 -25
- package/lib/simple/Configuration.js +80 -25
- package/lib/simple/Directory.js +12 -7
- package/lib/simple/Phone.js +80 -25
- package/lib/simple/Websocket.js +1 -1
- package/lib/simple/index.js +80 -25
- package/lib/simple/room/LocalParticipant.js +80 -25
- package/lib/simple/room/Participant.js +80 -25
- package/lib/simple/room/RemoteParticipant.js +80 -25
- package/lib/simple/room/Room.js +80 -25
- package/lib/simple/room/SipRoom.js +80 -25
- package/lib/simple/room/Stream.js +80 -25
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +80 -25
- package/lib/simple/utils.js +80 -25
- package/lib/types/WebSocketMessage.js +2 -0
- package/lib/utils/__tests__/api-requester.test.js +1 -1
- package/lib/utils/api-requester.js +1 -1
- package/lib/web-rtc-client.js +47 -20
- package/lib/websocket-client.js +1 -1
- package/package.json +1 -1
- package/src/domain/Contact.js +1 -1
- package/src/domain/Meeting.js +12 -5
- package/src/domain/Phone/WebRTCPhone.js +33 -5
- package/src/domain/__tests__/Meeting.test.js +50 -0
- package/src/lib/WazoSessionDescriptionHandler.js +8 -3
- package/src/utils/api-requester.js +1 -1
- package/src/web-rtc-client.js +27 -10
|
@@ -405,7 +405,7 @@ IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
|
|
|
405
405
|
|
|
406
406
|
// Use a function here to be able to mock it in tests
|
|
407
407
|
const realFetch = () => {
|
|
408
|
-
if (typeof document !== 'undefined') {
|
|
408
|
+
if (typeof document !== 'undefined' && window.fetch) {
|
|
409
409
|
// Browser
|
|
410
410
|
return window.fetch;
|
|
411
411
|
}
|
|
@@ -1051,6 +1051,7 @@ class WebRTCPhone extends Emitter {
|
|
|
1051
1051
|
constraints,
|
|
1052
1052
|
audioOnly,
|
|
1053
1053
|
conference,
|
|
1054
|
+
iceRestart,
|
|
1054
1055
|
});
|
|
1055
1056
|
|
|
1056
1057
|
if (!sipSession) {
|
|
@@ -1154,6 +1155,11 @@ class WebRTCPhone extends Emitter {
|
|
|
1154
1155
|
|
|
1155
1156
|
this.client.downgradeToAudio(sipSession);
|
|
1156
1157
|
|
|
1158
|
+
if (callSession) {
|
|
1159
|
+
callSession.cameraEnabled = false;
|
|
1160
|
+
this._updateCallSession(callSession);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1157
1163
|
if (withMessage) {
|
|
1158
1164
|
this._sendReinviteMessage(callSession, false);
|
|
1159
1165
|
}
|
|
@@ -1181,6 +1187,11 @@ class WebRTCPhone extends Emitter {
|
|
|
1181
1187
|
|
|
1182
1188
|
const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
|
|
1183
1189
|
|
|
1190
|
+
if (callSession) {
|
|
1191
|
+
callSession.cameraEnabled = true;
|
|
1192
|
+
this._updateCallSession(callSession);
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1184
1195
|
// If no stream is returned, it means we have to reinvite
|
|
1185
1196
|
if (!newStream) {
|
|
1186
1197
|
return true;
|
|
@@ -1450,7 +1461,7 @@ class WebRTCPhone extends Emitter {
|
|
|
1450
1461
|
}
|
|
1451
1462
|
|
|
1452
1463
|
_onCallAccepted(sipSession , cameraEnabled ) {
|
|
1453
|
-
logger.info('WebRTC phone -
|
|
1464
|
+
logger.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
|
|
1454
1465
|
|
|
1455
1466
|
const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
|
|
1456
1467
|
this.currentSipSession = sipSession;
|
|
@@ -1519,6 +1530,7 @@ class WebRTCPhone extends Emitter {
|
|
|
1519
1530
|
_onCallTerminated(sipSession ) {
|
|
1520
1531
|
logger.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
|
|
1521
1532
|
|
|
1533
|
+
const sipSessionId = this.getSipSessionId(sipSession);
|
|
1522
1534
|
const callSession = this._createCallSession(sipSession);
|
|
1523
1535
|
const isCurrentSession = this.isCurrentCallSipSession(callSession);
|
|
1524
1536
|
const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
|
|
@@ -1536,7 +1548,6 @@ class WebRTCPhone extends Emitter {
|
|
|
1536
1548
|
}, 5);
|
|
1537
1549
|
}
|
|
1538
1550
|
|
|
1539
|
-
const sipSessionId = this.getSipSessionId(sipSession);
|
|
1540
1551
|
if (sipSessionId) {
|
|
1541
1552
|
this.removeIncomingSessions(sipSessionId);
|
|
1542
1553
|
}
|
|
@@ -1962,7 +1973,7 @@ class WebRTCPhone extends Emitter {
|
|
|
1962
1973
|
// @TODO: line is not used here
|
|
1963
1974
|
async makeCall(number , line , cameraEnabled ,
|
|
1964
1975
|
audioOnly = false, conference = false) {
|
|
1965
|
-
logger.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
|
|
1976
|
+
logger.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
|
|
1966
1977
|
if (!number) {
|
|
1967
1978
|
return Promise.resolve(null);
|
|
1968
1979
|
}
|
|
@@ -2181,8 +2192,12 @@ class WebRTCPhone extends Emitter {
|
|
|
2181
2192
|
}
|
|
2182
2193
|
|
|
2183
2194
|
const sessionId = this.incomingSessions[0];
|
|
2195
|
+
const sipSession = this.client.getSipSession(sessionId);
|
|
2196
|
+
if (!sipSession) {
|
|
2197
|
+
return null;
|
|
2198
|
+
}
|
|
2184
2199
|
|
|
2185
|
-
return this._createCallSession(
|
|
2200
|
+
return this._createCallSession(sipSession);
|
|
2186
2201
|
}
|
|
2187
2202
|
|
|
2188
2203
|
sendMessage(sipSession = null, body , contentType = 'text/plain') {
|
|
@@ -2323,9 +2338,13 @@ class WebRTCPhone extends Emitter {
|
|
|
2323
2338
|
if (this.shouldSendReinvite && this.currentSipSession
|
|
2324
2339
|
&& this.currentSipSession.state === SessionState.Established) {
|
|
2325
2340
|
this.shouldSendReinvite = false;
|
|
2341
|
+
const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
|
|
2342
|
+
const isConference = pc ? pc.sfu : false;
|
|
2343
|
+
const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
|
|
2344
|
+
|
|
2326
2345
|
try {
|
|
2327
2346
|
// Send reinvite with iceRestart
|
|
2328
|
-
this.sendReinvite(this.currentCallSession, null,
|
|
2347
|
+
this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
|
|
2329
2348
|
} catch (e) {
|
|
2330
2349
|
logger.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
|
|
2331
2350
|
}
|
|
@@ -2409,6 +2428,15 @@ class WebRTCPhone extends Emitter {
|
|
|
2409
2428
|
return this.client.getSipSessionId(sipSession);
|
|
2410
2429
|
}
|
|
2411
2430
|
|
|
2431
|
+
_updateCallSession(callSession ) {
|
|
2432
|
+
const sipSession = this.findSipSession(callSession);
|
|
2433
|
+
const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
|
|
2434
|
+
|
|
2435
|
+
if (sipSessionId) {
|
|
2436
|
+
this.callSessions[sipSessionId] = callSession;
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
|
|
2412
2440
|
_onMessage(message ) {
|
|
2413
2441
|
if (!message || message.method !== 'MESSAGE') {
|
|
2414
2442
|
return;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import moment from 'moment';
|
|
2
|
+
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
var newFrom = (instance , ToClass ) => {
|
|
6
|
+
const args = {};
|
|
7
|
+
Object.getOwnPropertyNames(instance).forEach(prop => {
|
|
8
|
+
args[prop] = instance[prop];
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
return new ToClass(args);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
//
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Meeting {
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
static parse(plain ) {
|
|
42
|
+
return new Meeting({
|
|
43
|
+
guestSipAuthorization: plain.guest_sip_authorization,
|
|
44
|
+
uri: plain.ingress_http_uri,
|
|
45
|
+
name: plain.name,
|
|
46
|
+
ownerUuids: plain.owner_uuids,
|
|
47
|
+
port: plain.port,
|
|
48
|
+
uuid: plain.uuid,
|
|
49
|
+
extension: plain.exten,
|
|
50
|
+
persistent: plain.persistent,
|
|
51
|
+
creationTime: moment(plain.creation_time).toDate(),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static parseMany(items ) {
|
|
56
|
+
if (!items) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
return items.map(plain => Meeting.parse(plain));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static newFrom(meeting ) {
|
|
63
|
+
return newFrom(meeting, Meeting);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
constructor({
|
|
67
|
+
uuid,
|
|
68
|
+
name,
|
|
69
|
+
guestSipAuthorization,
|
|
70
|
+
ownerUuids,
|
|
71
|
+
port,
|
|
72
|
+
uri,
|
|
73
|
+
extension,
|
|
74
|
+
persistent,
|
|
75
|
+
creationTime,
|
|
76
|
+
} = {}) {
|
|
77
|
+
this.guestSipAuthorization = guestSipAuthorization;
|
|
78
|
+
this.uri = uri;
|
|
79
|
+
this.name = name;
|
|
80
|
+
this.ownerUuids = ownerUuids;
|
|
81
|
+
this.port = port;
|
|
82
|
+
this.uuid = uuid;
|
|
83
|
+
this.extension = extension;
|
|
84
|
+
this.persistent = persistent;
|
|
85
|
+
this.creationTime = creationTime;
|
|
86
|
+
|
|
87
|
+
// Useful to compare instead of instanceof with minified code
|
|
88
|
+
this.type = 'Meeting';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
getGuestSipCredentials() {
|
|
92
|
+
// eslint-disable-next-line no-undef
|
|
93
|
+
const [username, secret] = atob(this.guestSipAuthorization).split(':');
|
|
94
|
+
return { username, secret };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//
|
|
99
|
+
|
|
100
|
+
describe('Meeting domain', () => {
|
|
101
|
+
it('can return username and secret from an base64 encrypted string', () => {
|
|
102
|
+
const USERNAME = 'username';
|
|
103
|
+
const SECRET = 'secret';
|
|
104
|
+
|
|
105
|
+
const args = {
|
|
106
|
+
guest_sip_authorization: btoa(`${USERNAME}:${SECRET}`),
|
|
107
|
+
creation_time: '',
|
|
108
|
+
ingress_http_uri: '',
|
|
109
|
+
name: '',
|
|
110
|
+
owner_uuids: [],
|
|
111
|
+
port: '',
|
|
112
|
+
uuid: '',
|
|
113
|
+
exten: '',
|
|
114
|
+
persistent: false,
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const meeting = Meeting.parse(args);
|
|
118
|
+
|
|
119
|
+
const { username, secret } = meeting.getGuestSipCredentials();
|
|
120
|
+
|
|
121
|
+
expect(username).toEqual(USERNAME);
|
|
122
|
+
expect(secret).toEqual(SECRET);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should return a date from a string', () => {
|
|
126
|
+
const args = {
|
|
127
|
+
creation_time: '2021-12-21T15:56:42.880Z',
|
|
128
|
+
guest_sip_authorization: '',
|
|
129
|
+
ingress_http_uri: '',
|
|
130
|
+
name: '',
|
|
131
|
+
owner_uuids: [],
|
|
132
|
+
port: '',
|
|
133
|
+
uuid: '',
|
|
134
|
+
exten: '',
|
|
135
|
+
persistent: false,
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const { creationTime } = Meeting.parse(args);
|
|
139
|
+
|
|
140
|
+
expect(creationTime.getDate()).toEqual(21);
|
|
141
|
+
expect(creationTime.getFullYear()).toEqual(2021);
|
|
142
|
+
expect(creationTime.getMonth()).toEqual(11);
|
|
143
|
+
});
|
|
144
|
+
});
|
package/esm/index.js
CHANGED
|
@@ -464,7 +464,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
|
|
|
464
464
|
|
|
465
465
|
// Use a function here to be able to mock it in tests
|
|
466
466
|
const realFetch = () => {
|
|
467
|
-
if (typeof document !== 'undefined') {
|
|
467
|
+
if (typeof document !== 'undefined' && window.fetch) {
|
|
468
468
|
// Browser
|
|
469
469
|
return window.fetch;
|
|
470
470
|
}
|
|
@@ -1924,7 +1924,7 @@ class Contact {
|
|
|
1924
1924
|
this[key] = old[key] || this[key];
|
|
1925
1925
|
});
|
|
1926
1926
|
|
|
1927
|
-
if (old.lineState
|
|
1927
|
+
if (old.lineState) {
|
|
1928
1928
|
this.lineState = old.lineState;
|
|
1929
1929
|
}
|
|
1930
1930
|
|
|
@@ -2631,8 +2631,9 @@ class ExternalApp {
|
|
|
2631
2631
|
|
|
2632
2632
|
|
|
2633
2633
|
|
|
2634
|
-
|
|
2634
|
+
|
|
2635
2635
|
|
|
2636
|
+
|
|
2636
2637
|
|
|
2637
2638
|
|
|
2638
2639
|
class Meeting {
|
|
@@ -2643,9 +2644,10 @@ class Meeting {
|
|
|
2643
2644
|
|
|
2644
2645
|
|
|
2645
2646
|
|
|
2646
|
-
|
|
2647
|
+
|
|
2647
2648
|
|
|
2648
2649
|
|
|
2650
|
+
|
|
2649
2651
|
|
|
2650
2652
|
static parse(plain ) {
|
|
2651
2653
|
return new Meeting({
|
|
@@ -2655,8 +2657,9 @@ class Meeting {
|
|
|
2655
2657
|
ownerUuids: plain.owner_uuids,
|
|
2656
2658
|
port: plain.port,
|
|
2657
2659
|
uuid: plain.uuid,
|
|
2658
|
-
|
|
2660
|
+
extension: plain.exten,
|
|
2659
2661
|
persistent: plain.persistent,
|
|
2662
|
+
creationTime: moment(plain.creation_time).toDate(),
|
|
2660
2663
|
});
|
|
2661
2664
|
}
|
|
2662
2665
|
|
|
@@ -2678,8 +2681,9 @@ class Meeting {
|
|
|
2678
2681
|
ownerUuids,
|
|
2679
2682
|
port,
|
|
2680
2683
|
uri,
|
|
2681
|
-
|
|
2684
|
+
extension,
|
|
2682
2685
|
persistent,
|
|
2686
|
+
creationTime,
|
|
2683
2687
|
} = {}) {
|
|
2684
2688
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2685
2689
|
this.uri = uri;
|
|
@@ -2687,8 +2691,9 @@ class Meeting {
|
|
|
2687
2691
|
this.ownerUuids = ownerUuids;
|
|
2688
2692
|
this.port = port;
|
|
2689
2693
|
this.uuid = uuid;
|
|
2690
|
-
this.
|
|
2694
|
+
this.extension = extension;
|
|
2691
2695
|
this.persistent = persistent;
|
|
2696
|
+
this.creationTime = creationTime;
|
|
2692
2697
|
|
|
2693
2698
|
// Useful to compare instead of instanceof with minified code
|
|
2694
2699
|
this.type = 'Meeting';
|
|
@@ -5619,11 +5624,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
5619
5624
|
|
|
5620
5625
|
// $FlowFixMe
|
|
5621
5626
|
setRemoteSessionDescription(sessionDescription ) {
|
|
5622
|
-
|
|
5627
|
+
try {
|
|
5628
|
+
const result = super.setRemoteSessionDescription(sessionDescription);
|
|
5623
5629
|
|
|
5624
|
-
|
|
5630
|
+
this.eventEmitter.emit('setDescription', sessionDescription);
|
|
5625
5631
|
|
|
5626
|
-
|
|
5632
|
+
return result;
|
|
5633
|
+
} catch (error) {
|
|
5634
|
+
this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
|
|
5635
|
+
throw error;
|
|
5636
|
+
}
|
|
5627
5637
|
}
|
|
5628
5638
|
|
|
5629
5639
|
// Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
|
|
@@ -6528,7 +6538,7 @@ class WebRTCClient extends Emitter {
|
|
|
6528
6538
|
}
|
|
6529
6539
|
|
|
6530
6540
|
call(number , enableVideo , audioOnly = false, conference = false) {
|
|
6531
|
-
logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
|
|
6541
|
+
logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
|
|
6532
6542
|
const inviterOptions = {
|
|
6533
6543
|
sessionDescriptionHandlerOptionsReInvite: {
|
|
6534
6544
|
conference,
|
|
@@ -7604,6 +7614,7 @@ class WebRTCClient extends Emitter {
|
|
|
7604
7614
|
const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
|
|
7605
7615
|
const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
|
|
7606
7616
|
const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
|
|
7617
|
+
const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
|
|
7607
7618
|
|
|
7608
7619
|
logger$9.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
|
|
7609
7620
|
|
|
@@ -7611,7 +7622,8 @@ class WebRTCClient extends Emitter {
|
|
|
7611
7622
|
constraints: {
|
|
7612
7623
|
// Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
|
|
7613
7624
|
audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
|
|
7614
|
-
video: screenSharing ? (isDesktop
|
|
7625
|
+
video: screenSharing ? (isDesktop
|
|
7626
|
+
? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
|
|
7615
7627
|
: this._getVideoConstraints(enableVideo),
|
|
7616
7628
|
screen: screenSharing,
|
|
7617
7629
|
desktop: isDesktop,
|
|
@@ -7946,12 +7958,14 @@ class WebRTCClient extends Emitter {
|
|
|
7946
7958
|
|
|
7947
7959
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
7948
7960
|
|
|
7949
|
-
|
|
7950
|
-
|
|
7951
|
-
|
|
7952
|
-
|
|
7953
|
-
|
|
7954
|
-
|
|
7961
|
+
if (pc) {
|
|
7962
|
+
pc.oniceconnectionstatechange = () => {
|
|
7963
|
+
logger$9.info('on ice connection state changed', { state: pc.iceConnectionState });
|
|
7964
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
7965
|
+
this.eventEmitter.emit(ON_DISCONNECTED$1);
|
|
7966
|
+
}
|
|
7967
|
+
};
|
|
7968
|
+
}
|
|
7955
7969
|
|
|
7956
7970
|
if (withEvent) {
|
|
7957
7971
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
@@ -8161,13 +8175,17 @@ class WebRTCClient extends Emitter {
|
|
|
8161
8175
|
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
8162
8176
|
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
8163
8177
|
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
8178
|
+
const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
|
|
8164
8179
|
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
8165
8180
|
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
8181
|
+
const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
|
|
8166
8182
|
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
8167
8183
|
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
8168
8184
|
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
8169
|
-
let audioBytesSent = 0;
|
|
8170
|
-
let audioBytesReceived = 0;
|
|
8185
|
+
let audioBytesSent = 0; // content + header
|
|
8186
|
+
let audioBytesReceived = 0; // content + header
|
|
8187
|
+
let audioContentSent = 0; // useful to detect blank call
|
|
8188
|
+
let audioContentReceived = 0;
|
|
8171
8189
|
let videoBytesSent = 0;
|
|
8172
8190
|
let videoBytesReceived = 0;
|
|
8173
8191
|
let transportSent = 0;
|
|
@@ -8177,6 +8195,7 @@ class WebRTCClient extends Emitter {
|
|
|
8177
8195
|
stats.forEach(report => {
|
|
8178
8196
|
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
8179
8197
|
audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
8198
|
+
audioContentSent += Number(report.bytesSent);
|
|
8180
8199
|
}
|
|
8181
8200
|
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
8182
8201
|
audioBytesSent += Number(report.bytesSent);
|
|
@@ -8188,6 +8207,7 @@ class WebRTCClient extends Emitter {
|
|
|
8188
8207
|
packetsLost += Number(report.packetsLost);
|
|
8189
8208
|
networkStats.packetsReceived = Number(report.packetsReceived);
|
|
8190
8209
|
audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
8210
|
+
audioContentReceived += Number(report.bytesReceived);
|
|
8191
8211
|
}
|
|
8192
8212
|
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
8193
8213
|
videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
@@ -8216,10 +8236,17 @@ class WebRTCClient extends Emitter {
|
|
|
8216
8236
|
});
|
|
8217
8237
|
|
|
8218
8238
|
networkStats.packetsLost = packetsLost;
|
|
8239
|
+
|
|
8219
8240
|
networkStats.totalAudioBytesSent = audioBytesSent;
|
|
8220
8241
|
networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
|
|
8221
8242
|
networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
|
|
8222
8243
|
networkStats.audioBytesReceived = audioBytesReceived;
|
|
8244
|
+
|
|
8245
|
+
networkStats.totalAudioContentSent = audioContentSent;
|
|
8246
|
+
networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
|
|
8247
|
+
networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
|
|
8248
|
+
networkStats.audioContentReceived = audioContentReceived;
|
|
8249
|
+
|
|
8223
8250
|
networkStats.totalVideoBytesSent = videoBytesSent;
|
|
8224
8251
|
networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
|
|
8225
8252
|
networkStats.totalVideoBytesReceived = videoBytesReceived;
|
|
@@ -9324,6 +9351,7 @@ class WebRTCPhone extends Emitter {
|
|
|
9324
9351
|
constraints,
|
|
9325
9352
|
audioOnly,
|
|
9326
9353
|
conference,
|
|
9354
|
+
iceRestart,
|
|
9327
9355
|
});
|
|
9328
9356
|
|
|
9329
9357
|
if (!sipSession) {
|
|
@@ -9427,6 +9455,11 @@ class WebRTCPhone extends Emitter {
|
|
|
9427
9455
|
|
|
9428
9456
|
this.client.downgradeToAudio(sipSession);
|
|
9429
9457
|
|
|
9458
|
+
if (callSession) {
|
|
9459
|
+
callSession.cameraEnabled = false;
|
|
9460
|
+
this._updateCallSession(callSession);
|
|
9461
|
+
}
|
|
9462
|
+
|
|
9430
9463
|
if (withMessage) {
|
|
9431
9464
|
this._sendReinviteMessage(callSession, false);
|
|
9432
9465
|
}
|
|
@@ -9454,6 +9487,11 @@ class WebRTCPhone extends Emitter {
|
|
|
9454
9487
|
|
|
9455
9488
|
const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
|
|
9456
9489
|
|
|
9490
|
+
if (callSession) {
|
|
9491
|
+
callSession.cameraEnabled = true;
|
|
9492
|
+
this._updateCallSession(callSession);
|
|
9493
|
+
}
|
|
9494
|
+
|
|
9457
9495
|
// If no stream is returned, it means we have to reinvite
|
|
9458
9496
|
if (!newStream) {
|
|
9459
9497
|
return true;
|
|
@@ -9723,7 +9761,7 @@ class WebRTCPhone extends Emitter {
|
|
|
9723
9761
|
}
|
|
9724
9762
|
|
|
9725
9763
|
_onCallAccepted(sipSession , cameraEnabled ) {
|
|
9726
|
-
logger$7.info('WebRTC phone -
|
|
9764
|
+
logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
|
|
9727
9765
|
|
|
9728
9766
|
const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
|
|
9729
9767
|
this.currentSipSession = sipSession;
|
|
@@ -9792,6 +9830,7 @@ class WebRTCPhone extends Emitter {
|
|
|
9792
9830
|
_onCallTerminated(sipSession ) {
|
|
9793
9831
|
logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
|
|
9794
9832
|
|
|
9833
|
+
const sipSessionId = this.getSipSessionId(sipSession);
|
|
9795
9834
|
const callSession = this._createCallSession(sipSession);
|
|
9796
9835
|
const isCurrentSession = this.isCurrentCallSipSession(callSession);
|
|
9797
9836
|
const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
|
|
@@ -9809,7 +9848,6 @@ class WebRTCPhone extends Emitter {
|
|
|
9809
9848
|
}, 5);
|
|
9810
9849
|
}
|
|
9811
9850
|
|
|
9812
|
-
const sipSessionId = this.getSipSessionId(sipSession);
|
|
9813
9851
|
if (sipSessionId) {
|
|
9814
9852
|
this.removeIncomingSessions(sipSessionId);
|
|
9815
9853
|
}
|
|
@@ -10235,7 +10273,7 @@ class WebRTCPhone extends Emitter {
|
|
|
10235
10273
|
// @TODO: line is not used here
|
|
10236
10274
|
async makeCall(number , line , cameraEnabled ,
|
|
10237
10275
|
audioOnly = false, conference = false) {
|
|
10238
|
-
logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
|
|
10276
|
+
logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
|
|
10239
10277
|
if (!number) {
|
|
10240
10278
|
return Promise.resolve(null);
|
|
10241
10279
|
}
|
|
@@ -10454,8 +10492,12 @@ class WebRTCPhone extends Emitter {
|
|
|
10454
10492
|
}
|
|
10455
10493
|
|
|
10456
10494
|
const sessionId = this.incomingSessions[0];
|
|
10495
|
+
const sipSession = this.client.getSipSession(sessionId);
|
|
10496
|
+
if (!sipSession) {
|
|
10497
|
+
return null;
|
|
10498
|
+
}
|
|
10457
10499
|
|
|
10458
|
-
return this._createCallSession(
|
|
10500
|
+
return this._createCallSession(sipSession);
|
|
10459
10501
|
}
|
|
10460
10502
|
|
|
10461
10503
|
sendMessage(sipSession = null, body , contentType = 'text/plain') {
|
|
@@ -10596,9 +10638,13 @@ class WebRTCPhone extends Emitter {
|
|
|
10596
10638
|
if (this.shouldSendReinvite && this.currentSipSession
|
|
10597
10639
|
&& this.currentSipSession.state === SessionState.Established) {
|
|
10598
10640
|
this.shouldSendReinvite = false;
|
|
10641
|
+
const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
|
|
10642
|
+
const isConference = pc ? pc.sfu : false;
|
|
10643
|
+
const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
|
|
10644
|
+
|
|
10599
10645
|
try {
|
|
10600
10646
|
// Send reinvite with iceRestart
|
|
10601
|
-
this.sendReinvite(this.currentCallSession, null,
|
|
10647
|
+
this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
|
|
10602
10648
|
} catch (e) {
|
|
10603
10649
|
logger$7.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
|
|
10604
10650
|
}
|
|
@@ -10682,6 +10728,15 @@ class WebRTCPhone extends Emitter {
|
|
|
10682
10728
|
return this.client.getSipSessionId(sipSession);
|
|
10683
10729
|
}
|
|
10684
10730
|
|
|
10731
|
+
_updateCallSession(callSession ) {
|
|
10732
|
+
const sipSession = this.findSipSession(callSession);
|
|
10733
|
+
const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
|
|
10734
|
+
|
|
10735
|
+
if (sipSessionId) {
|
|
10736
|
+
this.callSessions[sipSessionId] = callSession;
|
|
10737
|
+
}
|
|
10738
|
+
}
|
|
10739
|
+
|
|
10685
10740
|
_onMessage(message ) {
|
|
10686
10741
|
if (!message || message.method !== 'MESSAGE') {
|
|
10687
10742
|
return;
|
|
@@ -15,7 +15,7 @@ IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
|
|
|
15
15
|
|
|
16
16
|
// Use a function here to be able to mock it in tests
|
|
17
17
|
const realFetch = () => {
|
|
18
|
-
if (typeof document !== 'undefined') {
|
|
18
|
+
if (typeof document !== 'undefined' && window.fetch) {
|
|
19
19
|
// Browser
|
|
20
20
|
return window.fetch;
|
|
21
21
|
}
|
|
@@ -487,11 +487,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
487
487
|
|
|
488
488
|
// $FlowFixMe
|
|
489
489
|
setRemoteSessionDescription(sessionDescription ) {
|
|
490
|
-
|
|
490
|
+
try {
|
|
491
|
+
const result = super.setRemoteSessionDescription(sessionDescription);
|
|
491
492
|
|
|
492
|
-
|
|
493
|
+
this.eventEmitter.emit('setDescription', sessionDescription);
|
|
493
494
|
|
|
494
|
-
|
|
495
|
+
return result;
|
|
496
|
+
} catch (error) {
|
|
497
|
+
this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
|
|
498
|
+
throw error;
|
|
499
|
+
}
|
|
495
500
|
}
|
|
496
501
|
|
|
497
502
|
// Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
|
package/esm/service/CallApi.js
CHANGED
|
@@ -1410,7 +1410,7 @@ class Contact {
|
|
|
1410
1410
|
this[key] = old[key] || this[key];
|
|
1411
1411
|
});
|
|
1412
1412
|
|
|
1413
|
-
if (old.lineState
|
|
1413
|
+
if (old.lineState) {
|
|
1414
1414
|
this.lineState = old.lineState;
|
|
1415
1415
|
}
|
|
1416
1416
|
|
|
@@ -2466,7 +2466,7 @@ const logger$1 = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
|
|
|
2466
2466
|
|
|
2467
2467
|
// Use a function here to be able to mock it in tests
|
|
2468
2468
|
const realFetch = () => {
|
|
2469
|
-
if (typeof document !== 'undefined') {
|
|
2469
|
+
if (typeof document !== 'undefined' && window.fetch) {
|
|
2470
2470
|
// Browser
|
|
2471
2471
|
return window.fetch;
|
|
2472
2472
|
}
|
|
@@ -3145,8 +3145,9 @@ class ExternalApp {
|
|
|
3145
3145
|
|
|
3146
3146
|
|
|
3147
3147
|
|
|
3148
|
-
|
|
3148
|
+
|
|
3149
3149
|
|
|
3150
|
+
|
|
3150
3151
|
|
|
3151
3152
|
|
|
3152
3153
|
class Meeting {
|
|
@@ -3157,9 +3158,10 @@ class Meeting {
|
|
|
3157
3158
|
|
|
3158
3159
|
|
|
3159
3160
|
|
|
3160
|
-
|
|
3161
|
+
|
|
3161
3162
|
|
|
3162
3163
|
|
|
3164
|
+
|
|
3163
3165
|
|
|
3164
3166
|
static parse(plain ) {
|
|
3165
3167
|
return new Meeting({
|
|
@@ -3169,8 +3171,9 @@ class Meeting {
|
|
|
3169
3171
|
ownerUuids: plain.owner_uuids,
|
|
3170
3172
|
port: plain.port,
|
|
3171
3173
|
uuid: plain.uuid,
|
|
3172
|
-
|
|
3174
|
+
extension: plain.exten,
|
|
3173
3175
|
persistent: plain.persistent,
|
|
3176
|
+
creationTime: moment(plain.creation_time).toDate(),
|
|
3174
3177
|
});
|
|
3175
3178
|
}
|
|
3176
3179
|
|
|
@@ -3192,8 +3195,9 @@ class Meeting {
|
|
|
3192
3195
|
ownerUuids,
|
|
3193
3196
|
port,
|
|
3194
3197
|
uri,
|
|
3195
|
-
|
|
3198
|
+
extension,
|
|
3196
3199
|
persistent,
|
|
3200
|
+
creationTime,
|
|
3197
3201
|
} = {}) {
|
|
3198
3202
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
3199
3203
|
this.uri = uri;
|
|
@@ -3201,8 +3205,9 @@ class Meeting {
|
|
|
3201
3205
|
this.ownerUuids = ownerUuids;
|
|
3202
3206
|
this.port = port;
|
|
3203
3207
|
this.uuid = uuid;
|
|
3204
|
-
this.
|
|
3208
|
+
this.extension = extension;
|
|
3205
3209
|
this.persistent = persistent;
|
|
3210
|
+
this.creationTime = creationTime;
|
|
3206
3211
|
|
|
3207
3212
|
// Useful to compare instead of instanceof with minified code
|
|
3208
3213
|
this.type = 'Meeting';
|
|
@@ -11,7 +11,7 @@ IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
|
|
|
11
11
|
|
|
12
12
|
// Use a function here to be able to mock it in tests
|
|
13
13
|
const realFetch = () => {
|
|
14
|
-
if (typeof document !== 'undefined') {
|
|
14
|
+
if (typeof document !== 'undefined' && window.fetch) {
|
|
15
15
|
// Browser
|
|
16
16
|
return window.fetch;
|
|
17
17
|
}
|
|
@@ -11,7 +11,7 @@ IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
|
|
|
11
11
|
|
|
12
12
|
// Use a function here to be able to mock it in tests
|
|
13
13
|
const realFetch = () => {
|
|
14
|
-
if (typeof document !== 'undefined') {
|
|
14
|
+
if (typeof document !== 'undefined' && window.fetch) {
|
|
15
15
|
// Browser
|
|
16
16
|
return window.fetch;
|
|
17
17
|
}
|