jspurefix 5.8.5 → 5.9.1

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 (92) hide show
  1. package/.gitattributes +4 -0
  2. package/BACKPORT_PLAN.md +71 -0
  3. package/DEMO_PORT_PLAN.md +10 -0
  4. package/README.md +3 -0
  5. package/dist/config/js-fix-config.d.ts +4 -0
  6. package/dist/config/js-fix-config.js.map +1 -1
  7. package/dist/runtime/session-launcher.js +1 -1
  8. package/dist/runtime/session-launcher.js.map +1 -1
  9. package/dist/runtime/session-scope.d.ts +3 -0
  10. package/dist/runtime/session-scope.js +47 -0
  11. package/dist/runtime/session-scope.js.map +1 -0
  12. package/dist/sample/http/oms/app.js +3 -3
  13. package/dist/sample/http/oms/app.js.map +1 -1
  14. package/dist/sample/tcp/qf-md/app.js +3 -3
  15. package/dist/sample/tcp/qf-md/app.js.map +1 -1
  16. package/dist/sample/tcp/skeleton/app.js +1 -1
  17. package/dist/sample/tcp/skeleton/app.js.map +1 -1
  18. package/dist/sample/tcp/trade-capture/app-launcher.js +3 -3
  19. package/dist/sample/tcp/trade-capture/app-launcher.js.map +1 -1
  20. package/dist/transport/ascii/ascii-session.d.ts +17 -3
  21. package/dist/transport/ascii/ascii-session.js +121 -8
  22. package/dist/transport/ascii/ascii-session.js.map +1 -1
  23. package/dist/transport/duplex/fix-duplex.d.ts +1 -0
  24. package/dist/transport/duplex/fix-duplex.js +3 -0
  25. package/dist/transport/duplex/fix-duplex.js.map +1 -1
  26. package/dist/transport/duplex/tcp-duplex.d.ts +1 -0
  27. package/dist/transport/duplex/tcp-duplex.js +5 -0
  28. package/dist/transport/duplex/tcp-duplex.js.map +1 -1
  29. package/dist/transport/factory/msg-transport.d.ts +2 -0
  30. package/dist/transport/factory/msg-transport.js +17 -2
  31. package/dist/transport/factory/msg-transport.js.map +1 -1
  32. package/dist/transport/session/a-session-msg-factory.d.ts +1 -0
  33. package/dist/transport/session/a-session-msg-factory.js +4 -0
  34. package/dist/transport/session/a-session-msg-factory.js.map +1 -1
  35. package/dist/transport/session/clone-session-description.d.ts +6 -0
  36. package/dist/transport/session/clone-session-description.js +11 -0
  37. package/dist/transport/session/clone-session-description.js.map +1 -0
  38. package/dist/transport/session/fix-session.d.ts +5 -1
  39. package/dist/transport/session/fix-session.js +93 -24
  40. package/dist/transport/session/fix-session.js.map +1 -1
  41. package/dist/transport/session/index.d.ts +2 -0
  42. package/dist/transport/session/index.js +2 -0
  43. package/dist/transport/session/index.js.map +1 -1
  44. package/dist/transport/session/session-msg-factory.d.ts +1 -0
  45. package/dist/transport/session/session-msg-factory.js.map +1 -1
  46. package/dist/transport/session/session-registry.d.ts +23 -0
  47. package/dist/transport/session/session-registry.js +59 -0
  48. package/dist/transport/session/session-registry.js.map +1 -0
  49. package/dist/transport/tcp/tcp-acceptor-listener.d.ts +3 -0
  50. package/dist/transport/tcp/tcp-acceptor-listener.js +26 -4
  51. package/dist/transport/tcp/tcp-acceptor-listener.js.map +1 -1
  52. package/dist/transport/tcp/tcp-acceptor.d.ts +5 -0
  53. package/dist/transport/tcp/tcp-acceptor.js +74 -20
  54. package/dist/transport/tcp/tcp-acceptor.js.map +1 -1
  55. package/dist/transport/tcp/tcp-initiator.js +15 -5
  56. package/dist/transport/tcp/tcp-initiator.js.map +1 -1
  57. package/dist/transport/tcp/tcp-transport-description.d.ts +1 -0
  58. package/dist/transport/tcp/tcp-transport-description.js.map +1 -1
  59. package/dist/transport/tcp/tls-diagnostics.d.ts +5 -0
  60. package/dist/transport/tcp/tls-diagnostics.js +64 -0
  61. package/dist/transport/tcp/tls-diagnostics.js.map +1 -0
  62. package/dist/transport/tcp/tls-options-factory.d.ts +1 -0
  63. package/dist/transport/tcp/tls-options-factory.js +24 -2
  64. package/dist/transport/tcp/tls-options-factory.js.map +1 -1
  65. package/docs/acceptor.md +207 -0
  66. package/jsfix.test_client.txt +62 -75
  67. package/jsfix.test_server.txt +72 -72
  68. package/package.json +11 -10
  69. package/script/pack-local.js +68 -0
  70. package/src/config/js-fix-config.ts +8 -0
  71. package/src/runtime/session-launcher.ts +5 -1
  72. package/src/runtime/session-scope.ts +84 -0
  73. package/src/sample/http/oms/app.ts +3 -3
  74. package/src/sample/tcp/qf-md/app.ts +3 -3
  75. package/src/sample/tcp/skeleton/app.ts +1 -1
  76. package/src/sample/tcp/trade-capture/app-launcher.ts +3 -3
  77. package/src/transport/ascii/ascii-session.ts +186 -11
  78. package/src/transport/duplex/fix-duplex.ts +9 -0
  79. package/src/transport/duplex/tcp-duplex.ts +10 -0
  80. package/src/transport/factory/msg-transport.ts +20 -0
  81. package/src/transport/session/a-session-msg-factory.ts +18 -0
  82. package/src/transport/session/clone-session-description.ts +41 -0
  83. package/src/transport/session/fix-session.ts +136 -25
  84. package/src/transport/session/index.ts +2 -0
  85. package/src/transport/session/session-msg-factory.ts +13 -0
  86. package/src/transport/session/session-registry.ts +112 -0
  87. package/src/transport/tcp/tcp-acceptor-listener.ts +43 -5
  88. package/src/transport/tcp/tcp-acceptor.ts +92 -18
  89. package/src/transport/tcp/tcp-initiator.ts +26 -5
  90. package/src/transport/tcp/tcp-transport-description.ts +7 -0
  91. package/src/transport/tcp/tls-diagnostics.ts +76 -0
  92. package/src/transport/tcp/tls-options-factory.ts +34 -2
