https://gitlab.synchro.net/main/sbbs/-/commit/d16135c1046c973abab5afad
Modified Files:
src/sbbs3/sexyz.c zmodem.c zmodem.h
Log Message:
zmodem: rebuild the plain-byte table when a receiver sets EscapeCtrlChars
rx_plain_tab[] caches escape_ctrl_chars, and the commit that derived the receive fast path from it rebuilt the table in only two places:
zmodem_init(), and zmodem_parse_zrinit(). A receiver never reaches the
second one -- only a sender parses a received ZRINIT -- so on the receive
side the table was whatever zmodem_init() built, with the flag still at
its FALSE default.
sexyz then assigns zm.escape_ctrl_chars directly from sexyz.ini's EscapeCtrlChars (sexyz.c), after zmodem_init() and with nothing to
rebuild the table. With EscapeCtrlChars=true a receive therefore ran
with a table that called control characters plain, and both new paths
took them at face value: zmodem_rx() returned them verbatim and
recv_span() copied them into the subpacket, where the old code dropped
them as "unescaped ctrl char". That is the whole point of ESCCTL, and
the config exists for exactly the links that need it.
Rebuild in zmodem_send_zrinit(). A receive session always passes
through it, the consumer's value is necessarily final there -- the
ZRINIT built in that function is what announces ESCCTL to the peer --
and it costs a 256-iteration loop once per session. Reproduced and
verified with a harness that replays sexyz's init order: before, an escape_ctrl_chars set after zmodem_init() left rx_plain_tab[0x01]=1;
after, send_zrinit() brings it to 0.
Since escape_ctrl_chars is a public struct field any consumer may
assign, say so where it is declared and list the three rebuild points in
the table function's comment.
Also stop bypassing recv_byte()'s DebugRx trace. The span path skips recv_byte() entirely, so with DebugRx=true the per-byte RX log lost
every byte a span carried -- around 97 % of the stream on random data,
leaving a trace of nothing but escapes. Disable the span path when
debug_rx is set, the way it already is for telnet mode, on the same
grounds: both are cases where recv_byte() has to see every byte. No
cost when the flag is off.
No throughput change: 484.4 MB/s against 484.2 before, receiver CPU
0.55 s. Clean receives verify byte-identical 3 of 3 and the 3e-6
corruption gate passes 5 of 5, sender gate 3 of 3.
Found by reviewing the series after the sexyz 3.5 release, at Rob
Swindell's request.
---
þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net