UNPKG

ilp-protocol-stream

Version:

Interledger Transport Protocol for sending multiple streams of money and data over ILP.

136 lines 5.75 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ServerConnectionPool = void 0; const ilp_logger_1 = __importDefault(require("ilp-logger")); const oer_utils_1 = require("oer-utils"); const connection_1 = require("./connection"); const cryptoHelper = __importStar(require("./crypto")); const log = (0, ilp_logger_1.default)('ilp-protocol-stream:Pool'); class ServerConnectionPool { constructor(serverSecret, connectionOpts, onConnection) { this.serverSecret = serverSecret; this.connectionOpts = connectionOpts; this.onConnection = onConnection; this.activeConnections = {}; this.pendingConnections = {}; } async close() { await Promise.all(Object.keys(this.activeConnections).map((id) => this.activeConnections[id].end())); } getServerAccount() { return this.connectionOpts.sourceAccount; } getAssetScale() { return this.connectionOpts.assetScale; } getAssetCode() { return this.connectionOpts.assetCode; } async getConnection(id, prepare) { const activeConnection = this.activeConnections[id]; if (activeConnection) return Promise.resolve(activeConnection); const pendingConnection = this.pendingConnections[id]; if (pendingConnection) return pendingConnection; const connectionPromise = (async () => { const token = Buffer.from(id, 'base64'); const sharedSecret = await this.getSharedSecret(token, prepare); let connectionTag; let receiptNonce; let receiptSecret; const reader = new oer_utils_1.Reader(cryptoHelper.decryptConnectionAddressToken(this.serverSecret, token)); reader.skipOctetString(cryptoHelper.TOKEN_NONCE_LENGTH); if (reader.peekVarOctetString().length) { connectionTag = reader.readVarOctetString().toString('ascii'); } else { reader.skipVarOctetString(); } switch (reader.peekVarOctetString().length) { case 0: reader.skipVarOctetString(); break; case 16: receiptNonce = reader.readVarOctetString(); break; default: throw new Error('receiptNonce must be 16 bytes'); } switch (reader.peekVarOctetString().length) { case 0: reader.skipVarOctetString(); break; case 32: receiptSecret = reader.readVarOctetString(); break; default: throw new Error('receiptSecret must be 32 bytes'); } const conn = await connection_1.Connection.build(Object.assign(Object.assign({}, this.connectionOpts), { sharedSecret, connectionTag, connectionId: id, receiptNonce, receiptSecret })); log.debug('got incoming packet for new connection: %s%s', id, connectionTag ? ' (connectionTag: ' + connectionTag + ')' : ''); try { this.onConnection(conn); } catch (err) { log.error('error in connection event handler:', err); } conn.once('close', () => { delete this.pendingConnections[id]; delete this.activeConnections[id]; }); return conn; })(); connectionPromise.catch(() => { delete this.pendingConnections[id]; }); this.pendingConnections[id] = connectionPromise; const connection = await connectionPromise; this.activeConnections[id] = connection; delete this.pendingConnections[id]; await new Promise((resolve) => setTimeout(resolve)); return connection; } async getSharedSecret(token, prepare) { try { const sharedSecret = cryptoHelper.generateSharedSecretFromToken(this.serverSecret, token); const pskKey = await cryptoHelper.generatePskEncryptionKey(sharedSecret); await cryptoHelper.decrypt(pskKey, prepare.data); return sharedSecret; } catch (err) { log.error('got prepare for an address and token that we did not generate: %s', prepare.destination); throw err; } } } exports.ServerConnectionPool = ServerConnectionPool; //# sourceMappingURL=pool.js.map