@telegenta/webclient 3.0.1 → 3.1.1
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/demos/calldata_available.html +1 -1
- package/demos/event_client.html +1 -1
- package/dist/telegenta.js +87 -5
- package/dist/telegenta.min.js +1 -1
- package/docs/EventServiceNotConnected.html +1 -1
- package/docs/NoActiveSession.html +1 -1
- package/docs/NotAllowed.html +1 -1
- package/docs/Phone.html +1 -1
- package/docs/Session.html +4 -1
- package/docs/UnableToConnect.html +1 -1
- package/docs/data/search.json +1 -1
- package/docs/event-client.js.html +1 -1
- package/docs/exceptions.js.html +3 -2
- package/docs/global.html +3 -3
- package/docs/phone-client.js.html +45 -1
- package/package.json +2 -2
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
eventClient = new Telegenta.EventClient(logger);
|
|
46
46
|
|
|
47
47
|
// Connect to event server
|
|
48
|
-
eventClient.connect('wss://
|
|
48
|
+
eventClient.connect('wss://esvc.telegenta.com/').then(function () {
|
|
49
49
|
console.info(`Connected to server`);
|
|
50
50
|
}, function (reason) {
|
|
51
51
|
console.error(`Unable to connect to event service: ${reason}`);
|
package/demos/event_client.html
CHANGED
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
let eventClient;
|
|
54
54
|
let subscriptionId = null;
|
|
55
55
|
const API_URL = 'https://api.telegenta.com/api';
|
|
56
|
-
const EVENT_CLIENT_URL = 'wss://
|
|
56
|
+
const EVENT_CLIENT_URL = 'wss://esvc.telegenta.com/';
|
|
57
57
|
|
|
58
58
|
// Start when DOM is ready
|
|
59
59
|
window.onload = function () {
|
package/dist/telegenta.js
CHANGED
|
@@ -168,10 +168,11 @@ class InvalidParameter extends Error {
|
|
|
168
168
|
|
|
169
169
|
/**
|
|
170
170
|
* Exception raised if trying to perform actions that require active session
|
|
171
|
+
* @property message - Error message
|
|
171
172
|
*/
|
|
172
173
|
class NoActiveSession extends Error {
|
|
173
|
-
constructor() {
|
|
174
|
-
super();
|
|
174
|
+
constructor(message) {
|
|
175
|
+
super(message);
|
|
175
176
|
this.name = 'NoActiveSession';
|
|
176
177
|
}
|
|
177
178
|
}
|
|
@@ -291,6 +292,43 @@ function browserIsEdge() {
|
|
|
291
292
|
return (navigator.userAgent.indexOf("Edge") !== -1)
|
|
292
293
|
}
|
|
293
294
|
|
|
295
|
+
// SIP header names are RFC 3261 tokens
|
|
296
|
+
const HEADER_NAME_RE = /^[A-Za-z0-9\-.!%*_+`'~]+$/;
|
|
297
|
+
|
|
298
|
+
const HTML_ENTITIES = {
|
|
299
|
+
'&': '&',
|
|
300
|
+
'<': '<',
|
|
301
|
+
'>': '>',
|
|
302
|
+
'"': '"',
|
|
303
|
+
"'": ''',
|
|
304
|
+
'\r': ' ',
|
|
305
|
+
'\n': ' ',
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
// Build custom SIP header lines from a { name: value } map.
|
|
309
|
+
// Names must be tokens - a bad one is always a programming error, so it throws.
|
|
310
|
+
// Values are HTML encoded rather than rejected: that strips the CR/LF which
|
|
311
|
+
// would otherwise let a value inject further headers, while still letting
|
|
312
|
+
// punctuation through.
|
|
313
|
+
function buildCustomHeaders(setHeader) {
|
|
314
|
+
if (!setHeader) {
|
|
315
|
+
return [];
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (typeof setHeader !== 'object' || Array.isArray(setHeader)) {
|
|
319
|
+
throw new TypeError(`Invalid setHeader argument: expected an object, got ${typeof setHeader}`);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return Object.entries(setHeader).map(([name, value]) => {
|
|
323
|
+
if (!HEADER_NAME_RE.test(name)) {
|
|
324
|
+
throw new TypeError(`Invalid SIP header name: "${name}"`);
|
|
325
|
+
}
|
|
326
|
+
// Single pass, so an encoded '&' is not encoded again.
|
|
327
|
+
const encoded = String(value).replace(/[&<>"'\r\n]/g, (c) => HTML_ENTITIES[c]);
|
|
328
|
+
return `${name}: ${encoded}`;
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
294
332
|
// Request timeout after 10 sec
|
|
295
333
|
const REQUEST_TIMEOUT = 10000;
|
|
296
334
|
|
|
@@ -522,7 +560,7 @@ class Requestor extends EventEmitter {
|
|
|
522
560
|
// Keep alive in seconds
|
|
523
561
|
const PING_INTERVAL = 50;
|
|
524
562
|
|
|
525
|
-
const ES_DEFAULT_SERVER_URL = 'wss://
|
|
563
|
+
const ES_DEFAULT_SERVER_URL = 'wss://esvc.telegenta.com/';
|
|
526
564
|
|
|
527
565
|
// Starting retry interval
|
|
528
566
|
const RETRY_INTERVAL_START = 1 + Math.random();
|
|
@@ -1504,7 +1542,7 @@ function camelcaseKeys(input, options) {
|
|
|
1504
1542
|
|
|
1505
1543
|
const options = {
|
|
1506
1544
|
wssServer: 'wss://api.telegenta.com/sip/',
|
|
1507
|
-
eventServer: 'wss://
|
|
1545
|
+
eventServer: 'wss://esvc.telegenta.com/',
|
|
1508
1546
|
provisionToken: null,
|
|
1509
1547
|
authorizationUsername: null,
|
|
1510
1548
|
password: null,
|
|
@@ -1913,9 +1951,11 @@ class Phone extends EventEmitter {
|
|
|
1913
1951
|
* @param {number} [params.answerCallTimeout=0] Hangup call with NO ANSWER if call is not picked up before specified interval (seconds). If 0, timeout is disabled.
|
|
1914
1952
|
* @param {number} [params.maximumCallCost] Maximum call cost (in customer currency) allowed for call. The call will automatically be stopped when the specified cost has been reached. Setting this to 0 disables checking for maximum cost.
|
|
1915
1953
|
* @param {string} [params.metaInfo] Add meta info to call, which will be available in server events and inside call complete webhook (max 256 chars)
|
|
1954
|
+
* @param {object} [params.setHeader] Custom SIP headers to add to the INVITE, as {name: value}.
|
|
1916
1955
|
* @return {Session} object for call
|
|
1917
1956
|
* @throws NotReady - If phone is not ready to call
|
|
1918
1957
|
* @throws NotAllowed - If there are calls currently connecting
|
|
1958
|
+
* @throws InvalidParameter - If setHeader contains an invalid header name or container
|
|
1919
1959
|
*
|
|
1920
1960
|
*/
|
|
1921
1961
|
call(number, params = {}) {
|
|
@@ -1940,6 +1980,7 @@ class Phone extends EventEmitter {
|
|
|
1940
1980
|
explicitCallerId: null,
|
|
1941
1981
|
explicitShortCallerId: null,
|
|
1942
1982
|
metaInfo: null,
|
|
1983
|
+
setHeader: null,
|
|
1943
1984
|
_isListenCall: false,
|
|
1944
1985
|
},
|
|
1945
1986
|
params,
|
|
@@ -2495,6 +2536,23 @@ class Session extends EventEmitter {
|
|
|
2495
2536
|
}
|
|
2496
2537
|
}
|
|
2497
2538
|
|
|
2539
|
+
// Custom headers last, so they cannot displace the built-in ones.
|
|
2540
|
+
// Must be before _UA.call() below: jssip clones extraHeaders synchronously
|
|
2541
|
+
// inside connect(), so anything pushed after that call never reaches the INVITE.
|
|
2542
|
+
let customHeaders;
|
|
2543
|
+
try {
|
|
2544
|
+
customHeaders = buildCustomHeaders(callParams.setHeader);
|
|
2545
|
+
} catch (error) {
|
|
2546
|
+
if (error instanceof TypeError) {
|
|
2547
|
+
throw new InvalidParameter(error.message);
|
|
2548
|
+
}
|
|
2549
|
+
throw error;
|
|
2550
|
+
}
|
|
2551
|
+
for (const header of customHeaders) {
|
|
2552
|
+
this.log.debug('Adding custom header: ' + header);
|
|
2553
|
+
options.extraHeaders.push(header);
|
|
2554
|
+
}
|
|
2555
|
+
|
|
2498
2556
|
// Prepare invite uri
|
|
2499
2557
|
const uri = 'sip:' + number + '@telegenta.com';
|
|
2500
2558
|
|
|
@@ -2867,6 +2925,30 @@ class Session extends EventEmitter {
|
|
|
2867
2925
|
}
|
|
2868
2926
|
}
|
|
2869
2927
|
|
|
2928
|
+
/**
|
|
2929
|
+
* Raw WebRTC statistics for this session's peer connection.
|
|
2930
|
+
*
|
|
2931
|
+
* Returns the browser's own `RTCStatsReport` untouched, so callers can read
|
|
2932
|
+
* any statistic the browser exposes - RTP packet and byte counters, the
|
|
2933
|
+
* DTLS/ICE transport state, codec and candidate-pair details.
|
|
2934
|
+
*
|
|
2935
|
+
* @returns {Promise<RTCStatsReport>} The peer connection's statistics
|
|
2936
|
+
* @throws NoActiveSession - If the session has no established peer connection
|
|
2937
|
+
* (thrown synchronously, before the promise is created)
|
|
2938
|
+
*
|
|
2939
|
+
* @example
|
|
2940
|
+
* const report = await session.getRTCStats();
|
|
2941
|
+
* for (const stat of report.values()) {
|
|
2942
|
+
* if (stat.type === 'inbound-rtp') console.log(stat.packetsReceived);
|
|
2943
|
+
* }
|
|
2944
|
+
*/
|
|
2945
|
+
getRTCStats() {
|
|
2946
|
+
if (!this._webRTCSession || !this._webRTCSession.connection) {
|
|
2947
|
+
throw new NoActiveSession('no peer connection for this session');
|
|
2948
|
+
}
|
|
2949
|
+
return this._webRTCSession.connection.getStats();
|
|
2950
|
+
}
|
|
2951
|
+
|
|
2870
2952
|
// RECORDING
|
|
2871
2953
|
/**
|
|
2872
2954
|
* Start recording
|
|
@@ -3660,4 +3742,4 @@ class Session extends EventEmitter {
|
|
|
3660
3742
|
}
|
|
3661
3743
|
}
|
|
3662
3744
|
|
|
3663
|
-
export { EventClient, EventServiceNotConnected, InvalidMediaDevice, InvalidOptions, InvalidParameter, LOGLVL$1 as LOGLVL, LogHandler, MediaNotPrepared, NoActiveSession, NotAllowed, NotReady, Phone, Request, Requestor, Session, UnableToConnect, browserIsChrome, browserIsEdge, browserIsFirefox, browserIsOpera, browserIsSafari, compareObjects, createDurationString, createUUID };
|
|
3745
|
+
export { EventClient, EventServiceNotConnected, InvalidMediaDevice, InvalidOptions, InvalidParameter, LOGLVL$1 as LOGLVL, LogHandler, MediaNotPrepared, NoActiveSession, NotAllowed, NotReady, Phone, Request, Requestor, Session, UnableToConnect, browserIsChrome, browserIsEdge, browserIsFirefox, browserIsOpera, browserIsSafari, buildCustomHeaders, compareObjects, createDurationString, createUUID };
|