https://gitlab.synchro.net/main/sbbs/-/commit/50dfd1318ca341eaea03d98b
Modified Files:
src/sftp/sftp.h sftp_client.c src/syncterm/Wren.adoc src/syncterm/scripts/syncterm.wren wrentest.wren src/syncterm/term.c wren_bind.c wren_host.c wren_host_internal.h
Log Message:
SyncTERM: Wren SFTP API + Input.nextEvent fiber-arg primitive
Adds a Wren-callable SFTP surface on top of the async sftpc_ library
and converts Input.nextEvent to the same fiber-arg shape.
Async ops take the fiber-to-resume as their first argument, fire the
underlying request, and return immediately:
SFTP.<op>(fiber, args...) -> null | SFTPError
null means the request was queued (the caller may yield to receive
the result via fiber.call); SFTPError means the request couldn't be
queued (session is gone, OOM at the foreign-method site) — no
callback will fire. All other errors round-trip through the result
queue so the caller's yield surfaces them as an SFTPError too.
Common idioms:
// fire and immediately await
var r = SFTP.realpath(Fiber.current, ".") || Fiber.yield()
// multi-fire event loop, demuxed by type
SFTP.stat(Fiber.current, "/a")
SFTP.stat(Fiber.current, "/b")
Input.nextEvent(Fiber.current)
while (true) {
var x = Fiber.yield()
if (x is SFTPStat) ...
if (x is KeyEvent) { Input.nextEvent(Fiber.current); ... }
if (x is SFTPError) break
}
// hook-friendly: callback fiber, calling fiber doesn't yield
SFTP.realpath(Fiber.new {|r| ... }, ".")
Library additions (src/sftp/):
sftpc_mkdir / sftpc_rmdir / sftpc_remove / sftpc_rename — four
status-only async ops that were stripped in 97dd3955d6. They
reuse the bare struct sftpc_pending plus parse_status_only and
share a do_one_path helper for the single-path variants.
Wren classes (foreign):
SFTP — static-only; available, pubdir, plus 12 async ops
(realpath, stat, opendir, readdir, close, open,
read, write, mkdir, rmdir, remove, rename).
SFTPEntry — name, longname, size, mtime, isDir, hash.
SFTPStat — size, mtime, atime, mode, uid, gid.
SFTPHandle — opaque server file/dir handle; finalizer fires
sftpc_close fire-and-forget when GC'd.
SFTPError — code (sftp_err_code_t), serverStatus (SSH_FX_*),
message, isTransient.
FileFlag — six SSH_FXF_* bitmask constants for SFTP.open.
Zero-copy delivery: the recv-thread cb runs under state->mtx and
just stamps ctx->pending = p + pushes onto the result queue. The
owner-thread deliver fn reads typed-pending fields directly
(sftp_str_t bytes, sftpc_attrs getters, sftpc_dir_entry array) and
frees the pending in the queue's free fn. No memcpy under the
mutex; the only Wren-heap copy is wrenSetSlotBytes / strdup at
delivery, which is unavoidable.
Input.nextEvent converted to the same shape:
Input.nextEvent(fiber) -> null
…replacing the prior Input.park_(fiber) primitive + Input.nextEvent() auto-yielding wrapper. The wrapper existed only to work around now-
removed quirks (implicit CTerm.suspended setting, the now-dropped Hook.onOutput). Dropping it lets hooks pass Fiber.new {|ev| ...}
for callback-style delivery without nesting Fiber.new {...}.call().
Throws if another fiber is already registered (single-subscriber
is structural).
Wren.adoc, wrentest.wren, and the relevant internal-comment
references updated to match the new API.
--- SBBSecho 3.37-Linux
* Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)