@wazo/sdk 0.43.5 → 1.0.0-alpha.0
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 +3 -3
- package/esm/__tests__/__voice__/call.test.js +72 -0
- package/esm/__tests__/__voice__/softphone.test.js +66 -0
- package/esm/api/auth.js +1 -5
- package/esm/checker/checks/webrtc.js +2 -1
- package/esm/domain/InvalidState.js +8 -0
- package/esm/domain/InvalidStateTransition.js +10 -0
- package/esm/domain/Phone/WebRTCPhone.js +33 -35
- package/esm/simple/Auth.js +12 -6
- package/esm/simple/Phone.js +2 -1
- package/esm/simple/__tests__/Auth.test.js +64 -8
- package/esm/simple/index.js +8 -2
- package/esm/simple/room/Room.js +2 -1
- package/esm/simple/room/SipRoom.js +2 -1
- package/esm/state-machine/call-state-machine.js +114 -0
- package/esm/state-machine/softphone-state-machine.js +39 -0
- package/esm/state-machine/utils.js +40 -0
- package/esm/types/__tests__/__voice__/call.test.d.ts +2 -0
- package/esm/types/__tests__/__voice__/call.test.d.ts.map +1 -0
- package/esm/types/__tests__/__voice__/softphone.test.d.ts +2 -0
- package/esm/types/__tests__/__voice__/softphone.test.d.ts.map +1 -0
- package/esm/types/api/auth.d.ts.map +1 -1
- package/esm/types/checker/checks/webrtc.d.ts.map +1 -1
- package/esm/types/domain/InvalidState.d.ts +6 -0
- package/esm/types/domain/InvalidState.d.ts.map +1 -0
- package/esm/types/domain/InvalidStateTransition.d.ts +7 -0
- package/esm/types/domain/InvalidStateTransition.d.ts.map +1 -0
- package/esm/types/domain/Phone/WebRTCPhone.d.ts +0 -1
- package/esm/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
- package/esm/types/domain/types.d.ts +4 -0
- package/esm/types/domain/types.d.ts.map +1 -1
- package/esm/types/simple/Auth.d.ts.map +1 -1
- package/esm/types/simple/Phone.d.ts.map +1 -1
- package/esm/types/simple/index.d.ts +7 -2
- package/esm/types/simple/index.d.ts.map +1 -1
- package/esm/types/simple/room/Room.d.ts.map +1 -1
- package/esm/types/simple/room/SipRoom.d.ts +1 -1
- package/esm/types/simple/room/SipRoom.d.ts.map +1 -1
- package/esm/types/state-machine/call-state-machine.d.ts +43 -0
- package/esm/types/state-machine/call-state-machine.d.ts.map +1 -0
- package/esm/types/state-machine/softphone-state-machine.d.ts +19 -0
- package/esm/types/state-machine/softphone-state-machine.d.ts.map +1 -0
- package/esm/types/state-machine/utils.d.ts +9 -0
- package/esm/types/state-machine/utils.d.ts.map +1 -0
- package/esm/types/utils/api-requester.d.ts.map +1 -1
- package/esm/types/utils/sdp.d.ts +6 -0
- package/esm/types/utils/sdp.d.ts.map +1 -1
- package/esm/types/utils/sip-logger.d.ts +4 -0
- package/esm/types/utils/sip-logger.d.ts.map +1 -0
- package/esm/types/utils/webrtc.d.ts +40 -0
- package/esm/types/utils/webrtc.d.ts.map +1 -1
- package/esm/types/voice/call.d.ts +110 -0
- package/esm/types/voice/call.d.ts.map +1 -0
- package/esm/types/voice/softphone.d.ts +77 -0
- package/esm/types/voice/softphone.d.ts.map +1 -0
- package/esm/types/web-rtc-client.d.ts +1 -36
- package/esm/types/web-rtc-client.d.ts.map +1 -1
- package/esm/utils/__tests__/api-requester.test.js +0 -17
- package/esm/utils/api-requester.js +1 -9
- package/esm/utils/sdp.js +26 -0
- package/esm/utils/sip-logger.js +32 -0
- package/esm/utils/webrtc.js +465 -0
- package/esm/voice/call.js +527 -0
- package/esm/voice/softphone.js +347 -0
- package/esm/web-rtc-client.js +86 -584
- package/lib/__tests__/__voice__/call.test.js +86 -0
- package/lib/__tests__/__voice__/softphone.test.js +80 -0
- package/lib/api/auth.js +1 -5
- package/lib/checker/checks/webrtc.js +2 -1
- package/lib/domain/InvalidState.js +9 -0
- package/lib/domain/InvalidStateTransition.js +10 -0
- package/lib/domain/Phone/WebRTCPhone.js +33 -35
- package/lib/simple/Auth.js +12 -6
- package/lib/simple/Phone.js +2 -1
- package/lib/simple/__tests__/Auth.test.js +64 -11
- package/lib/simple/index.js +6 -0
- package/lib/simple/room/Room.js +4 -3
- package/lib/simple/room/SipRoom.js +2 -1
- package/lib/state-machine/call-state-machine.js +120 -0
- package/lib/state-machine/softphone-state-machine.js +42 -0
- package/lib/state-machine/utils.js +52 -0
- package/lib/types/__tests__/__voice__/call.test.d.ts +2 -0
- package/lib/types/__tests__/__voice__/call.test.d.ts.map +1 -0
- package/lib/types/__tests__/__voice__/softphone.test.d.ts +2 -0
- package/lib/types/__tests__/__voice__/softphone.test.d.ts.map +1 -0
- package/lib/types/api/auth.d.ts.map +1 -1
- package/lib/types/checker/checks/webrtc.d.ts.map +1 -1
- package/lib/types/domain/InvalidState.d.ts +6 -0
- package/lib/types/domain/InvalidState.d.ts.map +1 -0
- package/lib/types/domain/InvalidStateTransition.d.ts +7 -0
- package/lib/types/domain/InvalidStateTransition.d.ts.map +1 -0
- package/lib/types/domain/Phone/WebRTCPhone.d.ts +0 -1
- package/lib/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
- package/lib/types/domain/types.d.ts +4 -0
- package/lib/types/domain/types.d.ts.map +1 -1
- package/lib/types/simple/Auth.d.ts.map +1 -1
- package/lib/types/simple/Phone.d.ts.map +1 -1
- package/lib/types/simple/index.d.ts +7 -2
- package/lib/types/simple/index.d.ts.map +1 -1
- package/lib/types/simple/room/Room.d.ts.map +1 -1
- package/lib/types/simple/room/SipRoom.d.ts +1 -1
- package/lib/types/simple/room/SipRoom.d.ts.map +1 -1
- package/lib/types/state-machine/call-state-machine.d.ts +43 -0
- package/lib/types/state-machine/call-state-machine.d.ts.map +1 -0
- package/lib/types/state-machine/softphone-state-machine.d.ts +19 -0
- package/lib/types/state-machine/softphone-state-machine.d.ts.map +1 -0
- package/lib/types/state-machine/utils.d.ts +9 -0
- package/lib/types/state-machine/utils.d.ts.map +1 -0
- package/lib/types/utils/api-requester.d.ts.map +1 -1
- package/lib/types/utils/sdp.d.ts +6 -0
- package/lib/types/utils/sdp.d.ts.map +1 -1
- package/lib/types/utils/sip-logger.d.ts +4 -0
- package/lib/types/utils/sip-logger.d.ts.map +1 -0
- package/lib/types/utils/webrtc.d.ts +40 -0
- package/lib/types/utils/webrtc.d.ts.map +1 -1
- package/lib/types/voice/call.d.ts +110 -0
- package/lib/types/voice/call.d.ts.map +1 -0
- package/lib/types/voice/softphone.d.ts +77 -0
- package/lib/types/voice/softphone.d.ts.map +1 -0
- package/lib/types/web-rtc-client.d.ts +1 -36
- package/lib/types/web-rtc-client.d.ts.map +1 -1
- package/lib/utils/__tests__/api-requester.test.js +0 -17
- package/lib/utils/api-requester.js +1 -9
- package/lib/utils/sdp.js +27 -1
- package/lib/utils/sip-logger.js +37 -0
- package/lib/utils/webrtc.js +521 -1
- package/lib/voice/call.js +577 -0
- package/lib/voice/softphone.js +375 -0
- package/lib/web-rtc-client.js +89 -601
- package/package.json +3 -2
- package/src/__tests__/__voice__/call.test.ts +90 -0
- package/src/__tests__/__voice__/softphone.test.ts +82 -0
- package/src/api/auth.ts +2 -13
- package/src/checker/checks/webrtc.ts +2 -1
- package/src/domain/InvalidState.ts +13 -0
- package/src/domain/InvalidStateTransition.ts +17 -0
- package/src/domain/Phone/WebRTCPhone.ts +34 -36
- package/src/domain/types.ts +6 -1
- package/src/simple/Auth.ts +13 -6
- package/src/simple/Phone.ts +2 -1
- package/src/simple/__tests__/Auth.test.ts +87 -9
- package/src/simple/index.ts +9 -2
- package/src/simple/room/Room.ts +2 -1
- package/src/simple/room/SipRoom.ts +2 -1
- package/src/state-machine/call-state-machine.ts +131 -0
- package/src/state-machine/softphone-state-machine.ts +49 -0
- package/src/state-machine/utils.ts +53 -0
- package/src/utils/__tests__/api-requester.test.ts +0 -20
- package/src/utils/api-requester.ts +1 -9
- package/src/utils/sdp.ts +36 -0
- package/src/utils/sip-logger.ts +40 -0
- package/src/utils/webrtc.ts +571 -0
- package/src/voice/call.ts +713 -0
- package/src/voice/softphone.ts +485 -0
- package/src/web-rtc-client.ts +90 -690
package/lib/web-rtc-client.js
CHANGED
|
@@ -1,28 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/* eslint-disable class-methods-use-this, no-param-reassign, max-classes-per-file, no-underscore-dangle */
|
|
3
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
-
if (k2 === undefined) k2 = k;
|
|
5
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
-
}
|
|
9
|
-
Object.defineProperty(o, k2, desc);
|
|
10
|
-
}) : (function(o, m, k, k2) {
|
|
11
|
-
if (k2 === undefined) k2 = k;
|
|
12
|
-
o[k2] = m[k];
|
|
13
|
-
}));
|
|
14
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
-
}) : function(o, v) {
|
|
17
|
-
o["default"] = v;
|
|
18
|
-
});
|
|
19
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
20
|
-
if (mod && mod.__esModule) return mod;
|
|
21
|
-
var result = {};
|
|
22
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
23
|
-
__setModuleDefault(result, mod);
|
|
24
|
-
return result;
|
|
25
|
-
};
|
|
26
3
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
27
4
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
28
5
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -47,8 +24,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
47
24
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
48
25
|
};
|
|
49
26
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
-
exports.CanceledCallError = exports.transportEvents = exports.events =
|
|
51
|
-
/* global
|
|
27
|
+
exports.CanceledCallError = exports.transportEvents = exports.events = void 0;
|
|
28
|
+
/* global document, navigator */
|
|
52
29
|
require("webrtc-adapter");
|
|
53
30
|
const user_agent_state_1 = require("sip.js/lib/api/user-agent-state");
|
|
54
31
|
const parser_1 = require("sip.js/lib/core/messages/parser");
|
|
@@ -60,21 +37,14 @@ const messager_1 = require("sip.js/lib/api/messager");
|
|
|
60
37
|
const registerer_state_1 = require("sip.js/lib/api/registerer-state");
|
|
61
38
|
const session_state_1 = require("sip.js/lib/api/session-state");
|
|
62
39
|
const transport_state_1 = require("sip.js/lib/api/transport-state");
|
|
63
|
-
const peer_connection_configuration_default_1 = require("sip.js/lib/platform/web/session-description-handler/peer-connection-configuration-default");
|
|
64
40
|
const getstats_1 = __importDefault(require("getstats"));
|
|
65
41
|
const api_1 = require("sip.js/lib/api");
|
|
66
|
-
const WazoSessionDescriptionHandler_1 = __importStar(require("./lib/WazoSessionDescriptionHandler"));
|
|
67
42
|
const Emitter_1 = __importDefault(require("./utils/Emitter"));
|
|
68
43
|
const api_client_1 = __importDefault(require("./api-client"));
|
|
69
44
|
const IssueReporter_1 = __importDefault(require("./service/IssueReporter"));
|
|
70
45
|
const Heartbeat_1 = __importDefault(require("./utils/Heartbeat"));
|
|
71
46
|
const sdp_1 = require("./utils/sdp");
|
|
72
|
-
const
|
|
73
|
-
// We need to replace 0.0.0.0 to 127.0.0.1 in the sdp to avoid MOH during a createOffer.
|
|
74
|
-
const replaceLocalIpModifier = (description) => Promise.resolve(Object.assign(Object.assign({}, JSON.parse(JSON.stringify(description))), { sdp: description.sdp.replace('c=IN IP4 0.0.0.0', 'c=IN IP4 127.0.0.1') }));
|
|
75
|
-
exports.replaceLocalIpModifier = replaceLocalIpModifier;
|
|
76
|
-
const SIP_ID_LENGTH = 36;
|
|
77
|
-
const DEFAULT_ICE_TIMEOUT = 3000;
|
|
47
|
+
const webrtc_1 = require("./utils/webrtc");
|
|
78
48
|
const SEND_STATS_DELAY = 5000;
|
|
79
49
|
const states = ['STATUS_NULL', 'STATUS_NEW', 'STATUS_CONNECTING', 'STATUS_CONNECTED', 'STATUS_COMPLETED'];
|
|
80
50
|
const logger = IssueReporter_1.default ? IssueReporter_1.default.loggerFor('webrtc-client') : console;
|
|
@@ -104,21 +74,7 @@ class CanceledCallError extends Error {
|
|
|
104
74
|
}
|
|
105
75
|
exports.CanceledCallError = CanceledCallError;
|
|
106
76
|
const MAX_REGISTER_TRIES = 5;
|
|
107
|
-
// setting a 24hr timeout and letting the backend define the actual value
|
|
108
|
-
const NO_ANSWER_TIMEOUT = 60 * 60 * 24; // in seconds
|
|
109
77
|
class WebRTCClient extends Emitter_1.default {
|
|
110
|
-
static isAPrivateIp(ip) {
|
|
111
|
-
const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
|
|
112
|
-
return regex.exec(ip) == null;
|
|
113
|
-
}
|
|
114
|
-
static getIceServers(ip) {
|
|
115
|
-
if (WebRTCClient.isAPrivateIp(ip)) {
|
|
116
|
-
return [{
|
|
117
|
-
urls: ['stun:stun.l.google.com:19302', 'stun:stun4.l.google.com:19302'],
|
|
118
|
-
}];
|
|
119
|
-
}
|
|
120
|
-
return [];
|
|
121
|
-
}
|
|
122
78
|
constructor(config, session, uaConfigOverrides) {
|
|
123
79
|
super();
|
|
124
80
|
// For debug purpose
|
|
@@ -183,7 +139,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
183
139
|
}
|
|
184
140
|
createUserAgent(uaConfigOverrides) {
|
|
185
141
|
var _a;
|
|
186
|
-
const uaOptions = this.
|
|
142
|
+
const uaOptions = (0, webrtc_1.createUaOptions)(this.config, uaConfigOverrides, this.audio, this.video);
|
|
187
143
|
logger.info('sdk webrtc, creating UA', {
|
|
188
144
|
uaOptions: Object.assign(Object.assign({}, uaOptions), { authorizationPassword: `${(_a = uaOptions === null || uaOptions === void 0 ? void 0 : uaOptions.authorizationPassword) === null || _a === void 0 ? void 0 : _a.slice(0, 5)}xxxx` }),
|
|
189
145
|
clientId: this.clientId,
|
|
@@ -200,7 +156,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
200
156
|
});
|
|
201
157
|
this._setupSession(invitation);
|
|
202
158
|
const shouldAutoAnswer = !!invitation.request.getHeader('alert-info');
|
|
203
|
-
this.eventEmitter.emit(INVITE, invitation,
|
|
159
|
+
this.eventEmitter.emit(INVITE, invitation, (0, webrtc_1.sessionWantsToDoVideo)(invitation), shouldAutoAnswer);
|
|
204
160
|
},
|
|
205
161
|
};
|
|
206
162
|
const ua = new user_agent_1.UserAgent(uaOptions);
|
|
@@ -299,7 +255,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
299
255
|
logger.info('sdk webrtc registering aborted due to a registration in progress.', { clientId: this.clientId });
|
|
300
256
|
return Promise.resolve();
|
|
301
257
|
}
|
|
302
|
-
const registerOptions =
|
|
258
|
+
const registerOptions = (0, webrtc_1.isWeb)() ? {} : {
|
|
303
259
|
extraContactHeaderParams: ['mobility=mobile'],
|
|
304
260
|
};
|
|
305
261
|
const onRegisterFailed = () => {
|
|
@@ -456,7 +412,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
456
412
|
if (audioOnly) {
|
|
457
413
|
inviterOptions.sessionDescriptionHandlerModifiersReInvite = [modifiers_1.stripVideo];
|
|
458
414
|
}
|
|
459
|
-
const uri =
|
|
415
|
+
const uri = (0, sdp_1.makeURI)(number, this.config.host);
|
|
460
416
|
let session = null;
|
|
461
417
|
if (uri) {
|
|
462
418
|
session = this.userAgent ? new api_1.Inviter(this.userAgent, uri, inviterOptions) : null;
|
|
@@ -469,7 +425,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
469
425
|
this._setupSession(session);
|
|
470
426
|
}
|
|
471
427
|
if (conference) {
|
|
472
|
-
this.conferences[
|
|
428
|
+
this.conferences[(0, sdp_1.getSipSessionId)(session)] = true;
|
|
473
429
|
}
|
|
474
430
|
const inviteOptions = {
|
|
475
431
|
requestDelegate: {
|
|
@@ -494,12 +450,12 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
494
450
|
this.eventEmitter.emit(REJECTED, session, response);
|
|
495
451
|
},
|
|
496
452
|
},
|
|
497
|
-
sessionDescriptionHandlerOptions:
|
|
453
|
+
sessionDescriptionHandlerOptions: (0, webrtc_1.getMediaConfiguration)(enableVideo || false, conference),
|
|
498
454
|
};
|
|
499
455
|
if (inviteOptions.sessionDescriptionHandlerOptions) {
|
|
500
456
|
inviteOptions.sessionDescriptionHandlerOptions.audioOnly = audioOnly;
|
|
501
457
|
}
|
|
502
|
-
inviteOptions.sessionDescriptionHandlerModifiers = [
|
|
458
|
+
inviteOptions.sessionDescriptionHandlerModifiers = [sdp_1.replaceLocalIpModifier];
|
|
503
459
|
if (audioOnly) {
|
|
504
460
|
inviteOptions.sessionDescriptionHandlerModifiers.push(modifiers_1.stripVideo);
|
|
505
461
|
}
|
|
@@ -524,7 +480,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
524
480
|
return Promise.reject(new Error(error));
|
|
525
481
|
}
|
|
526
482
|
const options = {
|
|
527
|
-
sessionDescriptionHandlerOptions:
|
|
483
|
+
sessionDescriptionHandlerOptions: (0, webrtc_1.getMediaConfiguration)(enableVideo || false),
|
|
528
484
|
};
|
|
529
485
|
return this._accept(session, options).then(() => {
|
|
530
486
|
// @ts-ignore: private
|
|
@@ -550,7 +506,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
550
506
|
try {
|
|
551
507
|
this._stopSendingStats(session);
|
|
552
508
|
this._cleanupMedia(session);
|
|
553
|
-
delete this.sipSessions[
|
|
509
|
+
delete this.sipSessions[(0, sdp_1.getSipSessionId)(session)];
|
|
554
510
|
// Check if Invitation or Inviter (Invitation = incoming call)
|
|
555
511
|
const isInviter = session instanceof api_1.Inviter;
|
|
556
512
|
// @see github.com/onsip/SIP.js/blob/f11dfd584bc9788ccfc94e03034020672b738975/src/platform/web/simple-user/simple-user.ts#L1004
|
|
@@ -571,19 +527,9 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
571
527
|
return Promise.resolve(null);
|
|
572
528
|
});
|
|
573
529
|
}
|
|
574
|
-
getStats(session) {
|
|
575
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
576
|
-
var _a;
|
|
577
|
-
const pc = (_a = session.sessionDescriptionHandler) === null || _a === void 0 ? void 0 : _a.peerConnection;
|
|
578
|
-
if (!pc) {
|
|
579
|
-
return null;
|
|
580
|
-
}
|
|
581
|
-
return pc.getStats(null);
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
530
|
// Fetch and emit an event at `interval` with session network stats
|
|
585
531
|
startNetworkMonitoring(session, interval = 1000) {
|
|
586
|
-
const sessionId =
|
|
532
|
+
const sessionId = (0, sdp_1.getSipSessionId)(session);
|
|
587
533
|
logger.info('starting network inspection', {
|
|
588
534
|
id: sessionId,
|
|
589
535
|
clientId: this.clientId,
|
|
@@ -592,7 +538,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
592
538
|
this.networkMonitoringInterval[sessionId] = setInterval(() => this._fetchNetworkStats(sessionId), interval);
|
|
593
539
|
}
|
|
594
540
|
stopNetworkMonitoring(session) {
|
|
595
|
-
const sessionId =
|
|
541
|
+
const sessionId = (0, sdp_1.getSipSessionId)(session);
|
|
596
542
|
const exists = (sessionId in this.networkMonitoringInterval);
|
|
597
543
|
logger.info('stopping network inspection', {
|
|
598
544
|
clientId: this.clientId,
|
|
@@ -664,24 +610,17 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
664
610
|
logger.info('sdk webrtc client closed', { clientId: this.clientId });
|
|
665
611
|
});
|
|
666
612
|
}
|
|
667
|
-
getNumber(session) {
|
|
668
|
-
if (!session) {
|
|
669
|
-
return null;
|
|
670
|
-
}
|
|
671
|
-
// @ts-ignore: private
|
|
672
|
-
return session.remoteIdentity.uri._normal.user;
|
|
673
|
-
}
|
|
674
613
|
mute(session) {
|
|
675
614
|
logger.info('sdk webrtc mute', {
|
|
676
615
|
id: session.id,
|
|
677
616
|
});
|
|
678
|
-
|
|
617
|
+
(0, webrtc_1.toggleAudio)(session, true);
|
|
679
618
|
}
|
|
680
619
|
unmute(session) {
|
|
681
620
|
logger.info('sdk webrtc unmute', {
|
|
682
621
|
id: session.id,
|
|
683
622
|
});
|
|
684
|
-
|
|
623
|
+
(0, webrtc_1.toggleAudio)(session, false);
|
|
685
624
|
}
|
|
686
625
|
isAudioMuted(session) {
|
|
687
626
|
if (!session || !session.sessionDescriptionHandler) {
|
|
@@ -718,16 +657,16 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
718
657
|
logger.info('sdk webrtc toggle camera on', {
|
|
719
658
|
id: session.id,
|
|
720
659
|
});
|
|
721
|
-
|
|
660
|
+
(0, webrtc_1.toggleVideo)(session, false);
|
|
722
661
|
}
|
|
723
662
|
toggleCameraOff(session) {
|
|
724
663
|
logger.info('sdk webrtc toggle camera off', {
|
|
725
664
|
id: session.id,
|
|
726
665
|
});
|
|
727
|
-
|
|
666
|
+
(0, webrtc_1.toggleVideo)(session, true);
|
|
728
667
|
}
|
|
729
668
|
hold(session, isConference = false, hadVideo = false) {
|
|
730
|
-
const sessionId =
|
|
669
|
+
const sessionId = (0, sdp_1.getSipSessionId)(session);
|
|
731
670
|
const hasVideo = hadVideo || this.hasLocalVideo(sessionId);
|
|
732
671
|
logger.info('sdk webrtc hold', {
|
|
733
672
|
sessionId,
|
|
@@ -755,8 +694,8 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
755
694
|
hold: true,
|
|
756
695
|
conference: isConference,
|
|
757
696
|
};
|
|
758
|
-
const options =
|
|
759
|
-
if (!
|
|
697
|
+
const options = (0, webrtc_1.getMediaConfiguration)(false, isConference);
|
|
698
|
+
if (!(0, webrtc_1.isWeb)()) {
|
|
760
699
|
options.sessionDescriptionHandlerModifiers = [modifiers_1.holdModifier];
|
|
761
700
|
}
|
|
762
701
|
options.sessionDescriptionHandlerOptions = {
|
|
@@ -775,7 +714,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
775
714
|
});
|
|
776
715
|
}
|
|
777
716
|
unhold(session, isConference = false) {
|
|
778
|
-
const sessionId =
|
|
717
|
+
const sessionId = (0, sdp_1.getSipSessionId)(session);
|
|
779
718
|
const hasVideo = sessionId in this.heldSessions && this.heldSessions[sessionId].hasVideo;
|
|
780
719
|
logger.info('sdk webrtc unhold', {
|
|
781
720
|
sessionId,
|
|
@@ -790,13 +729,13 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
790
729
|
return Promise.resolve();
|
|
791
730
|
}
|
|
792
731
|
this.unmute(session);
|
|
793
|
-
delete this.heldSessions[
|
|
732
|
+
delete this.heldSessions[(0, sdp_1.getSipSessionId)(session)];
|
|
794
733
|
session.sessionDescriptionHandlerOptionsReInvite = {
|
|
795
734
|
hold: false,
|
|
796
735
|
conference: isConference,
|
|
797
736
|
};
|
|
798
|
-
const options =
|
|
799
|
-
if (!
|
|
737
|
+
const options = (0, webrtc_1.getMediaConfiguration)(false, isConference);
|
|
738
|
+
if (!(0, webrtc_1.isWeb)()) {
|
|
800
739
|
// We should sent an empty `sessionDescriptionHandlerModifiers` or sip.js will take the last sent modifiers
|
|
801
740
|
// (eg: holdModifier)
|
|
802
741
|
options.sessionDescriptionHandlerModifiers = [];
|
|
@@ -811,110 +750,27 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
811
750
|
logger.warn('sdk webrtc re-invite during resume, error', e);
|
|
812
751
|
});
|
|
813
752
|
}
|
|
814
|
-
// Returns true if a re-INVITE is required
|
|
815
|
-
upgradeToVideo(session, constraints, isConference) {
|
|
816
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
817
|
-
var _a, _b;
|
|
818
|
-
const pc = (_a = session.sessionDescriptionHandler) === null || _a === void 0 ? void 0 : _a.peerConnection;
|
|
819
|
-
// Check if a video sender already exists
|
|
820
|
-
let videoSender;
|
|
821
|
-
if (isConference) {
|
|
822
|
-
// We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
|
|
823
|
-
const transceivers = (pc === null || pc === void 0 ? void 0 : pc.getTransceivers()) || [];
|
|
824
|
-
const transceiverIdx = (0, array_1.lastIndexOf)(transceivers, transceiver => transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
|
|
825
|
-
videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
|
|
826
|
-
}
|
|
827
|
-
else {
|
|
828
|
-
videoSender = pc && pc.getSenders && pc.getSenders().find((sender) => sender.track === null);
|
|
829
|
-
}
|
|
830
|
-
if (!videoSender) {
|
|
831
|
-
// When no video sender found, it means that we're in the first video upgrade in 1:1
|
|
832
|
-
return;
|
|
833
|
-
}
|
|
834
|
-
// Reuse bidirectional video stream
|
|
835
|
-
const newStream = yield this.getStreamFromConstraints(constraints);
|
|
836
|
-
if (!newStream) {
|
|
837
|
-
console.warn(`Can't create media stream with: ${JSON.stringify(constraints || {})}`);
|
|
838
|
-
return;
|
|
839
|
-
}
|
|
840
|
-
// Add previous local audio track
|
|
841
|
-
if (constraints && !constraints.audio) {
|
|
842
|
-
const localVideoStream = (_b = session.sessionDescriptionHandler) === null || _b === void 0 ? void 0 : _b.localMediaStream;
|
|
843
|
-
const localAudioTrack = localVideoStream.getTracks().find(track => track.kind === 'audio');
|
|
844
|
-
if (localAudioTrack) {
|
|
845
|
-
newStream.addTrack(localAudioTrack);
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
const videoTrack = newStream.getVideoTracks()[0];
|
|
849
|
-
if (videoTrack) {
|
|
850
|
-
videoSender.replaceTrack(videoTrack);
|
|
851
|
-
}
|
|
852
|
-
this.setLocalMediaStream(this.getSipSessionId(session), newStream);
|
|
853
|
-
return newStream;
|
|
854
|
-
});
|
|
855
|
-
}
|
|
856
|
-
downgradeToAudio(session) {
|
|
857
|
-
// Release local video stream when downgrading to audio
|
|
858
|
-
const sessionDescriptionHandler = session.sessionDescriptionHandler;
|
|
859
|
-
const localStream = sessionDescriptionHandler === null || sessionDescriptionHandler === void 0 ? void 0 : sessionDescriptionHandler.localMediaStream;
|
|
860
|
-
const pc = sessionDescriptionHandler === null || sessionDescriptionHandler === void 0 ? void 0 : sessionDescriptionHandler.peerConnection;
|
|
861
|
-
const videoTracks = localStream.getVideoTracks();
|
|
862
|
-
// Remove video senders
|
|
863
|
-
if (pc === null || pc === void 0 ? void 0 : pc.getSenders) {
|
|
864
|
-
pc.getSenders().filter((sender) => sender.track && sender.track.kind === 'video').forEach((videoSender) => {
|
|
865
|
-
videoSender.replaceTrack(null);
|
|
866
|
-
});
|
|
867
|
-
}
|
|
868
|
-
videoTracks.forEach((videoTrack) => {
|
|
869
|
-
videoTrack.enabled = false;
|
|
870
|
-
videoTrack.stop();
|
|
871
|
-
localStream.removeTrack(videoTrack);
|
|
872
|
-
});
|
|
873
|
-
}
|
|
874
|
-
getStreamFromConstraints(constraints_1) {
|
|
875
|
-
return __awaiter(this, arguments, void 0, function* (constraints, conference = false) {
|
|
876
|
-
const video = constraints && constraints.video;
|
|
877
|
-
const { constraints: newConstraints, } = this.getMediaConfiguration(video, conference, constraints);
|
|
878
|
-
let newStream = null;
|
|
879
|
-
try {
|
|
880
|
-
newStream = yield (0, WazoSessionDescriptionHandler_1.wazoMediaStreamFactory)(newConstraints);
|
|
881
|
-
}
|
|
882
|
-
catch (e) { // Nothing to do when the user cancel the screensharing prompt
|
|
883
|
-
}
|
|
884
|
-
if (!newStream) {
|
|
885
|
-
return null;
|
|
886
|
-
}
|
|
887
|
-
newStream.local = true;
|
|
888
|
-
return newStream;
|
|
889
|
-
});
|
|
890
|
-
}
|
|
891
753
|
getHeldSession(sessionId) {
|
|
892
754
|
return this.heldSessions[sessionId];
|
|
893
755
|
}
|
|
894
756
|
isCallHeld(session) {
|
|
895
|
-
return
|
|
757
|
+
return (0, sdp_1.getSipSessionId)(session) in this.heldSessions;
|
|
896
758
|
}
|
|
897
759
|
isVideoRemotelyHeld(sessionId) {
|
|
898
|
-
|
|
899
|
-
const sdp = pc && pc.remoteDescription ? pc.remoteDescription.sdp : null;
|
|
900
|
-
if (!sdp) {
|
|
901
|
-
return false;
|
|
902
|
-
}
|
|
903
|
-
const videoDirection = (0, sdp_1.getVideoDirection)(sdp);
|
|
904
|
-
return videoDirection === 'sendonly';
|
|
760
|
+
return (0, webrtc_1.isVideoRemotelyHeld)(this.heldSessions[sessionId]);
|
|
905
761
|
}
|
|
906
762
|
sendDTMF(session, tone) {
|
|
907
763
|
if (!session.sessionDescriptionHandler) {
|
|
908
764
|
return false;
|
|
909
765
|
}
|
|
910
766
|
logger.info('Sending DTMF', {
|
|
911
|
-
id:
|
|
767
|
+
id: (0, sdp_1.getSipSessionId)(session),
|
|
912
768
|
tone,
|
|
913
769
|
});
|
|
914
770
|
return session.sessionDescriptionHandler.sendDtmf(tone);
|
|
915
771
|
}
|
|
916
772
|
message(destination, message) {
|
|
917
|
-
const uri =
|
|
773
|
+
const uri = (0, sdp_1.makeURI)(destination, this.config.host);
|
|
918
774
|
if (!this.userAgent || !uri) {
|
|
919
775
|
logger.warn('Null value on message', { uri, userAgent: this.userAgent });
|
|
920
776
|
return;
|
|
@@ -925,7 +781,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
925
781
|
transfer(session, target) {
|
|
926
782
|
this.hold(session);
|
|
927
783
|
logger.info('Transfering a session', {
|
|
928
|
-
id:
|
|
784
|
+
id: (0, sdp_1.getSipSessionId)(session),
|
|
929
785
|
target,
|
|
930
786
|
});
|
|
931
787
|
const options = {
|
|
@@ -936,7 +792,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
936
792
|
},
|
|
937
793
|
};
|
|
938
794
|
setTimeout(() => {
|
|
939
|
-
const uri =
|
|
795
|
+
const uri = (0, sdp_1.makeURI)(target, this.config.host);
|
|
940
796
|
if (!uri) {
|
|
941
797
|
logger.warn('transfer timeout: null URI');
|
|
942
798
|
return;
|
|
@@ -948,21 +804,21 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
948
804
|
atxfer(session) {
|
|
949
805
|
this.hold(session);
|
|
950
806
|
logger.info('webrtc transfer started', {
|
|
951
|
-
id:
|
|
807
|
+
id: (0, sdp_1.getSipSessionId)(session),
|
|
952
808
|
});
|
|
953
809
|
const result = {
|
|
954
810
|
newSession: null,
|
|
955
811
|
init: (target) => __awaiter(this, void 0, void 0, function* () {
|
|
956
812
|
logger.info('webrtc transfer initialized', {
|
|
957
|
-
id:
|
|
813
|
+
id: (0, sdp_1.getSipSessionId)(session),
|
|
958
814
|
target,
|
|
959
815
|
});
|
|
960
816
|
result.newSession = yield this.call(target);
|
|
961
817
|
}),
|
|
962
818
|
complete: () => {
|
|
963
819
|
logger.info('webrtc transfer completed', {
|
|
964
|
-
id:
|
|
965
|
-
referId:
|
|
820
|
+
id: (0, sdp_1.getSipSessionId)(session),
|
|
821
|
+
referId: (0, sdp_1.getSipSessionId)(result.newSession),
|
|
966
822
|
});
|
|
967
823
|
session.refer(result.newSession);
|
|
968
824
|
},
|
|
@@ -1004,7 +860,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1004
860
|
return;
|
|
1005
861
|
}
|
|
1006
862
|
const core = (_a = this.userAgent) === null || _a === void 0 ? void 0 : _a.userAgentCore;
|
|
1007
|
-
const fromURI =
|
|
863
|
+
const fromURI = (0, sdp_1.makeURI)(this.config.authorizationUser || '', this.config.host);
|
|
1008
864
|
const toURI = new uri_1.URI('sip', '', this.config.host);
|
|
1009
865
|
if (fromURI) {
|
|
1010
866
|
const message = core === null || core === void 0 ? void 0 : core.makeOutgoingRequestMessage('OPTIONS', toURI, fromURI, toURI, {});
|
|
@@ -1022,9 +878,6 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1022
878
|
getContactIdentifier() {
|
|
1023
879
|
return this.userAgent ? `${this.userAgent.configuration.contactName}/${this.userAgent.contact.uri}` : null;
|
|
1024
880
|
}
|
|
1025
|
-
isFirefox() {
|
|
1026
|
-
return this._isWeb() && navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
|
1027
|
-
}
|
|
1028
881
|
changeAudioOutputVolume(volume) {
|
|
1029
882
|
logger.info('Changing audio output volume', {
|
|
1030
883
|
volume,
|
|
@@ -1132,12 +985,12 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1132
985
|
} });
|
|
1133
986
|
}
|
|
1134
987
|
changeSessionVideoInputDevice(id, session) {
|
|
1135
|
-
if (!
|
|
988
|
+
if (!(0, webrtc_1.sessionWantsToDoVideo)(session)) {
|
|
1136
989
|
return Promise.resolve();
|
|
1137
990
|
}
|
|
1138
991
|
const sdh = session.sessionDescriptionHandler;
|
|
1139
992
|
const pc = sdh.peerConnection;
|
|
1140
|
-
const sessionId =
|
|
993
|
+
const sessionId = (0, sdp_1.getSipSessionId)(session);
|
|
1141
994
|
const localStream = this.getLocalStream(sessionId);
|
|
1142
995
|
logger.info('changing video input device', {
|
|
1143
996
|
id,
|
|
@@ -1174,7 +1027,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1174
1027
|
}
|
|
1175
1028
|
// let's update the local stream
|
|
1176
1029
|
this.eventEmitter.emit('onVideoInputChange', stream);
|
|
1177
|
-
|
|
1030
|
+
(0, webrtc_1.setLocalMediaStream)(this.sipSessions[sessionId], stream);
|
|
1178
1031
|
return stream;
|
|
1179
1032
|
}));
|
|
1180
1033
|
}
|
|
@@ -1195,12 +1048,12 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1195
1048
|
return Promise.resolve();
|
|
1196
1049
|
}
|
|
1197
1050
|
const wasMuted = this.isAudioMuted(sipSession);
|
|
1198
|
-
const shouldDoVideo = newConstraints ? newConstraints.video :
|
|
1051
|
+
const shouldDoVideo = newConstraints ? newConstraints.video : (0, webrtc_1.sessionWantsToDoVideo)(sipSession);
|
|
1199
1052
|
const shouldDoScreenSharing = newConstraints && newConstraints.screen;
|
|
1200
1053
|
const desktop = newConstraints && newConstraints.desktop;
|
|
1201
1054
|
logger.info('Sending reinvite', {
|
|
1202
1055
|
clientId: this.clientId,
|
|
1203
|
-
id:
|
|
1056
|
+
id: (0, sdp_1.getSipSessionId)(sipSession),
|
|
1204
1057
|
newConstraints,
|
|
1205
1058
|
conference,
|
|
1206
1059
|
audioOnly,
|
|
@@ -1216,7 +1069,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1216
1069
|
}
|
|
1217
1070
|
sipSession.sessionDescriptionHandlerOptionsReInvite = Object.assign(Object.assign({}, sipSession.sessionDescriptionHandlerOptionsReInvite), { conference,
|
|
1218
1071
|
audioOnly });
|
|
1219
|
-
const { constraints, } =
|
|
1072
|
+
const { constraints, } = (0, webrtc_1.getMediaConfiguration)(shouldDoVideo, conference, newConstraints);
|
|
1220
1073
|
return sipSession.invite({
|
|
1221
1074
|
requestDelegate: {
|
|
1222
1075
|
onAccept: (response) => {
|
|
@@ -1232,11 +1085,11 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1232
1085
|
sipSession.incomingInviteRequest.message.body = response.message.body;
|
|
1233
1086
|
}
|
|
1234
1087
|
logger.info('on re-INVITE accepted', {
|
|
1235
|
-
id:
|
|
1088
|
+
id: (0, sdp_1.getSipSessionId)(sipSession),
|
|
1236
1089
|
wasMuted,
|
|
1237
1090
|
shouldDoScreenSharing,
|
|
1238
1091
|
});
|
|
1239
|
-
|
|
1092
|
+
(0, webrtc_1.updateRemoteStream)(sipSession, false);
|
|
1240
1093
|
if (wasMuted) {
|
|
1241
1094
|
this.mute(sipSession);
|
|
1242
1095
|
}
|
|
@@ -1247,7 +1100,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1247
1100
|
return this.eventEmitter.emit(ON_REINVITE, sipSession, response);
|
|
1248
1101
|
},
|
|
1249
1102
|
},
|
|
1250
|
-
sessionDescriptionHandlerModifiers: [
|
|
1103
|
+
sessionDescriptionHandlerModifiers: [sdp_1.replaceLocalIpModifier],
|
|
1251
1104
|
requestOptions: {
|
|
1252
1105
|
extraHeaders: [`Subject: ${shouldDoScreenSharing ? 'screenshare' : 'upgrade-video'}`],
|
|
1253
1106
|
},
|
|
@@ -1271,107 +1124,57 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1271
1124
|
});
|
|
1272
1125
|
}
|
|
1273
1126
|
getPeerConnection(sessionId) {
|
|
1274
|
-
|
|
1275
|
-
if (!sipSession) {
|
|
1276
|
-
return null;
|
|
1277
|
-
}
|
|
1278
|
-
return sipSession.sessionDescriptionHandler ? sipSession.sessionDescriptionHandler.peerConnection : null;
|
|
1127
|
+
return (0, webrtc_1.getPeerConnection)(this.sipSessions[sessionId]);
|
|
1279
1128
|
}
|
|
1280
1129
|
// Local streams
|
|
1281
1130
|
getLocalStream(sessionId) {
|
|
1282
|
-
|
|
1283
|
-
const sipSession = this.sipSessions[sessionId];
|
|
1284
|
-
return ((_a = sipSession === null || sipSession === void 0 ? void 0 : sipSession.sessionDescriptionHandler) === null || _a === void 0 ? void 0 : _a.localMediaStream) || null;
|
|
1131
|
+
return (0, webrtc_1.getLocalStream)(this.sipSessions[sessionId]);
|
|
1285
1132
|
}
|
|
1286
1133
|
getLocalTracks(sessionId) {
|
|
1287
|
-
|
|
1288
|
-
if (!localStream) {
|
|
1289
|
-
return [];
|
|
1290
|
-
}
|
|
1291
|
-
return localStream.getTracks();
|
|
1134
|
+
return (0, webrtc_1.getLocalTracks)(this.sipSessions[sessionId]);
|
|
1292
1135
|
}
|
|
1293
1136
|
hasLocalVideo(sessionId) {
|
|
1294
|
-
return
|
|
1137
|
+
return (0, webrtc_1.hasLocalVideo)(this.sipSessions[sessionId]);
|
|
1295
1138
|
}
|
|
1296
1139
|
// Check if we have at least one video track, even muted or not live
|
|
1297
1140
|
hasALocalVideoTrack(sessionId) {
|
|
1298
|
-
return
|
|
1141
|
+
return (0, webrtc_1.hasALocalVideoTrack)(this.sipSessions[sessionId]);
|
|
1299
1142
|
}
|
|
1300
1143
|
getLocalVideoStream(sessionId) {
|
|
1301
|
-
return
|
|
1144
|
+
return (0, webrtc_1.getLocalVideoStream)(this.sipSessions[sessionId]);
|
|
1302
1145
|
}
|
|
1303
1146
|
// Remote streams
|
|
1304
1147
|
getRemoteStream(sessionId) {
|
|
1305
|
-
|
|
1306
|
-
const sipSession = this.sipSessions[sessionId];
|
|
1307
|
-
return ((_a = sipSession === null || sipSession === void 0 ? void 0 : sipSession.sessionDescriptionHandler) === null || _a === void 0 ? void 0 : _a.remoteMediaStream) || null;
|
|
1148
|
+
return (0, webrtc_1.getRemoteStream)(this.sipSessions[sessionId]);
|
|
1308
1149
|
}
|
|
1309
1150
|
getRemoteTracks(sessionId) {
|
|
1310
|
-
|
|
1311
|
-
if (!remoteStream) {
|
|
1312
|
-
return [];
|
|
1313
|
-
}
|
|
1314
|
-
return remoteStream.getTracks();
|
|
1151
|
+
return (0, webrtc_1.getRemoteTracks)(this.sipSessions[sessionId]);
|
|
1315
1152
|
}
|
|
1316
1153
|
hasRemoteVideo(sessionId) {
|
|
1317
|
-
return
|
|
1154
|
+
return (0, webrtc_1.hasRemoteVideo)(this.sipSessions[sessionId]);
|
|
1318
1155
|
}
|
|
1319
1156
|
// Check if we have at least one video track, even muted or not live
|
|
1320
1157
|
hasARemoteVideoTrack(sessionId) {
|
|
1321
|
-
return
|
|
1158
|
+
return (0, webrtc_1.hasARemoteVideoTrack)(this.sipSessions[sessionId]);
|
|
1322
1159
|
}
|
|
1323
1160
|
getRemoteVideoStream(sessionId) {
|
|
1324
|
-
|
|
1325
|
-
return null;
|
|
1326
|
-
}
|
|
1327
|
-
return this.hasRemoteVideo(sessionId) ? this.getRemoteStream(sessionId) : null;
|
|
1161
|
+
return (0, webrtc_1.getRemoteVideoStream)(this.sipSessions[sessionId]);
|
|
1328
1162
|
}
|
|
1329
1163
|
// Useful in a react-native environment when remoteMediaStream is not updated
|
|
1330
1164
|
getRemoteVideoStreamFromPc(sessionId) {
|
|
1331
|
-
|
|
1332
|
-
if (!pc) {
|
|
1333
|
-
return null;
|
|
1334
|
-
}
|
|
1335
|
-
return pc.getRemoteStreams().find((stream) => !!stream.getVideoTracks().length);
|
|
1165
|
+
return (0, webrtc_1.getRemoteVideoStreamFromPc)(this.sipSessions[sessionId]);
|
|
1336
1166
|
}
|
|
1337
1167
|
hasVideo(sessionId) {
|
|
1338
|
-
return
|
|
1168
|
+
return (0, webrtc_1.hasVideoTrack)(this.sipSessions[sessionId]);
|
|
1339
1169
|
}
|
|
1340
1170
|
hasAVideoTrack(sessionId) {
|
|
1341
|
-
return
|
|
1342
|
-
}
|
|
1343
|
-
getSipSessionId(sipSession) {
|
|
1344
|
-
if (!sipSession) {
|
|
1345
|
-
return '';
|
|
1346
|
-
}
|
|
1347
|
-
const message = sipSession.message;
|
|
1348
|
-
if (message === null || message === void 0 ? void 0 : message.callId) {
|
|
1349
|
-
return message.callId.substring(0, SIP_ID_LENGTH);
|
|
1350
|
-
}
|
|
1351
|
-
// For Inviter
|
|
1352
|
-
// @ts-ignore: private
|
|
1353
|
-
if (sipSession instanceof api_1.Inviter && sipSession.outgoingRequestMessage) {
|
|
1354
|
-
// @ts-ignore: private
|
|
1355
|
-
return sipSession.outgoingRequestMessage.callId.substring(0, SIP_ID_LENGTH);
|
|
1356
|
-
}
|
|
1357
|
-
// For Invitation
|
|
1358
|
-
return (sipSession.id || '').substring(0, SIP_ID_LENGTH);
|
|
1171
|
+
return (0, webrtc_1.hasAVideoTrack)(this.sipSessions[sessionId]);
|
|
1359
1172
|
}
|
|
1360
1173
|
waitForRegister() {
|
|
1361
1174
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1362
1175
|
return new Promise(resolve => this.on(REGISTERED, resolve));
|
|
1363
1176
|
});
|
|
1364
1177
|
}
|
|
1365
|
-
// eslint-disable-next-line no-unused-vars
|
|
1366
|
-
sessionWantsToDoVideo(session) {
|
|
1367
|
-
if (!session) {
|
|
1368
|
-
return false;
|
|
1369
|
-
}
|
|
1370
|
-
const { body, } = session.request || session;
|
|
1371
|
-
// Sometimes with InviteClientContext the body is in the body attribute ...
|
|
1372
|
-
const sdp = typeof body === 'object' && body ? body.body : body;
|
|
1373
|
-
return (0, sdp_1.hasAnActiveVideo)(sdp);
|
|
1374
|
-
}
|
|
1375
1178
|
hasHeartbeat() {
|
|
1376
1179
|
return this.heartbeat.hasHeartbeat;
|
|
1377
1180
|
}
|
|
@@ -1397,7 +1200,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1397
1200
|
}
|
|
1398
1201
|
onCallEnded(session) {
|
|
1399
1202
|
this._cleanupMedia(session);
|
|
1400
|
-
delete this.sipSessions[
|
|
1203
|
+
delete this.sipSessions[(0, sdp_1.getSipSessionId)(session)];
|
|
1401
1204
|
this._stopSendingStats(session);
|
|
1402
1205
|
this.stopNetworkMonitoring(session);
|
|
1403
1206
|
}
|
|
@@ -1410,31 +1213,16 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1410
1213
|
this.userAgent.attemptReconnection();
|
|
1411
1214
|
}
|
|
1412
1215
|
storeSipSession(session) {
|
|
1413
|
-
const id =
|
|
1216
|
+
const id = (0, sdp_1.getSipSessionId)(session);
|
|
1414
1217
|
logger.info('storing sip session', { id, clientId: this.clientId });
|
|
1415
1218
|
this.sipSessions[id] = session;
|
|
1416
1219
|
}
|
|
1417
1220
|
getSipSession(id) {
|
|
1418
|
-
return id in this.sipSessions ? this.sipSessions[id.substring(0, SIP_ID_LENGTH)] : null;
|
|
1221
|
+
return id in this.sipSessions ? this.sipSessions[id.substring(0, sdp_1.SIP_ID_LENGTH)] : null;
|
|
1419
1222
|
}
|
|
1420
1223
|
getSipSessionIds() {
|
|
1421
1224
|
return Object.keys(this.sipSessions);
|
|
1422
1225
|
}
|
|
1423
|
-
setLocalMediaStream(sipSessionId, newStream) {
|
|
1424
|
-
const sipSession = this.sipSessions[sipSessionId];
|
|
1425
|
-
if (!sipSession) {
|
|
1426
|
-
return;
|
|
1427
|
-
}
|
|
1428
|
-
logger.info('setting local media stream', {
|
|
1429
|
-
sipSessionId,
|
|
1430
|
-
tracks: newStream ? newStream.getTracks() : null,
|
|
1431
|
-
});
|
|
1432
|
-
if (sipSession.sessionDescriptionHandler) {
|
|
1433
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
1434
|
-
// @ts-ignore: protected
|
|
1435
|
-
sipSession.sessionDescriptionHandler._localMediaStream = newStream;
|
|
1436
|
-
}
|
|
1437
|
-
}
|
|
1438
1226
|
updateLocalStream(sipSessionId, newStream) {
|
|
1439
1227
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1440
1228
|
const sipSession = this.sipSessions[sipSessionId];
|
|
@@ -1448,74 +1236,13 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1448
1236
|
tracks: newStream.getTracks(),
|
|
1449
1237
|
});
|
|
1450
1238
|
if (oldStream) {
|
|
1451
|
-
|
|
1239
|
+
(0, webrtc_1.cleanupStream)(oldStream);
|
|
1452
1240
|
}
|
|
1453
|
-
|
|
1241
|
+
(0, webrtc_1.setLocalMediaStream)(sipSession, newStream);
|
|
1454
1242
|
// Update the local video element
|
|
1455
1243
|
yield this._setupMedias(sipSession, newStream);
|
|
1456
1244
|
});
|
|
1457
1245
|
}
|
|
1458
|
-
updateRemoteStream(sessionId, allTracks = true) {
|
|
1459
|
-
const remoteStream = this.getRemoteStream(sessionId);
|
|
1460
|
-
const pc = this.getPeerConnection(sessionId);
|
|
1461
|
-
logger.info('Updating remote stream', {
|
|
1462
|
-
sessionId,
|
|
1463
|
-
tracks: remoteStream ? remoteStream.getTracks() : null,
|
|
1464
|
-
receiverTracks: pc && pc.getReceivers ? pc.getReceivers().map((receiver) => receiver.track) : null,
|
|
1465
|
-
});
|
|
1466
|
-
if (!pc || !remoteStream) {
|
|
1467
|
-
return;
|
|
1468
|
-
}
|
|
1469
|
-
remoteStream.getTracks().forEach(track => {
|
|
1470
|
-
if (allTracks || track.kind === 'video') {
|
|
1471
|
-
remoteStream.removeTrack(track);
|
|
1472
|
-
}
|
|
1473
|
-
});
|
|
1474
|
-
if (pc.getReceivers) {
|
|
1475
|
-
pc.getReceivers().forEach((receiver) => {
|
|
1476
|
-
if (allTracks || receiver.track.kind === 'video') {
|
|
1477
|
-
remoteStream.addTrack(receiver.track);
|
|
1478
|
-
}
|
|
1479
|
-
});
|
|
1480
|
-
}
|
|
1481
|
-
}
|
|
1482
|
-
getMediaConfiguration(enableVideo, conference = false, constraints = null) {
|
|
1483
|
-
const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
|
|
1484
|
-
const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
|
|
1485
|
-
const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
|
|
1486
|
-
const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
|
|
1487
|
-
logger.info('Retrieving media a configuration', {
|
|
1488
|
-
enableVideo,
|
|
1489
|
-
screenSharing,
|
|
1490
|
-
isDesktop,
|
|
1491
|
-
withAudio,
|
|
1492
|
-
constraints,
|
|
1493
|
-
});
|
|
1494
|
-
return {
|
|
1495
|
-
constraints: {
|
|
1496
|
-
// Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
|
|
1497
|
-
audio: screenSharing ? !isDesktop : withAudio ? this._getAudioConstraints() : false,
|
|
1498
|
-
video: screenSharing ? isDesktop ? {
|
|
1499
|
-
mandatory: Object.assign({ chromeMediaSource: 'desktop' }, (mandatoryVideo || {})),
|
|
1500
|
-
} : {
|
|
1501
|
-
cursor: 'always',
|
|
1502
|
-
} : this._getVideoConstraints(enableVideo),
|
|
1503
|
-
screen: screenSharing,
|
|
1504
|
-
desktop: isDesktop,
|
|
1505
|
-
conference,
|
|
1506
|
-
},
|
|
1507
|
-
enableVideo,
|
|
1508
|
-
conference,
|
|
1509
|
-
offerOptions: {
|
|
1510
|
-
OfferToReceiveAudio: this._hasAudio(),
|
|
1511
|
-
OfferToReceiveVideo: enableVideo,
|
|
1512
|
-
mandatory: {
|
|
1513
|
-
OfferToReceiveAudio: this._hasAudio(),
|
|
1514
|
-
OfferToReceiveVideo: enableVideo,
|
|
1515
|
-
},
|
|
1516
|
-
},
|
|
1517
|
-
};
|
|
1518
|
-
}
|
|
1519
1246
|
isConference(sessionId) {
|
|
1520
1247
|
return sessionId in this.conferences;
|
|
1521
1248
|
}
|
|
@@ -1596,27 +1323,14 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1596
1323
|
}
|
|
1597
1324
|
});
|
|
1598
1325
|
}
|
|
1599
|
-
_isWeb() {
|
|
1600
|
-
return typeof window === 'object' && typeof document === 'object';
|
|
1601
|
-
}
|
|
1602
|
-
_isVideoTrack(track) {
|
|
1603
|
-
return track.kind === 'video' && track.readyState === 'live';
|
|
1604
|
-
}
|
|
1605
1326
|
_hasAudio() {
|
|
1606
1327
|
return this.hasAudio;
|
|
1607
1328
|
}
|
|
1608
1329
|
_getAudioConstraints() {
|
|
1609
|
-
|
|
1610
|
-
// @ts-ignore: media constraints
|
|
1611
|
-
return ((_b = (_a = this.audio) === null || _a === void 0 ? void 0 : _a.deviceId) === null || _b === void 0 ? void 0 : _b.exact) ? this.audio : true;
|
|
1330
|
+
return (0, webrtc_1.getAudioConstraints)(this.audio);
|
|
1612
1331
|
}
|
|
1613
1332
|
_getVideoConstraints(video = false) {
|
|
1614
|
-
|
|
1615
|
-
if (!video) {
|
|
1616
|
-
return false;
|
|
1617
|
-
}
|
|
1618
|
-
// @ts-ignore: media constraints
|
|
1619
|
-
return ((_b = (_a = this.video) === null || _a === void 0 ? void 0 : _a.deviceId) === null || _b === void 0 ? void 0 : _b.exact) ? this.video : true;
|
|
1333
|
+
return (0, webrtc_1.getVideoConstraints)(video && this.video);
|
|
1620
1334
|
}
|
|
1621
1335
|
_connectIfNeeded() {
|
|
1622
1336
|
logger.info('connect if needed, checking', { connected: this.isConnected(), clientId: this.clientId });
|
|
@@ -1661,80 +1375,16 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1661
1375
|
client.setRefreshToken(session.refreshToken);
|
|
1662
1376
|
return client.confd.getUserLineSipFromToken(session.uuid).then(sipLine => (Object.assign({ authorizationUser: sipLine.username, password: sipLine.secret, uri: `${sipLine.username}@${config.host}` }, config)));
|
|
1663
1377
|
}
|
|
1664
|
-
_createUaOptions(uaOptionsOverrides = {}) {
|
|
1665
|
-
let { host, } = this.config;
|
|
1666
|
-
let port = this.config.port || 443;
|
|
1667
|
-
if (this.config.websocketSip) {
|
|
1668
|
-
const webSocketSip = this.config.websocketSip.split(':');
|
|
1669
|
-
[host] = webSocketSip;
|
|
1670
|
-
port = Number(webSocketSip[1]);
|
|
1671
|
-
}
|
|
1672
|
-
const { userUuid } = this.config;
|
|
1673
|
-
const uaOptions = {
|
|
1674
|
-
noAnswerTimeout: NO_ANSWER_TIMEOUT,
|
|
1675
|
-
authorizationUsername: this.config.authorizationUser,
|
|
1676
|
-
authorizationPassword: this.config.password,
|
|
1677
|
-
displayName: this.config.displayName,
|
|
1678
|
-
hackIpInContact: true,
|
|
1679
|
-
contactParams: {
|
|
1680
|
-
transport: 'wss',
|
|
1681
|
-
},
|
|
1682
|
-
logBuiltinEnabled: this.config.log ? this.config.log.builtinEnabled : null,
|
|
1683
|
-
logLevel: this.config.log ? this.config.log.logLevel : null,
|
|
1684
|
-
logConnector: this.config.log ? this.config.log.connector : null,
|
|
1685
|
-
uri: this._makeURI(this.config.authorizationUser || ''),
|
|
1686
|
-
userAgentString: this.config.userAgentString || 'wazo-sdk',
|
|
1687
|
-
reconnectionAttempts: 10000,
|
|
1688
|
-
reconnectionDelay: 5,
|
|
1689
|
-
sessionDescriptionHandlerFactory: (session, options = {}) => {
|
|
1690
|
-
const uaLogger = session.userAgent.getLogger('sip.WazoSessionDescriptionHandler');
|
|
1691
|
-
const isWeb = this._isWeb();
|
|
1692
|
-
const iceGatheringTimeout = 'peerConnectionOptions' in options ? options.peerConnectionOptions.iceGatheringTimeout || DEFAULT_ICE_TIMEOUT : DEFAULT_ICE_TIMEOUT;
|
|
1693
|
-
const sdhOptions = Object.assign(Object.assign({}, options), { iceGatheringTimeout, peerConnectionConfiguration: Object.assign(Object.assign({}, (0, peer_connection_configuration_default_1.defaultPeerConnectionConfiguration)()), (options.peerConnectionConfiguration || {})) });
|
|
1694
|
-
return new WazoSessionDescriptionHandler_1.default(uaLogger, WazoSessionDescriptionHandler_1.wazoMediaStreamFactory, sdhOptions, isWeb, session);
|
|
1695
|
-
},
|
|
1696
|
-
transportOptions: {
|
|
1697
|
-
traceSip: (uaOptionsOverrides === null || uaOptionsOverrides === void 0 ? void 0 : uaOptionsOverrides.traceSip) || false,
|
|
1698
|
-
wsServers: `wss://${host}:${port}/api/asterisk/ws${userUuid ? `?userUuid=${userUuid}` : ''}`,
|
|
1699
|
-
},
|
|
1700
|
-
sessionDescriptionHandlerFactoryOptions: {
|
|
1701
|
-
modifiers: [exports.replaceLocalIpModifier],
|
|
1702
|
-
alwaysAcquireMediaFirst: this.isFirefox(),
|
|
1703
|
-
constraints: {
|
|
1704
|
-
audio: this._getAudioConstraints(),
|
|
1705
|
-
video: this._getVideoConstraints(),
|
|
1706
|
-
},
|
|
1707
|
-
peerConnectionOptions: {
|
|
1708
|
-
iceCheckingTimeout: this.config.iceCheckingTimeout || 1000,
|
|
1709
|
-
iceGatheringTimeout: this.config.iceCheckingTimeout || 1000,
|
|
1710
|
-
rtcConfiguration: Object.assign(Object.assign({ rtcpMuxPolicy: 'require', iceServers: WebRTCClient.getIceServers(this.config.host) }, this._getRtcOptions()), ((uaOptionsOverrides === null || uaOptionsOverrides === void 0 ? void 0 : uaOptionsOverrides.peerConnectionOptions) || {})),
|
|
1711
|
-
},
|
|
1712
|
-
// Configuration used in SDH to create the PeerConnection
|
|
1713
|
-
peerConnectionConfiguration: Object.assign({ rtcpMuxPolicy: 'require', iceServers: WebRTCClient.getIceServers(this.config.host) }, ((uaOptionsOverrides === null || uaOptionsOverrides === void 0 ? void 0 : uaOptionsOverrides.peerConnectionOptions) || {})),
|
|
1714
|
-
},
|
|
1715
|
-
};
|
|
1716
|
-
uaOptionsOverrides === null || uaOptionsOverrides === void 0 ? true : delete uaOptionsOverrides.traceSip;
|
|
1717
|
-
return Object.assign(Object.assign({}, uaOptions), uaOptionsOverrides);
|
|
1718
|
-
}
|
|
1719
|
-
// eslint-disable-next-line no-unused-vars
|
|
1720
|
-
_getRtcOptions() {
|
|
1721
|
-
return {
|
|
1722
|
-
mandatory: {
|
|
1723
|
-
OfferToReceiveAudio: this._hasAudio(),
|
|
1724
|
-
OfferToReceiveVideo: false,
|
|
1725
|
-
},
|
|
1726
|
-
};
|
|
1727
|
-
}
|
|
1728
1378
|
// Invitation and Inviter extends Session
|
|
1729
1379
|
_setupSession(session) {
|
|
1730
|
-
const sipSessionId =
|
|
1380
|
+
const sipSessionId = (0, sdp_1.getSipSessionId)(session);
|
|
1731
1381
|
// When receiving an Invitation, the delegate is not defined.
|
|
1732
1382
|
if (!session.delegate) {
|
|
1733
1383
|
session.delegate = {};
|
|
1734
1384
|
}
|
|
1735
1385
|
session.delegate.onSessionDescriptionHandler = (sdh) => {
|
|
1736
1386
|
sdh.on('error', (e) => {
|
|
1737
|
-
this.eventEmitter.emit(ON_ERROR, e);
|
|
1387
|
+
this.eventEmitter.emit(ON_ERROR, e, session);
|
|
1738
1388
|
});
|
|
1739
1389
|
sdh.peerConnectionDelegate = {
|
|
1740
1390
|
onicecandidateerror: (error) => {
|
|
@@ -1783,7 +1433,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1783
1433
|
// @ts-ignore: private
|
|
1784
1434
|
session.outgoingInviteRequest.message.body.body = request.body;
|
|
1785
1435
|
}
|
|
1786
|
-
|
|
1436
|
+
(0, webrtc_1.updateRemoteStream)(this.sipSessions[sipSessionId], false);
|
|
1787
1437
|
yield this._setupMedias(session);
|
|
1788
1438
|
return this.eventEmitter.emit(ON_REINVITE, session, request, updatedCalleeName, updatedNumber, hadRemoteVideo);
|
|
1789
1439
|
});
|
|
@@ -1791,8 +1441,8 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1791
1441
|
_onProgress(session_1) {
|
|
1792
1442
|
return __awaiter(this, arguments, void 0, function* (session, early = false) {
|
|
1793
1443
|
yield this._setupMedias(session);
|
|
1794
|
-
const sessionId =
|
|
1795
|
-
|
|
1444
|
+
const sessionId = (0, sdp_1.getSipSessionId)(session).substr(0, 20);
|
|
1445
|
+
(0, webrtc_1.updateRemoteStream)(session);
|
|
1796
1446
|
logger.info('progress received', {
|
|
1797
1447
|
sessionId,
|
|
1798
1448
|
early,
|
|
@@ -1802,7 +1452,6 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1802
1452
|
}
|
|
1803
1453
|
_onAccepted(session_1, sessionDialog_1) {
|
|
1804
1454
|
return __awaiter(this, arguments, void 0, function* (session, sessionDialog, withEvent = true, initAllTracks = true) {
|
|
1805
|
-
var _a;
|
|
1806
1455
|
logger.info('on call accepted', {
|
|
1807
1456
|
id: session.id,
|
|
1808
1457
|
clientId: this.clientId,
|
|
@@ -1810,21 +1459,14 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1810
1459
|
});
|
|
1811
1460
|
this.storeSipSession(session);
|
|
1812
1461
|
yield this._setupMedias(session);
|
|
1813
|
-
|
|
1814
|
-
const pc = (
|
|
1462
|
+
(0, webrtc_1.updateRemoteStream)(session, initAllTracks);
|
|
1463
|
+
const pc = (0, webrtc_1.getPeerConnection)(session);
|
|
1815
1464
|
const onTrack = (event) => {
|
|
1816
|
-
const
|
|
1817
|
-
const { kind, label, readyState, id, muted
|
|
1818
|
-
logger.info('on track event', {
|
|
1819
|
-
isAudioOnly,
|
|
1820
|
-
kind,
|
|
1821
|
-
label,
|
|
1822
|
-
readyState,
|
|
1823
|
-
id,
|
|
1824
|
-
muted,
|
|
1825
|
-
});
|
|
1465
|
+
const audioOnly = (0, webrtc_1.isAudioOnly)(session);
|
|
1466
|
+
const { kind, label, readyState, id, muted } = event.track;
|
|
1467
|
+
logger.info('on track event', { audioOnly, kind, label, readyState, id, muted });
|
|
1826
1468
|
// Stop video track in audio only mode
|
|
1827
|
-
if (
|
|
1469
|
+
if (audioOnly && kind === 'video') {
|
|
1828
1470
|
event.track.stop();
|
|
1829
1471
|
}
|
|
1830
1472
|
this.eventEmitter.emit(ON_TRACK, session, event);
|
|
@@ -1850,17 +1492,14 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1850
1492
|
this._startSendingStats(session);
|
|
1851
1493
|
});
|
|
1852
1494
|
}
|
|
1853
|
-
_isAudioOnly(session) {
|
|
1854
|
-
return Boolean(session.sessionDescriptionHandlerModifiersReInvite.find(modifier => modifier === modifiers_1.stripVideo));
|
|
1855
|
-
}
|
|
1856
1495
|
_setupMedias(session_1) {
|
|
1857
1496
|
return __awaiter(this, arguments, void 0, function* (session, newStream = null) {
|
|
1858
|
-
if (!
|
|
1497
|
+
if (!(0, webrtc_1.isWeb)()) {
|
|
1859
1498
|
logger.info('Setup media on mobile, no need to setup html element, bailing');
|
|
1860
1499
|
return;
|
|
1861
1500
|
}
|
|
1862
1501
|
// Safari hack, because you cannot call .play() from a non user action
|
|
1863
|
-
const sessionId =
|
|
1502
|
+
const sessionId = (0, sdp_1.getSipSessionId)(session);
|
|
1864
1503
|
const isConference = this.isConference(sessionId);
|
|
1865
1504
|
if (sessionId in this.audioElements) {
|
|
1866
1505
|
logger.info('html element already exists for session', {
|
|
@@ -1868,7 +1507,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1868
1507
|
});
|
|
1869
1508
|
return;
|
|
1870
1509
|
}
|
|
1871
|
-
if (this._hasAudio() &&
|
|
1510
|
+
if (this._hasAudio() && (0, webrtc_1.isWeb)() && !(sessionId in this.audioElements)) {
|
|
1872
1511
|
yield this.createAudioElementFor(sessionId);
|
|
1873
1512
|
}
|
|
1874
1513
|
const audioElement = this.audioElements[sessionId];
|
|
@@ -1906,10 +1545,10 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1906
1545
|
});
|
|
1907
1546
|
}
|
|
1908
1547
|
_cleanupMedia(session) {
|
|
1909
|
-
const sessionId =
|
|
1548
|
+
const sessionId = (0, sdp_1.getSipSessionId)(session);
|
|
1910
1549
|
const localStream = this.getLocalStream(sessionId);
|
|
1911
1550
|
if (localStream) {
|
|
1912
|
-
|
|
1551
|
+
(0, webrtc_1.cleanupStream)(localStream);
|
|
1913
1552
|
}
|
|
1914
1553
|
const cleanLocalElement = (id) => {
|
|
1915
1554
|
const element = this.audioElements[id];
|
|
@@ -1923,80 +1562,15 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
1923
1562
|
element.srcObject = null;
|
|
1924
1563
|
delete this.audioElements[id];
|
|
1925
1564
|
};
|
|
1926
|
-
if (this._hasAudio() &&
|
|
1565
|
+
if (this._hasAudio() && (0, webrtc_1.isWeb)()) {
|
|
1927
1566
|
if (session) {
|
|
1928
|
-
cleanLocalElement(
|
|
1567
|
+
cleanLocalElement((0, sdp_1.getSipSessionId)(session));
|
|
1929
1568
|
}
|
|
1930
1569
|
else {
|
|
1931
1570
|
Object.keys(this.audioElements).forEach(id => cleanLocalElement(id));
|
|
1932
1571
|
}
|
|
1933
1572
|
}
|
|
1934
1573
|
}
|
|
1935
|
-
_cleanupStream(stream) {
|
|
1936
|
-
stream.getTracks().filter(track => track.enabled).forEach(track => track.stop());
|
|
1937
|
-
}
|
|
1938
|
-
_toggleAudio(session, muteAudio) {
|
|
1939
|
-
const sdh = session.sessionDescriptionHandler;
|
|
1940
|
-
const pc = ((sdh === null || sdh === void 0 ? void 0 : sdh.peerConnection) || null);
|
|
1941
|
-
if (!pc) {
|
|
1942
|
-
return;
|
|
1943
|
-
}
|
|
1944
|
-
if (pc.getSenders) {
|
|
1945
|
-
pc.getSenders().forEach((sender) => {
|
|
1946
|
-
if (sender && sender.track && sender.track.kind === 'audio') {
|
|
1947
|
-
// eslint-disable-next-line
|
|
1948
|
-
sender.track.enabled = !muteAudio;
|
|
1949
|
-
}
|
|
1950
|
-
});
|
|
1951
|
-
}
|
|
1952
|
-
else {
|
|
1953
|
-
pc.getLocalStreams().forEach((stream) => {
|
|
1954
|
-
stream.getAudioTracks().forEach(track => {
|
|
1955
|
-
// eslint-disable-next-line
|
|
1956
|
-
track.enabled = !muteAudio;
|
|
1957
|
-
});
|
|
1958
|
-
});
|
|
1959
|
-
}
|
|
1960
|
-
}
|
|
1961
|
-
_toggleVideo(session, muteCamera) {
|
|
1962
|
-
const sdh = session.sessionDescriptionHandler;
|
|
1963
|
-
const pc = sdh === null || sdh === void 0 ? void 0 : sdh.peerConnection;
|
|
1964
|
-
if (pc === null || pc === void 0 ? void 0 : pc.getSenders) {
|
|
1965
|
-
pc.getSenders().forEach((sender) => {
|
|
1966
|
-
if (sender && sender.track && sender.track.kind === 'video') {
|
|
1967
|
-
// eslint-disable-next-line
|
|
1968
|
-
sender.track.enabled = !muteCamera;
|
|
1969
|
-
}
|
|
1970
|
-
});
|
|
1971
|
-
}
|
|
1972
|
-
else {
|
|
1973
|
-
pc.getLocalStreams().forEach((stream) => {
|
|
1974
|
-
stream.getVideoTracks().forEach(track => {
|
|
1975
|
-
// eslint-disable-next-line
|
|
1976
|
-
track.enabled = !muteCamera;
|
|
1977
|
-
});
|
|
1978
|
-
});
|
|
1979
|
-
}
|
|
1980
|
-
}
|
|
1981
|
-
/**
|
|
1982
|
-
* @param pc RTCPeerConnection
|
|
1983
|
-
*/
|
|
1984
|
-
_getRemoteStream(pc) {
|
|
1985
|
-
let remoteStream = null;
|
|
1986
|
-
if (pc && pc.getReceivers) {
|
|
1987
|
-
remoteStream = typeof global !== 'undefined' && global.window && global.window.MediaStream ? new global.window.MediaStream() : new window.MediaStream();
|
|
1988
|
-
pc.getReceivers().forEach((receiver) => {
|
|
1989
|
-
const { track, } = receiver;
|
|
1990
|
-
if (track && remoteStream) {
|
|
1991
|
-
remoteStream.addTrack(track);
|
|
1992
|
-
}
|
|
1993
|
-
});
|
|
1994
|
-
}
|
|
1995
|
-
else if (pc) {
|
|
1996
|
-
[remoteStream] = pc.getRemoteStreams();
|
|
1997
|
-
}
|
|
1998
|
-
return remoteStream;
|
|
1999
|
-
}
|
|
2000
1574
|
_cleanupRegister() {
|
|
2001
1575
|
if (this.registerer) {
|
|
2002
1576
|
// @ts-ignore: removeAllListeners does not exist
|
|
@@ -2010,7 +1584,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
2010
1584
|
if (!pc) {
|
|
2011
1585
|
return;
|
|
2012
1586
|
}
|
|
2013
|
-
const sessionId =
|
|
1587
|
+
const sessionId = (0, sdp_1.getSipSessionId)(session);
|
|
2014
1588
|
(0, getstats_1.default)(pc, (result) => {
|
|
2015
1589
|
const { results, internal, nomore } = result, stats = __rest(result, ["results", "internal", "nomore"]);
|
|
2016
1590
|
this.statsIntervals[sessionId] = nomore;
|
|
@@ -2018,7 +1592,7 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
2018
1592
|
}, SEND_STATS_DELAY);
|
|
2019
1593
|
}
|
|
2020
1594
|
_stopSendingStats(session) {
|
|
2021
|
-
const sessionId =
|
|
1595
|
+
const sessionId = (0, sdp_1.getSipSessionId)(session);
|
|
2022
1596
|
logger.trace('Check for stopping stats', {
|
|
2023
1597
|
sessionId,
|
|
2024
1598
|
ids: Object.keys(this.statsIntervals),
|
|
@@ -2031,9 +1605,6 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
2031
1605
|
delete this.statsIntervals[sessionId];
|
|
2032
1606
|
}
|
|
2033
1607
|
}
|
|
2034
|
-
_makeURI(target) {
|
|
2035
|
-
return user_agent_1.UserAgent.makeURI(`sip:${target}@${this.config.host}`);
|
|
2036
|
-
}
|
|
2037
1608
|
_disconnectTransport() {
|
|
2038
1609
|
return __awaiter(this, arguments, void 0, function* (force = false) {
|
|
2039
1610
|
var _a;
|
|
@@ -2059,96 +1630,13 @@ class WebRTCClient extends Emitter_1.default {
|
|
|
2059
1630
|
}
|
|
2060
1631
|
_fetchNetworkStats(sessionId) {
|
|
2061
1632
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2062
|
-
const session = this.
|
|
2063
|
-
|
|
2064
|
-
if (!stats || !(sessionId in this.sessionNetworkStats)) {
|
|
1633
|
+
const session = this.sipSessions[sessionId];
|
|
1634
|
+
if (!(sessionId in this.sessionNetworkStats)) {
|
|
2065
1635
|
return Promise.resolve(null);
|
|
2066
1636
|
}
|
|
2067
|
-
const networkStats = {
|
|
2068
|
-
audioBytesSent: 0,
|
|
2069
|
-
videoBytesSent: 0,
|
|
2070
|
-
videoBytesReceived: 0,
|
|
2071
|
-
audioBytesReceived: 0,
|
|
2072
|
-
};
|
|
2073
1637
|
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
2074
1638
|
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
2075
|
-
const
|
|
2076
|
-
const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
|
|
2077
|
-
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
2078
|
-
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
2079
|
-
const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
|
|
2080
|
-
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
2081
|
-
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
2082
|
-
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
2083
|
-
let audioBytesSent = 0; // content + header
|
|
2084
|
-
let audioBytesReceived = 0; // content + header
|
|
2085
|
-
let audioContentSent = 0; // useful to detect blank call
|
|
2086
|
-
let audioContentReceived = 0;
|
|
2087
|
-
let videoBytesSent = 0;
|
|
2088
|
-
let videoBytesReceived = 0;
|
|
2089
|
-
let transportSent = 0;
|
|
2090
|
-
let transportReceived = 0;
|
|
2091
|
-
let packetsLost = 0;
|
|
2092
|
-
stats.forEach(report => {
|
|
2093
|
-
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
2094
|
-
audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
2095
|
-
audioContentSent += Number(report.bytesSent);
|
|
2096
|
-
}
|
|
2097
|
-
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
2098
|
-
audioBytesSent += Number(report.bytesSent);
|
|
2099
|
-
}
|
|
2100
|
-
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
2101
|
-
videoBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
2102
|
-
}
|
|
2103
|
-
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
2104
|
-
packetsLost += Number(report.packetsLost);
|
|
2105
|
-
networkStats.packetsReceived = Number(report.packetsReceived);
|
|
2106
|
-
audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
2107
|
-
audioContentReceived += Number(report.bytesReceived);
|
|
2108
|
-
}
|
|
2109
|
-
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
2110
|
-
videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
2111
|
-
}
|
|
2112
|
-
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
2113
|
-
if ('framesPerSecond' in report) {
|
|
2114
|
-
networkStats.framesPerSecond = Number(report.framesPerSecond);
|
|
2115
|
-
}
|
|
2116
|
-
if ('framerateMean' in report) {
|
|
2117
|
-
// framerateMean is only available in FF
|
|
2118
|
-
networkStats.framesPerSecond = Math.round(report.framerateMean);
|
|
2119
|
-
}
|
|
2120
|
-
}
|
|
2121
|
-
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
2122
|
-
packetsLost += Number(report.packetsLost);
|
|
2123
|
-
networkStats.roundTripTime = Number(report.roundTripTime);
|
|
2124
|
-
networkStats.jitter = Number(report.jitter);
|
|
2125
|
-
}
|
|
2126
|
-
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
2127
|
-
packetsLost += Number(report.packetsLost);
|
|
2128
|
-
}
|
|
2129
|
-
if (report.type === 'transport') {
|
|
2130
|
-
transportSent += Number(report.bytesSent);
|
|
2131
|
-
transportReceived += Number(report.bytesReceived);
|
|
2132
|
-
}
|
|
2133
|
-
});
|
|
2134
|
-
networkStats.packetsLost = packetsLost;
|
|
2135
|
-
networkStats.totalAudioBytesSent = audioBytesSent;
|
|
2136
|
-
networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
|
|
2137
|
-
networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
|
|
2138
|
-
networkStats.audioBytesReceived = audioBytesReceived;
|
|
2139
|
-
networkStats.totalAudioContentSent = audioContentSent;
|
|
2140
|
-
networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
|
|
2141
|
-
networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
|
|
2142
|
-
networkStats.audioContentReceived = audioContentReceived;
|
|
2143
|
-
networkStats.totalVideoBytesSent = videoBytesSent;
|
|
2144
|
-
networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
|
|
2145
|
-
networkStats.totalVideoBytesReceived = videoBytesReceived;
|
|
2146
|
-
networkStats.videoBytesReceived = videoBytesReceived - lastVideoReceived;
|
|
2147
|
-
networkStats.totalTransportSent = transportSent - lastTransportSent;
|
|
2148
|
-
networkStats.transportSent = transportSent;
|
|
2149
|
-
networkStats.totalTransportReceived = transportReceived;
|
|
2150
|
-
networkStats.transportReceived = transportReceived - lastTransportReceived;
|
|
2151
|
-
networkStats.bandwidth = networkStats.audioBytesSent + networkStats.audioBytesReceived + networkStats.videoBytesSent + networkStats.videoBytesReceived + networkStats.transportReceived + networkStats.transportSent;
|
|
1639
|
+
const networkStats = yield (0, webrtc_1.fetchNetworkStats)(session, lastNetworkStats);
|
|
2152
1640
|
if (this.sessionNetworkStats[sessionId]) {
|
|
2153
1641
|
this.eventEmitter.emit(ON_NETWORK_STATS, session, networkStats, this.sessionNetworkStats[sessionId]);
|
|
2154
1642
|
if (sessionId in this.sessionNetworkStats) {
|