• src/sbbs3/zmodem.c zmodem.h

    From Deucе@1:103/705 to Git commit to main/sbbs/master on Sun Aug 23 13:41:08 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/ea25028dae163a6c982d08e5
    Modified Files:
    src/sbbs3/zmodem.c zmodem.h
    Log Message:
    Relicense ZModem code under a 2-clause BSD licnese.
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)
  • From Rob Swindell (on Debian Linux)@1:103/705 to Git commit to main/sbbs/master on Mon Aug 24 20:32:03 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/81e5e3a3a6f008a7e11ff590
    Modified Files:
    src/sbbs3/zmodem.c zmodem.h
    Log Message:
    zmodem: derive the receive fast path from one table of plain bytes

    zmodem_rx() decided per byte, through a switch, whether the byte it had just read needed handling: ZDLE introduces an escape, the four XON/XOFF forms are dropped as flow control, and when the peer negotiated ZF0_ESCCTL a control character that arrived unescaped is dropped too. Everything else is returned verbatim, which on ordinary data is the overwhelming majority of bytes.

    Precompute that predicate into a 256-entry table and test it before the
    switch. The switch is then reached only by bytes that genuinely need it, and the common case is one indexed load. A 256 MiB localhost receive goes from 126.9 to 153.0 MB/s and from 2.11 to 1.74 CPU-seconds.

    The table is built in zmodem_init() and rebuilt where escape_ctrl_chars is assigned from the peer's ZRINIT, which is the only place it changes. Building it eagerly rather than on demand avoids needing a sentinel to distinguish
    "not built yet" from "built for escape_ctrl_chars == FALSE"; zmodem_init() memsets the struct, so any such sentinel would have to be assigned anyway and is easy to forget.

    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)