Declare the alphabet a GSM message is actually written in (#100)
* Regression tests for the alphabet a GSM message declares * Declare the alphabet a GSM message is actually written in * Reflow the composing-by-hand paragraph * Drop the ASCII alias SMPP's flat table shares with the option's own * Bound the receipt test's wait and tighten the notes around it
This commit is contained in:
@@ -152,6 +152,7 @@ naming the behaviour.
|
||||
| Short segments | `splitMsg` accumulates a full segment then pushes `msgPart.slice(0, -1)`, so every segment is one character short: 152 GSM characters instead of 153, 66 UCS2 instead of 67. Long messages are split into more segments than they need, and each extra segment is billed |
|
||||
| DLR month off by one | `smppDate()` uses `getMonth()` (0-based) without `+1`, so January renders as `00` |
|
||||
| Non-standard DLR status | Receipts emit `stat:UNDELIVERABLE`; the spec's field is 7 characters (`UNDELIV`) |
|
||||
| GSM 03.38 declared as IA5 | `sendSms` resolves its encoding through `consts.ENCODING`, so a GSM body goes out under `data_coding` 0x01 — SMPP 3.4 5.2.19's IA5 (CCITT T.50), where `$` and `@` are STX and NUL |
|
||||
| Flash destroys UCS2 | `flash: true` overwrites `data_coding` with 0x10, discarding the UCS2 alphabet, which needs 0x18 |
|
||||
| Shared concat reference | The concatenation reference counter is a module-level global shared by every session in the process |
|
||||
| `send()` never times out | Each call adds a listener keyed on the sequence number; a peer that never answers leaks it and the promise never settles |
|
||||
@@ -670,6 +671,38 @@ Grouped by what each one constrains.
|
||||
field, which `data_coding` says nothing about — an address is a C-Octet String and ASCII by 3.4's
|
||||
own definition.
|
||||
|
||||
- **A GSM 03.38 message declares `data_coding` 0x00, and an inbound 0x01 is still read as GSM.**
|
||||
Maintainer's call, 2026-09-09: `dataCodingFor()` and `encodeBody()` both resolved an alphabet
|
||||
through `consts.ENCODING`, so `encoding: 'ASCII'` went out as 0x01 — SMPP 3.4 5.2.19's *IA5 (CCITT
|
||||
T.50)/ASCII* — while the codec writes GSM 03.38, where `$` is 0x02 and `@` is 0x00 against IA5's
|
||||
STX and NUL. Goal 1 owns it, and this library's own reader hid it by resolving both codings to the
|
||||
same codec. `dataCodingByEncoding` is the single answer to which coding an alphabet is written
|
||||
under, as `unencodable()` is to whether one can carry a message: the mirror of
|
||||
`encodingByDataCoding()`, and reached by both the `sendSms()` path and `encodeBody()`'s detected
|
||||
one rather than each spelling the map again, which is what `sendDlr()` inherits it through. It is
|
||||
exported for the reason `unencodable()` is — a caller pairing `encodeMessage()`'s octets with a
|
||||
`data_coding` of its own had only `consts.ENCODING` to reach for, which is the trap. 0x00 is the
|
||||
*SMSC's* default alphabet rather than 03.38 by name, so it is a convention rather than a guarantee;
|
||||
it is also what every peer in `interop-tests/` submits under and what LINK Mobility, Route Mobile
|
||||
and Telesign all publish 03.38 as, where 0x01 names a different alphabet from the one written and
|
||||
so is wrong whatever the peer makes of it. Reading is untouched, goal 3: those same three map 0x01
|
||||
to 03.38 too, and Kaleyra and Route Mobile publish that value as known to cause problems, so no
|
||||
researched peer means IA5 by it. The two tables agree over most of the printable range and part at
|
||||
0x00-0x09, 0x0B-0x0C, 0x0E-0x1A, 0x1C-0x1F, 0x24, 0x40, 0x5B-0x60 and 0x7B-0x7F — line feed,
|
||||
carriage return and escape are common to both — which is where a peer that did mean IA5 is
|
||||
misread. Accepted with it: `consts.ENCODING` loses its `ASCII` alias and keeps `IA5`, the two
|
||||
names 5.2.19 gives 0x01, because that alias was the only name the two tables shared at different
|
||||
values and so the only one a reader could carry from the option's vocabulary into SMPP's flat
|
||||
table; `constsById.ENCODING[0x01]` already read `IA5`, so nothing moves but the forward name.
|
||||
Rejected: moving `consts.ENCODING.ASCII` to 0x00, which would make that table contradict the
|
||||
section it exists to spell — the group is SMPP's flat `data_coding` table, not the `encoding`
|
||||
option's vocabulary, the distinction the `FLASH` removal already drew. Rejected: reading 0x01 as
|
||||
Latin-1, the closest codec here to IA5, which mojibakes every peer that means GSM for one nothing
|
||||
researched has found. Accepted: a message already in flight is unmoved — both codings resolve to
|
||||
the same codec, `messageClassOf()` finds no class in either, and `Reassembler` groups on the
|
||||
concatenation reference rather than on `data_coding` — so a receipt or a segment that crossed the
|
||||
change reads exactly as it did.
|
||||
|
||||
### The session's life
|
||||
|
||||
- **A close arriving after our own `unbind` is a clean unbind, not an error.** Maintainer's call,
|
||||
|
||||
Reference in New Issue
Block a user