Files
TeslaSuite/vPOD/README.md
T
CydandClaude Fable 5 d30ce8bdbe vPOD: real C:\Games installs, optional real app launching, power-group swap
- InstallProduct now extracts into the real C:\Games (the launcher's
  GAMES_DIR) so deployed products land where their catalog launch entries
  point; uninstall removes the real product folder. Tests pass an isolated
  games root through the VirtualLauncher ctor.
- New "Actually launch apps (real processes)" toggle (off by default =
  simulated PIDs): LaunchApp starts the entry's exe exactly like the Agent
  (same start info, same registered-but-not-installed error), Kill*/
  Uninstall/Wipe terminate the real processes (kill before folder delete),
  and self-exited apps are pruned from GetLaunchedApps/FullUpdate. Real
  processes die with the machine: power off, reboot, or closing vPOD. The
  Agent's autoRestart watchdog is deliberately not emulated.
- Pod Power and Mimicking Game groups swapped (game left, power right).
- Provisioning round-trip test now skips as inconclusive when a running
  TeslaConsole holds UDP 53291 instead of failing the suite; two new tests
  cover real launch/kill (ping.exe) and the missing-exe error path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 10:46:55 -05:00

168 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# vPOD — virtual pod / game-client stand-in
A test tool that impersonates a Tesla game client (Red Planet's `rpl4opt.exe`
or BattleTech's `btl4.exe`) so the operator **consoles can be exercised without
real cockpit hardware**. It speaks the Munga command/control protocol as a
server on TCP 1501 — the console connects to it exactly as it would a real pod —
emulates the pod `ApplicationState` machine, reassembles the streamed egg, and
shows everything on a live display.
It also impersonates the pod's **TeslaLauncher service** (the "Launcher / Site
Management" column), so the console's Manage Site — provisioning, Install /
Uninstall Product, launch/kill, volume, restart/shutdown — can be tested
end-to-end with no cockpit and **no console changes**. See
[Site management / virtual launcher](#site-management--virtual-launcher).
## What it does
- **Listens on TCP 1501** (configurable) and answers the console's
`StateQuery` with a `StateResponse`, reporting the game (`ApplicationID`) and
the current `ApplicationState`.
- **Walks the mission lifecycle** the console drives it through:
`WaitingForEgg → LoadingMission → WaitingForLaunch → LaunchingMission →
RunningMission → …`, reacting to the egg stream and to Run / Stop / Abort /
Suspend / Resume messages, and acknowledging the egg.
- **End-mission graceful exit + watchdog restart** — on the console's end-mission
command the "game exe" exits (the listener closes, the console's connection
drops), then a watchdog relaunches it a moment later and it comes back up in
`WaitingForEgg`. This is the real pod's per-game cycle (`autoRestart`); the
*Restart game after mission ends (watchdog)* checkbox (on by default) toggles
it — unchecked, the pod just returns to `WaitingForEgg` without exiting.
- **Pod Power (Power On / Power Off)** — the whole virtual machine: Power Off
darkens the game listener AND the launcher / site-management side; Power On
boots the launcher (or provisioning beacons) and auto-starts the game, like a
real pod booting with an `autoRestart` product installed.
- **Start Game / Stop Game** — just the emulated game "exe", separate from pod
power: Stop Game closes the Munga listener (the console's game connection
drops) while the pod and its launcher service stay up — the state of a pod
whose game client crashed or was killed. **Reset** returns a running game to
`WaitingForEgg`.
- **Reassembles and shows the egg** the console streams (the `EggFileMessage`
chunks), one field per line, with a summary line (adventure / map / scenario /
pilot count). The last egg is **kept** across missions/restarts (so it can be
copied for dev use) until the **Clear** button empties the viewer.
- **Game toggle** — a Red Planet ⇄ BattleTech switch on the window changes which
`ApplicationID` the pod reports, live, so one vPOD can stand in for either
game. (`-app rp|bt` sets the initial choice.)
- A **newest-first protocol log** of the traffic.
## Running it
```
vPOD.exe [-net <port>] [-app rp|bt] [-lc|-mr] [-host <id>] [-res W H] [-nomanage]
```
- `-net <port>` Munga control port (default **1501**).
- `-app rp|bt` which game to report initially (also switchable in the UI).
- `-lc` / `-mr` live-camera / mission-review role (cosmetic; the state model is
identical to a game machine).
- `-host <id>` responding host id reported in state responses (default 1).
- `-res W H` accepted and ignored (real clients take it; kept for drop-in
launch compatibility).
- `-nomanage` vPOD-only: disable the virtual launcher / site-management side
(no provisioning beacons, no TCP 53290 listener) — e.g. when a real
TeslaLauncher runs on the same machine, or for a second vPOD instance.
## Site management / virtual launcher
vPOD's right-hand column is a stand-in for the pod's **TeslaLauncher service**:
the OFB-encrypted, framed-JSON `ILauncherService` RPC on **TCP 53290** that the
console's Manage Site and squad/pod panel talk to (`Tesla.Contract` /
`Tesla.SecureConfig` are the same shared wire libraries both real ends use).
### Provisioning (first run)
The console only talks to a pod's launcher after minting a 32-byte session key
for it via the SecureConfig **Configure** flow, so an unprovisioned vPOD
behaves like a freshly-imaged pod — minus the NIC/registry changes (the
assigned network config is shown in the window but never applied):
1. Run vPOD (no `-nomanage`). It broadcasts `RQST` beacons and displays a
**Request ID** and **Passphrase** (the real pod shows these on its screen).
2. In the console: **Manage Site** — a **"Configure &lt;Request ID&gt;"** button
appears at the bottom. Click it, enter the pod's name/squad, its IP
(**127.0.0.1** when vPOD runs on the console machine — accepted), any
subnet (e.g. 255.255.255.0), and the passphrase from vPOD's window.
3. The console sends the encrypted config + session key; vPOD stores the key
and starts the launcher RPC. The pod row goes healthy (`Idle [<n> ms]`).
The key persists in `%LocalAppData%\vPOD\TeslaKeyStore.key` (launcher format),
so provisioning is one-time. **Reprovision** resets to a fresh pod — drops the
key, clears the installed-apps store (`LaunchApps.json`) and returns to beacon
mode — pair it with deleting the pod in Manage Site (the console's
**Reconfigure…** does both ends automatically: its `ClearStore` makes vPOD do
the same wipe and beacon again). Extracted packages under `C:\Games` are left
on disk either way.
### Product deployments
Right-click the pod row → **Install Product ▸** works exactly as against a real
pod: the console streams the package zip out-of-band on a second 53290
connection while polling progress on the first; vPOD extracts it into the real
`C:\Games` — the launcher's games root, so products land where their catalog
launch entries point — and reports the launcher's usual `050%` receive /
`5095%` extract / `99% Complete` progression. Then:
- Installed apps land in the column's list (and in `GetInstalledApps`, so the
Uninstall menu populates). Registrations persist in
`%LocalAppData%\vPOD\LaunchApps.json`.
- Packages extract into `C:\Games` (created on first install if missing; if an
admin-owned `C:\Games` isn't writable by your account, the install reports
Failed — fix the folder's ACL or run vPOD elevated). Uninstalling a product
removes its `C:\Games\<product>` folder, like the real launcher. A packaged
`postinstall.bat` is logged and removed but **never executed**.
- **Launch/Kill** from the squad panel simulate PIDs by default. The
**"Actually launch apps (real processes)"** checkbox switches to the real
Agent's behavior: LaunchApp starts the entry's exe from `C:\Games` (missing
exe → the same "registered but not yet installed" error a real pod gives),
Kill\* terminate the processes, and apps that exit or crash on their own
disappear from the console's running list. Real processes also die when the
pod is powered off / rebooted / the vPOD window closes. Caveat: launching a
*deployed vPOD* or a real game client this way will fight the running vPOD
for ports 1501/53290. Volume round-trips; **Restart/Shutdown** power-cycle
the virtual pod (dark for a few seconds on restart).
### Ports
| Port | Proto | Direction | Purpose |
|---|---|---|---|
| 1501 | TCP | console → vPOD | Munga game control (existing) |
| 53290 | TCP | console → vPOD | Launcher RPC (`ILauncherService`) |
| 53291 | UDP | vPOD → console (broadcast) | `RQST` provisioning beacon |
| 53292 | UDP+TCP | console → vPOD | `RPLY` config broadcast + RSA key exchange |
Same-machine testing needs no firewall changes (loopback). Running vPOD on a
**different machine** needs inbound allows for TCP 1501/53290/53292 and UDP
53292 on the vPOD machine (the console installer already opens its own side).
Not emulated: the console's remote Windows-service control (`ServiceController`
over SCM/SMB, used by some SitePanel service start/stop paths — dormant against
real pods too, since it queries service name `TeslaLauncherService` while the
launcher registers as `Tesla Application Launcher`), and the Agent's
`autoRestart` watchdog (a real-launched app that dies is pruned from the
running list, not relaunched).
An end-to-end loopback test of this server against the console's real
`PodManagerConnection` client lives in the differential suite:
`Console/tests/TeslaConsole.DiffTests/VPodLauncherServerTests.cs`.
## Deploying from the console (Manage Site → Install Product)
vPOD is a catalog product (`Console\RedPlanet\Apps.xml`, id `0041C870-…`) with Game
Client / Live Camera / Mission Review entries, so it appears in **Manage Site →
Install Product** like any game. Build the deployable package first:
```
pwsh -File pack.ps1 # produces dist\vPOD.zip
```
The zip lays out `vPOD\vPOD.exe` (+ `Munga Net.dll`) so the launcher extracts it
to `C:\Games\vPOD` and the catalog entry launches `C:\Games\vPOD\vPOD.exe`.
## Testing locally against the console
The default site ships a **`local` pod at 127.0.0.1**. Run vPOD on the console
machine, open a game window (e.g. *Games → Red Planet: Death Race*), and enable
the local pod — the console connects to `127.0.0.1:1501` (vPOD), and you can
drive Load → Run → Stop and watch vPOD's state and egg viewer follow along.