• src/ssh/README.md deucessh-conn.h ssh-conn.c src/ssh/test/test_conn.c

    From Deuc¨@VERT to Git commit to main/sbbs/master on Tue May 5 08:28:03 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/cd48edf479cad089934c941c
    Modified Files:
    src/ssh/README.md deucessh-conn.h ssh-conn.c src/ssh/test/test_conn.c Log Message:
    DeuceSSH: dssh_chan_poll surfaces terminate as POLLHUP

    When a session is terminated mid-poll, dssh_chan_poll used to return
    0 -- indistinguishable from a timeout -- so a caller in a finite-
    timeout poll loop couldn't tell that the session was gone and would
    keep polling forever.

    Mirror POSIX POLLHUP: when sess->terminate is set, surface every
    requested data flag (READ, READEXT, WRITE) as ready regardless of
    buffer state, just as close_received already does for READ/READEXT.
    The caller's next dssh_chan_read returns 0 (EOF) once any buffered
    data has been drained, and dssh_chan_write returns a negative error,
    so a poll loop exits naturally through the subsequent I/O call.
    DSSH_POLL_EVENT is intentionally not surfaced -- no real event is
    queued, callers should rely on the data flags or the terminate
    callback to detect termination.

    Documented in deucessh-conn.h on the dssh_chan_poll prototype and in
    README.md "Poll events".

    Two new tests in test_conn.c:
    - poll/terminate_surfaces_data: terminate before poll, expect
    READ|READEXT|WRITE returned immediately even with timeout=5000;
    follow-up chan_read returns 0
    - poll/terminate_no_event_bit: poll(EVENT|READ) after terminate
    surfaces only READ, never EVENT

    OpenSSL: 3410/3410 pass. Botan: 3411/3411 pass.

    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Deuc¿@VERT to Git commit to main/sbbs/master on Wed May 6 12:19:12 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/74ea58b3f5384f92d62eebd4
    Modified Files:
    src/ssh/README.md deucessh-conn.h ssh-conn.c src/ssh/test/test_conn.c Log Message:
    DeuceSSH: non-blocking POSIX semantics for dssh_chan_read/write

    dssh_chan_read previously returned 0 for both empty-buffer and EOF; dssh_chan_write returned 0 for both bufsz==0 and remote-window-full.
    Both now return DSSH_ERROR_NOMORE for the would-block case (analog
    of POSIX -1/EAGAIN), reserving 0 for its POSIX meaning: read=EOF, write=zero-length write.

    Poll-then-{read,write} callers never see NOMORE because dssh_chan_
    poll only flags READ/READEXT/WRITE ready when actual progress is
    possible. Direct callers without a preceding poll now get an
    unambiguous signal instead of a foot-gun.

    Includes test_read_nomore_vs_eof covering empty/peek/data/drained/
    EOF on the read side and bufsz==0/window-full/normal on the write
    side. Two existing tests that hard-coded the old "w==0 means
    window-full" contract are updated; one direct-read test
    (test_data_after_eof) gains a poll() to wait for EOF instead of
    relying on the old "0 means empty or EOF" ambiguity.

    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net