ilp-protocol-stream
Version:
Interledger Transport Protocol for sending multiple streams of money and data over ILP.
136 lines • 5.75 kB
JavaScript
;
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