• src/sbbs3/main.cpp

    From Deucе@1:103/705 to Git commit to main/sbbs/master on Thu Jul 16 14:26:08 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/2154c2b9295e07c6cb38f551
    Modified Files:
    src/sbbs3/main.cpp
    Log Message:
    sbbs: drain buffered SSH plaintext before polling

    Cryptlib can consume all pending encrypted socket input while
    returning only one SSH channel packet from cryptPopData(). The input
    thread then waited for the raw socket to become readable before
    calling it again, leaving plaintext buffered inside Cryptlib. Large unidirectional transfers could stop near EOF until reverse traffic
    woke the socket path, causing ZMODEM timeouts and retransmission.

    After each successful SSH pop, bypass the raw-socket poll and keep
    popping through the existing input path until Cryptlib returns zero
    bytes or an error. Normal polling resumes once its buffered plaintext
    has been drained.

    Co-Authored-By: OpenAI Codex <[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 Sun Jul 19 15:25:25 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/7853fb5c959aa15a946c9434
    Modified Files:
    src/sbbs3/main.cpp
    Log Message:
    Terminal server: flag nodes to re-read config on recycle signal

    When a recycle was signaled (ctrl/recycle semaphore, MQTT recycle topic, SIGHUP/systemctl reload, or a console recycle command), the terminal
    server only acted on it once every node was idle: the recycle detection
    was gated on node_threads_running == 0. Until then, new connections
    kept attaching with the old configuration, so on a busy board that never
    fully drains, hand-edited config changes could effectively never reach
    new logins.

    Detect the recycle request every iteration now, and when one is seen,
    set the NODE_RRUN flag on this instance's nodes (first_node..last_node)
    so each node re-reads its per-node configuration on its next connection
    -- the same mechanism SCFG's refresh_cfg() already uses. The full
    server recycle (which re-reads the master config and reinitializes the listening sockets) still waits until all nodes are idle, so this only
    adds immediate per-connection config propagation without changing when
    the server-level reinitialization happens.

    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 Tue Jul 21 21:53:27 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/473e880ec144eb322ad4b5ec
    Modified Files:
    src/sbbs3/main.cpp
    Log Message:
    Terminal server: transmit the final output before hanging up

    sbbs_t::hangup() gave the output ring buffer a blind mswait(1000) and then
    tore the connection down, never confirming that the pending output had
    actually been sent. Over SSH the last output was lost every time -- most visibly the echoed command key of a fast log-off (/O), which produces no
    other output at all, so the user saw their keystroke simply vanish.

    Wait for the output to be transmitted instead, using WaitForOutbufDrained() (added in 9cf170c024, squad-4-memo, for issue #1157). WaitForOutbufEmpty() alone would not do: outbuf.empty_event fires when output_thread moves the
    ring buffer into its linear buffer, before the send, and the ssh_session_destroy() a few lines below then discards those still- untransmitted bytes. On telnet the equivalent window ends in sendsocket(), whose kernel buffer survives until close() -- hence the SSH-only symptom.

    The wait is performed while still online, so that flush_output()'s online short-circuit would not apply and input_thread keeps draining the receive
    queue meanwhile. It also turns the unconditional one-second sleep into a one-second ceiling, so an ordinary hang-up now completes as soon as the
    output has drained.

    Verified with three different SSH clients.

    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 Tue Jul 21 23:33:58 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/454cc802610dcfa661db6178
    Modified Files:
    src/sbbs3/main.cpp
    Log Message:
    Terminal server: apply the 8KB SSH send clamp that was never wired up

    757e389522 (deputy-13-floating) limited cryptPushData() sends to 8KB in
    both the web and terminal servers, after the same limit fixed a problem
    in js_socket.c. The web server half took effect; the terminal server
    half never did. output_thread() computed sendbytes and clamped it, then
    called cryptPushData() with buftop - bufbot anyway, so the variable has
    been dead ever since. Because the clamp expression reads sendbytes, no compiler warns about it.

    Pass sendbytes to the push, as websrvr.cpp and sftp.cpp both already do.
    Where getsockopt(TCP_MAXSEG) succeeds this changes nothing -- mss then
    caps a linear-buffer read well below 8KB -- but where TCP_MAXSEG is
    unavailable mss stays IO_THREAD_BUF_SIZE (20000) and pushes of up to
    ~20KB were bypassing the intended limit.

    Hoist sendbytes to cover the whole send, so that it means "bytes offered
    to the transport this iteration" for the sendsocket() path as well, and
    key the short-send warning off it. Otherwise a clamped push would be
    reported as a short send every time. The error paths that discard the
    linear buffer ("pretend we sent it all") reset sendbytes to the full
    remainder first, preserving their existing behavior of dropping it in
    one go rather than in 8KB steps.

    No functional change on this host, where TCP_MAXSEG is available.

    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/bd9a08274766f7097074dad9
    Modified Files:
    src/sbbs3/main.cpp
    Log Message:
    main: suppress output_thread INTEGER_OVERFLOW false positive (CID 651667)

    Coverity flagged the linear-buffer sends in output_thread() as passing a possibly-underflowed size to sendsocket(): sendbytes (buftop - bufbot) to
    the client-socket send, and i to the spy-socket send. Neither can wrap.
    The refill guard at the loop top keeps 0 <= bufbot < buftop wherever the subtraction runs, so sendbytes >= 1; and every error path resets i to a non-negative sendbytes before bufbot += i, so i is never negative where it feeds the spy send. The checker simply can't prove bufbot <= buftop across iterations.

    Annotate both sites with coverity[INTEGER_OVERFLOW:SUPPRESS] and the
    one-line invariant, matching the existing precedent in atcodes.cpp. No behavioral change.

    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)