Repository navigation
v1.3(Lovelace): DDial network integration, scrollback rendering fix, and crash forensics
Latestv1.3 (Lovelace) -- named after Ada Lovelace
Chatter joins the live DDial network: station-to-station linking through the MagViz hub, a full MagViz command set for retro dial-in terminals, and a root-cause fix for the scrollback duplication that made relay traffic unreadable.
DDial network integration
- Station (auxiliary) mode: Chatter now links into the DDial network as a full station via the MagViz hub (magviz.ca:2301). Registered on the hub user list and relaying chat bidirectionally with all linked stations in real time.
- User ("hijack") upstream mode (
CHATTER_DDIAL_MODE=user): the relay acts as an ordinary DDial account. Includes a per-account file lock so two processes never log in twice, a reconnect cooldown (double-login guard) that also covers abnormal termination,/Qlogout on shutdown, and dedup of the upstream's own-line echo. A chat message containing "bye" no longer drops the connection. - DDial listener (
-D bind:port): retro terminals dial in over raw TCP/telnet into a Diversi Dial engine with the MagViz command set —###passwordmember login, channels 1-999 with~dual-channel wire form, colors (/h#RRGGBB), mail, message box,/ig /null /pmoderation, paced/300-style output, and more. See docs/DDIAL.md. - Chat bridging: dial-in chat reaches the Chatter room (as system entries, so nothing loops back) and the upstream link; upstream chat reaches the room and local dial-ins. Link-echo and local handles are suppressed so no one sees a line twice.
DDial command interoperability from the Chatter room
- Read-only DDial commands typed in the room (
/s,/s1-/s4,/sm,/i,/h,/ls,/b?,/ver) are forwarded raw to the linked station; the reply returns through the normal relay path and lands in the room history (verified live against the MagViz hub). - Everything else stays local: protocol commands (
/K,/V,/E, ...) can never be injected from chat. Operator-only/ddial rawremains the sole protocol escape hatch.
Scrollback rendering fix
session_process_pending_sink's non-incremental fallback re-emitted the entire visible history window every time a single message arrived (incremental redraw had been disabled earlier to avoid screen clears). With relay traffic, every message repainted the whole recent history — the duplicate-block scrollback spam reported during DDial testing — and buried the input line.- The fallback now appends only entries newer than the sink cursor; the cursor is advanced when the sender's own line is rendered immediately, invalidated on hard screen clears and on return from protected modes (BBS/RSS/game), and reset when coming back from a scrolled view. Verified: every message renders exactly once across two SSH sessions, dial-in relay, scrollback navigation, and BBS exit.
DDial link line format and relay
- Linked stations showed our chat as
63Lee Yunjin) msginstead of63#1[T1:Lee Yunjin) msg: station mode dropped the#slot[T1:prefix whenever the remote never printed our#N(T1:?)status line. Link chat and/Pnow always carry the speaker's own line number (a Chatter member's chat-link slot, the same one its login was announced with; a dial-in's session slot). - The relay's own slot is learned only from our status line, so another user's
#2[T1:Bob)line can no longer overwrite it. - The idle keepalive no longer writes a telnet
IAC NOPinto the stream (remotes rendered it as��in front of the next line); kernel TCP keepalives are used instead. /pmfollows the public-chat relay path: a Chatter private message in the room, and the DDial equivalent when the target is on the DDial side (P#slot(handle) msgto a dial-in, link/P<slot> #slot[T1:handle) msgto a user on the linked station). Inbound link/Preaches only its recipient instead of the room history, and our own/Pcoming back is dropped./replyis relayed to DDial as a plain chat line (@author text), since DDial has no replies./usersand/connectedcount DDial participants: dial-ins, plus everyone behind the Station Link, kept in a hash map keyed by handle. It is filled from station user lists ([SYSOP] 73-.SynerChat #0[T1:AriZona Mae #2<T1:Joe Boo:232 ...), login events and chat lines, rebuilt at start-up from the last 2048 history entries, and a user is removed only when they leave (logout, or dropping out of their station's list).- History keeps what the link sent; one display-time filter decides what people see, for past and new entries alike and in every view (SSH, scrollback, live broadcast, JSON/web feed): link housekeeping (
[SYSOP]station lists,[LINK]login/logout events) is hidden, and relayed DDial chat such as71#4[T1:MaxMouse) ...is shown as a Chatter message ([id] <MaxMouse> ...).
Usernames with spaces and localized command messages
/pm,/mail send,/block confirmand/bbs mutetakename|args(e.g./pm Lee Yunjin|hello), matching the BBS comment syntax; single-word names still work without|.- Help labels, usage lines, the
/bbssubcommand help, and the system messages of/pm,/mail,/block,/unblock,/kick,/ban,/banname,/banlist,/getaddr,/poke,/pardon,/getos,/resetpwand/showstatusare available in all eight UI languages.
Crash forensics and BBS hardening
- The SIGSEGV handler now logs the first-fault signal, code, address, fault RIP/RSP, and TID to stderr (journald) before re-raising, because the re-raise used to overwrite the faulting ucontext and erase the real crash location from every core dump.
- BBS post lookup refuses to iterate a post arena whose capacity exceeds
SSH_CHATTER_BBS_MAX_POSTSand rejects ids above 2^40 (defense against the wild-pointer crash class seen on 2026-09-23).
Full changelog: v1.2...v1.3