Adapter talks to whatever server is on the RCON port, so a wrong Zandronum path looks like success #1
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
mobrule/mobrule-pack-doom#1
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What happened
The pack appears to ignore its Launcher-sidecar paths. Point the
zandronumpath at a completely unrelated executable — a Nintendo DS emulator from another pack was used to prove this — and the game still comes up and effects still work, exactly as if the path were correct. Nothing reports a problem.What's actually happening is worse than the path being ignored. The adapter spawns whatever binary the path names and then immediately connects over RCON to a fixed loopback port, without ever checking that the thing it spawned is the thing it's now talking to. If a Zandronum listen server is already running from an earlier, correct launch, the adapter connects straight to that leftover server. The bogus binary is spawned, fails or wanders off on its own, and is never noticed. Everything downstream looks healthy.
Confirmed on a live machine: with the DS emulator configured as the
zandronumpath, a Zandronum process from a previous session was still listening on the RCON port, and the adapter had been driving that server the whole time.There is a second, related silence. When no
zandronumpath is configured at all, launching is skipped entirely and the adapter assumes a server is already up. That's a deliberate and reasonable manual/dev path, but combined with the above it means "no path configured", "garbage path configured", and "correct path configured" all converge on the same observable outcome whenever any server happens to be listening.What I expected
A launcher path that cannot host the game should fail loudly, at launch, naming the path it tried. The adapter should not silently adopt a server it did not start. At minimum it should notice that the process it spawned died immediately, and it should be able to distinguish "the server I launched" from "a server that was already there" before treating the session as healthy.
Steps to reproduce
zandronumpath and let the listen server come up.zandronumpath to any unrelated executable.Additional context
The launch is fire-and-forget: the spawned process handle is kept only so it can be terminated at exit, and its exit status is never inspected. The RCON client is then pointed at the loopback host and port independently of what was spawned. The eager startup connect was deliberately added so that a wrong RCON password fails loudly at startup rather than on the first redeem — that instinct is right, and this issue is asking for the same treatment for a wrong binary.
Worth deciding while fixing: whether a pre-existing server should be adopted at all when a path is configured, or whether that should be an error telling the operator to stop the old server first. Note that a stale listen server holding the port is a known hazard in this project generally, so "detect and report" is likely more useful than "silently reuse".
When this is fixed, the tutorial must be updated in the same change. This repo's history is the tutorial: stages 1-9 are one commit each, and stage 2 is the one that introduces the RCON client and Launcher hosting, which is exactly the code at fault here. The README documents the Launcher flow and describes the no-path case as "assume a server is already up", so it needs to reflect whatever the new behavior becomes.
Findings from a code read — this issue's mechanism does not hold up
Parked pending a retest. Recording this so it is not re-derived, and so nobody builds from the current diagnosis.
The silence is real, but it is a different bug
main(),adapter.py:593:The comment is wrong. A failed eager connect is not fatal. After 8 seconds it prints one line to stderr and continues — then connects to MPP, sends
hello, gets its ack, and registers as a healthy adapter. RCON being completely dead is a stderr line nobody reads.This issue quotes that comment approvingly ("that instinct is right"). The instinct was never implemented. That is a genuine defect and is probably the real fix here:
_game_proc.poll()to notice the spawned binary dying immediately.But the leftover-server story needs a precondition this issue never mentions
Password resolution,
adapter.py:75:The spawned server receives that same password (
+sv_rconpassword, line 585). So the repro as written should fail: the leftover server from step 1 holdsP1, the relaunch generates a freshP2, and the connect getsSVRC_INVALIDPASSWORD(line 264) →RconError. Auth rejection is handled correctly and cannot look like success.Adopting a leftover server therefore requires
DOOM_RCON_PASSWORDto be set. Checked on the machine:DOOM_*or*RCON*variables at all;[adapter.env], and deliberately cannot be ("manifest values are hashed and visible");So: the ephemeral password is already acting as a "did I start this server?" check. Accidentally, but effectively.
DOOM_RCON_PASSWORDsilently disables it — which is arguably the more interesting finding, and a smaller fix than this issue proposes.What to confirm on retest
"The game still comes up and effects still work" is the claim that does not reconcile. DeSmuME spawned with Zandronum's argv cannot host RCON on 10666, so effects cannot work without a live Zandronum server and a matching password.
DOOM_RCON_PASSWORDset in the shell that launched the bridge? (Transient — it is gone now.)Machine state is preserved for the retest:
mobrule-doom/.local/launcher.tomlstill pointszandronumat the DeSmuME binary.Related
mobrule#176 settled on existence + executable validation only, and explicitly does not catch this case — DeSmuME is a real executable
.exeand passes. Catching it is this issue's job.Triage Notes
Labelling this
needs-info. The confirmed half of the diagnosis has been split into its own issue so it can proceed; what is left here is the part that a code read could not reconcile and that only a live retest can settle.What we've established so far:
DOOM_RCON_PASSWORDor, when a launcher path is configured, generated fresh per launch. The spawned server receives that same generated password. So the repro as written should fail: the leftover server from step 1 holds the old password, the relaunch mints a new one, and the connect is rejected with an invalid-password error, which is handled correctly and cannot look like success.DOOM_RCON_PASSWORDsilently disables it, which is arguably the more interesting finding here.DOOM_RCON_PASSWORDwas not set in Process, User, or Machine scope (noDOOM_*or*RCON*variables at all), it is not in[adapter.env]and deliberately cannot be, and nothing was listening on UDP 10666.mobrule-doom/.local/launcher.tomlstill pointszandronumat the DeSmuME binary.What we still need from you (@aiko):
DOOM_RCON_PASSWORDset in the shell that launched the bridge at the time? This is the load-bearing question — without it set, the leftover-server adoption described here should be impossible. It is transient, so it cannot be recovered after the fact.If the answer to 3 is "no" and the answer to 2 is "inferred", then this issue is fully explained by the split-out bug and this one can close. If a redeem genuinely landed, there is a real adoption path here that the password check should have prevented, and that is worth understanding properly.