@@ -4,6 +4,16 @@ exports.TlsOptionsFactory = void 0;
4
4
  const path = require('path');
5
5
  const fs = require('fs');
6
6
  class TlsOptionsFactory {
7
+ static asBoolean(value) {
8
+ if (typeof value === 'string') {
9
+ const lowered = value.toLowerCase();
10
+ if (lowered === 'true')
11
+ return true;
12
+ if (lowered === 'false')
13
+ return false;
14
+ }
15
+ return value;
16
+ }
7
17
  static read(filePath) {
8
18
  const root = path.join(__dirname, '../../../');
9
19
  const fullPath = path.join(root, filePath);
@@ -15,8 +25,8 @@ class TlsOptionsFactory {
15
25
  let tlsOptions = null;
16
26
  if (tls) {
17
27
  tlsOptions = {
18
- requestCert: tls.requestCert,
19
- rejectUnauthorized: tls.rejectUnauthorized
28
+ requestCert: TlsOptionsFactory.asBoolean(tls.requestCert),
29
+ rejectUnauthorized: TlsOptionsFactory.asBoolean(tls.rejectUnauthorized)
20
30
  };
21
31
  if (tls.key) {
22
32
  tlsOptions.key = TlsOptionsFactory.read(tls.key);
@@ -53,8 +63,20 @@ class TlsOptionsFactory {
53
63
  if (tcp.tls.sessionTimeout) {
54
64
  connectionOptions.sessionTimeout = tcp.tls.sessionTimeout;
55
65
  }
66
+ if (tls.requestCert !== undefined) {
67
+ connectionOptions.requestCert = TlsOptionsFactory.asBoolean(tls.requestCert);
68
+ }
69
+ if (tls.rejectUnauthorized !== undefined) {
70
+ connectionOptions.rejectUnauthorized = TlsOptionsFactory.asBoolean(tls.rejectUnauthorized);
71
+ }
56
72
  if (tls.nodeTlsConnectionOptions) {
57
73
  connectionOptions = Object.assign(Object.assign({}, connectionOptions), tls.nodeTlsConnectionOptions);
74
+ if (connectionOptions.rejectUnauthorized !== undefined) {
75
+ connectionOptions.rejectUnauthorized = TlsOptionsFactory.asBoolean(connectionOptions.rejectUnauthorized);
76
+ }
77
+ if (connectionOptions.requestCert !== undefined) {
78
+ connectionOptions.requestCert = TlsOptionsFactory.asBoolean(connectionOptions.requestCert);
79
+ }
58
80
  }
59
81
  }
60
82
  return connectionOptions;
@@ -1 +1 @@
1
- {"version":3,"file":"tls-options-factory.js","sourceRoot":"","sources":["../../../src/transport/tcp/tls-options-factory.ts"],"names":[],"mappings":"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","sourcesContent":["import { ConnectionOptions, TlsOptions } from 'tls'\nimport { ITlsOptions } from './tls-options'\nimport { ITcpTransportDescription } from './tcp-transport-description'\nconst path = require('path')\nconst fs = require('fs')\n\nexport class TlsOptionsFactory {\n static read (filePath: string): string {\n const root: string = path.join(__dirname, '../../../')\n const fullPath = path.join(root, filePath)\n return fs.readFileSync(fullPath,\n {\n encoding: 'utf8', flag: 'r'\n })\n }\n\n static getTlsOptions (tls: ITlsOptions): TlsOptions | null {\n let tlsOptions: TlsOptions | null = null\n if (tls) {\n tlsOptions = {\n requestCert: tls.requestCert,\n rejectUnauthorized: tls.rejectUnauthorized\n } as TlsOptions\n\n if (tls.key) {\n tlsOptions.key = TlsOptionsFactory.read(tls.key)\n tlsOptions.cert = tls?.cert ? TlsOptionsFactory.read(tls?.cert) : undefined\n }\n\n if (tls.ca && tls.ca.length > 0) {\n tlsOptions.ca = tls.ca.map(i => TlsOptionsFactory.read(i))\n }\n\n if (tls.nodeTlsServerOptions) {\n tlsOptions = {\n ...tlsOptions,\n ...tls.nodeTlsServerOptions\n }\n }\n }\n return tlsOptions\n }\n\n static getTlsConnectionOptions (tcp: ITcpTransportDescription): ConnectionOptions | null {\n let connectionOptions: ConnectionOptions | null = null\n const tls = tcp.tls\n if (tls) {\n connectionOptions = {\n port: tcp.port,\n host: tcp.host\n } as ConnectionOptions\n if (tls.key) {\n connectionOptions.key = TlsOptionsFactory.read(tcp.tls?.key ?? '')\n connectionOptions.cert = tcp.tls?.cert ? TlsOptionsFactory.read(tcp?.tls?.cert) : undefined\n }\n if (tcp.tls.ca && tcp.tls.ca.length > 0) {\n connectionOptions.ca = tcp.tls.ca.map(i => TlsOptionsFactory.read(i))\n }\n if (tcp.tls.timeout) {\n connectionOptions.timeout = tcp.tls.timeout\n }\n if (tcp.tls.sessionTimeout) {\n connectionOptions.sessionTimeout = tcp.tls.sessionTimeout\n }\n if (tls.nodeTlsConnectionOptions) {\n connectionOptions = {\n ...connectionOptions,\n ...tls.nodeTlsConnectionOptions\n }\n }\n }\n return connectionOptions\n }\n}\n"]}
1
+ {"version":3,"file":"tls-options-factory.js","sourceRoot":"","sources":["../../../src/transport/tcp/tls-options-factory.ts"],"names":[],"mappings":"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","sourcesContent":["import { ConnectionOptions, TlsOptions } from 'tls'\nimport { ITlsOptions } from './tls-options'\nimport { ITcpTransportDescription } from './tcp-transport-description'\nconst path = require('path')\nconst fs = require('fs')\n\nexport class TlsOptionsFactory {\n /*\n session descriptions are routinely hand written json, where a boolean flag is easily\n quoted by mistake i.e. \"rejectUnauthorized\": \"false\". node treats that string as truthy\n and so does exactly the opposite of what was intended, silently. accept the two string\n spellings rather than inverting the caller's meaning - anything else is left alone so it\n shows up as an obviously wrong value rather than being guessed at.\n */\n static asBoolean (value: any): any {\n if (typeof value === 'string') {\n const lowered = value.toLowerCase()\n if (lowered === 'true') return true\n if (lowered === 'false') return false\n }\n return value\n }\n\n static read (filePath: string): string {\n const root: string = path.join(__dirname, '../../../')\n const fullPath = path.join(root, filePath)\n return fs.readFileSync(fullPath,\n {\n encoding: 'utf8', flag: 'r'\n })\n }\n\n static getTlsOptions (tls: ITlsOptions): TlsOptions | null {\n let tlsOptions: TlsOptions | null = null\n if (tls) {\n tlsOptions = {\n requestCert: TlsOptionsFactory.asBoolean(tls.requestCert),\n rejectUnauthorized: TlsOptionsFactory.asBoolean(tls.rejectUnauthorized)\n } as TlsOptions\n\n if (tls.key) {\n tlsOptions.key = TlsOptionsFactory.read(tls.key)\n tlsOptions.cert = tls?.cert ? TlsOptionsFactory.read(tls?.cert) : undefined\n }\n\n if (tls.ca && tls.ca.length > 0) {\n tlsOptions.ca = tls.ca.map(i => TlsOptionsFactory.read(i))\n }\n\n if (tls.nodeTlsServerOptions) {\n tlsOptions = {\n ...tlsOptions,\n ...tls.nodeTlsServerOptions\n }\n }\n }\n return tlsOptions\n }\n\n static getTlsConnectionOptions (tcp: ITcpTransportDescription): ConnectionOptions | null {\n let connectionOptions: ConnectionOptions | null = null\n const tls = tcp.tls\n if (tls) {\n connectionOptions = {\n port: tcp.port,\n host: tcp.host\n } as ConnectionOptions\n if (tls.key) {\n connectionOptions.key = TlsOptionsFactory.read(tcp.tls?.key ?? '')\n connectionOptions.cert = tcp.tls?.cert ? TlsOptionsFactory.read(tcp?.tls?.cert) : undefined\n }\n if (tcp.tls.ca && tcp.tls.ca.length > 0) {\n connectionOptions.ca = tcp.tls.ca.map(i => TlsOptionsFactory.read(i))\n }\n if (tcp.tls.timeout) {\n connectionOptions.timeout = tcp.tls.timeout\n }\n if (tcp.tls.sessionTimeout) {\n connectionOptions.sessionTimeout = tcp.tls.sessionTimeout\n }\n // https://github.com/TimelordUK/jspurefix/issues/151 - ITlsOptions declares these and\n // getTlsOptions honours them on the server path, so map them here too rather than making\n // nodeTlsConnectionOptions the only spelling that works for an initiator. Applied before\n // the spread below so an explicit nodeTlsConnectionOptions value still wins.\n if (tls.requestCert !== undefined) {\n connectionOptions.requestCert = TlsOptionsFactory.asBoolean(tls.requestCert)\n }\n if (tls.rejectUnauthorized !== undefined) {\n connectionOptions.rejectUnauthorized = TlsOptionsFactory.asBoolean(tls.rejectUnauthorized)\n }\n if (tls.nodeTlsConnectionOptions) {\n connectionOptions = {\n ...connectionOptions,\n ...tls.nodeTlsConnectionOptions\n }\n if (connectionOptions.rejectUnauthorized !== undefined) {\n connectionOptions.rejectUnauthorized = TlsOptionsFactory.asBoolean(connectionOptions.rejectUnauthorized)\n }\n if (connectionOptions.requestCert !== undefined) {\n connectionOptions.requestCert = TlsOptionsFactory.asBoolean(connectionOptions.requestCert)\n }\n }\n }\n return connectionOptions\n }\n}\n"]}
@@ -0,0 +1,207 @@
1
+ # Running a FIX acceptor
2
+
3
+ The acceptor in jspurefix began as a smoke-test harness for the initiator — enough
4
+ to answer a Logon so the client side could be exercised. It is now used to host real
5
+ counterparties, and this document describes the model it follows, what it guarantees,
6
+ and what the log tells you.
7
+
8
+ Much of this is a back-port of
9
+ [cspurefix](https://github.com/TimelordUK/cspurefix), where the acceptor was hardened
10
+ against real brokers.
11
+
12
+ ## Transports and sessions are not the same thing
13
+
14
+ A **transport** is one TCP connection. A **session** is one FIX conversation,
15
+ identified by `SessionId` = `BeginString`-`SenderCompID`-`TargetCompID`, and owning
16
+ the sequence numbers and the message store behind that conversation.
17
+
18
+ The relationship is one session per transport, but a session **outlives** the
19
+ connection it started on: a counterparty that drops and reconnects is resuming the
20
+ same FIX session, from the same persisted sequence state, on a new transport.
21
+
22
+ ```
23
+ listener (TcpAcceptorListener)
24
+ └── acceptor (TcpAcceptor) one net/tls Server, one SessionRegistry
25
+ ├── transport 1 ──► session scope ──► FixSession ──► SessionId A ──► store A
26
+ ├── transport 2 ──► session scope ──► FixSession ──► SessionId B ──► store B
27
+ └── transport 3 ──► session scope ──► FixSession ──► SessionId A ──► store A
28
+ (replaces the first)
29
+ ```
30
+
31
+ ## Session scopes
32
+
33
+ Every accepted connection gets its own DI child container — a *session scope* —
34
+ carrying its own:
35
+
36
+ - parse buffer and transmit buffer (`ElasticBuffer`)
37
+ - `ISessionDescription`, and therefore its own `SessionId` and message store
38
+ - session message factory, so outbound headers carry that session's comp ids
39
+ - `IJsFixConfig`, which is what the application's session receives
40
+
41
+ This matters because those are otherwise process-wide singletons on the session
42
+ container. Two clients on one listener would parse into the same buffer and compute
43
+ the same `SessionId`.
44
+
45
+ Applications opt in by using the config they are **handed**, not the one they
46
+ captured:
47
+
48
+ ```ts
49
+ protected override makeFactory (config: IJsFixConfig): EngineFactory {
50
+ const isInitiator = this.isInitiator(config.description)
51
+ return {
52
+ // sessionConfig is this connection's own scope
53
+ makeSession: (sessionConfig: IJsFixConfig) => isInitiator
54
+ ? new MyClient(sessionConfig)
55
+ : new MyServer(sessionConfig)
56
+ } as EngineFactory
57
+ }
58
+ ```
59
+
60
+ Writing `makeSession: () => new MyServer(config)` closes over the launcher's config
61
+ and opts the application out of per-session isolation. It still works for a single
62
+ counterparty; it does not work for several.
63
+
64
+ ### Custom session message factories
65
+
66
+ If you supply your own `ISessionMsgFactory` — usually by overriding
67
+ `SessionContainer.makeSessionFactory` to stamp extra header fields — the scope needs
68
+ a copy of *your* factory bound to that session's description, not a stock one.
69
+
70
+ Extending `ASessionMsgFactory` (or `AsciiSessionMsgFactory` / `FixmlSessionMsgFactory`)
71
+ gets this for free: the default `cloneFor` reconstructs through the concrete
72
+ constructor, so a subclass taking `(description, mutator)` needs no extra work.
73
+ Override `cloneFor` if your constructor takes anything else:
74
+
75
+ ```ts
76
+ class BrokerMsgFactory extends AsciiSessionMsgFactory {
77
+ constructor (description: ISessionDescription, private readonly desk: string) {
78
+ super(description)
79
+ }
80
+
81
+ // the default clone would not know about `desk`
82
+ public override cloneFor (description: ISessionDescription): ISessionMsgFactory {
83
+ return new BrokerMsgFactory(description, this.desk)
84
+ }
85
+ }
86
+ ```
87
+
88
+ ## The session registry
89
+
90
+ FIX permits exactly one active session per `SessionId`. `SessionRegistry` enforces
91
+ that: a session claims its `SessionId` once its store is initialised, and any
92
+ *different* session already holding it is stopped first.
93
+
94
+ This is what answers the half-open socket problem. A counterparty whose network path
95
+ disappears without FIN or RST leaves the acceptor holding a socket it believes is
96
+ alive. When that counterparty reconnects and logs on, the registry stops the stale
97
+ session before the new one proceeds — otherwise two sessions write to one store and
98
+ the sequence numbers diverge beyond recovery.
99
+
100
+ ```
101
+ [SessionRegistry] FOUND EXISTING SESSION for FIX4.4-accept-comp-init-comp - this is a reconnection scenario
102
+ [SessionRegistry] stopping old session to prevent stale transport writes
103
+ [...FixSession] requestStop: replaced by new connection - stopping old session with stale transport
104
+ [SessionRegistry] session NOT unregistered (already replaced by new connection or not found): ...
105
+ ```
106
+
107
+ That last line is expected, not an error: the displaced session unregisters on its
108
+ way out, and the identity check stops it evicting its successor.
109
+
110
+ The listener creates a registry per listener. Supply your own via
111
+ `config.sessionRegistry` if you want to inspect it — `count`, `keys()` and `get()`
112
+ are read-only views over the live population.
113
+
114
+ An application can stop a session itself with `session.requestStop(reason)`.
115
+
116
+ ## Wildcard TargetCompID
117
+
118
+ An acceptor that sets `"TargetCompID": "*"` does not need to know its counterparties
119
+ in advance. On the first Logon the session adopts the peer's `SenderCompID` as its
120
+ target and only then builds the identity-derived state: `SessionId`, message store,
121
+ sequence coordinator, registry claim, and its logger name.
122
+
123
+ ```json
124
+ {
125
+ "SenderCompId": "accept-comp",
126
+ "TargetCompID": "*",
127
+ "store": { "type": "file", "directory": "store/acceptor" }
128
+ }
129
+ ```
130
+
131
+ Binding is deferred rather than done at construction so that each counterparty gets
132
+ its **own** store file — `FIX4.4-accept-comp-<peer>.seqnums` — which is what makes
133
+ persisted recovery work for a multi-client acceptor. (cspurefix binds in the
134
+ constructor and so keys a wildcard store on the literal `*`; that is fine for
135
+ in-memory stores only.)
136
+
137
+ Messages that arrive while the bind is in flight are queued and replayed in order.
138
+ `*` on an initiator is rejected at construction — an initiator has to know who it is
139
+ calling.
140
+
141
+ ## Detecting a peer that has gone
142
+
143
+ Three independent mechanisms, because no single one is sufficient:
144
+
145
+ | Level | Mechanism | Detects |
146
+ |-------|-----------|---------|
147
+ | Transport | TCP keep-alive (`tcp.keepAliveMs`, default 30s, `0` disables) | a peer whose host or network path has vanished |
148
+ | Protocol | `TestRequest` on heartbeat timeout, then terminate | a peer that is connected but not responding |
149
+ | Session | `SessionRegistry` replacing on the next Logon | a peer that has already reconnected |
150
+
151
+ `MsgTransport.end()` performs a graceful close and then destroys the socket after
152
+ `MsgTransport.lingerMs` (default 5s), so an unanswered FIN cannot pin the handle
153
+ indefinitely. `TcpAcceptor.close()` releases live connections rather than waiting on
154
+ them — `net.Server.close` otherwise blocks on whoever happens to be connected.
155
+
156
+ ## Reading the log
157
+
158
+ The lifecycle of one connection, in order:
159
+
160
+ ```
161
+ [TcpAcceptor] net creates session 2
162
+ [TcpAcceptor] transport 2 keep-alive enabled, initial delay 30000ms
163
+ [TcpAcceptor] transport 2 from ::1:55642 given its own session scope
164
+ [TcpAcceptor] new transport id = 2 from ::1:55642 created total transports = 2
165
+ [acceptor] transport 2: creating session via DI token FixSession [accept-comp -> *]
166
+ [acceptor] acceptor census: transports=2 [...] sessions=1 [...]
167
+ [...] wildcard acceptor: awaiting peer Logon to establish session identity
168
+ [...] wildcard acceptor: binding session identity to peer SenderCompID 'init-comp_2'
169
+ [...] session identity bound: FIX4.4-accept-comp-init-comp_2 nextSender=1, expectedTarget=1
170
+ [SessionRegistry] no existing session found - registering new session: FIX4.4-accept-comp-init-comp_2
171
+ ...
172
+ [SessionRegistry] successfully unregistered session: ..., remainingActiveSessions=1
173
+ [TcpAcceptor] transport 2 from ::1:55642 harvested after 18s (socket closed) total transports = 1
174
+ [acceptor] acceptor census: transports=1 [...] sessions=1 [...]
175
+ ```
176
+
177
+ The **census** line is emitted whenever the population changes and answers "how many
178
+ counterparties are connected, and which sessions are claimed" from the log alone.
179
+ Transports and sessions can legitimately differ for a moment: a connection that has
180
+ not logged on yet has a transport and no session; a session being replaced has both
181
+ counted until its socket is released.
182
+
183
+ Once a wildcard session has bound, its log prefix carries the counterparty
184
+ (`[my_server:init-comp_2:FixSession]`), so a multi-client server log can be read one
185
+ counterparty at a time.
186
+
187
+ ## Server-side recovery from a persisted store
188
+
189
+ With `"store": { "type": "file", "directory": "..." }` the acceptor persists, per
190
+ `SessionId`, the next sender sequence and the last processed peer sequence, plus the
191
+ sent message bodies for replay.
192
+
193
+ On a reconnect the session reads that store before responding to the Logon, so it
194
+ knows what it last sent and what it last received. If the peer's Logon sequence is
195
+ ahead of what the store expects, the acceptor issues a `ResendRequest`; if the peer
196
+ asks for a resend, the stored bodies are replayed with `PossDupFlag=Y`.
197
+ `ResetSeqNumFlag=Y` from either side clears the store and restarts at 1.
198
+
199
+ Because the store is keyed on `SessionId`, a wildcard acceptor recovers each
200
+ counterparty independently.
201
+
202
+ ## See also
203
+
204
+ - [`src/transport/tcp/tcp-acceptor.ts`](../src/transport/tcp/tcp-acceptor.ts) — listener, transport lifecycle
205
+ - [`src/transport/session/session-registry.ts`](../src/transport/session/session-registry.ts) — one session per SessionId
206
+ - [`src/runtime/session-scope.ts`](../src/runtime/session-scope.ts) — per-connection DI scope
207
+ - [jspf-demo](https://github.com/TimelordUK/jspf-demo) — `multi-client` and `stale-transport` scenarios
@@ -1,75 +1,62 @@
1
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:44:11.383|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=099|
2
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260702-18:44:11.389|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=153|
3
- 8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260702-18:44:11.390|7=1|16=1|10=232|
4
- 8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260702-18:44:11.395|122=20260702-18:44:11.394|123=Y|36=2|10=104|
5
- 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260702-18:44:13.395|58=5|10=215|
6
- 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260702-18:44:13.393|58=5|10=214|
7
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:44:16.213|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=096|
8
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260702-18:44:16.214|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=145|
9
- 8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260702-18:44:16.215|7=1|16=0|10=232|
10
- 8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260702-18:44:16.218|122=20260702-18:44:16.218|123=Y|36=2|10=103|
11
- 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260702-18:44:18.218|58=5|10=214|
12
- 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260702-18:44:18.217|58=5|10=214|
13
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:44:20.696|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=106|
14
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260702-18:44:20.697|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=155|
15
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=2|57=fix|52=20260702-18:44:20.697|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=108|
16
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:44:21.232|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=093|
17
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260702-18:44:21.233|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=142|
18
- 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260702-18:44:22.237|58=5|10=210|
19
- 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260702-18:44:22.235|58=5|10=208|
20
- 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260702-18:44:22.700|58=5|10=206|
21
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:44:24.949|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=111|
22
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260702-18:44:24.951|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=152|
23
- 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260702-18:44:25.953|58=5|10=218|
24
- 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260702-18:44:25.952|58=5|10=217|
25
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:44:28.714|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=105|
26
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260702-18:44:28.716|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=155|
27
- 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=0|57=fix|52=20260702-18:44:29.718|58=5|10=219|
28
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:44:32.201|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=091|
29
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=5|57=fix|52=20260702-18:44:32.202|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=144|
30
- 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260702-18:44:33.205|58=5|10=207|
31
- 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260702-18:44:33.204|58=5|10=206|
32
- 8=FIX.4.4|9=0000110|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:44:35.682|98=0|141=Y|553=js-client|554=pwd-client|10=175|
33
- 8=FIX.4.4|9=0000125|35=3|49=accept-comp|56=init-comp|34=1|57=fix|52=20260702-18:44:35.683|45=1|372=A|373=1|58=msgType A missing required tag 108|10=009|
34
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:44:40.298|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=106|
35
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260702-18:44:40.300|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=138|
36
- 8=FIX.4.4|9=0000111|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260702-18:44:40.301|45=2|372=ZZ|373=11|58=msgType ZZ unknown|10=140|
37
- 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260702-18:44:42.302|58=5|10=206|
38
- 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260702-18:44:42.301|58=5|10=205|
39
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:44:45.057|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=104|
40
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260702-18:44:45.059|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=154|
41
- 8=FIX.4.4|9=0000146|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260702-18:44:45.061|45=2|372=0|373=5|58=msgType 0 checksum failed. received = 95 computed = 143|10=069|
42
- 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260702-18:44:47.061|58=5|10=213|
43
- 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260702-18:44:47.060|58=5|10=212|
44
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:44:49.059|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=110|
45
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:44:49.059|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=110|
46
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:44:53.545|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=105|
47
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260702-18:44:53.546|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=154|
48
- 8=FIX.4.4|9=0000145|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260702-18:44:53.548|45=2|372=0|373=5|58=msgType 0 checksum failed. received = 95 computed = 59|10=035|
49
- 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260702-18:44:55.548|58=5|10=222|
50
- 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260702-18:44:55.547|58=5|10=221|
51
- 8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:44:58.026|98=0|108=2|141=Y|553=js-client|554=pwd-client|10=054|
52
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260702-18:44:58.027|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=153|
53
- 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260702-18:45:00.032|112=Thu, 02 Jul 2026 18:45:00 GMT|10=144|
54
- 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260702-18:45:02.036|112=Thu, 02 Jul 2026 18:45:02 GMT|10=153|
55
- 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260702-18:45:04.029|58=5|10=210|
56
- 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=4|57=fix|52=20260702-18:45:04.028|58=5|10=211|
57
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:45:06.501|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=096|
58
- 8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260702-18:45:06.502|98=0|108=2|141=Y|553=js-server|554=pwd-server|10=095|
59
- 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260702-18:45:08.505|112=Thu, 02 Jul 2026 18:45:08 GMT|10=165|
60
- 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=3|57=fix|52=20260702-18:45:10.509|112=Thu, 02 Jul 2026 18:45:10 GMT|10=156|
61
- 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=4|57=fix|52=20260702-18:45:12.514|112=Thu, 02 Jul 2026 18:45:12 GMT|10=157|
62
- 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=5|57=fix|52=20260702-18:45:14.504|58=5|10=212|
63
- 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260702-18:45:14.503|58=5|10=208|
64
- 8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:45:17.227|98=0|108=2|141=Y|553=js-client|554=pwd-client|10=053|
65
- 8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260702-18:45:17.229|98=0|108=5|141=Y|553=js-server|554=pwd-server|10=106|
66
- 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260702-18:45:19.235|112=Thu, 02 Jul 2026 18:45:19 GMT|10=169|
67
- 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260702-18:45:21.238|112=Thu, 02 Jul 2026 18:45:21 GMT|10=159|
68
- 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260702-18:45:22.241|112=Thu, 02 Jul 2026 18:45:22 GMT|10=154|
69
- 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=4|57=fix|52=20260702-18:45:23.241|112=Thu, 02 Jul 2026 18:45:23 GMT|10=158|
70
- 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260702-18:45:25.231|58=5|10=209|
71
- 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=5|57=fix|52=20260702-18:45:25.230|58=5|10=210|
72
- 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260702-18:46:56.521|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=104|
73
- 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260702-18:46:56.531|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=153|
74
- 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260702-18:46:57.536|58=5|10=222|
75
- 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260702-18:46:57.534|58=5|10=220|
1
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:51:15.489|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=104|
2
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260801-14:51:15.494|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=148|
3
+ 8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260801-14:51:15.495|7=1|16=1|10=236|
4
+ 8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260801-14:51:15.500|122=20260801-14:51:15.500|123=Y|36=2|10=077|
5
+ 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260801-14:51:17.499|58=5|10=218|
6
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:51:20.313|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=086|
7
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260801-14:51:20.315|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=136|
8
+ 8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260801-14:51:20.315|7=1|16=0|10=222|
9
+ 8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260801-14:51:20.318|122=20260801-14:51:20.318|123=Y|36=2|10=083|
10
+ 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260801-14:51:22.318|58=5|10=204|
11
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:51:24.804|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=095|
12
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260801-14:51:24.806|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=145|
13
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=2|57=fix|52=20260801-14:51:24.806|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=098|
14
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:51:25.344|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=095|
15
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260801-14:51:25.345|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=144|
16
+ 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260801-14:51:26.347|58=5|10=210|
17
+ 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260801-14:51:26.807|58=5|10=212|
18
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:51:29.063|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=097|
19
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260801-14:51:29.065|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=147|
20
+ 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260801-14:51:30.068|58=5|10=205|
21
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:51:32.552|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=094|
22
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260801-14:51:32.553|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=143|
23
+ 8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=0|57=fix|52=20260801-14:51:33.554|58=5|10=206|
24
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:51:36.035|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=094|
25
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=5|57=fix|52=20260801-14:51:36.036|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=147|
26
+ 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260801-14:51:37.039|58=5|10=210|
27
+ 8=FIX.4.4|9=0000110|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:51:39.686|98=0|141=Y|553=js-client|554=pwd-client|10=177|
28
+ 8=FIX.4.4|9=0000125|35=3|49=accept-comp|56=init-comp|34=1|57=fix|52=20260801-14:51:39.687|45=1|372=A|373=1|58=msgType A missing required tag 108|10=011|
29
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:51:44.447|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=100|
30
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260801-14:51:44.449|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=150|
31
+ 8=FIX.4.4|9=0000111|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260801-14:51:44.451|45=2|372=ZZ|373=11|58=msgType ZZ unknown|10=144|
32
+ 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260801-14:51:46.451|58=5|10=209|
33
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:51:48.955|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=108|
34
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260801-14:51:48.956|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=157|
35
+ 8=FIX.4.4|9=0000146|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260801-14:51:48.958|45=2|372=0|373=5|58=msgType 0 checksum failed. received = 95 computed = 143|10=081|
36
+ 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260801-14:51:50.959|58=5|10=217|
37
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:51:52.957|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=105|
38
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:51:57.567|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=107|
39
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260801-14:51:57.568|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=156|
40
+ 8=FIX.4.4|9=0000145|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260801-14:51:57.569|45=2|372=0|373=5|58=msgType 0 checksum failed. received = 95 computed = 59|10=036|
41
+ 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260801-14:51:59.570|58=5|10=215|
42
+ 8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:52:02.309|98=0|108=2|141=Y|553=js-client|554=pwd-client|10=042|
43
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260801-14:52:02.310|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=132|
44
+ 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260801-14:52:04.315|112=Sat, 01 Aug 2026 14:52:04 GMT|10=120|
45
+ 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260801-14:52:06.317|112=Sat, 01 Aug 2026 14:52:06 GMT|10=127|
46
+ 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260801-14:52:08.313|58=5|10=204|
47
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:52:10.828|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=097|
48
+ 8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260801-14:52:10.829|98=0|108=2|141=Y|553=js-server|554=pwd-server|10=096|
49
+ 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260801-14:52:12.833|112=Sat, 01 Aug 2026 14:52:12 GMT|10=123|
50
+ 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=3|57=fix|52=20260801-14:52:14.838|112=Sat, 01 Aug 2026 14:52:14 GMT|10=133|
51
+ 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=4|57=fix|52=20260801-14:52:16.841|112=Sat, 01 Aug 2026 14:52:16 GMT|10=132|
52
+ 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=5|57=fix|52=20260801-14:52:18.831|58=5|10=213|
53
+ 8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:52:21.327|98=0|108=2|141=Y|553=js-client|554=pwd-client|10=043|
54
+ 8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260801-14:52:21.328|98=0|108=5|141=Y|553=js-server|554=pwd-server|10=095|
55
+ 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260801-14:52:23.334|112=Sat, 01 Aug 2026 14:52:23 GMT|10=123|
56
+ 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260801-14:52:25.336|112=Sat, 01 Aug 2026 14:52:25 GMT|10=130|
57
+ 8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260801-14:52:26.339|112=Sat, 01 Aug 2026 14:52:26 GMT|10=134|
58
+ 8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=4|57=fix|52=20260801-14:52:27.338|112=Sat, 01 Aug 2026 14:52:27 GMT|10=137|
59
+ 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260801-14:52:29.330|58=5|10=207|
60
+ 8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260801-14:54:22.785|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=104|
61
+ 8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260801-14:54:22.794|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=152|
62
+ 8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260801-14:54:23.799|58=5|10=221|