UNPKG

camstreamerlib

Version:

Helper library for CamStreamer ACAP applications.

153 lines (152 loc) 6.6 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WsClient = void 0; const EventEmitter = require("events"); const WebSocket = require("ws"); const Digest_1 = require("./Digest"); class WsClient extends EventEmitter { constructor(options) { var _a, _b, _c, _d, _e, _f, _g, _h; super(); this.isAlive = true; this.isClosed = false; const tls = (_a = options === null || options === void 0 ? void 0 : options.tls) !== null && _a !== void 0 ? _a : false; const tlsInsecure = (_b = options === null || options === void 0 ? void 0 : options.tlsInsecure) !== null && _b !== void 0 ? _b : false; const ip = (_c = options === null || options === void 0 ? void 0 : options.ip) !== null && _c !== void 0 ? _c : '127.0.0.1'; const port = (_d = options === null || options === void 0 ? void 0 : options.port) !== null && _d !== void 0 ? _d : (tls ? 443 : 80); this.user = (_e = options === null || options === void 0 ? void 0 : options.user) !== null && _e !== void 0 ? _e : ''; this.pass = (_f = options === null || options === void 0 ? void 0 : options.pass) !== null && _f !== void 0 ? _f : ''; const protocol = tls ? 'wss' : 'ws'; this.address = `${protocol}://${ip}:${port}${options.address}`; this.digestAddress = options.address; this.pingInterval = (_g = options.pingInterval) !== null && _g !== void 0 ? _g : 30000; this.protocol = options.protocol; this.wsOptions = { auth: `${this.user}:${this.pass}`, rejectUnauthorized: !tlsInsecure, headers: (_h = options.headers) !== null && _h !== void 0 ? _h : {}, }; } open(wwwAuthenticateHeader) { try { if (this.ws !== undefined) { return; } this.isClosed = false; if (this.protocol === undefined) { this.ws = new WebSocket(this.address, this.wsOptions); } else { this.ws = new WebSocket(this.address, this.protocol, this.wsOptions); } this.ws.binaryType = 'arraybuffer'; this.isAlive = true; this.pingTimer = setInterval(() => __awaiter(this, void 0, void 0, function* () { var _a; if ((this.ws && this.ws.readyState !== WebSocket.OPEN) || this.isAlive === false) { this.emit('error', new Error('Connection timeout')); yield this.closeWsConnection(); } else { this.isAlive = false; (_a = this.ws) === null || _a === void 0 ? void 0 : _a.ping(); } }), this.pingInterval); this.ws.on('pong', () => { this.isAlive = true; }); if (wwwAuthenticateHeader !== undefined) { this.wsOptions.headers['Authorization'] = new Digest_1.Digest().getAuthHeader(this.user, this.pass, 'GET', this.digestAddress, wwwAuthenticateHeader); } this.ws.on('unexpected-response', (req, res) => __awaiter(this, void 0, void 0, function* () { var _b; if (res.statusCode === 401 && res.headers['www-authenticate'] !== undefined) { if (this.pingTimer) { clearInterval(this.pingTimer); } (_b = this.ws) === null || _b === void 0 ? void 0 : _b.removeAllListeners(); this.ws = undefined; this.open(res.headers['www-authenticate']); } else { this.emit('error', new Error('Status code: ' + res.statusCode)); yield this.closeWsConnection(); } })); this.ws.on('open', () => this.emit('open')); this.ws.on('message', (data) => this.emit('message', data)); this.ws.on('error', (error) => { this.emit('error', error); this.closeWsConnection(); }); this.ws.on('close', () => this.closeWsConnection()); } catch (error) { this.emit('error', error instanceof Error ? error : new Error('Unknown error')); this.closeWsConnection(); } } send(data) { if (this.ws === undefined) { throw new Error("This websocket hasn't been opened yet."); } if (this.ws.readyState === this.ws.OPEN) { this.ws.send(data); } } close() { if (this.isClosed) { return; } this.isClosed = true; this.closeWsConnection(); } reconnect() { this.closeWsConnection(); } closeWsConnection() { if (this.ws === undefined) { return; } const wsCopy = this.ws; this.ws = undefined; try { if (this.pingTimer) { clearInterval(this.pingTimer); } wsCopy.removeAllListeners(); wsCopy.on('error', () => { }); if (wsCopy.readyState !== WebSocket.CLOSING && wsCopy.readyState !== WebSocket.CLOSED) { wsCopy.close(); } setTimeout(() => { if (wsCopy.readyState !== WebSocket.CLOSED) { wsCopy.terminate(); } }, 5000); this.emit('close'); } catch (err) { console.error(err); } finally { const shouldRestart = !this.isClosed; setTimeout(() => { wsCopy.removeAllListeners(); if (shouldRestart && !this.isClosed) { this.open(); } }, 10000); } } } exports.WsClient = WsClient;