https://gitlab.synchro.net/main/sbbs/-/commit/3c3577994c6e06dbfcc34fa3
Added Files:
exec/tests/qwkjob/fixture.qwk hub.js
Modified Files:
exec/tests/qwkjob/skipif src/sbbs3/js_system.cpp pack_rep.cpp qwkjob.cpp qwkjob.h sbbs.h
Log Message:
qwkjob: QWKnet hub REP packing and QWK import for any server or script
Add the hub direction of the QWK job API, so this BBS acting as a QWKnet
node can pack a REP for, or import a QWK packet from, a hub outside the Terminal Server's event thread:
- qwkjob_pack_rep() loads the hub's export pointers
(data/qnet/<HUBID>.ptr), runs pack_rep() into data/<HUBID>.REP (an
unsent REP is merged into, as before) and saves the pointers. It does
not touch ctrl/time.ini or run the call-out command; those stay with
the event thread's schedule.
- qwkjob_unpack_qwk() imports a QWK packet from any path; on success the
file is removed, on failure it is kept as
data/<HUBID>.qwk.<hex-time>.bad (newest 10 kept), so a sysop can retry
it by renaming it back for the event thread's sweep. An empty packet is
discarded without an error.
- Both are serialized per hub by data/qnet/<HUBID>.lock and return
"busy" when it is held. qwkjob_lock_hub(), qwkjob_unlock_hub() and
qwkjob_pack_rep_locked() let the event thread hold that lock across
the pack and the call-out, so a scripted pack can't merge messages into
a REP the call-out is sending (and then deleting).
- An unknown or disabled hub is "bad_hub"; qwkjob_find_hub() matches a
hub ID case-insensitively.
- pack_rep() gains an optional out-parameter counting what it packed: it
returns true both when it packed something and when there was nothing
new (so the pointers get saved), which callers could not tell apart.
- system.qwk_pack(hub_id) and system.qwk_unpack(hub_id, path) now select
the hub direction for a string argument.
The hub job's sbbs_t has no user (useron.number == 0, online ==
ON_LOCAL), as in the event thread.
Audit of the hub paths in a headless job (pack_rep.cpp, un_qwk.cpp, qwktomsg.cpp, netmail.cpp qwktonetmail(), qwk.cpp update_qwkroute()):
- term->lncntr/newline() in pack_rep(): the job's discarding Terminal.
- useron: every use in qwk_import_msg() and qwktonetmail() is gated on
fromhub or reads the zeroed user (not a QWK node, not a sysop), the
same as the event thread.
- external() with the hub's pack/unpack commands, when libarchive can't
do the job: both ran in a job with the zeroed job startup (zip packing
a REP for an unsupported format, and an unpack command after a
libarchive extraction failure). As in the event thread, a command
whose program isn't listed as native in xtrn.ini is treated as a DOS
program and not run.
- sbbs_t::terminated (unpack_qwk's per-message check) stays false in a
job; host->terminated is polled only between job steps.
- update_qwkroute() rewrites data/qnet/route.dat without a lock, so two
imports at once (different hubs, or a hub and a QWK node's REP) can
lose a route entry; already true across hosts today.
- mqtt, startup->, ::lputs and node_num uses: none beyond those audited
for the user direction.
Co-Authored-By: Claude Opus 5.5 <
noreply@anthropic.com>
---
þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net