UNPKG

infobip-rtc

Version:

Infobip RTC JavaScript SDK - Infobip WebRTC API Implementation

200 lines 7.65 kB
import jwtDecode from 'jwt-decode'; import Properties from "./Properties"; import Status from "./Status"; import { version } from "../Version"; import Retry from '../util/Retry'; import Browser from '../util/Browser'; export class InfobipGatewayImpl { constructor(eventEmitter, logger, token) { this.eventEmitter = eventEmitter; this.logger = logger; this.token = token; this.status = Status.OFFLINE; this.host = this.generatePortunusHost(jwtDecode(token)); this.deviceInfo = this.encodeDeviceInfo(); this.initRetry(); } connect(isReconnect = false) { this.ws = new WebSocket(this.generatePortunusUrl(), [this.token, this.deviceInfo]); this.status = isReconnect ? Status.RECONNECTING : Status.CONNECTING; this.ws.onopen = this.onOpen.bind(this); this.ws.onclose = this.onClose.bind(this); this.ws.onmessage = this.onMessage.bind(this); this.ws.onerror = this.onError.bind(this); } disconnect() { if ([Status.RECONNECTING, Status.CONNECTING, Status.CONNECTED].indexOf(this.status) >= 0) { this.ws.close(4000, "USER_DISCONNECT"); } if (this.retry.cancel()) { this.eventEmitter.emit('disconnected', ({ code: 4000, reason: 'USER_DISCONNECT' })); } this.status = Status.OFFLINE; } ; send(data) { var _a; if (this.status !== Status.CONNECTED) { (_a = this.logger) === null || _a === void 0 ? void 0 : _a.error(`Socket to Infobip WebRTC Gateway not opened, could not send ${JSON.stringify(data)}!`); return; } this.logSendingMessage(data); let message = JSON.stringify(data); this.ws.send(message); } setLogger(logger) { this.logger = logger; } encodeDeviceInfo() { let generatedDeviceInfo = JSON.stringify(this.generateDeviceInfo()); return this.base64EncodeUrl(window.btoa(generatedDeviceInfo)); } generatePortunusHost(token) { let location = token.location; if (!location) { return "portunus.infobip.com"; } if (location === "io") { return "portunus.ioinfobip.com"; } if (["iop1", "iop2"].includes(location)) { return `portunus-${location}.ioinfobip.com`; } return "portunus-" + location + ".infobip.com"; } generatePortunusUrl() { let url = `wss://${this.host}`; if (this.portunusInstanceHash) { url += `?instance=${this.portunusInstanceHash}`; } return url; } logSendingMessage(message) { var _a; if (message.action !== 'heartbeat' && message.action !== 'heartbeat_resp') { (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug(`Sending ${JSON.stringify(message)} to Infobip WebRTC Gateway...`); } } onOpen() { var _a; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info('Socket to Infobip WebRTC Gateway opened.'); this.eventEmitter.once("registered", event => { this.portunusInstanceHash = event.instanceHash; }); let reconnected = this.status === Status.RECONNECTING; if (reconnected) { this.eventEmitter.once("registered", args => { this.eventEmitter.emit('reconnected'); }); } this.status = Status.CONNECTED; this.scheduleHeartbeat(); this.initRetry(); } onMessage(message) { let data = JSON.parse(message.data); this.logReceivedMessage(data); if (data.event === 'heartbeat_resp') { this.cancelHeartbeatCheck(); return; } if (data.event === 'heartbeat') { this.sendHeartbeatResponse(); return; } if (data.event === 'registration_failed') { this.disconnect(); } this.eventEmitter.emit(data.event, data); } sendHeartbeatResponse() { this.send({ action: 'heartbeat_resp' }); } logReceivedMessage(message) { var _a; if (message.event !== 'heartbeat_resp' && message.event !== 'heartbeat') { (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug(`Received message from Infobip Gateway: ${JSON.stringify(message)}.`); } } onClose(event) { var _a; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info(`Socket closed, code ${event.code}, reason: ${event.reason}.`); if (event.code === 1013) { this.portunusInstanceHash = null; } const prevStatus = this.status; this.status = Status.OFFLINE; this.cleanup(); if (prevStatus !== Status.OFFLINE && event.code < 4000) { this.retry.retry(); if (prevStatus === Status.CONNECTED) { this.eventEmitter.emit('reconnecting'); } } else { this.eventEmitter.emit('disconnected', event); } } cleanup() { clearInterval(this.heartbeat); this.cancelHeartbeatCheck(); this.ws.onopen = null; this.ws.onclose = null; this.ws.onmessage = null; this.ws.onerror = null; delete this.ws; } onError(event) { var _a; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.error(`Socket error: ${JSON.stringify(event)}.`); } scheduleHeartbeat() { this.heartbeat = setInterval(() => { if (this.ws.readyState === WebSocket.OPEN) { this.send({ 'action': 'heartbeat' }); this.scheduleHeartbeatCheck(); } }, Properties.HEARTBEAT_PERIOD); } scheduleHeartbeatCheck() { var _a; if (this.heartbeatCheck) { (_a = this.logger) === null || _a === void 0 ? void 0 : _a.warn("Did not receive previous heartbeat response, skipping new heartbeat check."); return; } this.heartbeatCheck = setTimeout(() => { var _a; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info(`No heartbeat response in ${Properties.HEARTBEAT_TIMEOUT} milliseconds. Closing socket...`); this.onClose({ code: 3000, reason: 'Heartbeat timeout.' }); }, Properties.HEARTBEAT_TIMEOUT); } initRetry() { var _a; (_a = this.retry) === null || _a === void 0 ? void 0 : _a.cancel(); this.retry = new Retry(iteration => { var _a; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info(`Reconnect attempt ${iteration}...`); this.connect(true); }, Retry.exponentialDelay(Properties.RECONNECT_INITIAL_DELAY), Properties.RECONNECT_MAX_DELAY, Properties.RECONNECT_MAX) .catch(reason => { var _a; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info(`Reconnecting failed, reason: ${reason}`); this.eventEmitter.emit('disconnected', { reason: 'Connection error.' }); }); } generateDeviceInfo() { let browser = new Browser(); return { sdk: { type: 'js', version: version }, device: { browser: browser.getBrowser(), os: browser.getOS() } }; } base64EncodeUrl(value) { return value.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); } cancelHeartbeatCheck() { clearTimeout(this.heartbeatCheck); this.heartbeatCheck = undefined; } } //# sourceMappingURL=InfobipGateway.js.map