jspurefix 5.10.4 → 5.10.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ATDL_PLAN.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # FIXatdl renderer and end-to-end test harness
2
2
 
3
- Design notes from 2026-08-08. Nothing is built yet. This exists so the next session
4
- can start from the thinking rather than redo it.
3
+ Design notes from 2026-08-08, fixtures added 2026-08-09. Nothing is built yet. This
4
+ exists so the next session can start from the thinking rather than redo it.
5
5
 
6
- **First decision to settle:** this is not jspurefix work and should almost certainly
7
- live in its own repository (`jspf-atdl`, or similar). The plan is parked here because
8
- it is where the conversation happened and because the back-end half does use the
9
- engine. Move it when the code starts.
6
+ **Where this lives:** staying in jspurefix for now (decided 2026-08-09). It is not
7
+ engine work and will want its own repository once there is code, but the back-end half
8
+ is a jspurefix acceptor and there is no benefit to a second repository holding only a
9
+ markdown file.
10
10
 
11
11
  ---
12
12
 
@@ -15,7 +15,7 @@ engine. Move it when the code starts.
15
15
  A broker publishes a FIXatdl document per algorithm: an XML definition of its
16
16
  parameters and the order ticket used to fill them in. An EMS — Bloomberg EMSX,
17
17
  Flextrade, Portware, Fidessa, ITG Triton — renders the ticket from that document, and
18
- the values map onto FIX tags, usually the `NoStrategyParameters` group.
18
+ the values map onto FIX tags.
19
19
 
20
20
  The observed pain, in more than one shop: getting a definition rendered is cobbled
21
21
  together, and **you cannot tell whether a definition is sound until a vendor renders
@@ -98,12 +98,80 @@ is FIXML-shaped and is not a good fit for this.
98
98
 
99
99
  ~1,500 lines of interpreter, zero runtime dependencies.
100
100
 
101
+ ## Fixtures
102
+
103
+ The expression engine is only as good as what it is tested against, and this is the
104
+ part most likely to be underestimated. Real broker documents vary enormously and most
105
+ are proprietary — the user has worked at a bank where every algo was defined in ATDL,
106
+ none of it publishable.
107
+
108
+ ### routefire/rf-fix-atdl
109
+
110
+ `rf_strategies-v1.1.xml` — the first public fixture, 184 lines, 7 strategies (TWAP,
111
+ VWAP, PVOL, ISO, FAST, ULMT, RLMT).
112
+
113
+ What it settles:
114
+
115
+ - **Version is 1.1.** Namespaces are `.../FIXatdl-1-1/Core`, `/Validation`, `/Layout`,
116
+ `/Flow`, `/Timezones`. Target 1.1 and stop worrying about it.
117
+ - **Strategy identification is an attribute of `<Strategies>`:**
118
+ `strategyIdentifierTag="847"` and `versionIdentifierTag="7621"`, with each
119
+ `<Strategy>` carrying `wireValue`. So the algorithm is named on the wire in tag 847
120
+ and the parameters go elsewhere.
121
+ - **Parameters carry their own `fixTag`** — `126`, `168`, and customs `8001`–`8004`
122
+ here. This resolves the earlier open question about `NoStrategyParameters`: the
123
+ mapping is *data driven per parameter*, not a per-broker configuration switch. Build
124
+ it from the `fixTag` attribute; treat the strategy-parameters group as a second
125
+ mode for documents that omit `fixTag`, not as the default.
126
+ - Useful attributes in the wild: `use="required|optional"`, `minValue`/`maxValue`,
127
+ `localMktTz`, `initValue`, `initValueMode`, `increment`.
128
+
129
+ **What it does not exercise, which matters more.** This file is a skeleton — good for
130
+ proving the parser, nearly useless for proving the interpreter:
131
+
132
+ | | |
133
+ |---|---|
134
+ | `StateRule` | **none at all** — zero occurrences |
135
+ | Control types | only `Clock_t`, `SingleSpinner_t`, `TextField_t` |
136
+ | Parameter types | only `Float_t`, `Int_t`, `UTCTimestamp_t` |
137
+ | `EnumPair` | none — so no dropdowns, no radio groups, no checkboxes |
138
+ | Validation | two `val:StrategyEdit`, each a single `val:Edit`, operator `GT` only |
139
+ | `logicOperator` / `editRef` | none — no AND/OR, no reusable named edits |
140
+ | `flow:` | namespace declared, never used |
141
+
142
+ So it will not tell us whether the hard half is right. Enable/disable/visibility logic
143
+ is entirely absent, and validation never gets beyond one field-to-field comparison.
144
+
145
+ ### What a representative fixture needs
146
+
147
+ Worth building by hand from experience rather than waiting to find one. Aim to cover:
148
+
149
+ - `StateRule` driving `enabled`, `visible` and value assignment, keyed off another
150
+ control's value
151
+ - a `StateRule` chain — B depends on A, C depends on B — to prove evaluation order and
152
+ catch cycles
153
+ - `DropDownList_t` and `RadioButtonList_t` with `EnumPair` (`wireValue` distinct from
154
+ `uiRep`, which is where renderers commonly go wrong)
155
+ - `CheckBox_t` and its `checkedEnumRef` / `uncheckedEnumRef`
156
+ - `val:Edit` with `logicOperator="AND"` / `"OR"` and nested edits
157
+ - `val:Edit` comparing against a literal `value=` as well as `field2=`
158
+ - a named `<val:Edit id="...">` referenced by `editRef`, since reuse is where scoping
159
+ bugs live
160
+ - `use="required"` interacting with a control that a `StateRule` has disabled — what
161
+ should validation do then? Real documents disagree, and vendors disagree with each
162
+ other
163
+ - a deliberately broken document, so the tool's error reporting is exercised too
164
+
101
165
  ## Open questions for next session
102
166
 
