https://github.com/sproctor/mud-mobile-connector
https://github.com/sproctor/mud-mobile-connector
Last synced: about 1 month ago
JSON representation
- Host: GitHub
- URL: https://github.com/sproctor/mud-mobile-connector
- Owner: sproctor
- Created: 2026-06-21T13:24:56.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-06-21T15:55:44.000Z (about 1 month ago)
- Last Synced: 2026-06-21T16:06:47.661Z (about 1 month ago)
- Language: Rust
- Size: 75.2 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# MUD Mobile Connector
A small, cross-platform desktop launcher that routes Simutronics play (GemStone IV /
DragonRealms) through [MUD Mobile](https://mudmobile.com)'s hosted-Lich service, then
hands a `.sal` launch file to the front end of your choice (Wrayth/StormFront, Warlock,
Genie, Mudlet, Wizard, …).
The play.net **password and game key never leave your machine**: the SGE login runs
locally and MUD Mobile only ever receives `sha256(key)`.
## How it works
1. Paste your MUD Mobile **device token** (`wlk_…`) once — stored in your OS keychain.
2. `GET /api/characters` lists your saved characters (or use **New connection** to log in
with account + password and discover them via SGE, saving them back).
3. Pick a character + a front end. The first time you launch an account you enter its
play.net password; it's saved to the OS keychain and reused after that. If a stored
password ever fails SGE, the bad one is forgotten and you're prompted to re-enter it.
4. The app runs the **SGE/EAccess** handshake locally (`eaccess.play.net:7910`, TLS) →
`{gamehost, gameport, key}`.
5. `POST /api/sessions` with `keyHash = sha256(key)` → a router endpoint + session id.
6. The app **waits for the runner to become functional**, polling `GET /api/sessions/{id}`
and reporting live status as it boots (bounded by a ~2-minute timeout, after which it
launches anyway since the router holds the connection).
7. A `.sal` is written locally (real `KEY` kept; `GAMEHOST`/`GAMEPORT` rewritten to the
router on the **plaintext port 7000**) and the chosen front end is launched against the
ready runner.
8. The launcher is fire-and-forget: after spawning the front end it exits the launch flow.
The hosted runner stays up idle, and MUD Mobile auto-routes the next connection back to
that same idle runner (no client-side session teardown).
## Build & run
```sh
cargo run # debug
cargo build --release # optimized, ~7 MB stripped binary at target/release/mudmobile-connector
cargo test # 26 unit/integration tests, no network required
```
Linux runtime needs OpenSSL (for TLS) and, for the keychain, a running Secret Service
(gnome-keyring / KWallet). Windows/macOS use the OS-native TLS + credential stores.
## Configuration
Config lives at the per-OS path (Linux: `~/.config/mudmobile-connector/config.toml`)
and holds the **editable front-end list** plus preferences. Edit it in **Settings**, or by
hand. The device token and per-account play.net passwords are in the OS keychain, never in config.
Each front end has a `command_template` where `%1` is replaced with the `.sal` path, an
executable path per OS, an optional `.sal` field override (e.g. Wizard → `GAME=WIZ`), and
a `protocol` (`storm`/`wiz`).
> **Note:** the hosted Lich serves a **Stormfront** stream, so Stormfront-protocol front
> ends are expected. The bundled **Wizard** entry uses the older WIZ protocol and may not
> be compatible — the UI warns when it's selected.
## Design notes
- **Stack:** Rust + egui/eframe (native GUI, no webview/JRE → small self-contained binary).
- **Networking:** blocking `ureq` (HTTPS) + `native-tls` for both HTTPS and the SGE socket
(single TLS stack, OS-native, no bundled crypto). SGE uses TLS by default. The certificate is
accepted if it's **either** the bundled `assets/simu.pem` (the Warlock-sourced self-signed
Simutronics cert, matched by pinning) **or** valid for a public CA — so the login keeps working
if Simutronics ever moves to a normally-trusted certificate, while anything else aborts before a
password is sent (there is no encrypted-but-unverified mode). TLS can be turned off entirely in
Settings (plaintext socket, e.g. for a test server), and a failed TLS connection offers a
one-off **retry over plaintext**.
- **Concurrency:** all blocking work runs on one worker thread (`worker.rs`); the egui UI
only drains events and renders. The worker calls `request_repaint()` to wake the UI.
- **Connection model:** plaintext-direct (the front end connects straight to the router on
port 7000). A local TLS-proxy mode could be added later, isolated to `sal.rs`/`worker.rs`.
### Module map
`sge.rs` SGE/EAccess handshake · `mudmobile.rs` HTTP API client · `sal.rs` `.sal` build/parse ·
`frontends.rs` registry + spawn · `config.rs`/`keychain.rs` persistence · `worker.rs`
background thread · `app.rs` egui UI/state machine · `model.rs`/`error.rs` shared types.
## Status / follow-ups
- Plaintext-only connection model; TLS-proxy mode not yet implemented.
- SGE socket uses a single read per response (like Lich's `sysread`); add grace-period
coalescing if a response ever arrives split across TCP segments.