UNPKG

jspurefix

Version:
236 lines 11.5 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; 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.TcpInitiator = exports.InitiatorState = void 0; const fix_initiator_1 = require("../fix-initiator"); const factory_1 = require("../factory"); const duplex_1 = require("../duplex"); const util = require("util"); const tls_1 = require("tls"); const net_1 = require("net"); const tls_options_factory_1 = require("./tls-options-factory"); const tsyringe_1 = require("tsyringe"); const di_tokens_1 = require("../../runtime/di-tokens"); var InitiatorState; (function (InitiatorState) { InitiatorState[InitiatorState["Idle"] = 1] = "Idle"; InitiatorState[InitiatorState["Connecting"] = 2] = "Connecting"; InitiatorState[InitiatorState["Connected"] = 3] = "Connected"; InitiatorState[InitiatorState["Stopped"] = 4] = "Stopped"; })(InitiatorState || (exports.InitiatorState = InitiatorState = {})); let TcpInitiator = class TcpInitiator extends fix_initiator_1.FixInitiator { constructor(jsFixConfig) { var _a, _b, _c, _d; super((_a = jsFixConfig.description.application) !== null && _a !== void 0 ? _a : null); this.jsFixConfig = jsFixConfig; this.state = InitiatorState.Idle; this.th = null; const name = (_c = (_b = this.application) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : 'initiator'; this.logger = jsFixConfig.logFactory.logger(`${name}:TcpInitiator`); if (!this.application) { throw new Error('no application in session description.'); } this.tcp = (_d = this.application.tcp) !== null && _d !== void 0 ? _d : null; if (!this.tcp) { throw new Error('no tcp in session description need tcp { host: hostname, port: port }'); } } end() { this.clearTimer(); switch (this.state) { case InitiatorState.Connected: { this.logger.info('end'); this.duplex.end(); this.state = InitiatorState.Stopped; break; } default: { this.logger.info(`end :state ${this.state}`); this.state = InitiatorState.Stopped; break; } } } connect(timeoutSeconds) { return __awaiter(this, void 0, void 0, function* () { return yield new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { switch (this.state) { case InitiatorState.Idle: { this.state = InitiatorState.Connecting; this.logger.info(`connecting with timeout ${timeoutSeconds}`); this.tryConnect() .then((t) => { resolve(t); }) .catch((_) => { this.repeatConnect(timeoutSeconds) .then((t) => { resolve(t); }) .catch((e) => { reject(e); }); }); break; } default: { const e = new Error('connect not valid from non idle state'); this.logger.warning(`rejecting from state ${this.state}`); reject(e); } } })); }); } unsecureDuplex() { return __awaiter(this, void 0, void 0, function* () { const tcp = this.tcp; return yield new Promise((resolve, reject) => { try { this.logger.info('unsecureDuplex try to connect to endPoint'); const socket = tcp ? (0, net_1.createConnection)(tcp, () => { try { this.logger.info('net.createConnection cb, resolving'); if (socket) { const tcpDuplex = new duplex_1.TcpDuplex(socket); resolve(tcpDuplex); } else { reject(new Error('no socket in tcp initiator')); } } catch (e) { reject(e); } }) : null; socket === null || socket === void 0 ? void 0 : socket.on('error', (err) => { reject(err); }); } catch (e) { reject(e); } }); }); } tlsDuplex() { return __awaiter(this, void 0, void 0, function* () { return yield new Promise((resolve, reject) => { let tlsSocket = null; const tcp = this.tcp; const connectionOptions = tcp ? tls_options_factory_1.TlsOptionsFactory.getTlsConnectionOptions(tcp) : null; if (connectionOptions) { try { tlsSocket = (0, tls_1.connect)(connectionOptions, () => { var _a; if (!tlsSocket) return null; this.logger.info(`client connected ${tlsSocket.authorized ? 'authorized' : 'unauthorized'}`); if (!tlsSocket.authorized) { const error = tlsSocket.authorizationError; this.logger.warning(`rejecting from state ${this.state} authorizationError ${error}`); tlsSocket.end(); reject(error); } else { tlsSocket.setEncoding('utf8'); const tlsDuplex = new duplex_1.TcpDuplex(tlsSocket); if ((_a = tcp === null || tcp === void 0 ? void 0 : tcp.tls) === null || _a === void 0 ? void 0 : _a.enableTrace) { this.logger.info('enabling tls session trace'); tlsSocket.enableTrace(); } this.logger.info('tlsDuplex resolving'); resolve(tlsDuplex); } }); tlsSocket.on('error', (err) => { reject(err); }); } catch (e) { reject(e); } } }); }); } tryConnect() { return __awaiter(this, void 0, void 0, function* () { return yield new Promise((resolve, reject) => { const tcp = this.tcp; const connectionOptions = tcp ? tls_options_factory_1.TlsOptionsFactory.getTlsConnectionOptions(tcp) : null; const connector = connectionOptions ? this.tlsDuplex() : this.unsecureDuplex(); this.logger.info(`tryConnect ${tcp === null || tcp === void 0 ? void 0 : tcp.host}:${tcp === null || tcp === void 0 ? void 0 : tcp.port}`); connector.then(duplex => { this.duplex = duplex; resolve(new factory_1.MsgTransport(0, this.jsFixConfig, duplex)); }).catch(e => { reject(e); }); }); }); } clearTimer() { if (this.th) { clearInterval(this.th); this.th = null; } } repeatConnect(timeoutSeconds) { return __awaiter(this, void 0, void 0, function* () { return yield new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { var _a, _b; const application = this.application; const promisify = util.promisify; const timeoutPromise = promisify(setTimeout); const reconnectSeconds = (_a = application === null || application === void 0 ? void 0 : application.reconnectSeconds) !== null && _a !== void 0 ? _a : 5; let retries = 0; let lastError; const name = (_b = application === null || application === void 0 ? void 0 : application.name) !== null && _b !== void 0 ? _b : 'initiator'; this.th = setInterval(() => { ++retries; this.tryConnect() .then((t) => { this.state = InitiatorState.Connected; this.clearTimer(); resolve(t); }).catch((e) => { lastError = e; this.logger.info(`${name}: retries ${retries} ${e.message}`); }); }, reconnectSeconds * 1000); timeoutPromise(timeoutSeconds * 1000).then(() => { this.clearTimer(); this.state = InitiatorState.Stopped; const e = lastError !== null && lastError !== void 0 ? lastError : new Error(`${name}: timeout of ${timeoutSeconds} whilst connecting`); reject(e); }).catch(e => { reject(e); }); })); }); } }; exports.TcpInitiator = TcpInitiator; exports.TcpInitiator = TcpInitiator = __decorate([ (0, tsyringe_1.injectable)(), __param(0, (0, tsyringe_1.inject)(di_tokens_1.DITokens.IJsFixConfig)), __metadata("design:paramtypes", [Object]) ], TcpInitiator); //# sourceMappingURL=tcp-initiator.js.map