jspurefix 5.9.2 → 5.10.0

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.
Files changed (54) hide show
  1. package/README.md +35 -0
  2. package/dist/buffer/ascii/ascii-encoder.d.ts +1 -0
  3. package/dist/buffer/ascii/ascii-encoder.js +15 -0
  4. package/dist/buffer/ascii/ascii-encoder.js.map +1 -1
  5. package/dist/buffer/msg-encoder.d.ts +2 -0
  6. package/dist/buffer/msg-encoder.js +1 -0
  7. package/dist/buffer/msg-encoder.js.map +1 -1
  8. package/dist/runtime/session-container.d.ts +3 -0
  9. package/dist/runtime/session-container.js +8 -0
  10. package/dist/runtime/session-container.js.map +1 -1
  11. package/dist/runtime/session-launcher.d.ts +2 -1
  12. package/dist/runtime/session-launcher.js +4 -1
  13. package/dist/runtime/session-launcher.js.map +1 -1
  14. package/dist/transport/ascii/ascii-msg-transmitter.d.ts +1 -0
  15. package/dist/transport/ascii/ascii-msg-transmitter.js +15 -0
  16. package/dist/transport/ascii/ascii-msg-transmitter.js.map +1 -1
  17. package/dist/transport/ascii/ascii-session-msg-factory.js +1 -7
  18. package/dist/transport/ascii/ascii-session-msg-factory.js.map +1 -1
  19. package/dist/transport/fixml/fixml-session-msg-factory.js +1 -6
  20. package/dist/transport/fixml/fixml-session-msg-factory.js.map +1 -1
  21. package/dist/transport/index.d.ts +3 -0
  22. package/dist/transport/index.js +3 -0
  23. package/dist/transport/index.js.map +1 -1
  24. package/dist/transport/msg-payload.d.ts +3 -1
  25. package/dist/transport/msg-payload.js +2 -1
  26. package/dist/transport/msg-payload.js.map +1 -1
  27. package/dist/transport/msg-transmitter.d.ts +4 -1
  28. package/dist/transport/msg-transmitter.js +18 -2
  29. package/dist/transport/msg-transmitter.js.map +1 -1
  30. package/dist/transport/send-callback.d.ts +7 -0
  31. package/dist/transport/send-callback.js +3 -0
  32. package/dist/transport/send-callback.js.map +1 -0
  33. package/dist/transport/session/fix-session.d.ts +2 -1
  34. package/dist/transport/session/fix-session.js +12 -3
  35. package/dist/transport/session/fix-session.js.map +1 -1
  36. package/dist/transport/session/session-description.d.ts +2 -0
  37. package/dist/transport/session/session-description.js.map +1 -1
  38. package/docs/custom-logon.md +225 -0
  39. package/jsfix.test_client.txt +62 -62
  40. package/jsfix.test_server.txt +72 -72
  41. package/package.json +1 -1
  42. package/src/buffer/ascii/ascii-encoder.ts +20 -0
  43. package/src/buffer/msg-encoder.ts +12 -0
  44. package/src/runtime/session-container.ts +20 -0
  45. package/src/runtime/session-launcher.ts +19 -2
  46. package/src/transport/ascii/ascii-msg-transmitter.ts +20 -0
  47. package/src/transport/ascii/ascii-session-msg-factory.ts +6 -1
  48. package/src/transport/fixml/fixml-session-msg-factory.ts +3 -1
  49. package/src/transport/index.ts +5 -0
  50. package/src/transport/msg-payload.ts +5 -1
  51. package/src/transport/msg-transmitter.ts +31 -2
  52. package/src/transport/send-callback.ts +33 -0
  53. package/src/transport/session/fix-session.ts +22 -3
  54. package/src/transport/session/session-description.ts +14 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwB;AACxB,+CAA4B;AAC5B,iDAA8B;AAC9B,kDAA+B;AAC/B,oDAAiC;AACjC,gDAA6B;AAC7B,gDAA6B;AAC7B,oDAAiC;AACjC,wDAAqC;AACrC,4CAAyB","sourcesContent":["export * from './duplex'\nexport * from './fix-entity'\nexport * from './fix-acceptor'\nexport * from './fix-initiator'\nexport * from './msg-transmitter'\nexport * from './msg-payload'\nexport * from './tick-action'\nexport * from './msg-application'\nexport * from './ascii/ascii-session'\nexport * from './session'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwB;AACxB,+CAA4B;AAC5B,iDAA8B;AAC9B,kDAA+B;AAC/B,oDAAiC;AACjC,gDAA6B;AAC7B,kDAA+B;AAC/B,gDAA6B;AAC7B,oDAAiC;AACjC,wDAAqC;AAGrC,oEAAiD;AACjD,oEAAiD;AACjD,4CAAyB","sourcesContent":["export * from './duplex'\nexport * from './fix-entity'\nexport * from './fix-acceptor'\nexport * from './fix-initiator'\nexport * from './msg-transmitter'\nexport * from './msg-payload'\nexport * from './send-callback'\nexport * from './tick-action'\nexport * from './msg-application'\nexport * from './ascii/ascii-session'\n// the factory an application extends to customise its Logon or header - it belongs\n// at the root alongside ASessionMsgFactory, not behind a dist/ path\nexport * from './ascii/ascii-session-msg-factory'\nexport * from './fixml/fixml-session-msg-factory'\nexport * from './session'\n"]}
@@ -1,7 +1,9 @@
1
1
  import { ILooseObject } from '../collections/collection';
2
+ import { SendCallback } from './send-callback';
2
3
  export declare class MsgPayload {
3
4
  readonly msgType: string;
4
5
  readonly obj: ILooseObject;
6
+ readonly callback: SendCallback | null;
5
7
  encoded: Buffer;
6
- constructor(msgType: string, obj: ILooseObject);
8
+ constructor(msgType: string, obj: ILooseObject, callback?: SendCallback | null);
7
9
  }
@@ -2,9 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MsgPayload = void 0;
4
4
  class MsgPayload {
5
- constructor(msgType, obj) {
5
+ constructor(msgType, obj, callback = null) {
6
6
  this.msgType = msgType;
7
7
  this.obj = obj;
8
+ this.callback = callback;
8
9
  }
9
10
  }
10
11
  exports.MsgPayload = MsgPayload;
@@ -1 +1 @@
1
- {"version":3,"file":"msg-payload.js","sourceRoot":"","sources":["../../src/transport/msg-payload.ts"],"names":[],"mappings":";;;AAEA,MAAa,UAAU;IAErB,YAA6B,OAAe,EAAkB,GAAiB;QAAlD,YAAO,GAAP,OAAO,CAAQ;QAAkB,QAAG,GAAH,GAAG,CAAc;IAC/E,CAAC;CACF;AAJD,gCAIC","sourcesContent":["import { ILooseObject } from '../collections/collection'\n\nexport class MsgPayload {\n public encoded: Buffer\n constructor (public readonly msgType: string, public readonly obj: ILooseObject) {\n }\n}\n"]}
1
+ {"version":3,"file":"msg-payload.js","sourceRoot":"","sources":["../../src/transport/msg-payload.ts"],"names":[],"mappings":";;;AAGA,MAAa,UAAU;IAErB,YAA6B,OAAe,EAC1B,GAAiB,EAEjB,WAAgC,IAAI;QAHzB,YAAO,GAAP,OAAO,CAAQ;QAC1B,QAAG,GAAH,GAAG,CAAc;QAEjB,aAAQ,GAAR,QAAQ,CAA4B;IACtD,CAAC;CACF;AAPD,gCAOC","sourcesContent":["import { ILooseObject } from '../collections/collection'\nimport { SendCallback } from './send-callback'\n\nexport class MsgPayload {\n public encoded: Buffer\n constructor (public readonly msgType: string,\n public readonly obj: ILooseObject,\n /** invoked once this payload has been encoded, or has failed to encode */\n public readonly callback: SendCallback | null = null) {\n }\n}\n"]}
@@ -1,8 +1,10 @@
1
1
  import { MsgEncoder, ElasticBuffer } from '../buffer';
2
2
  import { FixDefinitions } from '../dictionary/definition';
3
3
  import { Transform } from 'stream';
4
+ import { MsgPayload } from './msg-payload';
4
5
  import { ILooseObject } from '../collections/collection';
5
6
  import { ISessionDescription } from './session/session-description';
7
+ import { SendCallback } from './send-callback';
6
8
  import * as events from 'events';
7
9
  export declare abstract class MsgTransmitter extends events.EventEmitter {
8
10
  readonly buffer: ElasticBuffer;
@@ -11,7 +13,8 @@ export declare abstract class MsgTransmitter extends events.EventEmitter {
11
13
  readonly encodeStream: Transform;
12
14
  encoder: MsgEncoder;
13
15
  protected constructor(buffer: ElasticBuffer, definitions: FixDefinitions, session: ISessionDescription);
14
- send(msgType: string, obj: ILooseObject): void;
16
+ send(msgType: string, obj: ILooseObject, callback?: SendCallback | null): void;
17
+ protected settle(payload: MsgPayload, error: Error | null, header: ILooseObject | null): void;
15
18
  abstract encodeMessage(msgType: string, obj: ILooseObject): (ILooseObject | null);
16
19
  private encoderStream;
17
20
  }
@@ -51,8 +51,20 @@ class MsgTransmitter extends events.EventEmitter {
51
51
  this.emit('done');
52
52
  });
53
53
  }
