UNPKG

hfs

Version:
95 lines (94 loc) 3.84 kB
"use strict"; // This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.disconnectionsLog = exports.Connection = void 0; exports.normalizeIp = normalizeIp; exports.newConnection = newConnection; exports.getConnections = getConnections; exports.socket2connection = socket2connection; exports.getConnection = getConnection; exports.updateConnectionForCtx = updateConnectionForCtx; exports.updateConnection = updateConnection; exports.disconnect = disconnect; const events_1 = __importDefault(require("./events")); const geo_1 = require("./geo"); const lodash_1 = __importDefault(require("lodash")); class Connection { // the sockets we collect are the plain ones, as soon as the tcp layer is connected constructor(socket) { this.socket = socket; this.started = new Date(); this.sent = 0; // socket-scoped, not request-scoped this.got = 0; all.push(this); socket.on('close', () => { all.splice(all.indexOf(this), 1); events_1.default.emit('connectionClosed', this); }); events_1.default.emit('connection', this); } get ip() { var _a, _b; return ((_a = this.ctx) === null || _a === void 0 ? void 0 : _a.ip) || ((_b = this._cachedIp) !== null && _b !== void 0 ? _b : (this._cachedIp = normalizeIp(this.socket.remoteAddress || ''))); } get secure() { return this.socket.server.cert > ''; } } exports.Connection = Connection; function normalizeIp(ip) { return ip.replace(/^::ffff:/, ''); // simplify ipv6-mapped addresses } const all = []; function newConnection(socket) { const ip = normalizeIp(socket.remoteAddress || ''); const res = events_1.default.emit('newSocket', { socket, ip }); const msg = (res === null || res === void 0 ? void 0 : res.isDefaultPrevented()) ? 'plugin (newSocket)' : res === null || res === void 0 ? void 0 : res.find(lodash_1.default.isString); if (!msg) return new Connection(socket); disconnect(socket, msg); } function getConnections() { return all; } function socket2connection(socket) { return all.find(x => // socket exposed by Koa is TLSSocket which encapsulates simple Socket, and I've found no way to access it for simple comparison x.socket.remotePort === socket.remotePort // but we can still match them because IP:PORT is key && x.socket.remoteAddress === socket.remoteAddress); } function getConnection(ctx) { return ctx.state.connection; } function updateConnectionForCtx(ctx) { const conn = getConnection(ctx); if (conn) updateConnection(conn, { ctx }); return conn; } function updateConnection(conn, change, changeState) { const { ctx } = conn; if (changeState && ctx) { Object.assign(ctx.state, changeState); Object.assign(change, { ctx }); } Object.assign(conn, change); events_1.default.emit('connectionUpdated', conn, change); } exports.disconnectionsLog = []; function disconnect(what, debugLog = '') { if ('socket' in what) what = what.socket; const ip = normalizeIp(what.remoteAddress || ''); if (debugLog) console.debug("disconnection:", debugLog, ip); (0, geo_1.ip2country)(ip).then(res => { const rec = { ip, country: res || undefined, ts: new Date, msg: debugLog || undefined }; exports.disconnectionsLog.unshift(rec); exports.disconnectionsLog.length = Math.min(1000, exports.disconnectionsLog.length); events_1.default.emit('disconnection', rec); }); return what.destroy(); }