103
- 1. Own repository or a folder here? (Recommendation: own repository.)
104
- 2. Which real ATDL documents can be used as test fixtures? The expression engine is
105
- only as good as what it is tested against, and broker-published files vary a lot.
106
- 3. Which FIXatdl version to target. 1.1 is the one in widespread use; confirm before
107
- writing the parser rather than after.
108
- 4. How strategy parameters map onto the outbound order — the `NoStrategyParameters`
109
- group versus direct custom tags — likely needs to be configurable per broker.
167
+ 1. ~~Own repository or a folder here?~~ Settled: stays here for now.
168
+ 2. ~~Which FIXatdl version?~~ Settled: 1.1.
169
+ 3. ~~How do parameters map onto the order?~~ Settled: per-parameter `fixTag`, with the
170
+ strategy-parameters group as a fallback mode.
171
+ 4. Can any further public documents be found, or is the hand-built fixture above the
172
+ realistic path? The user has significant algo trading experience and can produce
173
+ something representative — that is likely to be worth more than another public file
174
+ of the routefire kind.
175
+ 5. What does the harness do when a `StateRule` disables a `required` parameter? Decide
176
+ deliberately and document it, because it is the sort of thing that differs between
177
+ EMSs and is exactly what the tool exists to surface.
package/README.md CHANGED
@@ -13,6 +13,7 @@ A fast, fully native TypeScript [FIX protocol](https://www.fixtrading.org/) engi
13
13
  - [Quickstart](#quickstart)
14
14
  - [Session Configuration](#session-configuration)
15
15
  - [Customising the Logon](#customising-the-logon)
16
+ - [Accepting or refusing a logon](#accepting-or-refusing-a-logon)
16
17
  - [TLS](#tls)
17
18
  - [Body length padding](#body-length-padding)
18
19
  - [Persistence & Recovery](#persistence--recovery)
@@ -168,6 +169,29 @@ Most counterparties want a tag on the Logon the standard message does not carry.
168
169
 
169
170
  A field named here must also be declared on `Logon` in the dictionary the session loads, or the encoder has no tag to write it to and will say so in the log. For values computed at run time, or for a header a counterparty stamps differently, supply your own session message factory. See [docs/custom-logon.md](docs/custom-logon.md) for the whole picture.
170
171
 
172
+ ### Accepting or refusing a logon
173
+
174
+ `onLogon` is where an acceptor decides who gets a session. Return `true` to let the handshake finish; return `false` and the peer is sent a `Logout` explaining why and then disconnected — `onReady` is never reached and no heartbeat starts. The application learns the outcome through `onStopped(error)`.
175
+
176
+ ```ts
177
+ protected onLogon (view: MsgView, user: string, password: string): boolean {
178
+ return user === 'js-client' && password === this.expectedPassword
179
+ }
180
+ ```
181
+
182
+ Credentials usually have to be checked against something the engine cannot wait on synchronously — an http api, a database, a secrets store. Return a promise and the session waits for it:
183
+
184
+ ```ts
185
+ protected async onLogon (view: MsgView, user: string, password: string): Promise<boolean> {
186
+ const account = await this.directory.lookup(user)
187
+ return account?.enabled === true && await account.verify(password)
188
+ }
189
+ ```
190
+
191
+ While that promise is pending the transport is paused and anything the peer sends is queued, then replayed in order once the verdict arrives — a counterparty that pipelines messages behind its Logon will not have them dropped or reordered. If the promise rejects, the logon is refused rather than allowed through, and the rejection message is carried to the peer.
192
+
193
+ An initiator can use the same hook: there `onLogon` fires on the acceptor's logon response, so returning `false` refuses the counterparty that answered.
194
+
171
195
  ### TLS
172
196
 
173
197
  Add a `tls` block under `application.tcp`. The `ca` field is only needed for self-signed certificates; commercial vendors will supply this for you. `script/getKey.ps1` will generate a self-signed CA + client/server pair (requires `openssl` on the path).
@@ -19,7 +19,7 @@ const mathjs_1 = require("mathjs");
19
19
  const tsyringe_1 = require("tsyringe");
20
20
  const di_tokens_1 = require("../runtime/di-tokens");
21
21
  let ElasticBuffer = ElasticBuffer_1 = class ElasticBuffer {
22
- constructor(size = 6 * 1024, returnTo = 6 * 1024) {
22
+ constructor(size = 6 * 1024, returnTo = 64 * 1024) {
23
23
  this.size = size;
24
24
  this.returnTo = returnTo;
25
25
  this.ptr = 0;
@@ -50,7 +50,7 @@ let ElasticBuffer = ElasticBuffer_1 = class ElasticBuffer {
50
50
  }
51
51
  setPos(ptr) {
52
52
  const r = this.ptr;
53
- if (ptr >= 0 && ptr <= this.size) {
53
+ if (ptr >= 0 && ptr <= this.buffer.length) {
54
54
  this.ptr = ptr;
55
55
  }
56
56
  return r;
@@ -130,7 +130,7 @@ let ElasticBuffer = ElasticBuffer_1 = class ElasticBuffer {
130
130
  const shrink = this.stretched > this.returnTo;
131
131
  if (shrink) {
132
132
  this.buffer = Buffer.allocUnsafe(this.returnTo);
133
- this.stretched = this.size;
133
+ this.stretched = this.returnTo;
134
134
  }
135
135
  return shrink;
136
136
  }
@@ -1 +1 @@
1
- {"version":3,"file":"elastic-buffer.js","sourceRoot":"","sources":["../../src/buffer/elastic-buffer.ts"],"names":[],"mappings":"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","sourcesContent":["import { AsciiChars } from './ascii/ascii-chars'\nimport { format } from 'mathjs'\nimport { inject, injectable } from 'tsyringe'\nimport { DITokens } from '../runtime/di-tokens'\n\n@injectable()\nexport class ElasticBuffer {\n private buffer: Buffer\n private ptr: number = 0\n private stretched: number\n\n constructor (@inject(DITokens.elasticBufferSize) public readonly size: number = 6 * 1024,\n @inject(DITokens.elasticBufferReturnSize) public readonly returnTo: number = 6 * 1024) {\n this.size = Math.max(1, this.size)\n this.buffer = Buffer.allocUnsafe(this.size)\n this.returnTo = Math.max(this.size, this.returnTo)\n this.stretched = this.size\n }\n\n private static precisionRound (n: number, precision: number): number {\n const factor: number = Math.pow(10, precision)\n return Math.round(n * factor) / factor\n }\n\n private static HowManyDigits (v: number): number {\n v = Math.abs(v)\n let digits: number = 0\n let w: number = v\n while (w > 0) {\n ++digits\n w = Math.floor(w / 10)\n }\n return Math.max(digits, 1)\n }\n\n public currentSize (): number {\n return this.stretched\n }\n\n public getPos (): number {\n return this.ptr\n }\n\n public setPos (ptr: number): number {\n const r = this.ptr\n if (ptr >= 0 && ptr <= this.size) {\n this.ptr = ptr\n }\n return r\n }\n\n public get (pos: number): number {\n return this.buffer[pos]\n }\n\n public writeBoolean (v: boolean): number {\n this.writeChar(v ? AsciiChars.Y : AsciiChars.N)\n return this.ptr\n }\n\n public switchChar (c: number): number {\n this.buffer[this.ptr - 1] = c\n return this.ptr\n }\n\n public saveChar (c: number): number {\n this.buffer[this.ptr++] = c\n return this.ptr\n }\n\n public writeChar (c: number): number {\n if (c > 255) throw new Error(`can't write ${c} to a byte`)\n this.checkGrowBuffer(1)\n this.buffer[this.ptr++] = c\n return this.ptr\n }\n\n public writeString (s: string): number {\n const begin = this.ptr\n this.checkGrowBuffer(s.length)\n const buffer = this.buffer\n this.ptr += buffer.write(s, begin, s.length, 'ascii')\n return this.ptr\n }\n\n public writeBuffer (v: Buffer): number {\n const begin = this.ptr\n this.checkGrowBuffer(v.length)\n const buffer = this.buffer\n const srcLen: number = v.length\n this.ptr += v.copy(buffer, begin, 0, srcLen)\n return this.ptr\n }\n\n public writeWholeNumber (n: number): number {\n const digits: number = ElasticBuffer.HowManyDigits(n)\n let reserve = digits\n const sign: number = Math.sign(n)\n let p: number = Math.pow(10, digits - 1)\n let v: number = Math.abs(n)\n if (sign < 0) {\n reserve++\n }\n this.checkGrowBuffer(reserve)\n const buffer = this.buffer\n if (sign < 0) {\n buffer[this.ptr++] = AsciiChars.Minus\n }\n while (p >= 1) {\n const d: number = Math.floor(v / p)\n v -= d * p\n p /= 10\n buffer[this.ptr++] = AsciiChars.Zero + d\n }\n\n return this.ptr\n }\n\n public writeNumber (v: number, places: number = 13): number {\n const rounded: number = Math.floor(v)\n const fraction: number = ElasticBuffer.precisionRound(v - rounded, places)\n if (fraction === 0) {\n // integer\n return this.writeWholeNumber(v)\n } else {\n // decimal with fraction turn to string\n const s: string = format(v, { notation: 'fixed' })\n return this.writeString(s)\n }\n }\n\n public reset (): boolean {\n this.ptr = 0\n const shrink = this.stretched > this.returnTo\n if (shrink) {\n this.buffer = Buffer.allocUnsafe(this.returnTo)\n this.stretched = this.size\n }\n return shrink\n }\n\n public slice (): Buffer {\n return this.buffer.subarray(0, this.ptr)\n }\n\n public copy (): Buffer {\n const m = Buffer.alloc(this.ptr)\n this.buffer.copy(m, 0, 0, this.ptr)\n return m\n }\n\n public clone (): ElasticBuffer {\n const cloned = new ElasticBuffer(this.ptr)\n this.buffer.copy(cloned.buffer, 0, 0, this.ptr)\n cloned.setPos(this.ptr)\n return cloned\n }\n\n public writePaddedHundreds (v: number): number {\n if (v > 999) throw new Error(`can't write ${v} as hundreds padding`)\n this.checkGrowBuffer(3)\n const buffer = this.buffer\n const zero: number = AsciiChars.Zero\n const units: number = v % 10 + zero\n v = v / 10\n const tens: number = v % 10 + zero\n v = v / 10\n buffer[this.ptr++] = v % 10 + zero\n buffer[this.ptr++] = tens\n buffer[this.ptr++] = units\n return this.ptr\n }\n\n public writePaddedTensUnits (v: number): number {\n if (v > 99) throw new Error(`can't write ${v} as hundreds padding`)\n this.checkGrowBuffer(2)\n const buffer = this.buffer\n const zero: number = AsciiChars.Zero\n const units: number = v % 10 + zero\n v = v / 10\n buffer[this.ptr++] = v % 10 + zero\n buffer[this.ptr++] = units\n return this.ptr\n }\n\n public patchPaddedNumberAtPos (ptr: number, numToWrite: number, padding: number): void {\n let digits: number = ElasticBuffer.HowManyDigits(numToWrite)\n const saved: number = this.ptr\n this.ptr = ptr\n const buffer = this.buffer\n while (digits++ < padding) {\n buffer[this.ptr++] = AsciiChars.Zero\n }\n this.writeWholeNumber(numToWrite)\n this.ptr = saved\n }\n\n public toString (ptr: number = this.ptr): string {\n return this.buffer.toString('ascii', 0, ptr)\n }\n\n public checksum (ptr: number = this.ptr): number {\n const cks: number = this.sum(ptr)\n return cks % 256\n }\n\n public sum (ptr: number = this.ptr): number {\n let total: number = 0\n ptr = Math.min(ptr, this.ptr)\n const buffer = this.buffer\n for (let idx: number = 0; idx < ptr; idx++) {\n total += buffer[idx]\n }\n return total\n }\n\n public getWholeNumber (start: number, vend: number): number {\n const buffer = this.buffer\n let sign = 1\n let raised = vend - start\n switch (buffer[start]) {\n case AsciiChars.Minus: {\n --raised\n sign = -1\n ++start\n break\n }\n case AsciiChars.Plus: {\n --raised\n ++start\n break\n }\n }\n let i: number = Math.pow(10, raised)\n let num: number = 0\n let scan: number = start\n\n while (scan <= vend) {\n const p: number = buffer[scan++]\n const d: number = p - AsciiChars.Zero\n num += d * i\n i /= 10\n }\n\n return num * sign\n }\n\n public getString (start: number, end: number): string {\n return this.buffer.toString('ascii', start, end)\n }\n\n public getBuffer (start: number, end: number): Buffer {\n return this.buffer.subarray(start, end)\n }\n\n public getBoolean (start: number): boolean {\n const b: number = this.buffer[start]\n return b === AsciiChars.Y\n }\n\n public getFloat (start: number, vend: number): number | null {\n let n: number = 0\n let digits: number = 0\n let dotPosition: number = 0\n const buffer = this.buffer\n let sign = 1\n switch (buffer[start]) {\n case AsciiChars.Minus: {\n sign = -1\n start++\n break\n }\n case AsciiChars.Plus: {\n start++\n break\n }\n }\n const len = vend - start\n let i: number = Math.pow(10, len - 1)\n for (let j: number = start; j <= vend; ++j) {\n const p: number = buffer[j]\n if (p >= AsciiChars.Zero && p <= AsciiChars.Nine) {\n const d: number = p - AsciiChars.Zero\n ++digits\n n += d * i\n i /= 10\n } else if (p === AsciiChars.Dot) {\n if (dotPosition > 0) {\n return null\n }\n dotPosition = j - start\n } else if (digits > 0) {\n return null\n }\n }\n const power: number = dotPosition === 0 ? 0 : len - dotPosition\n const raised = dotPosition === 0 ? 10 : Math.pow(10, -1 * power)\n const round = dotPosition === 0 ? 1 : Math.pow(10, power)\n const val = n * raised * sign\n return Math.round(val * round) / round\n }\n\n public checkGrowBuffer (required: number): void {\n let buffer = this.buffer\n let size = buffer.length\n const ptr = this.ptr\n if (size - ptr >= required) {\n return\n }\n while (size - ptr < required) {\n size *= 2\n }\n const old = buffer\n buffer = Buffer.allocUnsafe(size)\n old.copy(buffer, 0, 0, this.ptr)\n this.buffer = buffer\n this.stretched = size\n }\n}\n"]}
1
+ {"version":3,"file":"elastic-buffer.js","sourceRoot":"","sources":["../../src/buffer/elastic-buffer.ts"],"names":[],"mappings":"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","sourcesContent":["import { AsciiChars } from './ascii/ascii-chars'\nimport { format } from 'mathjs'\nimport { inject, injectable } from 'tsyringe'\nimport { DITokens } from '../runtime/di-tokens'\n\n@injectable()\nexport class ElasticBuffer {\n private buffer: Buffer\n private ptr: number = 0\n private stretched: number\n\n /**\n * A buffer grown to serve a large message keeps that capacity across reset, so a\n * steady stream of similarly sized messages does not re-grow (and re-allocate) on\n * every single message. Only a buffer that has ballooned past returnTo is handed\n * back, so one pathological message cannot pin a large allocation for the life of\n * the session. Unlike cspurefix - where the discarded array goes to a shared\n * ArrayPool - the retained bytes are held by this instance, so an acceptor with\n * many connections holds up to this much per connection. Tune with\n * DITokens.elasticBufferReturnSize.\n */\n constructor (@inject(DITokens.elasticBufferSize) public readonly size: number = 6 * 1024,\n @inject(DITokens.elasticBufferReturnSize) public readonly returnTo: number = 64 * 1024) {\n this.size = Math.max(1, this.size)\n this.buffer = Buffer.allocUnsafe(this.size)\n this.returnTo = Math.max(this.size, this.returnTo)\n this.stretched = this.size\n }\n\n private static precisionRound (n: number, precision: number): number {\n const factor: number = Math.pow(10, precision)\n return Math.round(n * factor) / factor\n }\n\n private static HowManyDigits (v: number): number {\n v = Math.abs(v)\n let digits: number = 0\n let w: number = v\n while (w > 0) {\n ++digits\n w = Math.floor(w / 10)\n }\n return Math.max(digits, 1)\n }\n\n public currentSize (): number {\n return this.stretched\n }\n\n public getPos (): number {\n return this.ptr\n }\n\n public setPos (ptr: number): number {\n const r = this.ptr\n if (ptr >= 0 && ptr <= this.buffer.length) {\n this.ptr = ptr\n }\n return r\n }\n\n public get (pos: number): number {\n return this.buffer[pos]\n }\n\n public writeBoolean (v: boolean): number {\n this.writeChar(v ? AsciiChars.Y : AsciiChars.N)\n return this.ptr\n }\n\n public switchChar (c: number): number {\n this.buffer[this.ptr - 1] = c\n return this.ptr\n }\n\n public saveChar (c: number): number {\n this.buffer[this.ptr++] = c\n return this.ptr\n }\n\n public writeChar (c: number): number {\n if (c > 255) throw new Error(`can't write ${c} to a byte`)\n this.checkGrowBuffer(1)\n this.buffer[this.ptr++] = c\n return this.ptr\n }\n\n public writeString (s: string): number {\n const begin = this.ptr\n this.checkGrowBuffer(s.length)\n const buffer = this.buffer\n this.ptr += buffer.write(s, begin, s.length, 'ascii')\n return this.ptr\n }\n\n public writeBuffer (v: Buffer): number {\n const begin = this.ptr\n this.checkGrowBuffer(v.length)\n const buffer = this.buffer\n const srcLen: number = v.length\n this.ptr += v.copy(buffer, begin, 0, srcLen)\n return this.ptr\n }\n\n public writeWholeNumber (n: number): number {\n const digits: number = ElasticBuffer.HowManyDigits(n)\n let reserve = digits\n const sign: number = Math.sign(n)\n let p: number = Math.pow(10, digits - 1)\n let v: number = Math.abs(n)\n if (sign < 0) {\n reserve++\n }\n this.checkGrowBuffer(reserve)\n const buffer = this.buffer\n if (sign < 0) {\n buffer[this.ptr++] = AsciiChars.Minus\n }\n while (p >= 1) {\n const d: number = Math.floor(v / p)\n v -= d * p\n p /= 10\n buffer[this.ptr++] = AsciiChars.Zero + d\n }\n\n return this.ptr\n }\n\n public writeNumber (v: number, places: number = 13): number {\n const rounded: number = Math.floor(v)\n const fraction: number = ElasticBuffer.precisionRound(v - rounded, places)\n if (fraction === 0) {\n // integer\n return this.writeWholeNumber(v)\n } else {\n // decimal with fraction turn to string\n const s: string = format(v, { notation: 'fixed' })\n return this.writeString(s)\n }\n }\n\n public reset (): boolean {\n this.ptr = 0\n const shrink = this.stretched > this.returnTo\n if (shrink) {\n this.buffer = Buffer.allocUnsafe(this.returnTo)\n this.stretched = this.returnTo\n }\n return shrink\n }\n\n public slice (): Buffer {\n return this.buffer.subarray(0, this.ptr)\n }\n\n public copy (): Buffer {\n const m = Buffer.alloc(this.ptr)\n this.buffer.copy(m, 0, 0, this.ptr)\n return m\n }\n\n public clone (): ElasticBuffer {\n const cloned = new ElasticBuffer(this.ptr)\n this.buffer.copy(cloned.buffer, 0, 0, this.ptr)\n cloned.setPos(this.ptr)\n return cloned\n }\n\n public writePaddedHundreds (v: number): number {\n if (v > 999) throw new Error(`can't write ${v} as hundreds padding`)\n this.checkGrowBuffer(3)\n const buffer = this.buffer\n const zero: number = AsciiChars.Zero\n const units: number = v % 10 + zero\n v = v / 10\n const tens: number = v % 10 + zero\n v = v / 10\n buffer[this.ptr++] = v % 10 + zero\n buffer[this.ptr++] = tens\n buffer[this.ptr++] = units\n return this.ptr\n }\n\n public writePaddedTensUnits (v: number): number {\n if (v > 99) throw new Error(`can't write ${v} as hundreds padding`)\n this.checkGrowBuffer(2)\n const buffer = this.buffer\n const zero: number = AsciiChars.Zero\n const units: number = v % 10 + zero\n v = v / 10\n buffer[this.ptr++] = v % 10 + zero\n buffer[this.ptr++] = units\n return this.ptr\n }\n\n public patchPaddedNumberAtPos (ptr: number, numToWrite: number, padding: number): void {\n let digits: number = ElasticBuffer.HowManyDigits(numToWrite)\n const saved: number = this.ptr\n this.ptr = ptr\n const buffer = this.buffer\n while (digits++ < padding) {\n buffer[this.ptr++] = AsciiChars.Zero\n }\n this.writeWholeNumber(numToWrite)\n this.ptr = saved\n }\n\n public toString (ptr: number = this.ptr): string {\n return this.buffer.toString('ascii', 0, ptr)\n }\n\n public checksum (ptr: number = this.ptr): number {\n const cks: number = this.sum(ptr)\n return cks % 256\n }\n\n public sum (ptr: number = this.ptr): number {\n let total: number = 0\n ptr = Math.min(ptr, this.ptr)\n const buffer = this.buffer\n for (let idx: number = 0; idx < ptr; idx++) {\n total += buffer[idx]\n }\n return total\n }\n\n public getWholeNumber (start: number, vend: number): number {\n const buffer = this.buffer\n let sign = 1\n let raised = vend - start\n switch (buffer[start]) {\n case AsciiChars.Minus: {\n --raised\n sign = -1\n ++start\n break\n }\n case AsciiChars.Plus: {\n --raised\n ++start\n break\n }\n }\n let i: number = Math.pow(10, raised)\n let num: number = 0\n let scan: number = start\n\n while (scan <= vend) {\n const p: number = buffer[scan++]\n const d: number = p - AsciiChars.Zero\n num += d * i\n i /= 10\n }\n\n return num * sign\n }\n\n public getString (start: number, end: number): string {\n return this.buffer.toString('ascii', start, end)\n }\n\n public getBuffer (start: number, end: number): Buffer {\n return this.buffer.subarray(start, end)\n }\n\n public getBoolean (start: number): boolean {\n const b: number = this.buffer[start]\n return b === AsciiChars.Y\n }\n\n public getFloat (start: number, vend: number): number | null {\n let n: number = 0\n let digits: number = 0\n let dotPosition: number = 0\n const buffer = this.buffer\n let sign = 1\n switch (buffer[start]) {\n case AsciiChars.Minus: {\n sign = -1\n start++\n break\n }\n case AsciiChars.Plus: {\n start++\n break\n }\n }\n const len = vend - start\n let i: number = Math.pow(10, len - 1)\n for (let j: number = start; j <= vend; ++j) {\n const p: number = buffer[j]\n if (p >= AsciiChars.Zero && p <= AsciiChars.Nine) {\n const d: number = p - AsciiChars.Zero\n ++digits\n n += d * i\n i /= 10\n } else if (p === AsciiChars.Dot) {\n if (dotPosition > 0) {\n return null\n }\n dotPosition = j - start\n } else if (digits > 0) {\n return null\n }\n }\n const power: number = dotPosition === 0 ? 0 : len - dotPosition\n const raised = dotPosition === 0 ? 10 : Math.pow(10, -1 * power)\n const round = dotPosition === 0 ? 1 : Math.pow(10, power)\n const val = n * raised * sign\n return Math.round(val * round) / round\n }\n\n public checkGrowBuffer (required: number): void {\n let buffer = this.buffer\n let size = buffer.length\n const ptr = this.ptr\n if (size - ptr >= required) {\n return\n }\n while (size - ptr < required) {\n size *= 2\n }\n const old = buffer\n buffer = Buffer.allocUnsafe(size)\n old.copy(buffer, 0, 0, this.ptr)\n this.buffer = buffer\n this.stretched = size\n }\n}\n"]}
@@ -6,7 +6,7 @@ export declare class AsciiSessionMsgFactory extends ASessionMsgFactory {
6
6
  readonly description: ISessionDescription;
7
7
  constructor(description: ISessionDescription, mutator?: ObjectMutator | null);
8
8
  logon(): ILooseObject;
9
- logout(text: string): ILooseObject;
9
+ logout(msgType: string, text: string): ILooseObject;
10
10
  header(msgType: string, seqNum: number, time: Date, overrideData?: Partial<IStandardHeader>): ILooseObject;
11
11
  }
12
12
  export declare class SessionMsgFactory extends AsciiSessionMsgFactory {
@@ -16,11 +16,11 @@ class AsciiSessionMsgFactory extends a_session_msg_factory_1.ASessionMsgFactory
16
16
  const o = Object.assign({ Username: description.Username, Password: description.Password, HeartBtInt: description.HeartBtInt, ResetSeqNumFlag: description.ResetSeqNumFlag, EncryptMethod: repo_1.EncryptMethod.None }, description.Logon);
17
17
  return this.mutate(o, types_1.MsgType.Logon);
18
18
  }
19
- logout(text) {
19
+ logout(msgType, text) {
20
20
  const o = {
21
21
  Text: text
22
22
  };
23
- return this.mutate(o, types_1.MsgType.Logout);
23
+ return this.mutate(o, msgType !== null && msgType !== void 0 ? msgType : types_1.MsgType.Logout);
24
24
  }
25
25
  header(msgType, seqNum, time, overrideData) {
26
26
  var _a;
@@ -1 +1 @@
1
- {"version":3,"file":"ascii-session-msg-factory.js","sourceRoot":"","sources":["../../../src/transport/ascii/ascii-session-msg-factory.ts"],"names":[],"mappings":";;;AAEA,uCAAqC;AACrC,4EAAoF;AAEpF,kDAKgC;AAEhC,MAAa,sBAAuB,SAAQ,0CAAkB;IAC5D,YAAsB,WAAgC,EAAE,UAAgC,IAAI;;QAC1F,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QADP,gBAAW,GAAX,WAAW,CAAqB;QAEpD,IAAI,CAAC,OAAO,GAAG,CAAA,MAAA,WAAW,CAAC,WAAW,0CAAE,QAAQ,MAAK,OAAO,CAAA;IAC9D,CAAC;IAEM,KAAK;QACV,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAA;QACpC,MAAM,CAAC,GAAW,gBAChB,QAAQ,EAAE,WAAW,CAAC,QAAQ,EAC9B,QAAQ,EAAE,WAAW,CAAC,QAAQ,EAC9B,UAAU,EAAE,WAAW,CAAC,UAAU,EAClC,eAAe,EAAE,WAAW,CAAC,eAAe,EAC5C,aAAa,EAAE,oBAAa,CAAC,IAAI,IAK9B,WAAW,CAAC,KAAK,CACX,CAAA;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,eAAO,CAAC,KAAK,CAAC,CAAA;IACtC,CAAC;IAEM,MAAM,CAAE,IAAY;QACzB,MAAM,CAAC,GAAY;YACjB,IAAI,EAAE,IAAI;SACA,CAAA;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,eAAO,CAAC,MAAM,CAAC,CAAA;IACvC,CAAC;IAEM,MAAM,CAAE,OAAe,EAAE,MAAc,EAAE,IAAU,EAAE,YAAuC;;QACjG,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAA;QACpC,MAAM,UAAU,GAAW,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAA,WAAW,CAAC,eAAe,mCAAI,CAAC,CAAC,CAAA;QACxE,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;QACpD,MAAM,CAAC,mBACL,WAAW,EAAE,WAAW,CAAC,WAAW,EACpC,UAAU,EAAE,WAAW,EACvB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,WAAW,CAAC,YAAY,EACtC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,IAAI,EACjB,YAAY,EAAE,WAAW,CAAC,YAAY,EACtC,WAAW,EAAE,WAAW,CAAC,WAAW,EACpC,WAAW,EAAE,WAAW,CAAC,WAAW,IACjC,YAAY,CAChB,CAAA;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAA;IACzC,CAAC;CACF;AAhDD,wDAgDC;AAED,MAAa,iBAAkB,SAAQ,sBAAsB;IAC3D,YAA6B,WAAgC,EAAS,UAAgC,IAAI;QACxG,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QADA,gBAAW,GAAX,WAAW,CAAqB;QAAS,YAAO,GAAP,OAAO,CAA6B;IAE1G,CAAC;CACF;AAJD,8CAIC","sourcesContent":["import { ISessionDescription } from '../session/session-description'\nimport { ILooseObject } from '../../collections/collection'\nimport { MsgType } from '../../types'\nimport { ASessionMsgFactory, ObjectMutator } from '../session/a-session-msg-factory'\n\nimport {\n EncryptMethod,\n ILogon,\n ILogout,\n IStandardHeader\n} from '../../types/FIX4.4/repo'\n\nexport class AsciiSessionMsgFactory extends ASessionMsgFactory {\n constructor (readonly description: ISessionDescription, mutator: ObjectMutator | null = null) {\n super(description, mutator)\n this.isAscii = description.application?.protocol === 'ascii'\n }\n\n public logon (): ILooseObject {\n const description = this.description\n const o: ILogon = {\n Username: description.Username,\n Password: description.Password,\n HeartBtInt: description.HeartBtInt,\n ResetSeqNumFlag: description.ResetSeqNumFlag,\n EncryptMethod: EncryptMethod.None,\n // a counterparty demanding a tag the standard Logon does not carry needs no\n // code at all - name it under \"Logon\" in the session description. Spread last\n // so an application can also override what the engine derived, or null out a\n // field it does not want sent. See issue #93.\n ...description.Logon\n } as ILogon\n return this.mutate(o, MsgType.Logon)\n }\n\n public logout (text: string): ILooseObject {\n const o: ILogout = {\n Text: text\n } as ILogout\n return this.mutate(o, MsgType.Logout)\n }\n\n public header (msgType: string, seqNum: number, time: Date, overrideData?: Partial<IStandardHeader>): ILooseObject {\n const description = this.description\n const bodyLength: number = Math.max(4, description.BodyLengthChars ?? 7)\n const placeHolder = Math.pow(10, bodyLength - 1) + 1\n const o: IStandardHeader = {\n BeginString: description.BeginString,\n BodyLength: placeHolder,\n MsgType: msgType,\n SenderCompID: description.SenderCompId,\n MsgSeqNum: seqNum,\n SendingTime: time,\n TargetCompID: description.TargetCompID,\n TargetSubID: description.TargetSubID,\n SenderSubID: description.SenderSubID,\n ...overrideData\n }\n return this.mutate(o, 'StandardHeader')\n }\n}\n\nexport class SessionMsgFactory extends AsciiSessionMsgFactory {\n constructor (public readonly description: ISessionDescription, public mutator: ObjectMutator | null = null) {\n super(description, mutator)\n }\n}\n"]}
1
+ {"version":3,"file":"ascii-session-msg-factory.js","sourceRoot":"","sources":["../../../src/transport/ascii/ascii-session-msg-factory.ts"],"names":[],"mappings":";;;AAEA,uCAAqC;AACrC,4EAAoF;AAEpF,kDAKgC;AAEhC,MAAa,sBAAuB,SAAQ,0CAAkB;IAC5D,YAAsB,WAAgC,EAAE,UAAgC,IAAI;;QAC1F,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QADP,gBAAW,GAAX,WAAW,CAAqB;QAEpD,IAAI,CAAC,OAAO,GAAG,CAAA,MAAA,WAAW,CAAC,WAAW,0CAAE,QAAQ,MAAK,OAAO,CAAA;IAC9D,CAAC;IAEM,KAAK;QACV,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAA;QACpC,MAAM,CAAC,GAAW,gBAChB,QAAQ,EAAE,WAAW,CAAC,QAAQ,EAC9B,QAAQ,EAAE,WAAW,CAAC,QAAQ,EAC9B,UAAU,EAAE,WAAW,CAAC,UAAU,EAClC,eAAe,EAAE,WAAW,CAAC,eAAe,EAC5C,aAAa,EAAE,oBAAa,CAAC,IAAI,IAK9B,WAAW,CAAC,KAAK,CACX,CAAA;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,eAAO,CAAC,KAAK,CAAC,CAAA;IACtC,CAAC;IAQM,MAAM,CAAE,OAAe,EAAE,IAAY;QAC1C,MAAM,CAAC,GAAY;YACjB,IAAI,EAAE,IAAI;SACA,CAAA;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,eAAO,CAAC,MAAM,CAAC,CAAA;IAClD,CAAC;IAEM,MAAM,CAAE,OAAe,EAAE,MAAc,EAAE,IAAU,EAAE,YAAuC;;QACjG,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAA;QACpC,MAAM,UAAU,GAAW,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAA,WAAW,CAAC,eAAe,mCAAI,CAAC,CAAC,CAAA;QACxE,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;QACpD,MAAM,CAAC,mBACL,WAAW,EAAE,WAAW,CAAC,WAAW,EACpC,UAAU,EAAE,WAAW,EACvB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,WAAW,CAAC,YAAY,EACtC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,IAAI,EACjB,YAAY,EAAE,WAAW,CAAC,YAAY,EACtC,WAAW,EAAE,WAAW,CAAC,WAAW,EACpC,WAAW,EAAE,WAAW,CAAC,WAAW,IACjC,YAAY,CAChB,CAAA;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAA;IACzC,CAAC;CACF;AAtDD,wDAsDC;AAED,MAAa,iBAAkB,SAAQ,sBAAsB;IAC3D,YAA6B,WAAgC,EAAS,UAAgC,IAAI;QACxG,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QADA,gBAAW,GAAX,WAAW,CAAqB;QAAS,YAAO,GAAP,OAAO,CAA6B;IAE1G,CAAC;CACF;AAJD,8CAIC","sourcesContent":["import { ISessionDescription } from '../session/session-description'\nimport { ILooseObject } from '../../collections/collection'\nimport { MsgType } from '../../types'\nimport { ASessionMsgFactory, ObjectMutator } from '../session/a-session-msg-factory'\n\nimport {\n EncryptMethod,\n ILogon,\n ILogout,\n IStandardHeader\n} from '../../types/FIX4.4/repo'\n\nexport class AsciiSessionMsgFactory extends ASessionMsgFactory {\n constructor (readonly description: ISessionDescription, mutator: ObjectMutator | null = null) {\n super(description, mutator)\n this.isAscii = description.application?.protocol === 'ascii'\n }\n\n public logon (): ILooseObject {\n const description = this.description\n const o: ILogon = {\n Username: description.Username,\n Password: description.Password,\n HeartBtInt: description.HeartBtInt,\n ResetSeqNumFlag: description.ResetSeqNumFlag,\n EncryptMethod: EncryptMethod.None,\n // a counterparty demanding a tag the standard Logon does not carry needs no\n // code at all - name it under \"Logon\" in the session description. Spread last\n // so an application can also override what the engine derived, or null out a\n // field it does not want sent. See issue #93.\n ...description.Logon\n } as ILogon\n return this.mutate(o, MsgType.Logon)\n }\n\n /**\n * ISessionMsgFactory declares logout (msgType, text) and FixSession calls it that\n * way. This override used to take the text alone, so it silently bound the msg\n * type to Text and every Logout jspurefix sent carried '58=5' in place of the\n * reason - the caller's message was dropped on the floor.\n */\n public logout (msgType: string, text: string): ILooseObject {\n const o: ILogout = {\n Text: text\n } as ILogout\n return this.mutate(o, msgType ?? MsgType.Logout)\n }\n\n public header (msgType: string, seqNum: number, time: Date, overrideData?: Partial<IStandardHeader>): ILooseObject {\n const description = this.description\n const bodyLength: number = Math.max(4, description.BodyLengthChars ?? 7)\n const placeHolder = Math.pow(10, bodyLength - 1) + 1\n const o: IStandardHeader = {\n BeginString: description.BeginString,\n BodyLength: placeHolder,\n MsgType: msgType,\n SenderCompID: description.SenderCompId,\n MsgSeqNum: seqNum,\n SendingTime: time,\n TargetCompID: description.TargetCompID,\n TargetSubID: description.TargetSubID,\n SenderSubID: description.SenderSubID,\n ...overrideData\n }\n return this.mutate(o, 'StandardHeader')\n }\n}\n\nexport class SessionMsgFactory extends AsciiSessionMsgFactory {\n constructor (public readonly description: ISessionDescription, public mutator: ObjectMutator | null = null) {\n super(description, mutator)\n }\n}\n"]}
@@ -18,6 +18,7 @@ export declare abstract class AsciiSession extends FixSession {
18
18
  protected readonly wildcardTarget: boolean;
19
19
  private identityBound;
20
20
  private bindInProgress;
21
+ private logonVerdictPending;
21
22
  private readonly pendingRx;
22
23
  private readonly clock;
23
24
  protected constructor(config: IJsFixConfig);
@@ -42,11 +43,16 @@ export declare abstract class AsciiSession extends FixSession {
42
43
  protected onSessionMsg(msgType: string, view: MsgView): void;
43
44
  protected onMsg(msgType: string, view: MsgView): void;
44
45
  private onMsgBeforeIdentity;
46
+ private rxGated;
47
+ private resumeRx;
45
48
  private drainPendingRx;
46
49
  private bindIdentity;
47
50
  private dispatchMsg;
48
51
  private startTimer;
49
52
  private peerLogon;
53
+ private awaitLogonVerdict;
54
+ private completePeerLogon;
55
+ private rejectLogon;
50
56
  private sendTestRequest;
51
57
  private sendHeartbeat;
52
58
  private tick;
@@ -29,6 +29,7 @@ class AsciiSession extends fix_session_1.FixSession {
29
29
  this.store = null;
30
30
  this.registered = false;
31
31
  this.bindInProgress = false;
32
+ this.logonVerdictPending = false;
32
33
  this.pendingRx = [];
33
34
  this.clock = new fix_clock_1.DefaultFixClock();
34
35
  this.requestLogoutType = this.respondLogoutType = types_1.MsgType.Logout;
@@ -419,6 +420,11 @@ class AsciiSession extends fix_session_1.FixSession {
419
420
  this.onMsgBeforeIdentity(msgType, view);
420
421
  return;
421
422
  }
423
+ if (this.logonVerdictPending) {
424
+ this.sessionLogger.info(`queueing '${msgType}' received while awaiting logon verdict`);
425
+ this.pendingRx.push({ msgType, view: view.clone() });
426
+ return;
427
+ }
422
428
  this.dispatchMsg(msgType, view);
423
429
  }
424
430
  onMsgBeforeIdentity(msgType, view) {
@@ -441,20 +447,34 @@ class AsciiSession extends fix_session_1.FixSession {
441
447
  const logon = view.clone();
442
448
  (_b = (_a = this.transport) === null || _a === void 0 ? void 0 : _a.duplex.readable) === null || _b === void 0 ? void 0 : _b.pause();
443
449
  this.bindIdentity(peerCompId).then(() => {
444
- var _a, _b;
445
450
  this.bindInProgress = false;
446
451
  this.identityBound = true;
447
452
  this.dispatchMsg(types_1.MsgType.Logon, logon);
448
- this.drainPendingRx();
449
- (_b = (_a = this.transport) === null || _a === void 0 ? void 0 : _a.duplex.readable) === null || _b === void 0 ? void 0 : _b.resume();
453
+ this.resumeRx();
450
454
  }).catch((e) => {
451
455
  this.bindInProgress = false;
452
456
  this.pendingRx.length = 0;
453
457
  this.terminate(new Error(`failed to bind session identity for peer '${peerCompId}': ${e.message}`));
454
458
  });
455
459
  }
460
+ rxGated() {
461
+ return this.bindInProgress || this.logonVerdictPending;
462
+ }
463
+ resumeRx() {
464
+ var _a, _b;
465
+ if (this.rxGated())
466
+ return;
467
+ this.drainPendingRx();
468
+ if (this.rxGated())
469
+ return;
470
+ (_b = (_a = this.transport) === null || _a === void 0 ? void 0 : _a.duplex.readable) === null || _b === void 0 ? void 0 : _b.resume();
471
+ }
456
472
  drainPendingRx() {
457
473
  while (this.pendingRx.length > 0) {
474
+ if (this.rxGated()) {
475
+ this.sessionLogger.info('suspending replay - logon handshake gated again');
476
+ return;
477
+ }
458
478
  const queued = this.pendingRx.shift();
459
479
  if (!queued)
460
480
  break;
@@ -528,7 +548,7 @@ class AsciiSession extends fix_session_1.FixSession {
528
548
  }, interval);
529
549
  }
530
550
  peerLogon(view) {
531
- var _a, _b, _c;
551
+ var _a, _b;
532
552
  const logger = this.sessionLogger;
533
553
  const [heartBtInt, peerCompId, userName, password] = view.getTypedTags([types_1.MsgTag.HeartBtInt, types_1.MsgTag.SenderCompID, types_1.MsgTag.Username, types_1.MsgTag.Password]);
534
554
  const resetSeqNumFlag = view.getTyped(types_1.MsgTag.ResetSeqNumFlag);
@@ -557,18 +577,57 @@ class AsciiSession extends fix_session_1.FixSession {
557
577
  const state = this.sessionState;
558
578
  state.peerHeartBeatSecs = view.getTyped(types_1.MsgTag.HeartBtInt);
559
579
  state.peerCompId = view.getTyped(types_1.MsgTag.SenderCompID);
560
- const res = this.onLogon(view, userName, password);
561
- logger.info(`peerLogon onLogon returns ${res}`);
580
+ const verdict = this.onLogon(view, userName, password);
581
+ if (typeof verdict === 'boolean') {
582
+ this.completePeerLogon(view, verdict, resetSeqNumFlag);
583
+ return;
584
+ }
585
+ this.awaitLogonVerdict(view, verdict, resetSeqNumFlag);
586
+ }
587
+ awaitLogonVerdict(view, verdict, peerReset) {
588
+ var _a, _b;
589
+ const logger = this.sessionLogger;
590
+ logger.info('onLogon returned a promise - awaiting logon verdict');
591
+ this.logonVerdictPending = true;
592
+ const logon = view.clone();
593
+ (_b = (_a = this.transport) === null || _a === void 0 ? void 0 : _a.duplex.readable) === null || _b === void 0 ? void 0 : _b.pause();
594
+ verdict.then((accepted) => {
595
+ this.logonVerdictPending = false;
596
+ if (this.sessionState.state === tcp_1.SessionState.Stopped) {
597
+ logger.info('session stopped while awaiting logon verdict - discarding');
598
+ this.pendingRx.length = 0;
599
+ return;
600
+ }
601
+ this.completePeerLogon(logon, accepted, peerReset);
602
+ if (!accepted) {
603
+ this.pendingRx.length = 0;
604
+ return;
605
+ }
606
+ this.resumeRx();
607
+ }).catch((e) => {
608
+ this.logonVerdictPending = false;
609
+ this.pendingRx.length = 0;
610
+ this.rejectLogon(`onLogon failed: ${e.message}`);
611
+ });
612
+ }
613
+ completePeerLogon(view, accepted, peerReset) {
614
+ var _a;
615
+ const logger = this.sessionLogger;
616
+ logger.info(`peerLogon onLogon returns ${accepted}`);
617
+ if (!accepted) {
618
+ this.rejectLogon('logon rejected by application');
619
+ return;
620
+ }
562
621
  if (this.acceptor) {
563
622
  this.setState(tcp_1.SessionState.InitiationLogonResponse);
564
623
  logger.info('acceptor responds to logon request');
565
624
  const weReset = this.config.description.ResetSeqNumFlag;
566
- if (weReset && resetSeqNumFlag !== true) {
625
+ if (weReset && peerReset !== true) {
567
626
  logger.info('acceptor sending ResetSeqNumFlag=Y (peer sent N), resetting sequences');
568
627
  this.coordinator.resetAsAcceptor().catch((e) => {
569
628
  this.sessionLogger.warning(`coordinator.resetAsAcceptor store persist failed: ${e.message}`);
570
629
  });
571
- const transmitter = (_c = this.transport) === null || _c === void 0 ? void 0 : _c.transmitter;
630
+ const transmitter = (_a = this.transport) === null || _a === void 0 ? void 0 : _a.transmitter;
572
631
  if (transmitter) {
573
632
  transmitter.msgSeqNum = 1;
574
633
  }
@@ -593,6 +652,11 @@ class AsciiSession extends fix_session_1.FixSession {
593
652
  logger.info('system ready, inform app');
594
653
  this.onReady(view);
595
654
  }
655
+ rejectLogon(reason) {
656
+ this.sessionLogger.warning(`refusing peer logon: ${reason}`);
657
+ this.sendLogout(reason);
658
+ this.terminate(new Error(reason));
659
+ }
596
660
  sendTestRequest() {
597
661
  const factory = this.config.factory;
598
662
  this.setState(tcp_1.SessionState.AwaitingProcessingResponseToTestRequest);