jspurefix 5.11.0 → 5.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -1
- package/dist/buffer/fixml/fixml-parser.js +1 -1
- package/dist/buffer/fixml/fixml-parser.js.map +1 -1
- package/dist/config/empty-log-factory.d.ts +2 -2
- package/dist/config/empty-log-factory.js +1 -1
- package/dist/config/empty-log-factory.js.map +1 -1
- package/dist/config/get-js-fx-logger.d.ts +2 -2
- package/dist/config/get-js-fx-logger.js.map +1 -1
- package/dist/config/js-fix-logger-factory.d.ts +2 -2
- package/dist/config/js-fix-logger-factory.js.map +1 -1
- package/dist/config/js-fix-logger.d.ts +9 -8
- package/dist/config/js-fix-logger.js +4 -4
- package/dist/config/js-fix-logger.js.map +1 -1
- package/dist/config/js-fix-winston-log-factory.d.ts +2 -2
- package/dist/config/js-fix-winston-log-factory.js +2 -2
- package/dist/config/js-fix-winston-log-factory.js.map +1 -1
- package/dist/config/winston-logger.d.ts +5 -2
- package/dist/config/winston-logger.js +55 -9
- package/dist/config/winston-logger.js.map +1 -1
- package/dist/dictionary/fragment-safety.d.ts +26 -0
- package/dist/dictionary/fragment-safety.js +154 -0
- package/dist/dictionary/fragment-safety.js.map +1 -0
- package/dist/dictionary/index.d.ts +1 -0
- package/dist/dictionary/index.js +1 -0
- package/dist/dictionary/index.js.map +1 -1
- package/dist/runtime/make-config.js +1 -1
- package/dist/runtime/make-config.js.map +1 -1
- package/dist/runtime/session-launcher.js +1 -1
- package/dist/runtime/session-launcher.js.map +1 -1
- package/dist/sample/http/oms/http-client.js +1 -1
- package/dist/sample/http/oms/http-client.js.map +1 -1
- package/dist/sample/http/oms/http-server.js +1 -1
- package/dist/sample/http/oms/http-server.js.map +1 -1
- package/dist/sample/tcp/qf-md/md-client.js +1 -1
- package/dist/sample/tcp/qf-md/md-client.js.map +1 -1
- package/dist/sample/tcp/qf-md/md-server.js +1 -1
- package/dist/sample/tcp/qf-md/md-server.js.map +1 -1
- package/dist/sample/tcp/recovering-skeleton/respawn-acceptor.js +1 -1
- package/dist/sample/tcp/recovering-skeleton/respawn-acceptor.js.map +1 -1
- package/dist/sample/tcp/recovering-skeleton/skeleton-client.js +1 -1
- package/dist/sample/tcp/recovering-skeleton/skeleton-client.js.map +1 -1
- package/dist/sample/tcp/recovering-skeleton/skeleton-server.js +1 -1
- package/dist/sample/tcp/recovering-skeleton/skeleton-server.js.map +1 -1
- package/dist/sample/tcp/skeleton/skeleton-session.js +1 -1
- package/dist/sample/tcp/skeleton/skeleton-session.js.map +1 -1
- package/dist/sample/tcp/trade-capture/trade-capture-client.js +1 -1
- package/dist/sample/tcp/trade-capture/trade-capture-client.js.map +1 -1
- package/dist/sample/tcp/trade-capture/trade-capture-server.js +1 -1
- package/dist/sample/tcp/trade-capture/trade-capture-server.js.map +1 -1
- package/dist/store/fix-msg-memory-store.js +1 -1
- package/dist/store/fix-msg-memory-store.js.map +1 -1
- package/dist/transport/ascii/ascii-msg-transmitter.js +1 -1
- package/dist/transport/ascii/ascii-msg-transmitter.js.map +1 -1
- package/dist/transport/ascii/ascii-session.js +1 -1
- package/dist/transport/ascii/ascii-session.js.map +1 -1
- package/dist/transport/http/http-acceptor-listener.js +1 -1
- package/dist/transport/http/http-acceptor-listener.js.map +1 -1
- package/dist/transport/http/http-acceptor.js +2 -2
- package/dist/transport/http/http-acceptor.js.map +1 -1
- package/dist/transport/http/http-initiator.js +1 -1
- package/dist/transport/http/http-initiator.js.map +1 -1
- package/dist/transport/http/http-json-sample-adapter.js +1 -1
- package/dist/transport/http/http-json-sample-adapter.js.map +1 -1
- package/dist/transport/session/fix-session.js +3 -3
- package/dist/transport/session/fix-session.js.map +1 -1
- package/dist/transport/session/session-registry.js +1 -1
- package/dist/transport/session/session-registry.js.map +1 -1
- package/dist/transport/tcp/connect-error.d.ts +2 -0
- package/dist/transport/tcp/connect-error.js +32 -0
- package/dist/transport/tcp/connect-error.js.map +1 -0
- package/dist/transport/tcp/recovering-tcp-initiator.js +3 -2
- package/dist/transport/tcp/recovering-tcp-initiator.js.map +1 -1
- package/dist/transport/tcp/tcp-acceptor-listener.js +2 -2
- package/dist/transport/tcp/tcp-acceptor-listener.js.map +1 -1
- package/dist/transport/tcp/tcp-acceptor.js +2 -2
- package/dist/transport/tcp/tcp-acceptor.js.map +1 -1
- package/dist/transport/tcp/tcp-initiator-connector.js +2 -2
- package/dist/transport/tcp/tcp-initiator-connector.js.map +1 -1
- package/dist/transport/tcp/tcp-initiator.js +5 -4
- package/dist/transport/tcp/tcp-initiator.js.map +1 -1
- package/docs/instrumentation.md +346 -0
- package/docs/scattered-components.md +280 -0
- package/jsfix.test_client.txt +62 -62
- package/jsfix.test_server.txt +72 -72
- package/package.json +1 -1
- package/src/buffer/fixml/fixml-parser.ts +1 -1
- package/src/config/empty-log-factory.ts +2 -2
- package/src/config/get-js-fx-logger.ts +2 -2
- package/src/config/js-fix-logger-factory.ts +8 -2
- package/src/config/js-fix-logger.ts +23 -8
- package/src/config/js-fix-winston-log-factory.ts +3 -3
- package/src/config/winston-logger.ts +85 -10
- package/src/dictionary/fragment-safety.ts +225 -0
- package/src/dictionary/index.ts +1 -0
- package/src/runtime/make-config.ts +1 -1
- package/src/runtime/session-launcher.ts +1 -1
- package/src/sample/http/oms/http-client.ts +1 -1
- package/src/sample/http/oms/http-server.ts +1 -1
- package/src/sample/tcp/qf-md/md-client.ts +1 -1
- package/src/sample/tcp/qf-md/md-server.ts +1 -1
- package/src/sample/tcp/recovering-skeleton/respawn-acceptor.ts +2 -1
- package/src/sample/tcp/recovering-skeleton/skeleton-client.ts +1 -1
- package/src/sample/tcp/recovering-skeleton/skeleton-server.ts +1 -1
- package/src/sample/tcp/skeleton/skeleton-session.ts +1 -1
- package/src/sample/tcp/trade-capture/trade-capture-client.ts +2 -1
- package/src/sample/tcp/trade-capture/trade-capture-server.ts +2 -1
- package/src/store/fix-msg-memory-store.ts +2 -1
- package/src/transport/ascii/ascii-msg-transmitter.ts +2 -1
- package/src/transport/ascii/ascii-session.ts +2 -1
- package/src/transport/http/http-acceptor-listener.ts +2 -1
- package/src/transport/http/http-acceptor.ts +2 -1
- package/src/transport/http/http-initiator.ts +2 -1
- package/src/transport/http/http-json-sample-adapter.ts +1 -1
- package/src/transport/session/fix-session.ts +2 -1
- package/src/transport/session/session-registry.ts +1 -1
- package/src/transport/tcp/connect-error.ts +56 -0
- package/src/transport/tcp/recovering-tcp-initiator.ts +4 -2
- package/src/transport/tcp/tcp-acceptor-listener.ts +4 -2
- package/src/transport/tcp/tcp-acceptor.ts +2 -1
- package/src/transport/tcp/tcp-initiator-connector.ts +4 -2
- package/src/transport/tcp/tcp-initiator.ts +9 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recovering-tcp-initiator.js","sourceRoot":"","sources":["../../../src/transport/tcp/recovering-tcp-initiator.ts"],"names":[],"mappings":"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","sourcesContent":["import { IJsFixConfig, IJsFixLogger } from '../../config'\nimport { FixSession } from '../session/fix-session'\nimport { TcpInitiator } from './tcp-initiator'\nimport { MsgTransport } from '../factory'\nimport Timeout = NodeJS.Timeout\nimport { SessionState } from '../session/session-state'\nimport { inject, injectable } from 'tsyringe'\nimport { DITokens } from '../../runtime/di-tokens'\nimport { ITcpTransportDescription } from './tcp-transport-description'\nimport { IMsgApplication } from '../msg-application'\nimport { FixEntity } from '../fix-entity'\n\n/*\n create one application session instance - and recover a lost transport. Hence, the application\n will automatically re-connected and the \"message recovery\" policy enacted i.e. replay from\n last known sequence number or sequence reset.\n */\n\n@injectable()\nexport class RecoveringTcpInitiator extends FixEntity {\n public tcp: ITcpTransportDescription | null\n public session: FixSession\n private readonly logger: IJsFixLogger\n private readonly application: IMsgApplication | null\n private initiator: TcpInitiator\n private transport: MsgTransport\n private th: Timeout | null = null\n private stopRequested: boolean = false\n public static readonly DefaultRecoveryAttemptSecs = 5\n public static readonly DefaultBackoffFailConnectSecs = 30\n public static readonly DefaultConnectTimeoutSecs = 60\n\n public recoveryAttemptSecs: number = RecoveringTcpInitiator.DefaultRecoveryAttemptSecs\n public backoffFailConnectSecs: number = RecoveringTcpInitiator.DefaultBackoffFailConnectSecs\n public connectTimeoutSecs: number = RecoveringTcpInitiator.DefaultConnectTimeoutSecs\n\n constructor (@inject(DITokens.IJsFixConfig) public readonly jsFixConfig: IJsFixConfig) {\n super(jsFixConfig)\n this.application = this.jsFixConfig.description.application ?? null\n const name = this.application?.name ?? 'na'\n this.logger = jsFixConfig.logFactory.logger(`${name}:RecoveringTcpInitiator`)\n if (!this.application) {\n throw new Error('no application in session description.')\n }\n this.tcp = this.application.tcp ?? null\n if (!this.tcp) {\n throw new Error('no tcp in session description need tcp { host: hostname, port: port }')\n }\n // the retry policy used to live only in these fields, which nothing set - an\n // application could not change how hard or how long the engine tried to get its\n // transport back without subclassing the launcher. See issue #72.\n this.recoveryAttemptSecs = this.application.recoveryAttemptSeconds ?? this.recoveryAttemptSecs\n this.backoffFailConnectSecs = this.application.backoffFailConnectSeconds ?? this.backoffFailConnectSecs\n this.connectTimeoutSecs = this.application.connectTimeoutSeconds ?? this.connectTimeoutSecs\n this.logger.info(`recovery policy: connectTimeout=${this.connectTimeoutSecs}s, ` +\n `recoveryAttempt=${this.recoveryAttemptSecs}s, backoffFailConnect=${this.backoffFailConnectSecs}s`)\n this.createSession(jsFixConfig)\n }\n\n private createSession (jsFixConfig: IJsFixConfig): void {\n this.logger.info(`creating an application session with DI token ${DITokens.FixSession}.`)\n this.session = jsFixConfig.sessionContainer.resolve<FixSession>(DITokens.FixSession)\n this.session.on('done', () => {\n this.logger.info('session has permanently ended')\n this.emit('end', this)\n })\n this.session.on('end', () => {\n this.logger.info('session has permanently ended')\n this.emit('end', this)\n })\n // A lost transport is this initiator's normal course of events, and recovery is\n // driven by session.run() rejecting rather than by this event. But whilst waiting\n // between attempts there is no run in flight to carry a listener, so a stop landing\n // then would emit 'error' to nobody - which node treats as fatal.\n this.session.on('error', (e: Error) => {\n this.logger.info(`session error: ${e.message}`)\n })\n this.session.setState(SessionState.DisconnectedNoConnectionToday)\n }\n\n public getState (): SessionState {\n return this.session.getState()\n }\n\n public lastSentSeqNum (): number {\n return this.session.lastSentSeqNum()\n }\n\n private resetSeq (): boolean {\n return this.jsFixConfig.description.ResetSeqNumFlag\n }\n\n private newTransport (transport: MsgTransport): void {\n this.transport = transport\n this.emit('transport', transport)\n this.logger.info(`initiator connects id ${(transport.id)}`)\n const session = this.session\n if (this.resetSeq()) {\n this.logger.info('reset sequence numbers')\n session.reset()\n }\n session.setState(SessionState.NetworkConnectionEstablished)\n session.run(transport).then((id: number) => {\n if (!transport || id === transport.id) {\n this.emit('end', this)\n } else {\n this.logger.info(`old transport ${id} ends waiting on ${(transport.id)}`)\n }\n }).catch(e => {\n this.logger.info(`transport id ${(transport.id)} failed - session state ${session.getState()}`)\n this.logger.warning(e.message)\n this.recover()\n })\n this.logger.info(`running session with transport ${transport.id} state = ${session.getState()}`)\n }\n\n private clearTimer (): void {\n if (this.th) {\n clearTimeout(this.th)\n this.th = null\n }\n }\n\n // at least one connection was established so retry to establish - either\n // succeed in which case can restart session or fails in which case wait and\n // restart an attempt to connect\n\n /**\n * Give up recovering and end the session for good.\n *\n * Without this a resilient initiator could not be shut down: losing the transport\n * schedules another attempt, and nothing cancelled that timer, so the process stayed\n * alive retrying a counterparty the application had finished with. Safe to call\n * twice, and safe whilst waiting between attempts with no transport at all.\n */\n public stop (): void {\n if (this.stopRequested) return\n this.stopRequested = true\n this.logger.info('stop requested - cancelling recovery')\n this.clearTimer()\n if (this.session.getState() !== SessionState.Stopped) {\n this.session.requestStop('initiator stopped')\n }\n this.emit('end', this)\n }\n\n private recover (): void {\n if (this.stopRequested) {\n this.logger.info('transport lost after a stop was requested - not recovering')\n this.emit('end', this)\n return\n }\n this.session.setState(SessionState.DetectBrokenNetworkConnection)\n this.logger.info(`recover session transport - attempt in ${this.recoveryAttemptSecs} secs`)\n if (!this.resetSeq()) {\n const lastSentSeqNum = this.lastSentSeqNum()\n if (lastSentSeqNum > 0) {\n this.logger.info(`recover session set LastSentSeqNum ${lastSentSeqNum} for new transport`)\n this.config.description.LastSentSeqNum = lastSentSeqNum\n }\n }\n this.th = setTimeout(() => {\n this.connect(this.connectTimeoutSecs).then(t => {\n this.logger.info(`new transport ${t.id}`)\n }).catch((e) => {\n this.logger.info(`failed to re-connect ${e.message} - backoff for ${this.backoffFailConnectSecs}`)\n this.th = setTimeout(() => {\n this.logger.info('returning to recover()')\n setImmediate(() => {\n this.recover()\n })\n }, this.backoffFailConnectSecs * 1000)\n })\n }, this.recoveryAttemptSecs * 1000)\n }\n\n public async start (): Promise<any> {\n return await this.run()\n }\n\n // for first connection - reject if no initial connection established within timeout\n // once connection established, will not resolve until session is ended - i.e. lost\n // connections are re-established using the same session instance. So this promise\n // is the lifetime of the application, not a signal that the session is up: for that,\n // use onReady on the session. See issue #72.\n\n public async run (initialTimeout: number = this.connectTimeoutSecs): Promise<any> {\n return await new Promise<any>((resolve, reject) => {\n // 'end' can arrive more than once - a stop both ends the session and calls off\n // recovery, and each path announces itself - so settle only on the first. The\n // listener goes on before connecting, not after: a stop landing whilst the first\n // connection is still being attempted has to be able to end this too, and until\n // now there was nothing listening that early to hear it.\n let ended = false\n const finish = (): void => {\n if (ended) return\n ended = true\n this.clearTimer()\n this.initiator?.end()\n this.logger.info(`run: transport ${this.transport?.id ?? 'none'} ends - resolving`)\n resolve(null)\n }\n this.on('end', finish)\n\n this.connect(initialTimeout).catch(e => {\n if (this.stopRequested) {\n this.logger.info('run: first connection abandoned on stop - resolving')\n finish()\n return\n }\n this.logger.info(`run: failed to connect to first transport ${initialTimeout} - rejecting`)\n reject(e)\n })\n })\n }\n\n // return a promise for new transport - or reject if no connection within timeout\n\n private async connect (timeout: number): Promise<MsgTransport> {\n return await new Promise<MsgTransport>((resolve, reject) => {\n this.logger.info(`connect: start initiator timeout ${timeout}`)\n this.session.setState(SessionState.InitiateConnection)\n this.initiator = new TcpInitiator(this.jsFixConfig)\n this.initiator.connect(timeout).then((transport: MsgTransport) => {\n this.logger.info(`connect: receive new transport ${transport.id}`)\n this.newTransport(transport)\n resolve(transport)\n }).catch(e => {\n this.logger.info(`connect: failed to connect within ${timeout} - rejecting`)\n this.session.setState(SessionState.DetectBrokenNetworkConnection)\n reject(e)\n })\n })\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"recovering-tcp-initiator.js","sourceRoot":"","sources":["../../../src/transport/tcp/recovering-tcp-initiator.ts"],"names":[],"mappings":"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","sourcesContent":["import { IJsFixConfig, IJsFixLogger } from '../../config'\nimport { FixSession } from '../session/fix-session'\nimport { TcpInitiator } from './tcp-initiator'\nimport { MsgTransport } from '../factory'\nimport Timeout = NodeJS.Timeout\nimport { SessionState } from '../session/session-state'\nimport { inject, injectable } from 'tsyringe'\nimport { DITokens } from '../../runtime/di-tokens'\nimport { ITcpTransportDescription } from './tcp-transport-description'\nimport { IMsgApplication } from '../msg-application'\nimport { FixEntity } from '../fix-entity'\nimport { describeConnectError } from './connect-error'\n\n/*\n create one application session instance - and recover a lost transport. Hence, the application\n will automatically re-connected and the \"message recovery\" policy enacted i.e. replay from\n last known sequence number or sequence reset.\n */\n\n@injectable()\nexport class RecoveringTcpInitiator extends FixEntity {\n public tcp: ITcpTransportDescription | null\n public session: FixSession\n private readonly logger: IJsFixLogger\n private readonly application: IMsgApplication | null\n private initiator: TcpInitiator\n private transport: MsgTransport\n private th: Timeout | null = null\n private stopRequested: boolean = false\n public static readonly DefaultRecoveryAttemptSecs = 5\n public static readonly DefaultBackoffFailConnectSecs = 30\n public static readonly DefaultConnectTimeoutSecs = 60\n\n public recoveryAttemptSecs: number = RecoveringTcpInitiator.DefaultRecoveryAttemptSecs\n public backoffFailConnectSecs: number = RecoveringTcpInitiator.DefaultBackoffFailConnectSecs\n public connectTimeoutSecs: number = RecoveringTcpInitiator.DefaultConnectTimeoutSecs\n\n constructor (@inject(DITokens.IJsFixConfig) public readonly jsFixConfig: IJsFixConfig) {\n super(jsFixConfig)\n this.application = this.jsFixConfig.description.application ?? null\n const name = this.application?.name ?? 'na'\n this.logger = jsFixConfig.logFactory.logger(`${name}:RecoveringTcpInitiator`,\n { component: 'RecoveringTcpInitiator', app: name, role: 'initiator' })\n if (!this.application) {\n throw new Error('no application in session description.')\n }\n this.tcp = this.application.tcp ?? null\n if (!this.tcp) {\n throw new Error('no tcp in session description need tcp { host: hostname, port: port }')\n }\n // the retry policy used to live only in these fields, which nothing set - an\n // application could not change how hard or how long the engine tried to get its\n // transport back without subclassing the launcher. See issue #72.\n this.recoveryAttemptSecs = this.application.recoveryAttemptSeconds ?? this.recoveryAttemptSecs\n this.backoffFailConnectSecs = this.application.backoffFailConnectSeconds ?? this.backoffFailConnectSecs\n this.connectTimeoutSecs = this.application.connectTimeoutSeconds ?? this.connectTimeoutSecs\n this.logger.info(`recovery policy: connectTimeout=${this.connectTimeoutSecs}s, ` +\n `recoveryAttempt=${this.recoveryAttemptSecs}s, backoffFailConnect=${this.backoffFailConnectSecs}s`)\n this.createSession(jsFixConfig)\n }\n\n private createSession (jsFixConfig: IJsFixConfig): void {\n this.logger.info(`creating an application session with DI token ${DITokens.FixSession}.`)\n this.session = jsFixConfig.sessionContainer.resolve<FixSession>(DITokens.FixSession)\n this.session.on('done', () => {\n this.logger.info('session has permanently ended')\n this.emit('end', this)\n })\n this.session.on('end', () => {\n this.logger.info('session has permanently ended')\n this.emit('end', this)\n })\n // A lost transport is this initiator's normal course of events, and recovery is\n // driven by session.run() rejecting rather than by this event. But whilst waiting\n // between attempts there is no run in flight to carry a listener, so a stop landing\n // then would emit 'error' to nobody - which node treats as fatal.\n this.session.on('error', (e: Error) => {\n this.logger.info(`session error: ${e.message}`)\n })\n this.session.setState(SessionState.DisconnectedNoConnectionToday)\n }\n\n public getState (): SessionState {\n return this.session.getState()\n }\n\n public lastSentSeqNum (): number {\n return this.session.lastSentSeqNum()\n }\n\n private resetSeq (): boolean {\n return this.jsFixConfig.description.ResetSeqNumFlag\n }\n\n private newTransport (transport: MsgTransport): void {\n this.transport = transport\n this.emit('transport', transport)\n this.logger.info(`initiator connects id ${(transport.id)}`)\n const session = this.session\n if (this.resetSeq()) {\n this.logger.info('reset sequence numbers')\n session.reset()\n }\n session.setState(SessionState.NetworkConnectionEstablished)\n session.run(transport).then((id: number) => {\n if (!transport || id === transport.id) {\n this.emit('end', this)\n } else {\n this.logger.info(`old transport ${id} ends waiting on ${(transport.id)}`)\n }\n }).catch(e => {\n this.logger.info(`transport id ${(transport.id)} failed - session state ${session.getState()}`)\n this.logger.warning(e.message)\n this.recover()\n })\n this.logger.info(`running session with transport ${transport.id} state = ${session.getState()}`)\n }\n\n private clearTimer (): void {\n if (this.th) {\n clearTimeout(this.th)\n this.th = null\n }\n }\n\n // at least one connection was established so retry to establish - either\n // succeed in which case can restart session or fails in which case wait and\n // restart an attempt to connect\n\n /**\n * Give up recovering and end the session for good.\n *\n * Without this a resilient initiator could not be shut down: losing the transport\n * schedules another attempt, and nothing cancelled that timer, so the process stayed\n * alive retrying a counterparty the application had finished with. Safe to call\n * twice, and safe whilst waiting between attempts with no transport at all.\n */\n public stop (): void {\n if (this.stopRequested) return\n this.stopRequested = true\n this.logger.info('stop requested - cancelling recovery')\n this.clearTimer()\n if (this.session.getState() !== SessionState.Stopped) {\n this.session.requestStop('initiator stopped')\n }\n this.emit('end', this)\n }\n\n private recover (): void {\n if (this.stopRequested) {\n this.logger.info('transport lost after a stop was requested - not recovering')\n this.emit('end', this)\n return\n }\n this.session.setState(SessionState.DetectBrokenNetworkConnection)\n this.logger.info(`recover session transport - attempt in ${this.recoveryAttemptSecs} secs`)\n if (!this.resetSeq()) {\n const lastSentSeqNum = this.lastSentSeqNum()\n if (lastSentSeqNum > 0) {\n this.logger.info(`recover session set LastSentSeqNum ${lastSentSeqNum} for new transport`)\n this.config.description.LastSentSeqNum = lastSentSeqNum\n }\n }\n this.th = setTimeout(() => {\n this.connect(this.connectTimeoutSecs).then(t => {\n this.logger.info(`new transport ${t.id}`)\n }).catch((e) => {\n this.logger.info(`failed to re-connect: ${describeConnectError(e)} - backoff for ${this.backoffFailConnectSecs}`)\n this.th = setTimeout(() => {\n this.logger.info('returning to recover()')\n setImmediate(() => {\n this.recover()\n })\n }, this.backoffFailConnectSecs * 1000)\n })\n }, this.recoveryAttemptSecs * 1000)\n }\n\n public async start (): Promise<any> {\n return await this.run()\n }\n\n // for first connection - reject if no initial connection established within timeout\n // once connection established, will not resolve until session is ended - i.e. lost\n // connections are re-established using the same session instance. So this promise\n // is the lifetime of the application, not a signal that the session is up: for that,\n // use onReady on the session. See issue #72.\n\n public async run (initialTimeout: number = this.connectTimeoutSecs): Promise<any> {\n return await new Promise<any>((resolve, reject) => {\n // 'end' can arrive more than once - a stop both ends the session and calls off\n // recovery, and each path announces itself - so settle only on the first. The\n // listener goes on before connecting, not after: a stop landing whilst the first\n // connection is still being attempted has to be able to end this too, and until\n // now there was nothing listening that early to hear it.\n let ended = false\n const finish = (): void => {\n if (ended) return\n ended = true\n this.clearTimer()\n this.initiator?.end()\n this.logger.info(`run: transport ${this.transport?.id ?? 'none'} ends - resolving`)\n resolve(null)\n }\n this.on('end', finish)\n\n this.connect(initialTimeout).catch(e => {\n if (this.stopRequested) {\n this.logger.info('run: first connection abandoned on stop - resolving')\n finish()\n return\n }\n this.logger.info(`run: failed to connect to first transport ${initialTimeout} - rejecting`)\n reject(e)\n })\n })\n }\n\n // return a promise for new transport - or reject if no connection within timeout\n\n private async connect (timeout: number): Promise<MsgTransport> {\n return await new Promise<MsgTransport>((resolve, reject) => {\n this.logger.info(`connect: start initiator timeout ${timeout}`)\n this.session.setState(SessionState.InitiateConnection)\n this.initiator = new TcpInitiator(this.jsFixConfig)\n this.initiator.connect(timeout).then((transport: MsgTransport) => {\n this.logger.info(`connect: receive new transport ${transport.id}`)\n this.newTransport(transport)\n resolve(transport)\n }).catch(e => {\n this.logger.info(`connect: failed to connect within ${timeout} - rejecting`)\n this.session.setState(SessionState.DetectBrokenNetworkConnection)\n reject(e)\n })\n })\n }\n}\n"]}
|
|
@@ -40,7 +40,7 @@ let TcpAcceptorListener = class TcpAcceptorListener extends fix_entity_1.FixEnti
|
|
|
40
40
|
start() {
|
|
41
41
|
return __awaiter(this, void 0, void 0, function* () {
|
|
42
42
|
return yield new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
43
|
-
const logger = this.config.logFactory.logger('acceptor');
|
|
43
|
+
const logger = this.config.logFactory.logger('acceptor', { component: 'TcpAcceptorListener', role: 'acceptor' });
|
|
44
44
|
const sessionContainer = this.config.sessionContainer;
|
|
45
45
|
if (!sessionContainer.isRegistered(di_tokens_1.DITokens.FixSession)) {
|
|
46
46
|
reject(new Error(`application must register a DI token '${di_tokens_1.DITokens.FixSession}' - see src/sample`));
|
|
@@ -84,7 +84,7 @@ let TcpAcceptorListener = class TcpAcceptorListener extends fix_entity_1.FixEnti
|
|
|
84
84
|
}
|
|
85
85
|
stop() {
|
|
86
86
|
if (this.acceptor) {
|
|
87
|
-
const logger = this.config.logFactory.logger('acceptor');
|
|
87
|
+
const logger = this.config.logFactory.logger('acceptor', { component: 'TcpAcceptorListener', role: 'acceptor' });
|
|
88
88
|
logger.info('acceptor stopping');
|
|
89
89
|
this.acceptor.close(() => {
|
|
90
90
|
logger.info('acceptor closed.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tcp-acceptor-listener.js","sourceRoot":"","sources":["../../../src/transport/tcp/tcp-acceptor-listener.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAEA,iDAA4C;AAE5C,uCAA6C;AAE7C,uDAAkD;AAClD,8CAAyC;AACzC,kEAA+E;AAGxE,IAAM,mBAAmB,GAAzB,MAAM,mBAAoB,SAAQ,sBAAS;IAUhD,YAA4C,MAAoC;;QAC9E,KAAK,CAAC,MAAM,CAAC,CAAA;QAD6C,WAAM,GAAN,MAAM,CAAc;QATxE,aAAQ,GAAuB,IAAI,CAAA;QACnC,iBAAY,GAAkC,IAAI,CAAA;QAUxD,IAAI,CAAC,eAAe,GAAG,MAAA,MAAM,CAAC,eAAe,mCAAI,IAAI,kCAAe,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;QACvF,MAAM,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAA;IAC/C,CAAC;IAEK,KAAK;;YACT,OAAO,MAAM,IAAI,OAAO,CAAM,CAAO,OAAO,EAAE,MAAM,EAAE,EAAE;gBACtD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"tcp-acceptor-listener.js","sourceRoot":"","sources":["../../../src/transport/tcp/tcp-acceptor-listener.ts"],"names":[],"mappings":"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","sourcesContent":["import { IJsFixConfig, IJsFixLogger } from '../../config'\nimport { FixAcceptor } from '../fix-acceptor'\nimport { TcpAcceptor } from './tcp-acceptor'\nimport { MsgTransport } from '../factory'\nimport { inject, injectable } from 'tsyringe'\nimport { FixSession } from '../session/fix-session'\nimport { DITokens } from '../../runtime/di-tokens'\nimport { FixEntity } from '../fix-entity'\nimport { ISessionRegistry, SessionRegistry } from '../session/session-registry'\n\n@injectable()\nexport class TcpAcceptorListener extends FixEntity {\n private acceptor: FixAcceptor | null = null\n private resolveStart: ((value: any) => void) | null = null\n /**\n * One registry per listener, so a counterparty reconnecting onto a fresh socket\n * replaces its previous session instead of running alongside it (issue #153).\n * An application may supply its own via config.sessionRegistry.\n */\n public readonly sessionRegistry: ISessionRegistry\n\n constructor (@inject(DITokens.IJsFixConfig) public readonly config: IJsFixConfig) {\n super(config)\n this.sessionRegistry = config.sessionRegistry ?? new SessionRegistry(config.logFactory)\n config.sessionRegistry = this.sessionRegistry\n }\n\n async start (): Promise<any> {\n return await new Promise<any>(async (resolve, reject) => {\n const logger = this.config.logFactory.logger('acceptor',\n { component: 'TcpAcceptorListener', role: 'acceptor' })\n const sessionContainer = this.config.sessionContainer\n if (!sessionContainer.isRegistered(DITokens.FixSession)) {\n reject(new Error(`application must register a DI token '${DITokens.FixSession}' - see src/sample`))\n return\n }\n logger.info('starting.')\n const acceptor: FixAcceptor = sessionContainer.resolve<FixAcceptor>(TcpAcceptor)\n this.acceptor = acceptor\n\n acceptor.on('transport', (t: MsgTransport) => {\n // resolve from the transport's own scope, not the listener's container, so\n // this session gets the per-connection description, buffers and message\n // factory created by TcpAcceptor. Falls back to the listener container for\n // transports created outside the acceptor (tests, custom entities).\n const scope = t.config?.sessionContainer ?? sessionContainer\n const description = t.config?.description\n logger.info(`transport ${t.id}: creating session via DI token ${DITokens.FixSession} ` +\n `[${description?.SenderCompId ?? '?'} -> ${description?.TargetCompID ?? '?'}]`)\n const acceptorSession = scope.resolve<FixSession>(DITokens.FixSession)\n this.emit('session', acceptorSession, t)\n // a wildcard acceptor has not claimed its SessionId yet - report again once\n // the session ends, by which time the registry line is meaningful\n this.census(logger)\n // Run the session but do NOT close the listener when it ends.\n // The acceptor keeps listening for new connections (reconnects).\n // This matches the C# TcpAcceptorListener accept-loop pattern.\n acceptorSession.run(t).then(() => {\n logger.info(`transport ${t.id}: session ended normally, acceptor continues listening`)\n this.census(logger)\n }).catch((e: Error) => {\n logger.warning(`transport ${t.id}: session ended with error: ${e.message}, acceptor continues listening`)\n this.census(logger)\n })\n })\n\n acceptor.on('harvested', (tid: number, reason: string) => {\n logger.info(`transport ${tid} harvested (${reason})`)\n this.census(logger)\n })\n\n this.resolveStart = resolve\n acceptor.listen()\n })\n }\n\n /**\n * What is actually connected, and which SessionIds are claimed. Emitted whenever\n * the population changes so \"how many clients do I have, and who are they\" is\n * answerable from the server log alone.\n */\n private census (logger: IJsFixLogger): void {\n const acceptor = this.acceptor as TcpAcceptor | null\n const transports = acceptor?.liveTransports() ?? []\n logger.info(`acceptor census: transports=${transports.length} [${transports.join(', ')}] ` +\n `sessions=${this.sessionRegistry.count} [${this.sessionRegistry.keys().join(', ')}]`)\n }\n\n /**\n * Explicitly stop the acceptor listener. Call this when the application\n * is shutting down (e.g., timeout, SIGINT). Without this call, the\n * acceptor keeps listening indefinitely — which is the correct\n * production behaviour for a FIX acceptor.\n */\n stop (): void {\n if (this.acceptor) {\n const logger = this.config.logFactory.logger('acceptor',\n { component: 'TcpAcceptorListener', role: 'acceptor' })\n logger.info('acceptor stopping')\n this.acceptor.close(() => {\n logger.info('acceptor closed.')\n if (this.resolveStart) {\n this.resolveStart(true)\n this.resolveStart = null\n }\n })\n this.acceptor = null\n }\n }\n}\n"]}
|
|
@@ -26,12 +26,12 @@ const di_tokens_1 = require("../../runtime/di-tokens");
|
|
|
26
26
|
const session_scope_1 = require("../../runtime/session-scope");
|
|
27
27
|
let TcpAcceptor = TcpAcceptor_1 = class TcpAcceptor extends fix_acceptor_1.FixAcceptor {
|
|
28
28
|
constructor(config) {
|
|
29
|
-
var _a, _b;
|
|
29
|
+
var _a, _b, _c;
|
|
30
30
|
super((_a = config.description.application) !== null && _a !== void 0 ? _a : null);
|
|
31
31
|
this.config = config;
|
|
32
32
|
this.nextId = 0;
|
|
33
33
|
this.accepted = {};
|
|
34
|
-
this.logger = config.logFactory.logger(`${(_b = config.description.application) === null || _b === void 0 ? void 0 : _b.name}:TcpAcceptor
|
|
34
|
+
this.logger = config.logFactory.logger(`${(_b = config.description.application) === null || _b === void 0 ? void 0 : _b.name}:TcpAcceptor`, { component: 'TcpAcceptor', app: (_c = config.description.application) === null || _c === void 0 ? void 0 : _c.name, role: 'acceptor' });
|
|
35
35
|
const tlsOptions = this.tlsOptions();
|
|
36
36
|
if (tlsOptions) {
|
|
37
37
|
this.tlsServer();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tcp-acceptor.js","sourceRoot":"","sources":["../../../src/transport/tcp/tcp-acceptor.ts"],"names":[],"mappings":"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","sourcesContent":["import { TcpDuplex } from '../duplex'\nimport { MsgTransport } from '../factory'\nimport { FixAcceptor } from '../fix-acceptor'\nimport { IJsFixConfig, IJsFixLogger } from '../../config'\nimport { createServer as netCreateServer, Server, Socket } from 'net'\nimport { createServer as tlsCreateServer, TlsOptions, TLSSocket } from 'tls'\nimport { TlsOptionsFactory } from './tls-options-factory'\nimport { describeNegotiated, describePeerCertificate, describeServerOptions } from './tls-diagnostics'\nimport { inject, injectable } from 'tsyringe'\nimport { DITokens } from '../../runtime/di-tokens'\nimport { makeSessionScope } from '../../runtime/session-scope'\n\n@injectable()\nexport class TcpAcceptor extends FixAcceptor {\n private server: Server\n private readonly logger: IJsFixLogger\n private nextId: number = 0\n\n constructor (@inject(DITokens.IJsFixConfig) public readonly config: IJsFixConfig) {\n super(config.description.application ?? null)\n this.logger = config.logFactory.logger(`${config.description.application?.name}:TcpAcceptor`)\n const tlsOptions: TlsOptions | null = this.tlsOptions()\n if (tlsOptions) {\n this.tlsServer()\n } else {\n this.unsecureServer()\n }\n this.server.on('error', (err: Error) => {\n throw err\n })\n }\n\n getId (): number {\n this.nextId++\n return this.nextId\n }\n\n tlsServer (): void {\n try {\n const config: IJsFixConfig = this.config\n const tcp = this.config.description.application?.tcp\n const tlsOptions: TlsOptions | null = tcp?.tls ? TlsOptionsFactory.getTlsOptions(tcp.tls) : null\n this.logger.info('create tls server')\n if (!tlsOptions) return\n this.logger.info(`tls server options ${describeServerOptions(tlsOptions)}`)\n this.server = tlsCreateServer(tlsOptions, (tlsSocket: TLSSocket) => {\n if (tcp?.tls?.enableTrace) {\n this.logger.info('enabling tls session trace')\n tlsSocket.enableTrace()\n }\n this.logger.info(`tls negotiated ${describeNegotiated(tlsSocket)}`)\n this.logger.info(`tls peer certificate ${describePeerCertificate(tlsSocket)}`)\n // mirrors the initiator fix for #94 - an unauthorized peer is only fatal when the\n // caller has not explicitly opted out. the default stays secure: rejectUnauthorized\n // undefined means reject, exactly as before.\n if (!tlsSocket.authorized && tlsOptions.rejectUnauthorized !== false) {\n this.logger.warning(`no transport created, unauthorized tls connection: ${String(tlsSocket.authorizationError)}`)\n tlsSocket.end()\n return\n }\n if (!tlsSocket.authorized) {\n this.logger.warning(`accepting unauthorized tls peer (rejectUnauthorized: false): ${String(tlsSocket.authorizationError)}`)\n }\n tlsSocket.setEncoding('utf8')\n const id: number = this.getId()\n this.logger.info(`tls creates session ${id} authorized ${tlsSocket.authorized}`)\n this.onSocket(id, tlsSocket, config)\n })\n } catch (e) {\n this.logger.error(e as Error)\n throw e\n }\n }\n\n unsecureServer (): void {\n try {\n const config = this.config\n this.logger.info('create unsecured server')\n this.server = netCreateServer((socket: Socket) => {\n const id: number = this.getId()\n this.logger.info(`net creates session ${id}`)\n socket.setNoDelay(true)\n this.onSocket(id, socket, config)\n })\n } catch (e) {\n this.logger.error(e as Error)\n throw e\n }\n }\n\n tlsOptions (): TlsOptions | null {\n const tcp = this.config.description.application?.tcp\n return tcp?.tls ? TlsOptionsFactory.getTlsOptions(tcp?.tls) : null\n }\n\n private onSocket (id: number, socket: Socket, config: IJsFixConfig): void {\n // Every accepted connection gets its own DI scope: its own parse and transmit\n // buffers, its own session description (hence its own SessionId and message\n // store) and its own session message factory. Without this, concurrent clients\n // on one listener share buffers and collide on a single store.\n const sessionConfig = makeSessionScope(config)\n const remote = `${socket.remoteAddress ?? '?'}:${socket.remotePort ?? 0}`\n this.applyKeepAlive(id, socket)\n this.logger.info(`transport ${id} from ${remote} given its own session scope`)\n const transport: MsgTransport = new MsgTransport(id, sessionConfig, new TcpDuplex(socket))\n this.saveTransport(id, transport, remote)\n transport.receiver.on('end', () => {\n this.harvestTransport(id, 'peer ended the connection')\n })\n transport.receiver.on('error', (e: Error) => {\n this.logger.error(e)\n this.harvestTransport(id, `receiver error: ${e.message}`)\n })\n // 'end' only fires on a clean FIN. A socket dropped by a firewall, or one this\n // side destroyed after a failed graceful close, arrives here instead - without\n // it the transport would sit in the map forever.\n socket.on('close', (hadError: boolean) => {\n this.harvestTransport(id, hadError ? 'socket closed after error' : 'socket closed')\n })\n }\n\n /**\n * TCP keep-alive is the only mechanism that detects a peer which has vanished\n * without sending FIN or RST - the half open socket described in issue #153. The\n * session level TestRequest timeout is the protocol level backstop; this is the\n * transport level one.\n */\n private applyKeepAlive (id: number, socket: Socket): void {\n const configured = this.config.description.application?.tcp?.keepAliveMs\n const keepAliveMs = configured ?? TcpAcceptor.defaultKeepAliveMs\n if (keepAliveMs <= 0) {\n this.logger.info(`transport ${id} keep-alive disabled`)\n return\n }\n socket.setKeepAlive(true, keepAliveMs)\n this.logger.info(`transport ${id} keep-alive enabled, initial delay ${keepAliveMs}ms`)\n }\n\n public static defaultKeepAliveMs: number = 30000\n\n public listen (): void {\n const port = this.config.description.application?.tcp?.port\n this.logger.info(`start to listen ${port}`)\n this.server.on('connection', () => {\n this.logger.info('insecure connection established')\n })\n this.server.on('secureConnection', (s) => {\n this.logger.info(`secure connection; client authorized: ${s.authorized}`)\n })\n this.server.listen(port)\n }\n\n public close (callback?: (err?: Error) => void): void {\n const port = this.config.description.application?.tcp?.port ?? -1\n this.logger.info(`close listener on port ${port} with ${this.transportCount} live transport(s)`)\n // Server.close only stops accepting - it waits for existing connections to go.\n // Release them, otherwise a shutdown blocks on whichever counterparty happens to\n // be connected (and forever on one that is half open).\n Object.keys(this.transports).forEach(id => {\n const tid = Number(id)\n this.logger.info(`close: releasing transport ${tid}`)\n this.transports[tid]?.end()\n })\n this.server.close(callback)\n }\n\n /** how many connections this listener currently holds */\n public get transportCount (): number {\n return Object.keys(this.transports).length\n }\n\n /** ids of the live transports, for a periodic census in the application log */\n public liveTransports (): string[] {\n return Object.keys(this.transports).map(id => {\n const meta = this.accepted[id as any]\n const age = meta ? Math.round((Date.now() - meta.at) / 1000) : -1\n return `${id}@${meta?.remote ?? '?'} up ${age}s`\n })\n }\n\n private readonly accepted: Record<number, { remote: string, at: number }> = {}\n\n private saveTransport (tid: number, transport: MsgTransport, remote: string): void {\n this.transports[tid] = transport\n this.accepted[tid] = { remote, at: Date.now() }\n this.logger.info(`new transport id = ${tid} from ${remote} created total transports = ${this.transportCount}`)\n this.emit('transport', transport)\n }\n\n private harvestTransport (tid: number, reason: string): void {\n if (!this.transports[tid]) return\n const meta = this.accepted[tid]\n const lifetime = meta ? Math.round((Date.now() - meta.at) / 1000) : -1\n delete this.transports[tid]\n delete this.accepted[tid]\n this.logger.info(`transport ${tid} from ${meta?.remote ?? '?'} harvested after ${lifetime}s ` +\n `(${reason}) total transports = ${this.transportCount}`)\n this.emit('harvested', tid, reason)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tcp-acceptor.js","sourceRoot":"","sources":["../../../src/transport/tcp/tcp-acceptor.ts"],"names":[],"mappings":"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","sourcesContent":["import { TcpDuplex } from '../duplex'\nimport { MsgTransport } from '../factory'\nimport { FixAcceptor } from '../fix-acceptor'\nimport { IJsFixConfig, IJsFixLogger } from '../../config'\nimport { createServer as netCreateServer, Server, Socket } from 'net'\nimport { createServer as tlsCreateServer, TlsOptions, TLSSocket } from 'tls'\nimport { TlsOptionsFactory } from './tls-options-factory'\nimport { describeNegotiated, describePeerCertificate, describeServerOptions } from './tls-diagnostics'\nimport { inject, injectable } from 'tsyringe'\nimport { DITokens } from '../../runtime/di-tokens'\nimport { makeSessionScope } from '../../runtime/session-scope'\n\n@injectable()\nexport class TcpAcceptor extends FixAcceptor {\n private server: Server\n private readonly logger: IJsFixLogger\n private nextId: number = 0\n\n constructor (@inject(DITokens.IJsFixConfig) public readonly config: IJsFixConfig) {\n super(config.description.application ?? null)\n this.logger = config.logFactory.logger(`${config.description.application?.name}:TcpAcceptor`,\n { component: 'TcpAcceptor', app: config.description.application?.name, role: 'acceptor' })\n const tlsOptions: TlsOptions | null = this.tlsOptions()\n if (tlsOptions) {\n this.tlsServer()\n } else {\n this.unsecureServer()\n }\n this.server.on('error', (err: Error) => {\n throw err\n })\n }\n\n getId (): number {\n this.nextId++\n return this.nextId\n }\n\n tlsServer (): void {\n try {\n const config: IJsFixConfig = this.config\n const tcp = this.config.description.application?.tcp\n const tlsOptions: TlsOptions | null = tcp?.tls ? TlsOptionsFactory.getTlsOptions(tcp.tls) : null\n this.logger.info('create tls server')\n if (!tlsOptions) return\n this.logger.info(`tls server options ${describeServerOptions(tlsOptions)}`)\n this.server = tlsCreateServer(tlsOptions, (tlsSocket: TLSSocket) => {\n if (tcp?.tls?.enableTrace) {\n this.logger.info('enabling tls session trace')\n tlsSocket.enableTrace()\n }\n this.logger.info(`tls negotiated ${describeNegotiated(tlsSocket)}`)\n this.logger.info(`tls peer certificate ${describePeerCertificate(tlsSocket)}`)\n // mirrors the initiator fix for #94 - an unauthorized peer is only fatal when the\n // caller has not explicitly opted out. the default stays secure: rejectUnauthorized\n // undefined means reject, exactly as before.\n if (!tlsSocket.authorized && tlsOptions.rejectUnauthorized !== false) {\n this.logger.warning(`no transport created, unauthorized tls connection: ${String(tlsSocket.authorizationError)}`)\n tlsSocket.end()\n return\n }\n if (!tlsSocket.authorized) {\n this.logger.warning(`accepting unauthorized tls peer (rejectUnauthorized: false): ${String(tlsSocket.authorizationError)}`)\n }\n tlsSocket.setEncoding('utf8')\n const id: number = this.getId()\n this.logger.info(`tls creates session ${id} authorized ${tlsSocket.authorized}`)\n this.onSocket(id, tlsSocket, config)\n })\n } catch (e) {\n this.logger.error(e as Error)\n throw e\n }\n }\n\n unsecureServer (): void {\n try {\n const config = this.config\n this.logger.info('create unsecured server')\n this.server = netCreateServer((socket: Socket) => {\n const id: number = this.getId()\n this.logger.info(`net creates session ${id}`)\n socket.setNoDelay(true)\n this.onSocket(id, socket, config)\n })\n } catch (e) {\n this.logger.error(e as Error)\n throw e\n }\n }\n\n tlsOptions (): TlsOptions | null {\n const tcp = this.config.description.application?.tcp\n return tcp?.tls ? TlsOptionsFactory.getTlsOptions(tcp?.tls) : null\n }\n\n private onSocket (id: number, socket: Socket, config: IJsFixConfig): void {\n // Every accepted connection gets its own DI scope: its own parse and transmit\n // buffers, its own session description (hence its own SessionId and message\n // store) and its own session message factory. Without this, concurrent clients\n // on one listener share buffers and collide on a single store.\n const sessionConfig = makeSessionScope(config)\n const remote = `${socket.remoteAddress ?? '?'}:${socket.remotePort ?? 0}`\n this.applyKeepAlive(id, socket)\n this.logger.info(`transport ${id} from ${remote} given its own session scope`)\n const transport: MsgTransport = new MsgTransport(id, sessionConfig, new TcpDuplex(socket))\n this.saveTransport(id, transport, remote)\n transport.receiver.on('end', () => {\n this.harvestTransport(id, 'peer ended the connection')\n })\n transport.receiver.on('error', (e: Error) => {\n this.logger.error(e)\n this.harvestTransport(id, `receiver error: ${e.message}`)\n })\n // 'end' only fires on a clean FIN. A socket dropped by a firewall, or one this\n // side destroyed after a failed graceful close, arrives here instead - without\n // it the transport would sit in the map forever.\n socket.on('close', (hadError: boolean) => {\n this.harvestTransport(id, hadError ? 'socket closed after error' : 'socket closed')\n })\n }\n\n /**\n * TCP keep-alive is the only mechanism that detects a peer which has vanished\n * without sending FIN or RST - the half open socket described in issue #153. The\n * session level TestRequest timeout is the protocol level backstop; this is the\n * transport level one.\n */\n private applyKeepAlive (id: number, socket: Socket): void {\n const configured = this.config.description.application?.tcp?.keepAliveMs\n const keepAliveMs = configured ?? TcpAcceptor.defaultKeepAliveMs\n if (keepAliveMs <= 0) {\n this.logger.info(`transport ${id} keep-alive disabled`)\n return\n }\n socket.setKeepAlive(true, keepAliveMs)\n this.logger.info(`transport ${id} keep-alive enabled, initial delay ${keepAliveMs}ms`)\n }\n\n public static defaultKeepAliveMs: number = 30000\n\n public listen (): void {\n const port = this.config.description.application?.tcp?.port\n this.logger.info(`start to listen ${port}`)\n this.server.on('connection', () => {\n this.logger.info('insecure connection established')\n })\n this.server.on('secureConnection', (s) => {\n this.logger.info(`secure connection; client authorized: ${s.authorized}`)\n })\n this.server.listen(port)\n }\n\n public close (callback?: (err?: Error) => void): void {\n const port = this.config.description.application?.tcp?.port ?? -1\n this.logger.info(`close listener on port ${port} with ${this.transportCount} live transport(s)`)\n // Server.close only stops accepting - it waits for existing connections to go.\n // Release them, otherwise a shutdown blocks on whichever counterparty happens to\n // be connected (and forever on one that is half open).\n Object.keys(this.transports).forEach(id => {\n const tid = Number(id)\n this.logger.info(`close: releasing transport ${tid}`)\n this.transports[tid]?.end()\n })\n this.server.close(callback)\n }\n\n /** how many connections this listener currently holds */\n public get transportCount (): number {\n return Object.keys(this.transports).length\n }\n\n /** ids of the live transports, for a periodic census in the application log */\n public liveTransports (): string[] {\n return Object.keys(this.transports).map(id => {\n const meta = this.accepted[id as any]\n const age = meta ? Math.round((Date.now() - meta.at) / 1000) : -1\n return `${id}@${meta?.remote ?? '?'} up ${age}s`\n })\n }\n\n private readonly accepted: Record<number, { remote: string, at: number }> = {}\n\n private saveTransport (tid: number, transport: MsgTransport, remote: string): void {\n this.transports[tid] = transport\n this.accepted[tid] = { remote, at: Date.now() }\n this.logger.info(`new transport id = ${tid} from ${remote} created total transports = ${this.transportCount}`)\n this.emit('transport', transport)\n }\n\n private harvestTransport (tid: number, reason: string): void {\n if (!this.transports[tid]) return\n const meta = this.accepted[tid]\n const lifetime = meta ? Math.round((Date.now() - meta.at) / 1000) : -1\n delete this.transports[tid]\n delete this.accepted[tid]\n this.logger.info(`transport ${tid} from ${meta?.remote ?? '?'} harvested after ${lifetime}s ` +\n `(${reason}) total transports = ${this.transportCount}`)\n this.emit('harvested', tid, reason)\n }\n}\n"]}
|
|
@@ -38,7 +38,7 @@ let TcpInitiatorConnector = TcpInitiatorConnector_1 = class TcpInitiatorConnecto
|
|
|
38
38
|
start() {
|
|
39
39
|
return __awaiter(this, arguments, void 0, function* (reconnectTimeout = 0) {
|
|
40
40
|
return yield new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
41
|
-
const logger = this.config.logFactory.logger('initiator');
|
|
41
|
+
const logger = this.config.logFactory.logger('initiator', { component: 'TcpInitiatorConnector', role: 'initiator' });
|
|
42
42
|
const sessionContainer = this.config.sessionContainer;
|
|
43
43
|
if (!sessionContainer.isRegistered(di_tokens_1.DITokens.FixSession)) {
|
|
44
44
|
reject(new Error(`application must register a DI token '${di_tokens_1.DITokens.FixSession}' - see src/sample`));
|
|
@@ -86,7 +86,7 @@ let TcpInitiatorConnector = TcpInitiatorConnector_1 = class TcpInitiatorConnecto
|
|
|
86
86
|
}
|
|
87
87
|
connect(initiatorSession) {
|
|
88
88
|
return __awaiter(this, void 0, void 0, function* () {
|
|
89
|
-
const logger = this.config.logFactory.logger('initiator');
|
|
89
|
+
const logger = this.config.logFactory.logger('initiator', { component: 'TcpInitiatorConnector', role: 'initiator' });
|
|
90
90
|
const initiator = this.config.sessionContainer.resolve(tcp_initiator_1.TcpInitiator);
|
|
91
91
|
logger.info('connecting ...');
|
|
92
92
|
const initiatorTransport = yield initiator.connect(this.connectTimeoutSecs);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tcp-initiator-connector.js","sourceRoot":"","sources":["../../../src/transport/tcp/tcp-initiator-connector.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAEA,mDAA8C;AAG9C,uCAA6C;AAC7C,uDAAkD;AAClD,8CAAyC;AAGlC,IAAM,qBAAqB,6BAA3B,MAAM,qBAAsB,SAAQ,sBAAS;IAKlD,YAA4C,MAAoC;;QAC9E,KAAK,CAAC,MAAM,CAAC,CAAA;QAD6C,WAAM,GAAN,MAAM,CAAc;QAFzE,uBAAkB,GAAW,uBAAqB,CAAC,yBAAyB,CAAA;QAIjF,IAAI,CAAC,kBAAkB,GAAG,MAAA,MAAA,MAAM,CAAC,WAAW,CAAC,WAAW,0CAAE,qBAAqB,mCAAI,IAAI,CAAC,kBAAkB,CAAA;IAC5G,CAAC;IAEK,KAAK;6DAAE,mBAA2B,CAAC;YAEvC,OAAO,MAAM,IAAI,OAAO,CAAM,CAAO,OAAO,EAAE,MAAM,EAAE,EAAE;gBACtD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"tcp-initiator-connector.js","sourceRoot":"","sources":["../../../src/transport/tcp/tcp-initiator-connector.ts"],"names":[],"mappings":"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","sourcesContent":["import { IJsFixConfig } from '../../config'\nimport { FixInitiator } from '../fix-initiator'\nimport { TcpInitiator } from './tcp-initiator'\nimport { MsgTransport } from '../factory'\nimport { FixSession } from '../session/fix-session'\nimport { inject, injectable } from 'tsyringe'\nimport { DITokens } from '../../runtime/di-tokens'\nimport { FixEntity } from '../fix-entity'\n\n@injectable()\nexport class TcpInitiatorConnector extends FixEntity {\n public static readonly DefaultConnectTimeoutSecs = 22\n\n public connectTimeoutSecs: number = TcpInitiatorConnector.DefaultConnectTimeoutSecs\n\n constructor (@inject(DITokens.IJsFixConfig) public readonly config: IJsFixConfig) {\n super(config)\n this.connectTimeoutSecs = config.description.application?.connectTimeoutSeconds ?? this.connectTimeoutSecs\n }\n\n async start (reconnectTimeout: number = 0): Promise<any> {\n\n return await new Promise<any>(async (resolve, reject) => {\n const logger = this.config.logFactory.logger('initiator',\n { component: 'TcpInitiatorConnector', role: 'initiator' })\n const sessionContainer = this.config.sessionContainer\n if (!sessionContainer.isRegistered(DITokens.FixSession)) {\n reject(new Error(`application must register a DI token '${DITokens.FixSession}' - see src/sample`))\n }\n logger.info(`create session with DI Token ${DITokens.FixSession}`)\n const initiatorSession = sessionContainer.resolve<FixSession>(DITokens.FixSession)\n let connecting: boolean = true\n while (connecting) {\n try {\n await this.connect(initiatorSession)\n logger.info('session has ended')\n connecting = false\n resolve(true)\n } catch (e) {\n if (!reconnectTimeout) {\n connecting = false\n reject(e)\n } else {\n logger.info(`waiting ${reconnectTimeout} to reconnect following error`)\n await this.delay(reconnectTimeout)\n }\n }\n }\n })\n }\n\n async delay (p: number): Promise<any> {\n return await new Promise<any>((resolve, reject) => {\n try {\n if (!p) {\n resolve(true)\n }\n setTimeout(() => {\n resolve(true)\n }, p)\n } catch (e) {\n reject(e)\n }\n })\n }\n\n async connect (initiatorSession: FixSession): Promise<any> {\n const logger = this.config.logFactory.logger('initiator',\n { component: 'TcpInitiatorConnector', role: 'initiator' })\n const initiator: FixInitiator = this.config.sessionContainer.resolve<FixInitiator>(TcpInitiator)\n logger.info('connecting ...')\n const initiatorTransport: MsgTransport = await initiator.connect(this.connectTimeoutSecs)\n logger.info('... connected, run session')\n await initiatorSession.run(initiatorTransport)\n logger.info('ends')\n return true\n }\n}\n"]}
|
|
@@ -29,6 +29,7 @@ const tls_1 = require("tls");
|
|
|
29
29
|
const net_1 = require("net");
|
|
30
30
|
const tls_options_factory_1 = require("./tls-options-factory");
|
|
31
31
|
const tls_diagnostics_1 = require("./tls-diagnostics");
|
|
32
|
+
const connect_error_1 = require("./connect-error");
|
|
32
33
|
const tsyringe_1 = require("tsyringe");
|
|
33
34
|
const di_tokens_1 = require("../../runtime/di-tokens");
|
|
34
35
|
var InitiatorState;
|
|
@@ -47,7 +48,7 @@ let TcpInitiator = class TcpInitiator extends fix_initiator_1.FixInitiator {
|
|
|
47
48
|
this.th = null;
|
|
48
49
|
this.timeoutTh = null;
|
|
49
50
|
const name = (_c = (_b = this.application) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : 'initiator';
|
|
50
|
-
this.logger = jsFixConfig.logFactory.logger(`${name}:TcpInitiator
|
|
51
|
+
this.logger = jsFixConfig.logFactory.logger(`${name}:TcpInitiator`, { component: 'TcpInitiator', app: name, role: 'initiator' });
|
|
51
52
|
if (!this.application) {
|
|
52
53
|
throw new Error('no application in session description.');
|
|
53
54
|
}
|
|
@@ -82,7 +83,7 @@ let TcpInitiator = class TcpInitiator extends fix_initiator_1.FixInitiator {
|
|
|
82
83
|
this.tryConnect()
|
|
83
84
|
.then((t) => { resolve(t); })
|
|
84
85
|
.catch((first) => {
|
|
85
|
-
this.logger.info(`first connect attempt failed: ${first
|
|
86
|
+
this.logger.info(`first connect attempt failed: ${(0, connect_error_1.describeConnectError)(first)}`);
|
|
86
87
|
this.repeatConnect(timeoutSeconds, first)
|
|
87
88
|
.then((t) => { resolve(t); })
|
|
88
89
|
.catch((e) => { reject(e); });
|
|
@@ -223,13 +224,13 @@ let TcpInitiator = class TcpInitiator extends fix_initiator_1.FixInitiator {
|
|
|
223
224
|
resolve(t);
|
|
224
225
|
}).catch((e) => {
|
|
225
226
|
lastError = e;
|
|
226
|
-
this.logger.info(`${name}: retries ${retries} ${e
|
|
227
|
+
this.logger.info(`${name}: retries ${retries} ${(0, connect_error_1.describeConnectError)(e)}`);
|
|
227
228
|
});
|
|
228
229
|
}, reconnectSeconds * 1000);
|
|
229
230
|
this.timeoutTh = setTimeout(() => {
|
|
230
231
|
this.clearTimer();
|
|
231
232
|
this.state = InitiatorState.Stopped;
|
|
232
|
-
const e = lastError !== null && lastError !== void 0 ? lastError : new Error(`${name}: timeout of ${timeoutSeconds} whilst connecting`);
|
|
233
|
+
const e = (0, connect_error_1.withConnectReason)(lastError !== null && lastError !== void 0 ? lastError : new Error(`${name}: timeout of ${timeoutSeconds} whilst connecting`));
|
|
233
234
|
this.logger.warning(`${name}: giving up after ${timeoutSeconds}s and ${retries} retries, last error: ${e.message}`);
|
|
234
235
|
reject(e);
|
|
235
236
|
}, timeoutSeconds * 1000);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tcp-initiator.js","sourceRoot":"","sources":["../../../src/transport/tcp/tcp-initiator.ts"],"names":[],"mappings":"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","sourcesContent":["import { FixInitiator } from '../fix-initiator'\nimport { MsgTransport } from '../factory'\n\nimport { IJsFixConfig, IJsFixLogger } from '../../config'\nimport { TcpDuplex, FixDuplex } from '../duplex'\n\nimport * as util from 'util'\nimport { connect as tlsConnect, ConnectionOptions, TLSSocket } from 'tls'\nimport { createConnection } from 'net'\nimport Timeout = NodeJS.Timeout\nimport { TlsOptionsFactory } from './tls-options-factory'\nimport { describeConnectionOptions, describeNegotiated, describePeerCertificate } from './tls-diagnostics'\nimport { inject, injectable } from 'tsyringe'\nimport { DITokens } from '../../runtime/di-tokens'\nimport { ITcpTransportDescription } from './tcp-transport-description'\n\nexport enum InitiatorState {\n Idle = 1,\n Connecting = 2,\n Connected = 3,\n Stopped = 4\n}\n\n@injectable()\nexport class TcpInitiator extends FixInitiator {\n public tcp: ITcpTransportDescription | null\n public state: InitiatorState = InitiatorState.Idle\n private readonly logger: IJsFixLogger\n private duplex: FixDuplex\n private th: Timeout | null = null\n private timeoutTh: Timeout | null = null\n\n constructor (@inject(DITokens.IJsFixConfig) public readonly jsFixConfig: IJsFixConfig) {\n super(jsFixConfig.description.application ?? null)\n const name = this.application?.name ?? 'initiator'\n this.logger = jsFixConfig.logFactory.logger(`${name}:TcpInitiator`)\n if (!this.application) {\n throw new Error('no application in session description.')\n }\n this.tcp = this.application.tcp ?? null\n if (!this.tcp) {\n throw new Error('no tcp in session description need tcp { host: hostname, port: port }')\n }\n }\n\n public end (): void {\n this.clearTimer()\n switch (this.state) {\n case InitiatorState.Connected: {\n this.logger.info('end')\n this.duplex.end()\n this.state = InitiatorState.Stopped\n break\n }\n\n default: {\n this.logger.info(`end :state ${this.state}`)\n this.state = InitiatorState.Stopped\n break\n }\n }\n }\n\n public async connect (timeoutSeconds: number): Promise<MsgTransport> {\n return await new Promise<MsgTransport>(async (resolve, reject) => {\n switch (this.state) {\n case InitiatorState.Idle: {\n this.state = InitiatorState.Connecting\n this.logger.info(`connecting with timeout ${timeoutSeconds}`)\n this.tryConnect()\n .then((t: MsgTransport) => { resolve(t) })\n .catch((first: Error) => {\n // carry the first failure into repeatConnect. it used to be discarded, so a\n // connect() whose timeout expires before the first retry interval fires - the\n // default case, timeout and reconnectSeconds are both 5 - reported a generic\n // \"timeout whilst connecting\" and threw away the reason. see #94.\n this.logger.info(`first connect attempt failed: ${first.message}`)\n this.repeatConnect(timeoutSeconds, first)\n .then((t: MsgTransport) => { resolve(t) })\n .catch((e: Error) => { reject(e) })\n })\n break\n }\n\n default: {\n const e: Error = new Error('connect not valid from non idle state')\n this.logger.warning(`rejecting from state ${this.state}`)\n reject(e)\n }\n }\n })\n }\n\n private async unsecureDuplex (): Promise<TcpDuplex> {\n const tcp = this.tcp\n return await new Promise<TcpDuplex>((resolve, reject) => {\n try {\n this.logger.info('unsecureDuplex try to connect to endPoint')\n const socket = tcp\n ? createConnection(tcp, () => {\n try {\n this.logger.info('net.createConnection cb, resolving')\n if (socket) {\n const tcpDuplex = new TcpDuplex(socket)\n resolve(tcpDuplex)\n } else {\n reject(new Error('no socket in tcp initiator'))\n }\n } catch (e) {\n reject(e)\n }\n })\n : null\n socket?.on('error', (err) => {\n reject(err)\n })\n } catch (e) {\n reject(e)\n }\n })\n }\n\n private async tlsDuplex (): Promise<TcpDuplex > {\n return await new Promise<TcpDuplex>((resolve, reject) => {\n let tlsSocket: TLSSocket | null = null\n const tcp = this.tcp\n const connectionOptions: ConnectionOptions | null = tcp ? TlsOptionsFactory.getTlsConnectionOptions(tcp) : null\n if (connectionOptions) {\n try {\n this.logger.info(`tls connect with ${describeConnectionOptions(connectionOptions)}`)\n tlsSocket = tlsConnect(connectionOptions, () => {\n if (!tlsSocket) return null\n this.logger.info(`client connected ${tlsSocket.authorized ? 'authorized' : 'unauthorized'}`)\n this.logger.info(`tls negotiated ${describeNegotiated(tlsSocket)}`)\n this.logger.info(`tls peer certificate ${describePeerCertificate(tlsSocket)}`)\n // https://github.com/TimelordUK/jspurefix/issues/94 - honour rejectUnauthorized:\n // false rather than always rejecting on an unauthorized cert. Node's tls.connect()\n // never throws for an unauthorized peer by itself; it's the caller's job to decide\n // what to do with tlsSocket.authorized, and rejectUnauthorized is how a caller opts\n // out of that check - so only reject here when the caller didn't opt out.\n if (!tlsSocket.authorized && connectionOptions.rejectUnauthorized !== false) {\n const error = tlsSocket.authorizationError\n this.logger.warning(`rejecting from state ${this.state} authorizationError ${error}`)\n tlsSocket.end()\n reject(error)\n } else {\n if (!tlsSocket.authorized) {\n this.logger.warning(`proceeding despite unauthorized TLS peer (rejectUnauthorized: false): ${tlsSocket.authorizationError}`)\n }\n tlsSocket.setEncoding('utf8')\n const tlsDuplex = new TcpDuplex(tlsSocket)\n if (tcp?.tls?.enableTrace) {\n this.logger.info('enabling tls session trace')\n tlsSocket.enableTrace()\n }\n this.logger.info('tlsDuplex resolving')\n resolve(tlsDuplex)\n }\n })\n tlsSocket.on('error', (err) => {\n // previously silent - the socket error is the real reason a tls session failed,\n // and without it the caller only ever sees repeatConnect's generic timeout.\n this.logger.warning(`tls socket error from state ${this.state}: ${err.message}`)\n reject(err)\n })\n } catch (e) {\n reject(e)\n }\n }\n })\n }\n\n private async tryConnect (): Promise < MsgTransport > {\n return await new Promise<MsgTransport>((resolve, reject) => {\n const tcp = this.tcp\n const connectionOptions: ConnectionOptions | null = tcp ? TlsOptionsFactory.getTlsConnectionOptions(tcp) : null\n const connector = connectionOptions ? this.tlsDuplex() : this.unsecureDuplex()\n this.logger.info(`tryConnect ${tcp?.host}:${tcp?.port}`)\n connector.then(duplex => {\n this.duplex = duplex\n resolve(new MsgTransport(0, this.jsFixConfig, duplex))\n }).catch(e => {\n reject(e)\n })\n })\n }\n\n public clearTimer (): void {\n if (this.th) {\n clearInterval(this.th)\n this.th = null\n }\n if (this.timeoutTh) {\n clearTimeout(this.timeoutTh)\n this.timeoutTh = null\n }\n }\n\n private async repeatConnect (timeoutSeconds: number, initialError?: Error): Promise < MsgTransport > {\n return await new Promise<MsgTransport>(async (resolve, reject) => {\n const application = this.application\n const reconnectSeconds = application?.reconnectSeconds ?? 5\n let retries = 0\n let lastError: Error | undefined = initialError\n const name = application?.name ?? 'initiator'\n this.th = setInterval(() => {\n ++retries\n this.tryConnect()\n .then((t: MsgTransport) => {\n this.state = InitiatorState.Connected\n this.clearTimer()\n resolve(t)\n }).catch((e: Error) => {\n lastError = e\n this.logger.info(`${name}: retries ${retries} ${e.message}`)\n })\n }, reconnectSeconds * 1000)\n // a plain timer, not a promisified one: promisify(setTimeout) hands back no\n // handle, so this deadline could never be cancelled. Connecting successfully\n // cleared the retry interval and left this one running to its full term - up to\n // the 60s an initiator allows - holding the event loop open long after the\n // session was up, and stopping a process (or a test runner) from exiting.\n this.timeoutTh = setTimeout(() => {\n this.clearTimer()\n this.state = InitiatorState.Stopped\n const e = lastError ?? new Error(`${name}: timeout of ${timeoutSeconds} whilst connecting`)\n this.logger.warning(`${name}: giving up after ${timeoutSeconds}s and ${retries} retries, last error: ${e.message}`)\n reject(e)\n }, timeoutSeconds * 1000)\n })\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tcp-initiator.js","sourceRoot":"","sources":["../../../src/transport/tcp/tcp-initiator.ts"],"names":[],"mappings":"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","sourcesContent":["import { FixInitiator } from '../fix-initiator'\nimport { MsgTransport } from '../factory'\n\nimport { IJsFixConfig, IJsFixLogger } from '../../config'\nimport { TcpDuplex, FixDuplex } from '../duplex'\n\nimport { connect as tlsConnect, ConnectionOptions, TLSSocket } from 'tls'\nimport { createConnection } from 'net'\nimport Timeout = NodeJS.Timeout\nimport { TlsOptionsFactory } from './tls-options-factory'\nimport { describeConnectionOptions, describeNegotiated, describePeerCertificate } from './tls-diagnostics'\nimport { describeConnectError, withConnectReason } from './connect-error'\nimport { inject, injectable } from 'tsyringe'\nimport { DITokens } from '../../runtime/di-tokens'\nimport { ITcpTransportDescription } from './tcp-transport-description'\n\nexport enum InitiatorState {\n Idle = 1,\n Connecting = 2,\n Connected = 3,\n Stopped = 4\n}\n\n@injectable()\nexport class TcpInitiator extends FixInitiator {\n public tcp: ITcpTransportDescription | null\n public state: InitiatorState = InitiatorState.Idle\n private readonly logger: IJsFixLogger\n private duplex: FixDuplex\n private th: Timeout | null = null\n private timeoutTh: Timeout | null = null\n\n constructor (@inject(DITokens.IJsFixConfig) public readonly jsFixConfig: IJsFixConfig) {\n super(jsFixConfig.description.application ?? null)\n const name = this.application?.name ?? 'initiator'\n this.logger = jsFixConfig.logFactory.logger(`${name}:TcpInitiator`,\n { component: 'TcpInitiator', app: name, role: 'initiator' })\n if (!this.application) {\n throw new Error('no application in session description.')\n }\n this.tcp = this.application.tcp ?? null\n if (!this.tcp) {\n throw new Error('no tcp in session description need tcp { host: hostname, port: port }')\n }\n }\n\n public end (): void {\n this.clearTimer()\n switch (this.state) {\n case InitiatorState.Connected: {\n this.logger.info('end')\n this.duplex.end()\n this.state = InitiatorState.Stopped\n break\n }\n\n default: {\n this.logger.info(`end :state ${this.state}`)\n this.state = InitiatorState.Stopped\n break\n }\n }\n }\n\n public async connect (timeoutSeconds: number): Promise<MsgTransport> {\n return await new Promise<MsgTransport>(async (resolve, reject) => {\n switch (this.state) {\n case InitiatorState.Idle: {\n this.state = InitiatorState.Connecting\n this.logger.info(`connecting with timeout ${timeoutSeconds}`)\n this.tryConnect()\n .then((t: MsgTransport) => { resolve(t) })\n .catch((first: Error) => {\n // carry the first failure into repeatConnect. it used to be discarded, so a\n // connect() whose timeout expires before the first retry interval fires - the\n // default case, timeout and reconnectSeconds are both 5 - reported a generic\n // \"timeout whilst connecting\" and threw away the reason. see #94.\n this.logger.info(`first connect attempt failed: ${describeConnectError(first)}`)\n this.repeatConnect(timeoutSeconds, first)\n .then((t: MsgTransport) => { resolve(t) })\n .catch((e: Error) => { reject(e) })\n })\n break\n }\n\n default: {\n const e: Error = new Error('connect not valid from non idle state')\n this.logger.warning(`rejecting from state ${this.state}`)\n reject(e)\n }\n }\n })\n }\n\n private async unsecureDuplex (): Promise<TcpDuplex> {\n const tcp = this.tcp\n return await new Promise<TcpDuplex>((resolve, reject) => {\n try {\n this.logger.info('unsecureDuplex try to connect to endPoint')\n const socket = tcp\n ? createConnection(tcp, () => {\n try {\n this.logger.info('net.createConnection cb, resolving')\n if (socket) {\n const tcpDuplex = new TcpDuplex(socket)\n resolve(tcpDuplex)\n } else {\n reject(new Error('no socket in tcp initiator'))\n }\n } catch (e) {\n reject(e)\n }\n })\n : null\n socket?.on('error', (err) => {\n reject(err)\n })\n } catch (e) {\n reject(e)\n }\n })\n }\n\n private async tlsDuplex (): Promise<TcpDuplex > {\n return await new Promise<TcpDuplex>((resolve, reject) => {\n let tlsSocket: TLSSocket | null = null\n const tcp = this.tcp\n const connectionOptions: ConnectionOptions | null = tcp ? TlsOptionsFactory.getTlsConnectionOptions(tcp) : null\n if (connectionOptions) {\n try {\n this.logger.info(`tls connect with ${describeConnectionOptions(connectionOptions)}`)\n tlsSocket = tlsConnect(connectionOptions, () => {\n if (!tlsSocket) return null\n this.logger.info(`client connected ${tlsSocket.authorized ? 'authorized' : 'unauthorized'}`)\n this.logger.info(`tls negotiated ${describeNegotiated(tlsSocket)}`)\n this.logger.info(`tls peer certificate ${describePeerCertificate(tlsSocket)}`)\n // https://github.com/TimelordUK/jspurefix/issues/94 - honour rejectUnauthorized:\n // false rather than always rejecting on an unauthorized cert. Node's tls.connect()\n // never throws for an unauthorized peer by itself; it's the caller's job to decide\n // what to do with tlsSocket.authorized, and rejectUnauthorized is how a caller opts\n // out of that check - so only reject here when the caller didn't opt out.\n if (!tlsSocket.authorized && connectionOptions.rejectUnauthorized !== false) {\n const error = tlsSocket.authorizationError\n this.logger.warning(`rejecting from state ${this.state} authorizationError ${error}`)\n tlsSocket.end()\n reject(error)\n } else {\n if (!tlsSocket.authorized) {\n this.logger.warning(`proceeding despite unauthorized TLS peer (rejectUnauthorized: false): ${tlsSocket.authorizationError}`)\n }\n tlsSocket.setEncoding('utf8')\n const tlsDuplex = new TcpDuplex(tlsSocket)\n if (tcp?.tls?.enableTrace) {\n this.logger.info('enabling tls session trace')\n tlsSocket.enableTrace()\n }\n this.logger.info('tlsDuplex resolving')\n resolve(tlsDuplex)\n }\n })\n tlsSocket.on('error', (err) => {\n // previously silent - the socket error is the real reason a tls session failed,\n // and without it the caller only ever sees repeatConnect's generic timeout.\n this.logger.warning(`tls socket error from state ${this.state}: ${err.message}`)\n reject(err)\n })\n } catch (e) {\n reject(e)\n }\n }\n })\n }\n\n private async tryConnect (): Promise < MsgTransport > {\n return await new Promise<MsgTransport>((resolve, reject) => {\n const tcp = this.tcp\n const connectionOptions: ConnectionOptions | null = tcp ? TlsOptionsFactory.getTlsConnectionOptions(tcp) : null\n const connector = connectionOptions ? this.tlsDuplex() : this.unsecureDuplex()\n this.logger.info(`tryConnect ${tcp?.host}:${tcp?.port}`)\n connector.then(duplex => {\n this.duplex = duplex\n resolve(new MsgTransport(0, this.jsFixConfig, duplex))\n }).catch(e => {\n reject(e)\n })\n })\n }\n\n public clearTimer (): void {\n if (this.th) {\n clearInterval(this.th)\n this.th = null\n }\n if (this.timeoutTh) {\n clearTimeout(this.timeoutTh)\n this.timeoutTh = null\n }\n }\n\n private async repeatConnect (timeoutSeconds: number, initialError?: Error): Promise < MsgTransport > {\n return await new Promise<MsgTransport>(async (resolve, reject) => {\n const application = this.application\n const reconnectSeconds = application?.reconnectSeconds ?? 5\n let retries = 0\n let lastError: Error | undefined = initialError\n const name = application?.name ?? 'initiator'\n this.th = setInterval(() => {\n ++retries\n this.tryConnect()\n .then((t: MsgTransport) => {\n this.state = InitiatorState.Connected\n this.clearTimer()\n resolve(t)\n }).catch((e: Error) => {\n lastError = e\n this.logger.info(`${name}: retries ${retries} ${describeConnectError(e)}`)\n })\n }, reconnectSeconds * 1000)\n // a plain timer, not a promisified one: promisify(setTimeout) hands back no\n // handle, so this deadline could never be cancelled. Connecting successfully\n // cleared the retry interval and left this one running to its full term - up to\n // the 60s an initiator allows - holding the event loop open long after the\n // session was up, and stopping a process (or a test runner) from exiting.\n this.timeoutTh = setTimeout(() => {\n this.clearTimer()\n this.state = InitiatorState.Stopped\n // this error is what the application catches from run() - so give it a message\n // it can print. An AggregateError arrives with none at all, which meant a\n // caller handling a failed connect had nothing to report but an empty string.\n const e = withConnectReason(lastError ?? new Error(`${name}: timeout of ${timeoutSeconds} whilst connecting`))\n this.logger.warning(`${name}: giving up after ${timeoutSeconds}s and ${retries} retries, last error: ${e.message}`)\n reject(e)\n }, timeoutSeconds * 1000)\n })\n }\n}\n"]}
|