• src/sbbs3/sexyz.c

    From Rob Swindell (on Debian Linux)@1:103/705 to Git commit to main/sbbs/master on Thu Feb 20 20:29:35 2025
    https://gitlab.synchro.net/main/sbbs/-/commit/c5b1b4b5c65f56b4bc3da536
    Modified Files:
    src/sbbs3/sexyz.c
    Log Message:
    Bug fix for multi-file zmodem-send using wildcards

    If the first specified file in the list had a wildcard pattern, multiple ZRQINIT (request init) frames would be sent (one for each file matching
    the first list item file pattern).

    This was just found via code review, not in the wild.
    --- SBBSecho 3.23-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)
  • From Rob Swindell (on Windows 11)@1:103/705 to Git commit to main/sbbs/master on Fri Sep 26 14:17:14 2025
    https://gitlab.synchro.net/main/sbbs/-/commit/6bc626bedf028105f520ad56
    Modified Files:
    src/sbbs3/sexyz.c
    Log Message:
    Increment version to 3.1
    --- SBBSecho 3.29-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 Fri Sep 26 18:16:24 2025
    https://gitlab.synchro.net/main/sbbs/-/commit/70a445decf8a4c69f1ac0c65
    Modified Files:
    src/sbbs3/sexyz.c
    Log Message:
    Sanitize the stdio-path of sendbuf()

    Fix what appear to be bugs in the mix-up of the global 'sock', the 's' argument, and FILENO_STDIN versus FILENO_STDOUT.

    This seemed to work anyway since stdout was blocking (would never return EAGAIN/EWOULDBLOCK).

    Just wanted to clean this up before pollifying (related to issue #445).
    --- SBBSecho 3.29-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)
  • From Rob Swindell (on Windows 11)@1:103/705 to Git commit to main/sbbs/master on Fri Sep 26 19:38:47 2025
    https://gitlab.synchro.net/main/sbbs/-/commit/fa6202f2a587411b40d3a94d
    Modified Files:
    src/sbbs3/sexyz.c
    Log Message:
    Implement poll (rather than select) support when PREFER_POLL defined

    Attempt to fix issue #445
    --- SBBSecho 3.29-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)
  • From Deucе@1:103/705 to Git commit to main/sbbs/master on Fri Oct 24 22:27:59 2025
    https://gitlab.synchro.net/main/sbbs/-/commit/929fc7cde612b44a7dbb9489
    Modified Files:
    src/sbbs3/sexyz.c
    Log Message:
    Fix error on systems where poll() is preferred (ie: *nix)

    Broken in fa6202f2a58, after poll() indicates there is data to
    read, recv_buffer() would return a timeout rather than set the
    timeout to zero and retry the recv().
    --- SBBSecho 3.30-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)
  • From Rob Swindell (on Windows 11)@1:103/705 to Git commit to main/sbbs/master on Thu Jan 8 03:55:52 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/231233096fde3a7595afcf69
    Modified Files:
    src/sbbs3/sexyz.c
    Log Message:
    Remove glob() usage

    If we really need to expand wildcards in specified transmit path/filenames
    (do we?), there's better ways to do it.

    Increment version to 3.2

    Fix issue #1044
    --- SBBSecho 3.34-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 Thu Jul 23 23:03:46 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/1672d1f70b2d5f2f14c794c4
    Modified Files:
    src/sbbs3/sexyz.c
    Log Message:
    sexyz: batch ZMODEM output into the ring buffer to fix send throughput

    The transmit path fed the output ring buffer one byte at a time via send_byte(), so the protocol thread and the draining output_thread
    ping-ponged over tiny amounts: a 32 MB send made ~2.3 million futex calls
    and ~409 K writes averaging ~84 bytes. lrzsz and SyncTERM, which buffer
    their output, ran several times faster over the same protocol.

    Accumulate escaped output in a per-session buffer and push it into the
    ring one subpacket-sized span at a time (on the zmodem flush callback, or
    when the buffer fills). The output_thread and its asynchronous socket
    draining are kept intact: that asynchrony is what lets the protocol thread service ZRPOS on the back-channel during error recovery, so removing the
    thread (measured) stalled lossy transfers.

    Results, sending to lrz over a localhost socket:
    - 32 MB send: ~2.3 M -> ~12 K futex calls, ~409 K -> ~4 K writes (~8 KB ea)
    - 256 MB steady-state send: ~11 -> ~66 MB/s
    - error-recovery time under injected bit errors: unchanged (~50 s)
    - receiver throughput: unchanged (~130 MB/s)

    The remaining gap to lrzsz (~204 MB/s) is zmodem.c's per-byte send_byte-callback overhead, addressed separately.

    Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
    --- 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 Thu Jul 23 23:03:46 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/da546fbe1bd20ff1754e49b6
    Modified Files:
    src/sbbs3/sexyz.c
    Log Message:
    Revert "sexyz: batch ZMODEM output into the ring buffer to fix send throughput"

    This reverts commit 4e671c75640ccf8248ea9b3822df2d0a08f4f6c9.
    --- 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 Fri Jul 24 23:28:15 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/34af5f34b57436e1430bdf80
    Modified Files:
    src/sbbs3/sexyz.c
    Log Message:
    sexyz: buffer the ZMODEM streaming send path (#1195)

    The send bottleneck was never the two output threads or the ring -- it
    was feeding the ring one byte at a time. send_byte() took the ring mutex
    twice per byte while output_thread hot-looped on it, so a 256 MB send
    cost 44 CPU-seconds and 1.46 million voluntary context switches and
    topped out near 11 MB/s on localhost.

    Accumulate bytes into a 4 KB buffer and hand whole spans to the ring
    instead. The two-thread architecture, flow control and error handling
    are all unchanged; the producer just stops trickling. A 256 MB send now
    runs at ~115 MB/s using 0.85 CPU-seconds and 64 K context switches -- the
    same throughput a single-threaded rewrite would give, for a fraction of
    the change and none of the risk.

    Buffering only applies to full ZMODEM streaming. A transmit window or segmented mode (-w, -s) depends on the receiver's acks flowing back as
    data is sent; bursty buffered output would fill the window before any ack returns and stall the transfer, so those modes fall through to the
    original byte-at-a-time path and are byte-for-byte unchanged.

    A fast streaming sender also fills the socket's auto-tuned, possibly multi-megabyte send buffer, so a single line error would cost a ZRPOS retransmission of everything in flight and break error recovery. Bound SO_SNDBUF to the ring size to cap the in-flight backlog (streaming only --
    a window already bounds it, and a socket buffer smaller than the window
    would fight it). This is applied outside the stdio guard so it takes
    effect for a piped socket as well, and [sockopts] can override it for a
    high bandwidth-delay link.

    Verified against lrz over the bench harness: 256 MB streaming MATCH at
    ~115 MB/s; the 3x error-injection gate passes 5/5; windowed (-w8192
    through -w65536), segmented (-s) and the receive path are unchanged from before; an 8 MB transfer over a 25 ms link matches the byte-at-a-time
    sender (both link-bound). No zmodem.c change, so SyncTERM is untouched
    (and it already has a buffered send path of its own).

    Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)