54
- send(msgType, obj) {
55
- this.encodeStream.write(new msg_payload_1.MsgPayload(msgType, obj));
54
+ send(msgType, obj, callback = null) {
55
+ this.encodeStream.write(new msg_payload_1.MsgPayload(msgType, obj, callback));
56
+ }
57
+ settle(payload, error, header) {
58
+ var _a;
59
+ const callback = payload.callback;
60
+ if (!callback)
61
+ return;
62
+ try {
63
+ callback(error, { msgType: payload.msgType, header, encoded: (_a = payload.encoded) !== null && _a !== void 0 ? _a : null });
64
+ }
65
+ catch (e) {
66
+ this.emit('error', e);
67
+ }
56
68
  }
57
69
  encoderStream() {
58
70
  const transmitter = this;
@@ -67,9 +79,13 @@ class MsgTransmitter extends events.EventEmitter {
67
79
  this.push(payload.encoded);
68
80
  const encodedTxt = transmitter.buffer.toString();
69
81
  transmitter.emit('encoded', msgType, encodedTxt, state);
82
+ state
83
+ ? transmitter.settle(payload, null, state)
84
+ : transmitter.settle(payload, new Error(`could not encode ${msgType}`), null);
70
85
  done();
71
86
  }
72
87
  catch (e) {
88
+ transmitter.settle(payload, e, null);
73
89
  done(e);
74
90
  }
75
91
  }
@@ -1 +1 @@
1
- {"version":3,"file":"msg-transmitter.js","sourceRoot":"","sources":["../../src/transport/msg-transmitter.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,mCAAkC;AAClC,+CAA0C;AAG1C,+CAAgC;AAEhC,MAAsB,cAAe,SAAQ,MAAM,CAAC,YAAY;IAI9D,YAAuC,MAAqB,EAC1C,WAA2B,EAC3B,OAA4B;QAC5C,KAAK,EAAE,CAAA;QAH8B,WAAM,GAAN,MAAM,CAAe;QAC1C,gBAAW,GAAX,WAAW,CAAgB;QAC3B,YAAO,GAAP,OAAO,CAAqB;QAE5C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,aAAa,EAAE,CAAA;QACxC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAQ,EAAE,EAAE;YACzC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QACvB,CAAC,CAAC,CAAA;QACF,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;YAChC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACnB,CAAC,CAAC,CAAA;IACJ,CAAC;IAGM,IAAI,CAAE,OAAe,EAAE,GAAiB;QAC7C,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,wBAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAA;IACvD,CAAC;IAOO,aAAa;QACnB,MAAM,WAAW,GAAG,IAAI,CAAA;QACxB,OAAO,IAAI,kBAAS,CAAC;YACnB,kBAAkB,EAAE,IAAI;YACxB,SAAS,CAAE,OAAmB,EAAE,QAAQ,EAAE,IAAc;gBACtD,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAA;oBAC/B,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;oBAC3B,MAAM,KAAK,GAAG,WAAW,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;oBAC7D,OAAO,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;oBAC5C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;oBAC1B,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAA;oBAChD,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,CAAC,CAAA;oBACvD,IAAI,EAAE,CAAA;gBACR,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,IAAI,CAAC,CAAC,CAAC,CAAA;gBACT,CAAC;YACH,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;CACF;AA/CD,wCA+CC","sourcesContent":["import { MsgEncoder, ElasticBuffer } from '../buffer'\nimport { FixDefinitions } from '../dictionary/definition'\nimport { Transform } from 'stream'\nimport { MsgPayload } from './msg-payload'\nimport { ILooseObject } from '../collections/collection'\nimport { ISessionDescription } from './session/session-description'\nimport * as events from 'events'\n\nexport abstract class MsgTransmitter extends events.EventEmitter {\n public readonly encodeStream: Transform\n public encoder: MsgEncoder\n\n protected constructor (public readonly buffer: ElasticBuffer,\n public readonly definitions: FixDefinitions,\n public readonly session: ISessionDescription) {\n super()\n this.encodeStream = this.encoderStream()\n this.encodeStream.on('error', (e: Error) => {\n this.emit('error', e)\n })\n this.encodeStream.on('done', () => {\n this.emit('done')\n })\n }\n\n // messages at front, byte stream at back\n public send (msgType: string, obj: ILooseObject): void {\n this.encodeStream.write(new MsgPayload(msgType, obj))\n }\n\n public abstract encodeMessage (msgType: string, obj: ILooseObject): (ILooseObject | null)\n\n // read fix messages from one side, encode buffers on other ready to pipe\n // to output stream, say a socket\n\n private encoderStream (): Transform {\n const transmitter = this\n return new Transform({\n writableObjectMode: true,\n transform (payload: MsgPayload, encoding, done: Function) {\n try {\n const msgType = payload.msgType\n transmitter.encoder.reset()\n const state = transmitter.encodeMessage(msgType, payload.obj)\n payload.encoded = transmitter.encoder.trim()\n this.push(payload.encoded)\n const encodedTxt = transmitter.buffer.toString()\n transmitter.emit('encoded', msgType, encodedTxt, state)\n done()\n } catch (e) {\n done(e)\n }\n }\n })\n }\n}\n"]}
1
+ {"version":3,"file":"msg-transmitter.js","sourceRoot":"","sources":["../../src/transport/msg-transmitter.ts"],"names":[],"mappings":"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","sourcesContent":["import { MsgEncoder, ElasticBuffer } from '../buffer'\nimport { FixDefinitions } from '../dictionary/definition'\nimport { Transform } from 'stream'\nimport { MsgPayload } from './msg-payload'\nimport { ILooseObject } from '../collections/collection'\nimport { ISessionDescription } from './session/session-description'\nimport { SendCallback } from './send-callback'\nimport * as events from 'events'\n\nexport abstract class MsgTransmitter extends events.EventEmitter {\n public readonly encodeStream: Transform\n public encoder: MsgEncoder\n\n protected constructor (public readonly buffer: ElasticBuffer,\n public readonly definitions: FixDefinitions,\n public readonly session: ISessionDescription) {\n super()\n this.encodeStream = this.encoderStream()\n this.encodeStream.on('error', (e: Error) => {\n this.emit('error', e)\n })\n this.encodeStream.on('done', () => {\n this.emit('done')\n })\n }\n\n // messages at front, byte stream at back\n public send (msgType: string, obj: ILooseObject, callback: SendCallback | null = null): void {\n this.encodeStream.write(new MsgPayload(msgType, obj, callback))\n }\n\n /**\n * Report a send outcome to whoever asked for one, without letting their code break\n * the encode stream - a throwing callback would otherwise surface as a transform\n * failure and be indistinguishable from an encoding fault.\n */\n protected settle (payload: MsgPayload, error: Error | null, header: ILooseObject | null): void {\n const callback = payload.callback\n if (!callback) return\n try {\n callback(error, { msgType: payload.msgType, header, encoded: payload.encoded ?? null })\n } catch (e) {\n this.emit('error', e)\n }\n }\n\n public abstract encodeMessage (msgType: string, obj: ILooseObject): (ILooseObject | null)\n\n // read fix messages from one side, encode buffers on other ready to pipe\n // to output stream, say a socket\n\n private encoderStream (): Transform {\n const transmitter = this\n return new Transform({\n writableObjectMode: true,\n transform (payload: MsgPayload, encoding, done: Function) {\n try {\n const msgType = payload.msgType\n transmitter.encoder.reset()\n const state = transmitter.encodeMessage(msgType, payload.obj)\n payload.encoded = transmitter.encoder.trim()\n this.push(payload.encoded)\n const encodedTxt = transmitter.buffer.toString()\n transmitter.emit('encoded', msgType, encodedTxt, state)\n // encodeMessage returns null when it could not build the message - an\n // unknown msgType, or a factory that produced no header. It reports that\n // on the error channel and carries on, so without this the callback would\n // announce success for a message that never formed.\n state\n ? transmitter.settle(payload, null, state)\n : transmitter.settle(payload, new Error(`could not encode ${msgType}`), null)\n // note: the second argument to a Transform callback is *pushed to the\n // readable side*, and this readable side is piped to the socket - so a\n // result cannot be returned that way without corrupting the byte stream.\n // Hence the per-payload callback above.\n done()\n } catch (e) {\n transmitter.settle(payload, e as Error, null)\n // still fail the stream, so the session's error handling is unchanged\n done(e)\n }\n }\n })\n }\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import { ILooseObject } from '../collections/collection';
2
+ export interface SendResult {
3
+ msgType: string;
4
+ header: ILooseObject | null;
5
+ encoded: Buffer | null;
6
+ }
7
+ export type SendCallback = (error: Error | null, result: SendResult) => void;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=send-callback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-callback.js","sourceRoot":"","sources":["../../src/transport/send-callback.ts"],"names":[],"mappings":"","sourcesContent":["import { ILooseObject } from '../collections/collection'\n\n/**\n * What a send produced. `header` is the StandardHeader the engine stamped on the\n * message - the sequence number it went out under, the sending time, the comp ids -\n * which is the piece applications most often need to correlate an outbound message\n * with an acknowledgement, a database row, or a resend.\n */\nexport interface SendResult {\n msgType: string\n /** the stamped StandardHeader, or null if the message never got that far */\n header: ILooseObject | null\n /** the bytes written to the transport */\n encoded: Buffer | null\n}\n\n/**\n * Called once per `send`, after the message has been encoded and pushed to the\n * transport, or as soon as encoding fails.\n *\n * `send` is otherwise fire and forget: it writes into a stream and returns, so\n * nothing tells the caller which sequence number their message went out under, and a\n * failure surfaces on the session's error channel with no way to tell which call\n * caused it. See https://github.com/TimelordUK/jspurefix/issues/86\n *\n * Note this fires when the message has been *encoded and handed to the transport*,\n * not when the socket has flushed it - the FIX session layer has no acknowledgement\n * of the latter either.\n *\n * A callback that throws is reported on the transmitter's error channel rather than\n * being allowed to tear down the encode stream.\n */\nexport type SendCallback = (error: Error | null, result: SendResult) => void\n"]}
@@ -3,6 +3,7 @@ import { IJsFixConfig, IJsFixLogger } from '../../config';
3
3
  import { FixSessionState } from './fix-session-state';
4
4
  import { MsgTransport } from '../factory';
5
5
  import { ILooseObject } from '../../collections/collection';
6
+ import { SendCallback } from '../send-callback';
6
7
  import * as events from 'events';
7
8
  import { SessionState } from './session-state';
8
9
  export declare abstract class FixSession extends events.EventEmitter {
@@ -48,7 +49,7 @@ export declare abstract class FixSession extends events.EventEmitter {
48
49
  private stopTimer;
49
50
  protected terminate(error: Error): void;
50
51
  protected peerLogout(view: MsgView): void;
51
- protected send(msgType: string, obj: ILooseObject): void;
52
+ protected send(msgType: string, obj: ILooseObject, callback?: SendCallback | null): void;
52
53
  protected sendLogout(msg: string): void;
53
54
  protected sessionLogout(): void;
54
55
  done(): void;
@@ -379,17 +379,26 @@ class FixSession extends events.EventEmitter {
379
379
  }
380
380
  }
381
381
  }
382
- send(msgType, obj) {
382
+ send(msgType, obj, callback = null) {
383
383
  var _a;
384
384
  const state = this.sessionState.state;
385
385
  switch (state) {
386
386
  case session_state_1.SessionState.Stopped: {
387
- this.sessionLogger.warning(`can't send in state ${this.stateString()}`);
387
+ const msg = `can't send in state ${this.stateString()}`;
388
+ this.sessionLogger.warning(msg);
389
+ callback === null || callback === void 0 ? void 0 : callback(new Error(msg), { msgType, header: null, encoded: null });
388
390
  break;
389
391
  }
390
392
  default: {
391
393
  this.sessionState.LastSentAt = new Date();
392
- (_a = this.transport) === null || _a === void 0 ? void 0 : _a.transmitter.send(msgType, obj);
394
+ const transmitter = (_a = this.transport) === null || _a === void 0 ? void 0 : _a.transmitter;
395
+ if (!transmitter) {
396
+ const msg = `no transport to send ${msgType} on`;
397
+ this.sessionLogger.warning(msg);
398
+ callback === null || callback === void 0 ? void 0 : callback(new Error(msg), { msgType, header: null, encoded: null });
399
+ break;
400
+ }
401
+ transmitter.send(msgType, obj, callback);
393
402
  break;
394
403
  }
395
404
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fix-session.js","sourceRoot":"","sources":["../../../src/transport/session/fix-session.ts"],"names":[],"mappings":"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","sourcesContent":["import { ElasticBuffer, MsgView } from '../../buffer'\nimport { IJsFixConfig, IJsFixLogger } from '../../config'\nimport { FixSessionState } from './fix-session-state'\nimport { MsgTransport } from '../factory'\nimport { MsgTag } from '../../types'\nimport { ILooseObject } from '../../collections/collection'\n\nimport * as events from 'events'\nimport { SessionState } from './session-state'\nimport { SegmentType } from '../../buffer/segment/segment-type'\n\n/**\n * The set of listeners this session attached to one specific transport.\n *\n * The handlers must be kept as stable references - `EventEmitter.removeListener`\n * matches on identity, so subscribing with a fresh closure and unsubscribing with\n * a method reference silently leaves the listener attached (issue #153). Holding\n * the transport alongside the handlers also lets `unsubscribe` detach from the\n * transport it actually subscribed to, even when `this.transport` has already\n * moved on to a newer connection.\n */\ninterface ITransportSubscription {\n readonly transport: MsgTransport\n readonly rxOnMsg: (msgType: string, view: MsgView) => void\n readonly rxOnError: (e: Error) => void\n readonly rxOnDone: () => void\n readonly rxOnEnd: () => void\n readonly rxOnDecoded: (msgType: string, data: ElasticBuffer, ptr: number) => void\n readonly txOnError: (e: Error) => void\n readonly txOnEncoded: (msgType: string, data: string, hdr: ILooseObject) => void\n}\n\nexport abstract class FixSession extends events.EventEmitter {\n public logReceivedMsgs: boolean = false\n protected timer: NodeJS.Timeout | null = null\n protected transport: MsgTransport | null = null\n private subscription: ITransportSubscription | null = null\n public manageSession: boolean = true\n public checkMsgIntegrity: boolean = false\n protected readonly me: string\n protected readonly initiator: boolean\n protected readonly acceptor: boolean\n protected readonly sessionState: FixSessionState\n /**\n * Not readonly: a wildcard acceptor does not know which counterparty it is\n * serving until the Logon arrives, and every session on that listener would\n * otherwise log under the same name. Rebound once the identity is known.\n */\n protected sessionLogger: IJsFixLogger\n protected requestLogoutType: string\n protected respondLogoutType: string\n protected requestLogonType: string\n\n protected constructor (public readonly config: IJsFixConfig) {\n super()\n const description = config.description\n this.me = description?.application?.name ?? 'me'\n this.sessionState = new FixSessionState(\n {\n heartBeat: config.description.HeartBtInt,\n lastPeerMsgSeqNum: config.description.LastReceivedSeqNum\n })\n this.sessionLogger = config.logFactory.logger(`${this.me}:FixSession`)\n this.initiator = description?.application?.type === 'initiator'\n this.acceptor = !this.initiator\n this.checkMsgIntegrity = this.acceptor\n this.sessionState.compId = description.SenderCompId\n }\n\n stateStr (theState: SessionState): string {\n return SessionState[theState]\n }\n\n assignState (newState: SessionState): void {\n const currentState = this.sessionState.state\n const currentStateStr = this.stateStr(currentState)\n const logger = this.sessionLogger\n const msg = `current state ${currentStateStr} (${currentState}) moves to ${SessionState[newState]} (${newState})`\n logger.info(msg)\n this.sessionState.state = newState\n }\n\n public setState (state: SessionState): void {\n const logger = this.sessionLogger\n const currentState = this.sessionState.state\n const currentStateStr = this.stateStr(currentState)\n if (state === currentState) return\n switch (currentState) {\n case SessionState.ConfirmingLogout:\n case SessionState.Stopped:\n if (state !== SessionState.NetworkConnectionEstablished) {\n logger.info(`ignoring request to change state as now already in ${currentStateStr}`)\n } else {\n this.assignState(state)\n }\n break\n\n default: {\n this.assignState(state)\n }\n }\n }\n\n public getState (): SessionState {\n return this.sessionState.state\n }\n\n public lastSentSeqNum (): number {\n return this.sessionState.lastSentSeqNum()\n }\n\n public lastPeerSeqNum (): number {\n return this.sessionState.lastPeerMsgSeqNum\n }\n\n public sendLogon (): void {\n const lo = this.config.factory?.logon()\n if (lo) {\n this.send(this.requestLogonType, lo)\n }\n }\n\n private async waitPromise (): Promise<number> {\n const logger = this.sessionLogger\n if (this.initiator) {\n // Hook for subclasses to reset sequences when ResetSeqNumFlag=Y is configured —\n // must run after the store is loaded, before sendLogon stamps a seq num.\n await this.onPreLogon()\n }\n return await new Promise<any>((resolve, reject) => {\n if (this.initiator) {\n logger.debug(`initiator sending logon state = ${this.stateString()}`)\n this.sendLogon()\n this.setState(SessionState.InitiationLogonSent)\n } else {\n logger.debug(`acceptor waits for logon state = ${this.stateString()}`)\n this.setState(SessionState.WaitingForALogon)\n }\n\n // Use named handlers and detach BOTH when the promise settles. Only one of\n // 'error'/'done' fires per run; without removing the sibling the unfired\n // listener would leak on every reconnect (issue #146). `once` alone is not\n // enough for the same reason — the sibling never fires, so never self-detaches.\n const cleanup = (): void => {\n this.removeListener('error', onError)\n this.removeListener('done', onDone)\n }\n const onError = (e: Error): void => {\n cleanup()\n // read the logger now, not the one captured when the run started - a\n // wildcard acceptor rebinds it once it knows which peer it is serving\n this.sessionLogger.error(e)\n reject(e)\n }\n const onDone = (): void => {\n cleanup()\n resolve(this.transport?.id)\n }\n\n this.on('error', onError)\n this.on('done', onDone)\n })\n }\n\n public async run (transport: MsgTransport): Promise<number> {\n const logger = this.sessionLogger\n if (this.transport) {\n logger.info(`reset from previous transport. state ${this.stateString()}`)\n this.reset()\n }\n this.transport = transport\n this.subscribe()\n return await this.waitPromise()\n }\n\n protected expectedEndState (): boolean {\n switch (this.sessionState.state) {\n case SessionState.Stopped:\n case SessionState.ConfirmingLogout:\n return true\n\n default:\n return false\n }\n }\n\n protected rxOnEnd (): void {\n const logger = this.sessionLogger\n logger.info(`rx end received sessionState = [${this.sessionState.toString()}]`)\n const expectedState = this.expectedEndState()\n if (expectedState) {\n logger.info(`rx receives end state = ${this.stateString()} - stop session`)\n this.stop()\n } else {\n this.setState(SessionState.DetectBrokenNetworkConnection)\n const e = new Error(`unexpected state - transport failed? = ${this.stateString()}`)\n logger.info(`rx error ${e.message}`)\n this.terminate(e)\n }\n }\n\n protected rxOnMsg (msgType: string, view: MsgView): void {\n const logger = this.sessionLogger\n\n if (this.logReceivedMsgs) {\n const name = view.segment.type !== SegmentType.Unknown ? view?.segment?.set?.name : 'unknown'\n logger.info(`${msgType}: ${name}`)\n logger.info(`${view.toString()}`)\n }\n this.sessionState.lastReceivedAt = new Date()\n if (this.manageSession) {\n this.onMsg(msgType, view)\n } else {\n this.checkForwardMsg(msgType, view)\n }\n }\n\n protected rxOnDone (): void {\n const logger = this.sessionLogger\n logger.info('rx done received')\n this.done()\n }\n\n protected rxOnError (e: Error): void {\n const logger = this.sessionLogger\n logger.warning(`rx error event: ${e.message} ${JSON.stringify(e)}`)\n this.terminate(e)\n }\n\n protected rxOnDecoded (msgType: string, data: ElasticBuffer, ptr: number): void {\n const logger = this.sessionLogger\n logger.debug(`rx: [${msgType}] ${ptr} bytes`)\n this.onDecoded(msgType, data.toString(ptr))\n }\n\n protected txOnError (e: Error): void {\n const logger = this.sessionLogger\n logger.warning(`tx error event: ${e.message} ${JSON.stringify(e)}`)\n this.terminate(e)\n }\n\n protected txOnEncoded (msgType: string, data: string, hdr: ILooseObject): void {\n const logger = this.sessionLogger\n this.sessionState.lastHeader = hdr\n logger.debug(`tx: [${msgType}] ${data.length} bytes seqNo = ${this.lastSentSeqNum()}`)\n this.onEncoded(msgType, data)\n }\n\n /**\n * true when the event which has just fired came from the transport this session\n * is currently running. A half open socket can keep emitting long after the peer\n * has reconnected on a fresh connection - those events must not be allowed to drive\n * the live session (issue #153).\n */\n private isCurrentTransport (transport: MsgTransport, event: string): boolean {\n if (this.subscription?.transport === transport && this.transport === transport) {\n return true\n }\n const current = this.transport?.id ?? 'none'\n this.sessionLogger.warning(`ignoring '${event}' from stale transport ${transport.id} - current transport is ${current}`)\n return false\n }\n\n protected unsubscribe (): void {\n const logger = this.sessionLogger\n const subscription = this.subscription\n if (!subscription) {\n logger.debug('unsubscribe called with no active subscription')\n return\n }\n const transport = subscription.transport\n logger.info(`unsubscribe transport ${transport.id} sessionState = [${this.sessionState.toString()}]`)\n const rx = transport.receiver\n const tx = transport.transmitter\n\n rx?.removeListener('msg', subscription.rxOnMsg)\n rx?.removeListener('error', subscription.rxOnError)\n rx?.removeListener('done', subscription.rxOnDone)\n rx?.removeListener('end', subscription.rxOnEnd)\n rx?.removeListener('decoded', subscription.rxOnDecoded)\n tx?.removeListener('error', subscription.txOnError)\n tx?.removeListener('encoded', subscription.txOnEncoded)\n this.subscription = null\n logger.debug(`unsubscribe complete - rx listeners now ${rx?.listenerCount('msg') ?? 0} msg, ${rx?.listenerCount('end') ?? 0} end`)\n }\n\n protected subscribe (): void {\n const transport = this.transport\n if (!transport) {\n this.sessionLogger.warning('subscribe called with no transport')\n return\n }\n // detach from any previous transport before attaching to this one\n if (this.subscription) {\n this.unsubscribe()\n }\n const inst = this\n const subscription: ITransportSubscription = {\n transport,\n rxOnMsg: (msgType: string, view: MsgView) => {\n if (inst.isCurrentTransport(transport, 'msg')) inst.rxOnMsg(msgType, view)\n },\n rxOnError: (e: Error) => {\n if (inst.isCurrentTransport(transport, 'error')) inst.rxOnError(e)\n },\n rxOnDone: () => {\n if (inst.isCurrentTransport(transport, 'done')) inst.rxOnDone()\n },\n rxOnEnd: () => {\n if (inst.isCurrentTransport(transport, 'end')) inst.rxOnEnd()\n },\n rxOnDecoded: (msgType: string, data: ElasticBuffer, ptr: number) => {\n if (inst.isCurrentTransport(transport, 'decoded')) inst.rxOnDecoded(msgType, data, ptr)\n },\n txOnError: (e: Error) => {\n if (inst.isCurrentTransport(transport, 'tx error')) inst.txOnError(e)\n },\n txOnEncoded: (msgType: string, data: string, hdr: ILooseObject) => {\n if (inst.isCurrentTransport(transport, 'encoded')) inst.txOnEncoded(msgType, data, hdr)\n }\n }\n const rx = transport.receiver\n const tx = transport.transmitter\n rx?.on('msg', subscription.rxOnMsg)\n rx?.on('error', subscription.rxOnError)\n rx?.on('done', subscription.rxOnDone)\n rx?.on('end', subscription.rxOnEnd)\n rx?.on('decoded', subscription.rxOnDecoded)\n tx?.on('error', subscription.txOnError)\n tx?.on('encoded', subscription.txOnEncoded)\n this.subscription = subscription\n this.sessionLogger.info(`subscribed to transport ${transport.id}`)\n }\n\n protected validStateApplicationMsg (): boolean {\n switch (this.sessionState.state) {\n case SessionState.Idle:\n case SessionState.InitiateConnection:\n case SessionState.InitiationLogonSent:\n case SessionState.WaitingForALogon:\n case SessionState.HandleResendRequest:\n case SessionState.AwaitingProcessingResponseToTestRequest:\n case SessionState.AwaitingProcessingResponseToResendRequest:\n return false\n default:\n return true\n }\n }\n\n protected stateString (): string {\n return SessionState[this.sessionState.state]\n }\n\n protected checkForwardMsg (msgType: string, view: MsgView): void {\n this.sessionLogger.info(`forwarding msgType = '${msgType}' to application`)\n this.setState(SessionState.ActiveNormalSession)\n this.onApplicationMsg(msgType, view)\n }\n\n private stopTimer (): void {\n if (this.timer) {\n this.sessionLogger.info('stopTimer')\n clearInterval(this.timer)\n this.timer = null\n }\n }\n\n protected terminate (error: Error): void {\n if (this.sessionState.state === SessionState.Stopped) return\n this.sessionLogger.error(error)\n this.stopTimer()\n this.unsubscribe()\n if (this.transport) {\n this.sessionLogger.info(`terminate: kill transport ${this.transport.id}`)\n this.transport.end()\n }\n this.transport = null\n this.setState(SessionState.Stopped)\n this.onSessionStopping()\n this.emit('error', error)\n this.onStopped(error)\n }\n\n protected peerLogout (view: MsgView): void {\n const msg = view.getString(MsgTag.Text)\n const state = this.sessionState.state\n switch (state) {\n case SessionState.WaitingLogoutConfirm: {\n this.sessionLogger.info(`peer confirms logout Text = '${msg}'`)\n this.stop()\n break\n }\n\n case SessionState.InitiationLogonResponse:\n case SessionState.ActiveNormalSession:\n case SessionState.InitiationLogonReceived: {\n this.setState(SessionState.ConfirmingLogout)\n this.sessionLogger.info(`peer initiates logout Text = '${msg}'`)\n this.sessionLogout()\n }\n }\n }\n\n protected send (msgType: string, obj: ILooseObject): void {\n const state = this.sessionState.state\n switch (state) {\n case SessionState.Stopped: {\n this.sessionLogger.warning(`can't send in state ${this.stateString()}`)\n break\n }\n\n default: {\n this.sessionState.LastSentAt = new Date()\n this.transport?.transmitter.send(msgType, obj)\n break\n }\n }\n }\n\n protected sendLogout (msg: string): void {\n const factory = this.config.factory\n this.sessionLogger.info(`sending logout with ${msg}`)\n const lo = factory?.logout(this.requestLogoutType, msg)\n if (lo) {\n this.send(this.requestLogoutType, lo)\n }\n }\n\n protected sessionLogout (): void {\n const sessionState = this.sessionState\n if (sessionState.logoutSentAt) {\n return\n }\n\n switch (sessionState.state) {\n case SessionState.ActiveNormalSession:\n case SessionState.InitiationLogonResponse:\n case SessionState.InitiationLogonReceived: {\n // this instance initiates logout\n this.setState(SessionState.WaitingLogoutConfirm)\n sessionState.logoutSentAt = new Date()\n const msg = `${this.me} initiate logout`\n this.sessionLogger.info(msg)\n this.sendLogout(msg)\n break\n }\n\n case SessionState.ConfirmingLogout: {\n // this instance responds to log out\n this.setState(SessionState.ConfirmingLogout)\n sessionState.logoutSentAt = new Date()\n const msg = `${this.me} confirming logout`\n this.sessionLogger.info(msg)\n this.sendLogout(msg)\n break\n }\n\n default: {\n this.sessionLogger.info(`sessionLogout ignored as in state ${sessionState.state}`)\n }\n }\n }\n\n public done (): void {\n switch (this.sessionState.state) {\n case SessionState.InitiationLogonResponse:\n case SessionState.ActiveNormalSession:\n case SessionState.InitiationLogonReceived: {\n this.sessionLogout()\n break\n }\n\n case SessionState.Stopped:\n this.sessionLogger.info('done. session is now stopped')\n break\n\n default: {\n this.stop()\n break\n }\n }\n this.sessionLogger.info(`done. check logout sequence state ${this.stateString()}`)\n }\n\n public reset (resetSeqNum?: number | null): void {\n this.stopTimer()\n // unsubscribe from old transport before clearing reference\n this.unsubscribe()\n // reset parser to clear any partial message state from dropped connection\n const receiver: any = this.transport?.receiver\n if (receiver?.reset) {\n receiver.reset()\n }\n this.transport = null\n const resetFlag = this.config.description.ResetSeqNumFlag\n const seqNum = resetFlag ? 0 : resetSeqNum ?? this.sessionState.lastPeerMsgSeqNum\n this.sessionState.reset(seqNum) // from header def ... eventually\n this.onPrepareForReconnect()\n this.setState(SessionState.NetworkConnectionEstablished)\n }\n\n protected onPrepareForReconnect (): void {\n // Override in subclass to reset coordinator/transient state\n }\n\n /**\n * Called once as the session moves to Stopped, before the application is informed\n * via onStopped. Override to release session scoped resources - the ascii session\n * uses this to remove itself from the session registry. Mirrors cspurefix\n * FixSession.OnSessionStopping.\n */\n protected onSessionStopping (): void {\n // Default no-op\n }\n\n /**\n * Called for initiators after the store is loaded but before the Logon is sent.\n * Override to reset sequences/store when ResetSeqNumFlag=Y so the Logon goes out\n * with MsgSeqNum=1 instead of the recovered sender seq num.\n */\n protected async onPreLogon (): Promise<void> {\n // Default no-op\n }\n\n /**\n * Stop this session on behalf of an external caller - typically the session registry\n * when a new connection for the same SessionId replaces this one, but equally an\n * application which has decided the peer is gone. Mirrors cspurefix\n * FixSession.RequestStop.\n * @param reason recorded in the session log and carried on the emitted error\n */\n public requestStop (reason: string): void {\n this.sessionLogger.info(`requestStop: ${reason}`)\n this.stop(new Error(reason))\n }\n\n protected stop (error: Error | null = null): void {\n if (this.sessionState.state === SessionState.Stopped) {\n return\n }\n this.stopTimer()\n this.unsubscribe()\n this.sessionLogger.info(`stop: kill transport ${this.transport?.id ?? 'none'}`)\n this.onSessionStopping()\n this.transport?.end()\n if (error) {\n this.sessionLogger.info(`stop: emit error ${error.message}`)\n this.emit('error', error)\n } else {\n this.emit('done')\n }\n\n this.setState(SessionState.Stopped)\n this.onStopped(error ?? undefined)\n this.transport = null\n }\n\n /**\n * dispatches a message into the subclass that inherits from FixSession. The view contains\n * the parsed message which has utility methods such as toObject(). The Ascii session provides\n * an implementation to handle admin level messages such as logon, hearbeat and resest request.\n * Any application messges are dispatched via onApplicationMsg where the application can action\n * the message.\n * @param msgType the string based msg type the view represents\n * @param view container for all parsed fields representing the received message.\n * @protected\n */\n protected abstract onMsg (msgType: string, view: MsgView): void\n /**\n * the parsed txt recieved from the peer application. Given the applicaton is\n * responible for maintaining the fix log, this can be used to persist all received\n * messages.\n * @param msgType the string based msg type the view represents\n * @param txt the received message where for Ascii, the wire SOH delimeter is replaced\n * with that specified in the config e.g. '|'\n * @protected\n */\n protected abstract onDecoded (msgType: string, txt: string): void\n /**\n * the formatted txt sent to the peer application as an outbound message. Given the applicaton is\n * responible for maintaining the fix log, this can be used to persist all transmitted\n * messages. use msgType for example to persist only trade capture messages to database\n * @param msgType the msg type representing the message.\n * @param txt the sent message where for Ascii, the wire SOH delimeter is replaced\n * with that specified in the config e.g. '|'\n * @protected\n */\n protected abstract onEncoded (msgType: string, txt: string): void\n /**\n * typically all session level messages are handled by AsciiSession and these are\n * application level such as MarketDataRefresh. This will represent the applications main\n * work functiono where responses can be sent back to the peer. If manageSession has been set false\n * (not recommended) all messages are sent to this function\n * @param msgType the msg type representing the message.\n * @param view a wrapper containing the parsed message received.\n * @protected\n */\n protected abstract onApplicationMsg (msgType: string, view: MsgView): void\n /**\n * at this point the application is ready to send messages - peer login has been achieved\n * and the session can be considered ready to use. In the case of an initiator the application\n * may at this point send for security definitions or send market data subscriptions\n * @param view the login message causing session to be ready\n * @protected\n */\n protected abstract onReady (view: MsgView): void\n\n /**\n * Inform application this session has now ended - either from logout or connection dropped\n * @param error if session has been terminated via an error it is provided\n * @protected\n */\n protected abstract onStopped (error?: Error): void\n /**\n * Placeholder infomring the application of a peer login attempt.\n * @param view the login message\n * @param user extracted user from message\n * @param password extracted password from the message.\n * @protected\n */\n protected abstract onLogon (view: MsgView, user: string, password: string): boolean\n}\n"]}
1
+ {"version":3,"file":"fix-session.js","sourceRoot":"","sources":["../../../src/transport/session/fix-session.ts"],"names":[],"mappings":"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","sourcesContent":["import { ElasticBuffer, MsgView } from '../../buffer'\nimport { IJsFixConfig, IJsFixLogger } from '../../config'\nimport { FixSessionState } from './fix-session-state'\nimport { MsgTransport } from '../factory'\nimport { MsgTag } from '../../types'\nimport { ILooseObject } from '../../collections/collection'\nimport { SendCallback } from '../send-callback'\n\nimport * as events from 'events'\nimport { SessionState } from './session-state'\nimport { SegmentType } from '../../buffer/segment/segment-type'\n\n/**\n * The set of listeners this session attached to one specific transport.\n *\n * The handlers must be kept as stable references - `EventEmitter.removeListener`\n * matches on identity, so subscribing with a fresh closure and unsubscribing with\n * a method reference silently leaves the listener attached (issue #153). Holding\n * the transport alongside the handlers also lets `unsubscribe` detach from the\n * transport it actually subscribed to, even when `this.transport` has already\n * moved on to a newer connection.\n */\ninterface ITransportSubscription {\n readonly transport: MsgTransport\n readonly rxOnMsg: (msgType: string, view: MsgView) => void\n readonly rxOnError: (e: Error) => void\n readonly rxOnDone: () => void\n readonly rxOnEnd: () => void\n readonly rxOnDecoded: (msgType: string, data: ElasticBuffer, ptr: number) => void\n readonly txOnError: (e: Error) => void\n readonly txOnEncoded: (msgType: string, data: string, hdr: ILooseObject) => void\n}\n\nexport abstract class FixSession extends events.EventEmitter {\n public logReceivedMsgs: boolean = false\n protected timer: NodeJS.Timeout | null = null\n protected transport: MsgTransport | null = null\n private subscription: ITransportSubscription | null = null\n public manageSession: boolean = true\n public checkMsgIntegrity: boolean = false\n protected readonly me: string\n protected readonly initiator: boolean\n protected readonly acceptor: boolean\n protected readonly sessionState: FixSessionState\n /**\n * Not readonly: a wildcard acceptor does not know which counterparty it is\n * serving until the Logon arrives, and every session on that listener would\n * otherwise log under the same name. Rebound once the identity is known.\n */\n protected sessionLogger: IJsFixLogger\n protected requestLogoutType: string\n protected respondLogoutType: string\n protected requestLogonType: string\n\n protected constructor (public readonly config: IJsFixConfig) {\n super()\n const description = config.description\n this.me = description?.application?.name ?? 'me'\n this.sessionState = new FixSessionState(\n {\n heartBeat: config.description.HeartBtInt,\n lastPeerMsgSeqNum: config.description.LastReceivedSeqNum\n })\n this.sessionLogger = config.logFactory.logger(`${this.me}:FixSession`)\n this.initiator = description?.application?.type === 'initiator'\n this.acceptor = !this.initiator\n this.checkMsgIntegrity = this.acceptor\n this.sessionState.compId = description.SenderCompId\n }\n\n stateStr (theState: SessionState): string {\n return SessionState[theState]\n }\n\n assignState (newState: SessionState): void {\n const currentState = this.sessionState.state\n const currentStateStr = this.stateStr(currentState)\n const logger = this.sessionLogger\n const msg = `current state ${currentStateStr} (${currentState}) moves to ${SessionState[newState]} (${newState})`\n logger.info(msg)\n this.sessionState.state = newState\n }\n\n public setState (state: SessionState): void {\n const logger = this.sessionLogger\n const currentState = this.sessionState.state\n const currentStateStr = this.stateStr(currentState)\n if (state === currentState) return\n switch (currentState) {\n case SessionState.ConfirmingLogout:\n case SessionState.Stopped:\n if (state !== SessionState.NetworkConnectionEstablished) {\n logger.info(`ignoring request to change state as now already in ${currentStateStr}`)\n } else {\n this.assignState(state)\n }\n break\n\n default: {\n this.assignState(state)\n }\n }\n }\n\n public getState (): SessionState {\n return this.sessionState.state\n }\n\n public lastSentSeqNum (): number {\n return this.sessionState.lastSentSeqNum()\n }\n\n public lastPeerSeqNum (): number {\n return this.sessionState.lastPeerMsgSeqNum\n }\n\n public sendLogon (): void {\n const lo = this.config.factory?.logon()\n if (lo) {\n this.send(this.requestLogonType, lo)\n }\n }\n\n private async waitPromise (): Promise<number> {\n const logger = this.sessionLogger\n if (this.initiator) {\n // Hook for subclasses to reset sequences when ResetSeqNumFlag=Y is configured —\n // must run after the store is loaded, before sendLogon stamps a seq num.\n await this.onPreLogon()\n }\n return await new Promise<any>((resolve, reject) => {\n if (this.initiator) {\n logger.debug(`initiator sending logon state = ${this.stateString()}`)\n this.sendLogon()\n this.setState(SessionState.InitiationLogonSent)\n } else {\n logger.debug(`acceptor waits for logon state = ${this.stateString()}`)\n this.setState(SessionState.WaitingForALogon)\n }\n\n // Use named handlers and detach BOTH when the promise settles. Only one of\n // 'error'/'done' fires per run; without removing the sibling the unfired\n // listener would leak on every reconnect (issue #146). `once` alone is not\n // enough for the same reason — the sibling never fires, so never self-detaches.\n const cleanup = (): void => {\n this.removeListener('error', onError)\n this.removeListener('done', onDone)\n }\n const onError = (e: Error): void => {\n cleanup()\n // read the logger now, not the one captured when the run started - a\n // wildcard acceptor rebinds it once it knows which peer it is serving\n this.sessionLogger.error(e)\n reject(e)\n }\n const onDone = (): void => {\n cleanup()\n resolve(this.transport?.id)\n }\n\n this.on('error', onError)\n this.on('done', onDone)\n })\n }\n\n public async run (transport: MsgTransport): Promise<number> {\n const logger = this.sessionLogger\n if (this.transport) {\n logger.info(`reset from previous transport. state ${this.stateString()}`)\n this.reset()\n }\n this.transport = transport\n this.subscribe()\n return await this.waitPromise()\n }\n\n protected expectedEndState (): boolean {\n switch (this.sessionState.state) {\n case SessionState.Stopped:\n case SessionState.ConfirmingLogout:\n return true\n\n default:\n return false\n }\n }\n\n protected rxOnEnd (): void {\n const logger = this.sessionLogger\n logger.info(`rx end received sessionState = [${this.sessionState.toString()}]`)\n const expectedState = this.expectedEndState()\n if (expectedState) {\n logger.info(`rx receives end state = ${this.stateString()} - stop session`)\n this.stop()\n } else {\n this.setState(SessionState.DetectBrokenNetworkConnection)\n const e = new Error(`unexpected state - transport failed? = ${this.stateString()}`)\n logger.info(`rx error ${e.message}`)\n this.terminate(e)\n }\n }\n\n protected rxOnMsg (msgType: string, view: MsgView): void {\n const logger = this.sessionLogger\n\n if (this.logReceivedMsgs) {\n const name = view.segment.type !== SegmentType.Unknown ? view?.segment?.set?.name : 'unknown'\n logger.info(`${msgType}: ${name}`)\n logger.info(`${view.toString()}`)\n }\n this.sessionState.lastReceivedAt = new Date()\n if (this.manageSession) {\n this.onMsg(msgType, view)\n } else {\n this.checkForwardMsg(msgType, view)\n }\n }\n\n protected rxOnDone (): void {\n const logger = this.sessionLogger\n logger.info('rx done received')\n this.done()\n }\n\n protected rxOnError (e: Error): void {\n const logger = this.sessionLogger\n logger.warning(`rx error event: ${e.message} ${JSON.stringify(e)}`)\n this.terminate(e)\n }\n\n protected rxOnDecoded (msgType: string, data: ElasticBuffer, ptr: number): void {\n const logger = this.sessionLogger\n logger.debug(`rx: [${msgType}] ${ptr} bytes`)\n this.onDecoded(msgType, data.toString(ptr))\n }\n\n protected txOnError (e: Error): void {\n const logger = this.sessionLogger\n logger.warning(`tx error event: ${e.message} ${JSON.stringify(e)}`)\n this.terminate(e)\n }\n\n protected txOnEncoded (msgType: string, data: string, hdr: ILooseObject): void {\n const logger = this.sessionLogger\n this.sessionState.lastHeader = hdr\n logger.debug(`tx: [${msgType}] ${data.length} bytes seqNo = ${this.lastSentSeqNum()}`)\n this.onEncoded(msgType, data)\n }\n\n /**\n * true when the event which has just fired came from the transport this session\n * is currently running. A half open socket can keep emitting long after the peer\n * has reconnected on a fresh connection - those events must not be allowed to drive\n * the live session (issue #153).\n */\n private isCurrentTransport (transport: MsgTransport, event: string): boolean {\n if (this.subscription?.transport === transport && this.transport === transport) {\n return true\n }\n const current = this.transport?.id ?? 'none'\n this.sessionLogger.warning(`ignoring '${event}' from stale transport ${transport.id} - current transport is ${current}`)\n return false\n }\n\n protected unsubscribe (): void {\n const logger = this.sessionLogger\n const subscription = this.subscription\n if (!subscription) {\n logger.debug('unsubscribe called with no active subscription')\n return\n }\n const transport = subscription.transport\n logger.info(`unsubscribe transport ${transport.id} sessionState = [${this.sessionState.toString()}]`)\n const rx = transport.receiver\n const tx = transport.transmitter\n\n rx?.removeListener('msg', subscription.rxOnMsg)\n rx?.removeListener('error', subscription.rxOnError)\n rx?.removeListener('done', subscription.rxOnDone)\n rx?.removeListener('end', subscription.rxOnEnd)\n rx?.removeListener('decoded', subscription.rxOnDecoded)\n tx?.removeListener('error', subscription.txOnError)\n tx?.removeListener('encoded', subscription.txOnEncoded)\n this.subscription = null\n logger.debug(`unsubscribe complete - rx listeners now ${rx?.listenerCount('msg') ?? 0} msg, ${rx?.listenerCount('end') ?? 0} end`)\n }\n\n protected subscribe (): void {\n const transport = this.transport\n if (!transport) {\n this.sessionLogger.warning('subscribe called with no transport')\n return\n }\n // detach from any previous transport before attaching to this one\n if (this.subscription) {\n this.unsubscribe()\n }\n const inst = this\n const subscription: ITransportSubscription = {\n transport,\n rxOnMsg: (msgType: string, view: MsgView) => {\n if (inst.isCurrentTransport(transport, 'msg')) inst.rxOnMsg(msgType, view)\n },\n rxOnError: (e: Error) => {\n if (inst.isCurrentTransport(transport, 'error')) inst.rxOnError(e)\n },\n rxOnDone: () => {\n if (inst.isCurrentTransport(transport, 'done')) inst.rxOnDone()\n },\n rxOnEnd: () => {\n if (inst.isCurrentTransport(transport, 'end')) inst.rxOnEnd()\n },\n rxOnDecoded: (msgType: string, data: ElasticBuffer, ptr: number) => {\n if (inst.isCurrentTransport(transport, 'decoded')) inst.rxOnDecoded(msgType, data, ptr)\n },\n txOnError: (e: Error) => {\n if (inst.isCurrentTransport(transport, 'tx error')) inst.txOnError(e)\n },\n txOnEncoded: (msgType: string, data: string, hdr: ILooseObject) => {\n if (inst.isCurrentTransport(transport, 'encoded')) inst.txOnEncoded(msgType, data, hdr)\n }\n }\n const rx = transport.receiver\n const tx = transport.transmitter\n rx?.on('msg', subscription.rxOnMsg)\n rx?.on('error', subscription.rxOnError)\n rx?.on('done', subscription.rxOnDone)\n rx?.on('end', subscription.rxOnEnd)\n rx?.on('decoded', subscription.rxOnDecoded)\n tx?.on('error', subscription.txOnError)\n tx?.on('encoded', subscription.txOnEncoded)\n this.subscription = subscription\n this.sessionLogger.info(`subscribed to transport ${transport.id}`)\n }\n\n protected validStateApplicationMsg (): boolean {\n switch (this.sessionState.state) {\n case SessionState.Idle:\n case SessionState.InitiateConnection:\n case SessionState.InitiationLogonSent:\n case SessionState.WaitingForALogon:\n case SessionState.HandleResendRequest:\n case SessionState.AwaitingProcessingResponseToTestRequest:\n case SessionState.AwaitingProcessingResponseToResendRequest:\n return false\n default:\n return true\n }\n }\n\n protected stateString (): string {\n return SessionState[this.sessionState.state]\n }\n\n protected checkForwardMsg (msgType: string, view: MsgView): void {\n this.sessionLogger.info(`forwarding msgType = '${msgType}' to application`)\n this.setState(SessionState.ActiveNormalSession)\n this.onApplicationMsg(msgType, view)\n }\n\n private stopTimer (): void {\n if (this.timer) {\n this.sessionLogger.info('stopTimer')\n clearInterval(this.timer)\n this.timer = null\n }\n }\n\n protected terminate (error: Error): void {\n if (this.sessionState.state === SessionState.Stopped) return\n this.sessionLogger.error(error)\n this.stopTimer()\n this.unsubscribe()\n if (this.transport) {\n this.sessionLogger.info(`terminate: kill transport ${this.transport.id}`)\n this.transport.end()\n }\n this.transport = null\n this.setState(SessionState.Stopped)\n this.onSessionStopping()\n this.emit('error', error)\n this.onStopped(error)\n }\n\n protected peerLogout (view: MsgView): void {\n const msg = view.getString(MsgTag.Text)\n const state = this.sessionState.state\n switch (state) {\n case SessionState.WaitingLogoutConfirm: {\n this.sessionLogger.info(`peer confirms logout Text = '${msg}'`)\n this.stop()\n break\n }\n\n case SessionState.InitiationLogonResponse:\n case SessionState.ActiveNormalSession:\n case SessionState.InitiationLogonReceived: {\n this.setState(SessionState.ConfirmingLogout)\n this.sessionLogger.info(`peer initiates logout Text = '${msg}'`)\n this.sessionLogout()\n }\n }\n }\n\n /**\n * @param callback optional, invoked once the message has been encoded and handed to\n * the transport, or as soon as that fails. Without it a send is fire and forget:\n * nothing tells the caller which sequence number the message went out under, and a\n * message dropped because the session is down, or refused by the encoder, goes\n * unanswered. See https://github.com/TimelordUK/jspurefix/issues/86\n */\n protected send (msgType: string, obj: ILooseObject, callback: SendCallback | null = null): void {\n const state = this.sessionState.state\n switch (state) {\n case SessionState.Stopped: {\n const msg = `can't send in state ${this.stateString()}`\n this.sessionLogger.warning(msg)\n // the message is dropped either way - but a caller that asked to be told is\n // now told, instead of watching for a log line\n callback?.(new Error(msg), { msgType, header: null, encoded: null })\n break\n }\n\n default: {\n this.sessionState.LastSentAt = new Date()\n const transmitter = this.transport?.transmitter\n if (!transmitter) {\n const msg = `no transport to send ${msgType} on`\n this.sessionLogger.warning(msg)\n callback?.(new Error(msg), { msgType, header: null, encoded: null })\n break\n }\n transmitter.send(msgType, obj, callback)\n break\n }\n }\n }\n\n protected sendLogout (msg: string): void {\n const factory = this.config.factory\n this.sessionLogger.info(`sending logout with ${msg}`)\n const lo = factory?.logout(this.requestLogoutType, msg)\n if (lo) {\n this.send(this.requestLogoutType, lo)\n }\n }\n\n protected sessionLogout (): void {\n const sessionState = this.sessionState\n if (sessionState.logoutSentAt) {\n return\n }\n\n switch (sessionState.state) {\n case SessionState.ActiveNormalSession:\n case SessionState.InitiationLogonResponse:\n case SessionState.InitiationLogonReceived: {\n // this instance initiates logout\n this.setState(SessionState.WaitingLogoutConfirm)\n sessionState.logoutSentAt = new Date()\n const msg = `${this.me} initiate logout`\n this.sessionLogger.info(msg)\n this.sendLogout(msg)\n break\n }\n\n case SessionState.ConfirmingLogout: {\n // this instance responds to log out\n this.setState(SessionState.ConfirmingLogout)\n sessionState.logoutSentAt = new Date()\n const msg = `${this.me} confirming logout`\n this.sessionLogger.info(msg)\n this.sendLogout(msg)\n break\n }\n\n default: {\n this.sessionLogger.info(`sessionLogout ignored as in state ${sessionState.state}`)\n }\n }\n }\n\n public done (): void {\n switch (this.sessionState.state) {\n case SessionState.InitiationLogonResponse:\n case SessionState.ActiveNormalSession:\n case SessionState.InitiationLogonReceived: {\n this.sessionLogout()\n break\n }\n\n case SessionState.Stopped:\n this.sessionLogger.info('done. session is now stopped')\n break\n\n default: {\n this.stop()\n break\n }\n }\n this.sessionLogger.info(`done. check logout sequence state ${this.stateString()}`)\n }\n\n public reset (resetSeqNum?: number | null): void {\n this.stopTimer()\n // unsubscribe from old transport before clearing reference\n this.unsubscribe()\n // reset parser to clear any partial message state from dropped connection\n const receiver: any = this.transport?.receiver\n if (receiver?.reset) {\n receiver.reset()\n }\n this.transport = null\n const resetFlag = this.config.description.ResetSeqNumFlag\n const seqNum = resetFlag ? 0 : resetSeqNum ?? this.sessionState.lastPeerMsgSeqNum\n this.sessionState.reset(seqNum) // from header def ... eventually\n this.onPrepareForReconnect()\n this.setState(SessionState.NetworkConnectionEstablished)\n }\n\n protected onPrepareForReconnect (): void {\n // Override in subclass to reset coordinator/transient state\n }\n\n /**\n * Called once as the session moves to Stopped, before the application is informed\n * via onStopped. Override to release session scoped resources - the ascii session\n * uses this to remove itself from the session registry. Mirrors cspurefix\n * FixSession.OnSessionStopping.\n */\n protected onSessionStopping (): void {\n // Default no-op\n }\n\n /**\n * Called for initiators after the store is loaded but before the Logon is sent.\n * Override to reset sequences/store when ResetSeqNumFlag=Y so the Logon goes out\n * with MsgSeqNum=1 instead of the recovered sender seq num.\n */\n protected async onPreLogon (): Promise<void> {\n // Default no-op\n }\n\n /**\n * Stop this session on behalf of an external caller - typically the session registry\n * when a new connection for the same SessionId replaces this one, but equally an\n * application which has decided the peer is gone. Mirrors cspurefix\n * FixSession.RequestStop.\n * @param reason recorded in the session log and carried on the emitted error\n */\n public requestStop (reason: string): void {\n this.sessionLogger.info(`requestStop: ${reason}`)\n this.stop(new Error(reason))\n }\n\n protected stop (error: Error | null = null): void {\n if (this.sessionState.state === SessionState.Stopped) {\n return\n }\n this.stopTimer()\n this.unsubscribe()\n this.sessionLogger.info(`stop: kill transport ${this.transport?.id ?? 'none'}`)\n this.onSessionStopping()\n this.transport?.end()\n if (error) {\n this.sessionLogger.info(`stop: emit error ${error.message}`)\n this.emit('error', error)\n } else {\n this.emit('done')\n }\n\n this.setState(SessionState.Stopped)\n this.onStopped(error ?? undefined)\n this.transport = null\n }\n\n /**\n * dispatches a message into the subclass that inherits from FixSession. The view contains\n * the parsed message which has utility methods such as toObject(). The Ascii session provides\n * an implementation to handle admin level messages such as logon, hearbeat and resest request.\n * Any application messges are dispatched via onApplicationMsg where the application can action\n * the message.\n * @param msgType the string based msg type the view represents\n * @param view container for all parsed fields representing the received message.\n * @protected\n */\n protected abstract onMsg (msgType: string, view: MsgView): void\n /**\n * the parsed txt recieved from the peer application. Given the applicaton is\n * responible for maintaining the fix log, this can be used to persist all received\n * messages.\n * @param msgType the string based msg type the view represents\n * @param txt the received message where for Ascii, the wire SOH delimeter is replaced\n * with that specified in the config e.g. '|'\n * @protected\n */\n protected abstract onDecoded (msgType: string, txt: string): void\n /**\n * the formatted txt sent to the peer application as an outbound message. Given the applicaton is\n * responible for maintaining the fix log, this can be used to persist all transmitted\n * messages. use msgType for example to persist only trade capture messages to database\n * @param msgType the msg type representing the message.\n * @param txt the sent message where for Ascii, the wire SOH delimeter is replaced\n * with that specified in the config e.g. '|'\n * @protected\n */\n protected abstract onEncoded (msgType: string, txt: string): void\n /**\n * typically all session level messages are handled by AsciiSession and these are\n * application level such as MarketDataRefresh. This will represent the applications main\n * work functiono where responses can be sent back to the peer. If manageSession has been set false\n * (not recommended) all messages are sent to this function\n * @param msgType the msg type representing the message.\n * @param view a wrapper containing the parsed message received.\n * @protected\n */\n protected abstract onApplicationMsg (msgType: string, view: MsgView): void\n /**\n * at this point the application is ready to send messages - peer login has been achieved\n * and the session can be considered ready to use. In the case of an initiator the application\n * may at this point send for security definitions or send market data subscriptions\n * @param view the login message causing session to be ready\n * @protected\n */\n protected abstract onReady (view: MsgView): void\n\n /**\n * Inform application this session has now ended - either from logout or connection dropped\n * @param error if session has been terminated via an error it is provided\n * @protected\n */\n protected abstract onStopped (error?: Error): void\n /**\n * Placeholder infomring the application of a peer login attempt.\n * @param view the login message\n * @param user extracted user from message\n * @param password extracted password from the message.\n * @protected\n */\n protected abstract onLogon (view: MsgView, user: string, password: string): boolean\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { IMsgApplication } from '../msg-application';
2
2
  import { StoreConfig } from '../../store/store-config';
3
+ import { ILooseObject } from '../../collections/collection';
3
4
  export interface IDynamicSessionParams {
4
5
  readonly Name: string;
5
6
  readonly SenderCompId: string;
@@ -13,6 +14,7 @@ export interface IDynamicSessionParams {
13
14
  }
14
15
  export interface ISessionDescription extends IDynamicSessionParams {
15
16
  readonly application?: IMsgApplication;
17
+ readonly Logon?: ILooseObject;
16
18
  HeartBtInt: number;
17
19
  LastSentSeqNum?: number;
18
20
  readonly LastReceivedSeqNum?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"session-description.js","sourceRoot":"","sources":["../../../src/transport/session/session-description.ts"],"names":[],"mappings":"","sourcesContent":["import { IMsgApplication } from '../msg-application'\nimport { StoreConfig } from '../../store/store-config'\n\nexport interface IDynamicSessionParams {\n readonly Name: string\n readonly SenderCompId: string\n readonly TargetCompID: string\n readonly ResetSeqNumFlag: boolean\n readonly SenderSubID: string\n readonly TargetSubID: string\n readonly BeginString: string\n readonly Username: string\n readonly Password: string\n}\n\nexport interface ISessionDescription extends IDynamicSessionParams {\n readonly application?: IMsgApplication\n HeartBtInt: number\n LastSentSeqNum?: number\n readonly LastReceivedSeqNum?: number\n readonly BodyLengthChars?: number\n readonly store?: StoreConfig\n}\n"]}
1
+ {"version":3,"file":"session-description.js","sourceRoot":"","sources":["../../../src/transport/session/session-description.ts"],"names":[],"mappings":"","sourcesContent":["import { IMsgApplication } from '../msg-application'\nimport { StoreConfig } from '../../store/store-config'\nimport { ILooseObject } from '../../collections/collection'\n\nexport interface IDynamicSessionParams {\n readonly Name: string\n readonly SenderCompId: string\n readonly TargetCompID: string\n readonly ResetSeqNumFlag: boolean\n readonly SenderSubID: string\n readonly TargetSubID: string\n readonly BeginString: string\n readonly Username: string\n readonly Password: string\n}\n\nexport interface ISessionDescription extends IDynamicSessionParams {\n readonly application?: IMsgApplication\n /**\n * Extra fields to place on the outbound Logon, merged over the ones the engine\n * derives from this description. Counterparties routinely demand a tag the\n * standard Logon does not carry - an account, a default application version, a\n * free text token - and this is the no-code way to send it:\n *\n * \"Logon\": { \"Account\": \"TVKD_001\", \"DefaultApplVerID\": \"9\" }\n *\n * A field named here still has to exist on Logon in the dictionary the session\n * loads, otherwise the encoder has no tag to write it to. Set a field to null to\n * suppress one the engine would otherwise send. See issues #93, #39, #96.\n */\n readonly Logon?: ILooseObject\n HeartBtInt: number\n LastSentSeqNum?: number\n readonly LastReceivedSeqNum?: number\n readonly BodyLengthChars?: number\n readonly store?: StoreConfig\n}\n"]}