@wazo/sdk 0.37.22 → 0.37.26
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 +37 -6
- package/esm/__tests__/web-rtc-client.test.js +78 -68
- package/esm/api/call-logd.js +7 -0
- package/esm/api/calld.js +10 -0
- package/esm/api/chatd.js +7 -0
- package/esm/api/confd.js +13 -5
- package/esm/api/ctid-ng.js +10 -0
- package/esm/api/dird.js +4 -1
- package/esm/api-client.js +37 -6
- package/esm/checker/Checker.js +78 -68
- package/esm/checker/checks/aor.js +37 -6
- package/esm/checker/checks/api.js +37 -6
- package/esm/checker/checks/index.js +78 -68
- package/esm/checker/checks/webrtc-transport.js +78 -68
- package/esm/checker/checks/webrtc.js +78 -68
- package/esm/domain/AdHocAPIConference.js +37 -6
- package/esm/domain/Call.js +3 -0
- package/esm/domain/CallLog.js +7 -0
- package/esm/domain/ChatMessage.js +4 -0
- package/esm/domain/ChatRoom.js +3 -0
- package/esm/domain/Contact.js +4 -1
- package/esm/domain/Features.js +37 -6
- package/esm/domain/Meeting.js +15 -5
- package/esm/domain/Phone/CTIPhone.js +41 -6
- package/esm/domain/Phone/WebRTCPhone.js +41 -15
- package/esm/domain/Recording.js +3 -0
- package/esm/domain/Voicemail.js +3 -0
- package/esm/domain/__tests__/Call.test.js +3 -0
- package/esm/domain/__tests__/CallLog.test.js +7 -0
- package/esm/domain/__tests__/Contact.test.js +4 -1
- package/esm/domain/__tests__/Meeting.test.js +144 -0
- package/esm/domain/__tests__/Voicemail.test.js +3 -0
- package/esm/index.js +122 -82
- package/esm/lib/WazoSessionDescriptionHandler.js +0 -38
- package/esm/service/CallApi.js +37 -6
- package/esm/service/getApiClient.js +37 -6
- package/esm/simple/Auth.js +122 -82
- package/esm/simple/Configuration.js +122 -82
- package/esm/simple/Directory.js +37 -6
- package/esm/simple/Phone.js +122 -82
- package/esm/simple/index.js +122 -82
- package/esm/simple/room/LocalParticipant.js +122 -82
- package/esm/simple/room/Participant.js +122 -82
- package/esm/simple/room/RemoteParticipant.js +122 -82
- package/esm/simple/room/Room.js +122 -82
- package/esm/simple/room/SipRoom.js +122 -82
- package/esm/simple/room/Stream.js +122 -82
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +122 -82
- package/esm/simple/utils.js +122 -82
- package/esm/types/WebSocketMessage.js +1 -1
- package/esm/web-rtc-client.js +78 -68
- package/lib/__tests__/api-client.test.js +37 -6
- package/lib/__tests__/web-rtc-client.test.js +78 -68
- package/lib/api/call-logd.js +7 -0
- package/lib/api/calld.js +10 -0
- package/lib/api/chatd.js +7 -0
- package/lib/api/confd.js +13 -5
- package/lib/api/ctid-ng.js +10 -0
- package/lib/api/dird.js +4 -1
- package/lib/api-client.js +37 -6
- package/lib/checker/Checker.js +78 -68
- package/lib/checker/checks/aor.js +37 -6
- package/lib/checker/checks/api.js +37 -6
- package/lib/checker/checks/index.js +78 -68
- package/lib/checker/checks/webrtc-transport.js +78 -68
- package/lib/checker/checks/webrtc.js +78 -68
- package/lib/domain/AdHocAPIConference.js +37 -6
- package/lib/domain/Call.js +3 -0
- package/lib/domain/CallLog.js +7 -0
- package/lib/domain/ChatMessage.js +4 -0
- package/lib/domain/ChatRoom.js +3 -0
- package/lib/domain/Contact.js +4 -1
- package/lib/domain/Features.js +37 -6
- package/lib/domain/Meeting.js +19 -5
- package/lib/domain/Phone/CTIPhone.js +41 -6
- package/lib/domain/Phone/WebRTCPhone.js +41 -15
- package/lib/domain/Recording.js +3 -0
- package/lib/domain/Voicemail.js +3 -0
- package/lib/domain/__tests__/Call.test.js +3 -0
- package/lib/domain/__tests__/CallLog.test.js +7 -0
- package/lib/domain/__tests__/Contact.test.js +4 -1
- package/lib/domain/__tests__/Meeting.test.js +150 -0
- package/lib/domain/__tests__/Voicemail.test.js +3 -0
- package/lib/index.js +122 -82
- package/lib/lib/WazoSessionDescriptionHandler.js +0 -38
- package/lib/service/CallApi.js +37 -6
- package/lib/service/getApiClient.js +37 -6
- package/lib/simple/Auth.js +122 -82
- package/lib/simple/Configuration.js +122 -82
- package/lib/simple/Directory.js +37 -6
- package/lib/simple/Phone.js +122 -82
- package/lib/simple/index.js +122 -82
- package/lib/simple/room/LocalParticipant.js +122 -82
- package/lib/simple/room/Participant.js +122 -82
- package/lib/simple/room/RemoteParticipant.js +122 -82
- package/lib/simple/room/Room.js +122 -82
- package/lib/simple/room/SipRoom.js +122 -82
- package/lib/simple/room/Stream.js +122 -82
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +122 -82
- package/lib/simple/utils.js +122 -82
- package/lib/types/WebSocketMessage.js +2 -0
- package/lib/web-rtc-client.js +78 -68
- package/package.json +1 -1
- package/src/domain/Call.js +3 -0
- package/src/domain/CallLog.js +4 -0
- package/src/domain/ChatMessage.js +4 -0
- package/src/domain/ChatRoom.js +3 -0
- package/src/domain/Contact.js +4 -1
- package/src/domain/Meeting.js +15 -5
- package/src/domain/Phone/CTIPhone.js +4 -0
- package/src/domain/Phone/Phone.js +2 -0
- package/src/domain/Phone/WebRTCPhone.js +41 -15
- package/src/domain/Recording.js +3 -0
- package/src/domain/Voicemail.js +3 -0
- package/src/domain/__tests__/Meeting.test.js +50 -0
- package/src/lib/WazoSessionDescriptionHandler.js +1 -35
- package/src/web-rtc-client.js +41 -24
package/lib/web-rtc-client.js
CHANGED
|
@@ -735,10 +735,6 @@ const getSrflxOrRelay = (candidates ) =>
|
|
|
735
735
|
candidates
|
|
736
736
|
.filter(candidate => candidate && (candidate.type === 'srflx' || candidate.type === 'relay'));
|
|
737
737
|
|
|
738
|
-
const areCandidateValid = (candidates ) =>
|
|
739
|
-
getSrflxOrRelay(candidates)
|
|
740
|
-
.length > 0;
|
|
741
|
-
|
|
742
738
|
const getVideoDirection = (sdp ) => {
|
|
743
739
|
const parsedSdp = sdpParser__default['default'].parse(sdp);
|
|
744
740
|
const videoMedia = parsedSdp.media.find(media => media.type === 'video');
|
|
@@ -791,8 +787,6 @@ const fixSdp = (sdp , candidates , forcePort = true)
|
|
|
791
787
|
/* global RTCSessionDescriptionInit, navigator */
|
|
792
788
|
|
|
793
789
|
const wazoLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-sdh') : console;
|
|
794
|
-
const MAX_WAIT_FOR_ICE_TRIES = 20;
|
|
795
|
-
const WAIT_FOR_ICE_TIMEOUT = 500;
|
|
796
790
|
|
|
797
791
|
// Customized mediaStreamFactory allowing to send screensharing stream directory when upgrading
|
|
798
792
|
const wazoMediaStreamFactory = (constraints ) => {
|
|
@@ -982,38 +976,6 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
982
976
|
this._peerConnection = undefined;
|
|
983
977
|
}
|
|
984
978
|
|
|
985
|
-
async _waitForValidGatheredIce() {
|
|
986
|
-
let tries = 0;
|
|
987
|
-
|
|
988
|
-
while (!areCandidateValid(this.gatheredCandidates) && tries < MAX_WAIT_FOR_ICE_TRIES) {
|
|
989
|
-
wazoLogger.trace('SessionDescriptionHandler._waitForValidGatheredIce, waiting for ice', {
|
|
990
|
-
tries,
|
|
991
|
-
max: MAX_WAIT_FOR_ICE_TRIES,
|
|
992
|
-
});
|
|
993
|
-
|
|
994
|
-
tries++;
|
|
995
|
-
|
|
996
|
-
// eslint-disable-next-line no-await-in-loop
|
|
997
|
-
await new Promise(resolve => setTimeout(resolve, WAIT_FOR_ICE_TIMEOUT));
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
if (tries >= MAX_WAIT_FOR_ICE_TRIES) {
|
|
1001
|
-
const errorMsg = 'No valid candidates found, can\'t answer the call';
|
|
1002
|
-
const error = new Error(errorMsg);
|
|
1003
|
-
wazoLogger.error(errorMsg, { tries, max: MAX_WAIT_FOR_ICE_TRIES });
|
|
1004
|
-
|
|
1005
|
-
// Emit an error, because sip.js catches the exception and switch to status Terminated.
|
|
1006
|
-
this.eventEmitter.emit('error', error);
|
|
1007
|
-
|
|
1008
|
-
wazoLogger.error('No valid candidates found', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
// eslint-disable-next-line
|
|
1012
|
-
wazoLogger.trace('Found valid candidates', { tries, candidates: JSON.stringify(this.gatheredCandidates) });
|
|
1013
|
-
|
|
1014
|
-
return this.getLocalSessionDescription();
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
979
|
// Overridden to send `inactive` in conference
|
|
1018
980
|
updateDirection(options , isConference = false,
|
|
1019
981
|
audioOnly = false) {
|
|
@@ -2123,6 +2085,9 @@ class Contact {
|
|
|
2123
2085
|
}
|
|
2124
2086
|
|
|
2125
2087
|
static parseMany(response ) {
|
|
2088
|
+
if (!response || !response.results) {
|
|
2089
|
+
return [];
|
|
2090
|
+
}
|
|
2126
2091
|
return response.results.map(r => Contact.parse(r, response.column_types));
|
|
2127
2092
|
}
|
|
2128
2093
|
|
|
@@ -2493,7 +2458,7 @@ class Contact {
|
|
|
2493
2458
|
this[key] = old[key] || this[key];
|
|
2494
2459
|
});
|
|
2495
2460
|
|
|
2496
|
-
if (old.lineState
|
|
2461
|
+
if (old.lineState) {
|
|
2497
2462
|
this.lineState = old.lineState;
|
|
2498
2463
|
}
|
|
2499
2464
|
|
|
@@ -3200,8 +3165,9 @@ class ExternalApp {
|
|
|
3200
3165
|
|
|
3201
3166
|
|
|
3202
3167
|
|
|
3203
|
-
|
|
3168
|
+
|
|
3204
3169
|
|
|
3170
|
+
|
|
3205
3171
|
|
|
3206
3172
|
|
|
3207
3173
|
class Meeting {
|
|
@@ -3212,9 +3178,10 @@ class Meeting {
|
|
|
3212
3178
|
|
|
3213
3179
|
|
|
3214
3180
|
|
|
3215
|
-
|
|
3181
|
+
|
|
3216
3182
|
|
|
3217
3183
|
|
|
3184
|
+
|
|
3218
3185
|
|
|
3219
3186
|
static parse(plain ) {
|
|
3220
3187
|
return new Meeting({
|
|
@@ -3224,12 +3191,16 @@ class Meeting {
|
|
|
3224
3191
|
ownerUuids: plain.owner_uuids,
|
|
3225
3192
|
port: plain.port,
|
|
3226
3193
|
uuid: plain.uuid,
|
|
3227
|
-
|
|
3194
|
+
extension: plain.exten,
|
|
3228
3195
|
persistent: plain.persistent,
|
|
3196
|
+
creationTime: moment__default['default'](plain.creation_time).toDate(),
|
|
3229
3197
|
});
|
|
3230
3198
|
}
|
|
3231
3199
|
|
|
3232
3200
|
static parseMany(items ) {
|
|
3201
|
+
if (!items) {
|
|
3202
|
+
return [];
|
|
3203
|
+
}
|
|
3233
3204
|
return items.map(plain => Meeting.parse(plain));
|
|
3234
3205
|
}
|
|
3235
3206
|
|
|
@@ -3244,8 +3215,9 @@ class Meeting {
|
|
|
3244
3215
|
ownerUuids,
|
|
3245
3216
|
port,
|
|
3246
3217
|
uri,
|
|
3247
|
-
|
|
3218
|
+
extension,
|
|
3248
3219
|
persistent,
|
|
3220
|
+
creationTime,
|
|
3249
3221
|
} = {}) {
|
|
3250
3222
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
3251
3223
|
this.uri = uri;
|
|
@@ -3253,8 +3225,9 @@ class Meeting {
|
|
|
3253
3225
|
this.ownerUuids = ownerUuids;
|
|
3254
3226
|
this.port = port;
|
|
3255
3227
|
this.uuid = uuid;
|
|
3256
|
-
this.
|
|
3228
|
+
this.extension = extension;
|
|
3257
3229
|
this.persistent = persistent;
|
|
3230
|
+
this.creationTime = creationTime;
|
|
3258
3231
|
|
|
3259
3232
|
// Useful to compare instead of instanceof with minified code
|
|
3260
3233
|
this.type = 'Meeting';
|
|
@@ -3432,6 +3405,10 @@ class ChatMessage {
|
|
|
3432
3405
|
|
|
3433
3406
|
|
|
3434
3407
|
static parseMany(plain ) {
|
|
3408
|
+
if (!plain || !plain.items) {
|
|
3409
|
+
return [];
|
|
3410
|
+
}
|
|
3411
|
+
|
|
3435
3412
|
return plain.items.map(item => ChatMessage.parse(item));
|
|
3436
3413
|
}
|
|
3437
3414
|
|
|
@@ -3541,6 +3518,9 @@ class Voicemail {
|
|
|
3541
3518
|
}
|
|
3542
3519
|
|
|
3543
3520
|
static parseMany(plain ) {
|
|
3521
|
+
if (!plain) {
|
|
3522
|
+
return [];
|
|
3523
|
+
}
|
|
3544
3524
|
const plainUnread = plain.folders.filter(folder => folder.type === 'new')[0].messages;
|
|
3545
3525
|
const plainRead = plain.folders.filter(folder => folder.type === 'old')[0].messages;
|
|
3546
3526
|
|
|
@@ -3650,6 +3630,9 @@ class Call {
|
|
|
3650
3630
|
|
|
3651
3631
|
|
|
3652
3632
|
static parseMany(plain ) {
|
|
3633
|
+
if (!plain) {
|
|
3634
|
+
return [];
|
|
3635
|
+
}
|
|
3653
3636
|
return plain.map((plainCall ) => Call.parse(plainCall));
|
|
3654
3637
|
}
|
|
3655
3638
|
|
|
@@ -3822,6 +3805,9 @@ class Recording {
|
|
|
3822
3805
|
|
|
3823
3806
|
|
|
3824
3807
|
static parseMany(recordings = []) {
|
|
3808
|
+
if (!recordings) {
|
|
3809
|
+
return [];
|
|
3810
|
+
}
|
|
3825
3811
|
return recordings.map(item => Recording.parse(item));
|
|
3826
3812
|
}
|
|
3827
3813
|
|
|
@@ -3923,6 +3909,10 @@ class CallLog {
|
|
|
3923
3909
|
}
|
|
3924
3910
|
|
|
3925
3911
|
static parseMany(plain ) {
|
|
3912
|
+
if (!plain || !plain.items) {
|
|
3913
|
+
return [];
|
|
3914
|
+
}
|
|
3915
|
+
|
|
3926
3916
|
return plain.items.map(item => CallLog.parse(item));
|
|
3927
3917
|
}
|
|
3928
3918
|
|
|
@@ -4495,6 +4485,9 @@ class ChatRoom {
|
|
|
4495
4485
|
|
|
4496
4486
|
|
|
4497
4487
|
static parseMany(plain ) {
|
|
4488
|
+
if (!plain || !plain.items) {
|
|
4489
|
+
return [];
|
|
4490
|
+
}
|
|
4498
4491
|
return plain.items.map(item => ChatRoom.parse(item));
|
|
4499
4492
|
}
|
|
4500
4493
|
|
|
@@ -5726,7 +5719,7 @@ class WebRTCClient extends Emitter {
|
|
|
5726
5719
|
}
|
|
5727
5720
|
|
|
5728
5721
|
call(number , enableVideo , audioOnly = false, conference = false) {
|
|
5729
|
-
logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
|
|
5722
|
+
logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
|
|
5730
5723
|
const inviterOptions = {
|
|
5731
5724
|
sessionDescriptionHandlerOptionsReInvite: {
|
|
5732
5725
|
conference,
|
|
@@ -6802,6 +6795,7 @@ class WebRTCClient extends Emitter {
|
|
|
6802
6795
|
const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
|
|
6803
6796
|
const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
|
|
6804
6797
|
const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
|
|
6798
|
+
const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
|
|
6805
6799
|
|
|
6806
6800
|
logger.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
|
|
6807
6801
|
|
|
@@ -6809,7 +6803,8 @@ class WebRTCClient extends Emitter {
|
|
|
6809
6803
|
constraints: {
|
|
6810
6804
|
// Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
|
|
6811
6805
|
audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
|
|
6812
|
-
video: screenSharing ? (isDesktop
|
|
6806
|
+
video: screenSharing ? (isDesktop
|
|
6807
|
+
? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
|
|
6813
6808
|
: this._getVideoConstraints(enableVideo),
|
|
6814
6809
|
screen: screenSharing,
|
|
6815
6810
|
desktop: isDesktop,
|
|
@@ -7144,12 +7139,14 @@ class WebRTCClient extends Emitter {
|
|
|
7144
7139
|
|
|
7145
7140
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
7146
7141
|
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7142
|
+
if (pc) {
|
|
7143
|
+
pc.oniceconnectionstatechange = () => {
|
|
7144
|
+
logger.info('on ice connection state changed', { state: pc.iceConnectionState });
|
|
7145
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
7146
|
+
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
7147
|
+
}
|
|
7148
|
+
};
|
|
7149
|
+
}
|
|
7153
7150
|
|
|
7154
7151
|
if (withEvent) {
|
|
7155
7152
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
@@ -7359,13 +7356,17 @@ class WebRTCClient extends Emitter {
|
|
|
7359
7356
|
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
7360
7357
|
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
7361
7358
|
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
7359
|
+
const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
|
|
7362
7360
|
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
7363
7361
|
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
7362
|
+
const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
|
|
7364
7363
|
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
7365
7364
|
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
7366
7365
|
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
7367
|
-
let audioBytesSent = 0;
|
|
7368
|
-
let audioBytesReceived = 0;
|
|
7366
|
+
let audioBytesSent = 0; // content + header
|
|
7367
|
+
let audioBytesReceived = 0; // content + header
|
|
7368
|
+
let audioContentSent = 0; // useful to detect blank call
|
|
7369
|
+
let audioContentReceived = 0;
|
|
7369
7370
|
let videoBytesSent = 0;
|
|
7370
7371
|
let videoBytesReceived = 0;
|
|
7371
7372
|
let transportSent = 0;
|
|
@@ -7374,25 +7375,27 @@ class WebRTCClient extends Emitter {
|
|
|
7374
7375
|
|
|
7375
7376
|
stats.forEach(report => {
|
|
7376
7377
|
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
7377
|
-
audioBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7378
|
+
audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
7379
|
+
audioContentSent += Number(report.bytesSent);
|
|
7378
7380
|
}
|
|
7379
7381
|
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
7380
|
-
audioBytesSent += report.bytesSent;
|
|
7382
|
+
audioBytesSent += Number(report.bytesSent);
|
|
7381
7383
|
}
|
|
7382
7384
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7383
|
-
videoBytesSent += report.bytesSent + report.headerBytesSent;
|
|
7385
|
+
videoBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
7384
7386
|
}
|
|
7385
7387
|
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
7386
|
-
packetsLost += report.packetsLost;
|
|
7387
|
-
networkStats.packetsReceived = report.packetsReceived;
|
|
7388
|
-
audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7388
|
+
packetsLost += Number(report.packetsLost);
|
|
7389
|
+
networkStats.packetsReceived = Number(report.packetsReceived);
|
|
7390
|
+
audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
7391
|
+
audioContentReceived += Number(report.bytesReceived);
|
|
7389
7392
|
}
|
|
7390
7393
|
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
7391
|
-
videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
|
|
7394
|
+
videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
7392
7395
|
}
|
|
7393
7396
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
7394
7397
|
if ('framesPerSecond' in report) {
|
|
7395
|
-
networkStats.framesPerSecond = report.framesPerSecond;
|
|
7398
|
+
networkStats.framesPerSecond = Number(report.framesPerSecond);
|
|
7396
7399
|
}
|
|
7397
7400
|
if ('framerateMean' in report) {
|
|
7398
7401
|
// framerateMean is only available in FF
|
|
@@ -7400,24 +7403,31 @@ class WebRTCClient extends Emitter {
|
|
|
7400
7403
|
}
|
|
7401
7404
|
}
|
|
7402
7405
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
7403
|
-
packetsLost += report.packetsLost;
|
|
7404
|
-
networkStats.roundTripTime = report.roundTripTime;
|
|
7405
|
-
networkStats.jitter = report.jitter;
|
|
7406
|
+
packetsLost += Number(report.packetsLost);
|
|
7407
|
+
networkStats.roundTripTime = Number(report.roundTripTime);
|
|
7408
|
+
networkStats.jitter = Number(report.jitter);
|
|
7406
7409
|
}
|
|
7407
7410
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
7408
|
-
packetsLost += report.packetsLost;
|
|
7411
|
+
packetsLost += Number(report.packetsLost);
|
|
7409
7412
|
}
|
|
7410
7413
|
if (report.type === 'transport') {
|
|
7411
|
-
transportSent += report.bytesSent;
|
|
7412
|
-
transportReceived += report.bytesReceived;
|
|
7414
|
+
transportSent += Number(report.bytesSent);
|
|
7415
|
+
transportReceived += Number(report.bytesReceived);
|
|
7413
7416
|
}
|
|
7414
7417
|
});
|
|
7415
7418
|
|
|
7416
7419
|
networkStats.packetsLost = packetsLost;
|
|
7420
|
+
|
|
7417
7421
|
networkStats.totalAudioBytesSent = audioBytesSent;
|
|
7418
7422
|
networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
|
|
7419
7423
|
networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
|
|
7420
7424
|
networkStats.audioBytesReceived = audioBytesReceived;
|
|
7425
|
+
|
|
7426
|
+
networkStats.totalAudioContentSent = audioContentSent;
|
|
7427
|
+
networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
|
|
7428
|
+
networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
|
|
7429
|
+
networkStats.audioContentReceived = audioContentReceived;
|
|
7430
|
+
|
|
7421
7431
|
networkStats.totalVideoBytesSent = videoBytesSent;
|
|
7422
7432
|
networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
|
|
7423
7433
|
networkStats.totalVideoBytesReceived = videoBytesReceived;
|
package/package.json
CHANGED
package/src/domain/Call.js
CHANGED
package/src/domain/CallLog.js
CHANGED
package/src/domain/ChatRoom.js
CHANGED
package/src/domain/Contact.js
CHANGED
|
@@ -281,6 +281,9 @@ export default class Contact {
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
static parseMany(response: ContactsResponse): Array<Contact> {
|
|
284
|
+
if (!response || !response.results) {
|
|
285
|
+
return [];
|
|
286
|
+
}
|
|
284
287
|
return response.results.map(r => Contact.parse(r, response.column_types));
|
|
285
288
|
}
|
|
286
289
|
|
|
@@ -651,7 +654,7 @@ export default class Contact {
|
|
|
651
654
|
this[key] = old[key] || this[key];
|
|
652
655
|
});
|
|
653
656
|
|
|
654
|
-
if (old.lineState
|
|
657
|
+
if (old.lineState) {
|
|
655
658
|
this.lineState = old.lineState;
|
|
656
659
|
}
|
|
657
660
|
|
package/src/domain/Meeting.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
// @flow
|
|
2
|
+
import moment from 'moment';
|
|
3
|
+
|
|
2
4
|
import newFrom from '../utils/new-from';
|
|
3
5
|
|
|
4
6
|
export type MeetingCreationResponse = {
|
|
@@ -8,8 +10,9 @@ export type MeetingCreationResponse = {
|
|
|
8
10
|
owner_uuids: Array<string>,
|
|
9
11
|
port: string,
|
|
10
12
|
uuid: string,
|
|
11
|
-
|
|
13
|
+
exten: string,
|
|
12
14
|
persistent: boolean,
|
|
15
|
+
creation_time: string,
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
export default class Meeting {
|
|
@@ -20,9 +23,10 @@ export default class Meeting {
|
|
|
20
23
|
uuid: string;
|
|
21
24
|
name: string;
|
|
22
25
|
port: string;
|
|
23
|
-
|
|
26
|
+
extension: string;
|
|
24
27
|
persistent: boolean;
|
|
25
28
|
ownerUuids: Array<string>;
|
|
29
|
+
creationTime: Date;
|
|
26
30
|
|
|
27
31
|
static parse(plain: MeetingCreationResponse): Meeting {
|
|
28
32
|
return new Meeting({
|
|
@@ -32,12 +36,16 @@ export default class Meeting {
|
|
|
32
36
|
ownerUuids: plain.owner_uuids,
|
|
33
37
|
port: plain.port,
|
|
34
38
|
uuid: plain.uuid,
|
|
35
|
-
|
|
39
|
+
extension: plain.exten,
|
|
36
40
|
persistent: plain.persistent,
|
|
41
|
+
creationTime: moment(plain.creation_time).toDate(),
|
|
37
42
|
});
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
static parseMany(items: MeetingCreationResponse[]): Array<Meeting> {
|
|
46
|
+
if (!items) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
41
49
|
return items.map(plain => Meeting.parse(plain));
|
|
42
50
|
}
|
|
43
51
|
|
|
@@ -52,8 +60,9 @@ export default class Meeting {
|
|
|
52
60
|
ownerUuids,
|
|
53
61
|
port,
|
|
54
62
|
uri,
|
|
55
|
-
|
|
63
|
+
extension,
|
|
56
64
|
persistent,
|
|
65
|
+
creationTime,
|
|
57
66
|
}: Object = {}) {
|
|
58
67
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
59
68
|
this.uri = uri;
|
|
@@ -61,8 +70,9 @@ export default class Meeting {
|
|
|
61
70
|
this.ownerUuids = ownerUuids;
|
|
62
71
|
this.port = port;
|
|
63
72
|
this.uuid = uuid;
|
|
64
|
-
this.
|
|
73
|
+
this.extension = extension;
|
|
65
74
|
this.persistent = persistent;
|
|
75
|
+
this.creationTime = creationTime;
|
|
66
76
|
|
|
67
77
|
// Useful to compare instead of instanceof with minified code
|
|
68
78
|
this.type = 'Meeting';
|
|
@@ -203,6 +203,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
203
203
|
constraints,
|
|
204
204
|
audioOnly,
|
|
205
205
|
conference,
|
|
206
|
+
iceRestart,
|
|
206
207
|
});
|
|
207
208
|
|
|
208
209
|
if (!sipSession) {
|
|
@@ -306,6 +307,11 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
306
307
|
|
|
307
308
|
this.client.downgradeToAudio(sipSession);
|
|
308
309
|
|
|
310
|
+
if (callSession) {
|
|
311
|
+
callSession.cameraEnabled = false;
|
|
312
|
+
this._updateCallSession(callSession);
|
|
313
|
+
}
|
|
314
|
+
|
|
309
315
|
if (withMessage) {
|
|
310
316
|
this._sendReinviteMessage(callSession, false);
|
|
311
317
|
}
|
|
@@ -333,6 +339,11 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
333
339
|
|
|
334
340
|
const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
|
|
335
341
|
|
|
342
|
+
if (callSession) {
|
|
343
|
+
callSession.cameraEnabled = true;
|
|
344
|
+
this._updateCallSession(callSession);
|
|
345
|
+
}
|
|
346
|
+
|
|
336
347
|
// If no stream is returned, it means we have to reinvite
|
|
337
348
|
if (!newStream) {
|
|
338
349
|
return true;
|
|
@@ -571,18 +582,20 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
571
582
|
screenTrack,
|
|
572
583
|
});
|
|
573
584
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
585
|
+
if (screenTrack) {
|
|
586
|
+
screenTrack.onended = () => {
|
|
587
|
+
logger.info('WebRTC phone - on screenshare ended', {
|
|
588
|
+
hadVideo,
|
|
589
|
+
id: this.getSipSessionId(sipSession),
|
|
590
|
+
screenTrack,
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
this.eventEmitter.emit(
|
|
594
|
+
ON_SHARE_SCREEN_ENDING,
|
|
595
|
+
this._createCallSession(sipSession, callSession),
|
|
596
|
+
);
|
|
597
|
+
};
|
|
598
|
+
}
|
|
586
599
|
|
|
587
600
|
this.currentScreenShare = {
|
|
588
601
|
stream: screenStream,
|
|
@@ -602,7 +615,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
602
615
|
}
|
|
603
616
|
|
|
604
617
|
_onCallAccepted(sipSession: Session, cameraEnabled: boolean): CallSession {
|
|
605
|
-
logger.info('WebRTC phone -
|
|
618
|
+
logger.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
|
|
606
619
|
|
|
607
620
|
const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
|
|
608
621
|
this.currentSipSession = sipSession;
|
|
@@ -1114,7 +1127,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
1114
1127
|
// @TODO: line is not used here
|
|
1115
1128
|
async makeCall(number: string, line: any, cameraEnabled?: boolean,
|
|
1116
1129
|
audioOnly: boolean = false, conference: boolean = false): Promise<?CallSession> {
|
|
1117
|
-
logger.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
|
|
1130
|
+
logger.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
|
|
1118
1131
|
if (!number) {
|
|
1119
1132
|
return Promise.resolve(null);
|
|
1120
1133
|
}
|
|
@@ -1475,9 +1488,13 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
1475
1488
|
if (this.shouldSendReinvite && this.currentSipSession
|
|
1476
1489
|
&& this.currentSipSession.state === SessionState.Established) {
|
|
1477
1490
|
this.shouldSendReinvite = false;
|
|
1491
|
+
const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
|
|
1492
|
+
const isConference = pc ? pc.sfu : false;
|
|
1493
|
+
const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
|
|
1494
|
+
|
|
1478
1495
|
try {
|
|
1479
1496
|
// Send reinvite with iceRestart
|
|
1480
|
-
this.sendReinvite(this.currentCallSession, null,
|
|
1497
|
+
this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
|
|
1481
1498
|
} catch (e) {
|
|
1482
1499
|
logger.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
|
|
1483
1500
|
}
|
|
@@ -1561,6 +1578,15 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
1561
1578
|
return this.client.getSipSessionId(sipSession);
|
|
1562
1579
|
}
|
|
1563
1580
|
|
|
1581
|
+
_updateCallSession(callSession: CallSession) {
|
|
1582
|
+
const sipSession = this.findSipSession(callSession);
|
|
1583
|
+
const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
|
|
1584
|
+
|
|
1585
|
+
if (sipSessionId) {
|
|
1586
|
+
this.callSessions[sipSessionId] = callSession;
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1564
1590
|
_onMessage(message: Message) {
|
|
1565
1591
|
if (!message || message.method !== 'MESSAGE') {
|
|
1566
1592
|
return;
|
package/src/domain/Recording.js
CHANGED
package/src/domain/Voicemail.js
CHANGED
|
@@ -61,6 +61,9 @@ export default class Voicemail {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
static parseMany(plain: Response): Array<Voicemail> {
|
|
64
|
+
if (!plain) {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
64
67
|
const plainUnread = plain.folders.filter(folder => folder.type === 'new')[0].messages;
|
|
65
68
|
const plainRead = plain.folders.filter(folder => folder.type === 'old')[0].messages;
|
|
66
69
|
|