CI / build (push) Successful in 28s
A manager runs the hub connection, so signing in or out takes effect while the client runs; the client's T5DE settings page asks it for the status and to sign in (showing the code and opening the hub's page) or out. Co-Authored-By: Claude Opus 5.5 <[email protected]>
79 lines
5.1 KiB
Markdown
79 lines
5.1 KiB
Markdown
# t5de-proxy
|
|
|
|
T5DE's local proxy for IMVU Classic. With T5DE's `t5de-proxy` patch, the client starts `t5de-proxy.exe` and
|
|
connects to IMVU through it:
|
|
|
|
- **Every HTTP request**, the embedded browser's included (IMVU's browser hands its requests to the client's
|
|
Python). The proxy makes them with current TLS and root certificates (the client has only IMVU's bundled
|
|
certificates and TLS 1.2), pooled connections and HTTP/2.
|
|
- **HTTPS for IMVU hosts the client reaches over plain HTTP** (its XML-RPC API, images, CSS), so its account
|
|
headers don't cross the network in the clear ([docs/hosts.md](docs/hosts.md)).
|
|
- **IMQ**, IMVU's chat and presence connection: the client speaks plaintext to the proxy, which connects to the
|
|
gateway over TLS.
|
|
- **IMVU's reporting endpoints refused**, as T5DE's patches already do in the client.
|
|
- **Community products** from local packs (t5de-api's pack format), kept away from IMVU (below).
|
|
|
|
If the proxy isn't there or stops, the client connects directly, as before.
|
|
|
|
Unofficial: not made by or affiliated with IMVU.
|
|
|
|
## How it works
|
|
|
|
The proxy listens on a free port of 127.0.0.1 and accepts only requests carrying the token it gave the client
|
|
(`Proxy-Authorization: Basic t5de:<token>`), so other programs and web pages can't use it.
|
|
|
|
- HTTP: requests in absolute form (`GET https://api.imvu.com/... HTTP/1.1`) over plain HTTP on loopback, for
|
|
http and https URLs alike. Responses come back as the server sent them: redirects aren't followed, bodies
|
|
aren't decompressed. When the proxy can't reach a server it answers 502 with `X-T5de-Proxy-Error`, which the
|
|
client raises as the network error it would have had connecting directly.
|
|
- `CONNECT host:port`: the client then speaks plaintext and the proxy connects to `host:port` over TLS. The
|
|
proxy reads IMQ's framing (message type and size, not contents) to log it.
|
|
|
|
The client starts it as `t5de-proxy -parent <pid> -ready <file> -log %TEMP%\t5de-proxy.log`; it writes its
|
|
address and token to the ready file once listening, and exits with the client. Setting `T5DE_PROXY_TRACE=1`
|
|
before starting the client adds full URLs (with queries) and every IMQ frame to the log.
|
|
|
|
## Community products
|
|
|
|
Phase 1 of T5DE's community products (design: t5de-hub's `docs/design.md`): products in local packs, a folder
|
|
each, in `%APPDATA%\T5DE\packs` and the folders in `T5DE_PACKS` (separated by `;`). Each product gets a local ID
|
|
from 2,000,000,000 up, kept in `%APPDATA%\T5DE\proxy\products.json`. For those IDs the proxy answers the client
|
|
itself:
|
|
|
|
- `test.inventoryProductBatch` (product info) and `test.authorizeProducts2` (permission, the CFL's address and
|
|
checksum): for a product deriving from an IMVU product, IMVU is asked about the parent and the proxy adds its own
|
|
entry (the client needs the parent's derivation chain).
|
|
- `productdata/<local ID>/<revision>`: the pack built into a CFL.
|
|
- `api/shop/product.php` (putting a product on asks whether it's a bundle).
|
|
|
|
IMVU never sees community products: they're taken out of outfit saves (`api/base_look.php`) and outfit chat
|
|
commands (`*use`, `*putOn`, `*putOnOutfit`, `*remove`, `*takeOff` on `/chat/` queues; a command left empty is
|
|
answered by the proxy), so IMVU and everyone else see the defaults. The proxy remembers each account's community
|
|
products with the outfit they were saved with, and adds them back when the client loads that same outfit
|
|
(`base_look.php`, and `look` in the login response); an outfit changed elsewhere comes back without them.
|
|
Requests it changes are re-signed (`X-imvu-auth`) with the session key from the login response, which never
|
|
leaves the machine.
|
|
|
|
## The hub
|
|
|
|
The client's Settings > T5DE page signs in and out (the proxy answers it at `http://t5de-proxy.local/hub`,
|
|
`internal/control`). `t5de-proxy signin [-hub URL]` also signs the proxy in to T5DE's hub (git.t5de.dev/t5de/t5de-hub; URL is the hub's
|
|
API): it shows a code to enter on the hub's website (`/device`, OAuth 2.0 device authorization) and saves the
|
|
session token it gets in `%APPDATA%\T5DE\proxy\hub.json`, encrypted for the Windows user (DPAPI). From then on the
|
|
running proxy keeps a WebSocket to the hub (`internal/hub`) with the token as a bearer token, reporting which IMVU
|
|
account the client signed in as, the community products it wears, and the IMVU chats it's in. If the hub ends the
|
|
session (signed out everywhere, banned), the proxy stops connecting until `signin` is run again.
|
|
|
|
The room channel (`internal/products/room.go`): the hub tells the proxy which other T5DE users are in the same chat
|
|
and what they wear; the proxy gives the client those of their products it has packs for, as `*use`/`*remove` lines
|
|
from them, and adds them to the whole outfits they send. It also keeps community products out of the outfit the
|
|
client posts to IMVU's chat participant endpoint.
|
|
|
|
## Building
|
|
|
|
go test ./...
|
|
GOOS=windows GOARCH=amd64 go build -trimpath -ldflags "-H=windowsgui" -o dist/t5de-proxy.exe ./cmd/t5de-proxy
|
|
|
|
CI publishes `t5de-proxy.exe`: pushes to main replace the `nightly` pre-release, `vX.Y.Z` tags make releases.
|
|
To ship a release in T5DE, copy its url and sha256 into t5de's `t5de.toml` (`[[programs]]`, patch `t5de-proxy`).
|