• src/sbbs3/sexyz.c zmodem.c zmodem.h

    From Rob Swindell@VERT to Git commit to main/sbbs/master on Fri Dec 4 00:17:14 2020
    https://gitlab.synchro.net/main/sbbs/-/commit/483c86debf4357fbdcf83bf2
    Modified Files:
    src/sbbs3/sexyz.c zmodem.c zmodem.h
    Log Message:
    ZMODEM Window Management support

    The default is still full-streaming mode. The default can be changed by
    setting [ZMODEM] MaxWindowSize in sexyz.ini to a maximum window size to
    use by default (e.g. "100K"). Additionally, a [ZMODDEM] TargetWindowSize
    can be set to a duration (e.g. 60s) to dynamically adjust the maximum
    window size to match the through-put rate while keeping the outstanding data in-flight to an estimated "duration". When TargetWindowSize is used, the MaxWindowSize only specifies the *initial* maximum window size.

    The new '-w' command-line option can be used to control Window Management support (e.g. over-riding the .ini set default) - by using '-w' or '-w0', Window Management won't be used or by using '-w<max-size>', a maximum window size will be imposed (subject to the TargetWindowSize setting mentioned
    above). <max-size> can be specified in bytes or multiples (e.g. "-w100K").
    Ths option is similar to the [l]sz '-w' option except no space is expected between '-w' and the (optional) max-size value.

    Also new, when receiving [ZMODEM] FullDuplex can be set to FALSE to disable streaming mode: if the RecvBufSize is not set (0), the sender should use the subpacket data length (block size, e.g. 1K) as the segment size. Otherwise, setting FullDuplex=FALSE should produce the same behavior as setting the RecvBufSize would before (the result being the use of "segmented ZMODEM" instead of "streaming ZMODEM").

    All sexyz command-line options are case-sensitive now (not just the 'cmds').
    A lot of code clean-up in zmodem.c.

    Incremented zmodem.c rev to 2.0.
    Incremented sexyz version to 3.0.
    ---
    ■ Synchronet ■ Vertrauen ■ Home of Synchronet ■ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian Linux)@VERT to Git commit to main/sbbs/master on Mon Aug 24 22:46:27 2026
    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