Skip to content

Multi-line concurrency + web admin UI#28

Open
nicolasumaras wants to merge 1 commit into
feat/slmodem-highspeed-v34from
feat/multi-line-admin
Open

Multi-line concurrency + web admin UI#28
nicolasumaras wants to merge 1 commit into
feat/slmodem-highspeed-v34from
feat/multi-line-admin

Conversation

@nicolasumaras

Copy link
Copy Markdown
Owner

Stacked on #27 (slmodem V.34 engine). Lifts SIPfax from single-session to N concurrent modem lines (configurable, hot-changeable cap) behind a FreePBX PJSIP trunk, plus a Basic-auth web admin UI.

Core

  • SingleSessionManagerMultiSessionManager (Map by Call-ID, mutable cap). Each call is a Line (src/line.js) owning its own RTP port (RtpPortPool), modem process, and pppd. One SIP socket multiplexes by Call-ID; per-call RTP sockets need no demux.
  • src/config.js — JSON config file (SIPFAX_CONFIG_FILE) seeded from the existing env vars; hot-applies user/cap changes live, flags structural changes (ports, CIDR) needs-restart; atomic 0600 persistence.
  • Admin UI (src/operator.js + public/admin.html) — HTTP Basic auth on /admin*, vanilla no-build page + JSON API: users (add/remove), cap, live lines, FreePBX trunk snippet (Max Channels = cap).
  • PPP: render all configured users to {chap,pap}-secrets (was a per-call overwrite that wiped the shared file on teardown and broke concurrent calls); PppCredentialStore.removeUser.

Tests

46 pass — cap accept/reject, RtpPortPool, config seed/redact/persist/hot-apply, credential CRUD, admin Basic-auth + CRUD. Smoke-tested live on the VM (boot, 401/200 auth, persisted user add, trunk snippet).

🤖 Generated with Claude Code

Lifts SIPfax from single-session to N concurrent modem calls (configurable,
hot-changeable cap) fronted by a FreePBX PJSIP trunk, plus a Basic-auth web
admin UI to manage users, the cap, and view live lines.

- Multi-session core: SingleSessionManager -> MultiSessionManager (Map keyed by
  Call-ID, mutable cap). Each call is a Line (src/line.js) owning its own RTP
  port (RtpPortPool), modem process, and pppd. One SIP socket multiplexes by
  Call-ID; per-call RTP sockets need no demux.
- Config layer (src/config.js): JSON config file (SIPFAX_CONFIG_FILE) seeded
  from the existing env vars; hot-applies user/cap changes live and flags
  structural changes (ports, CIDR) needsRestart; atomic 0600 persistence.
- Web admin UI (src/operator.js + public/admin.html): HTTP Basic auth on
  /admin*, a vanilla no-build page + JSON API for users (add/remove), the cap,
  live sessions, and the FreePBX trunk snippet (Max Channels = cap).
- PPP: render ALL configured users to {chap,pap}-secrets (was a per-call
  overwrite that wiped the shared file on teardown and broke concurrent calls);
  add PppCredentialStore.removeUser.
- index.js builds a per-call modem factory (unique tty link per call) and wires
  config hot-apply into the live server.

Tests: 46 pass (cap accept/reject, RtpPortPool, config seed/redact/persist/
hot-apply, credential CRUD, admin Basic-auth + CRUD). Smoke-tested live on the
VM: boots multi-line, 401/200 auth, persisted user add, trunk snippet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant