--lan startup: lead with the default-route address, demote the rest
A multi-homed machine (VM bridges, Ethernet + Wi-Fi) has several addresses and the server cannot know which network the phone is on — but the OS's default route is the right answer nearly always. The banner now prints one "on your phone" URL from the route probe, with the other interfaces on an if-that-doesn't-answer line; when the probe fails, the settings hint plus candidates. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016jXZFSTZQKzAC8fqpWSz9g
This commit is contained in:
co-authored by
Claude Fable 5
parent
eb2e841d27
commit
95fd18ca5c
+43
-22
@@ -247,6 +247,21 @@ NAV_PAGES = (
|
||||
PHOTO_SUFFIXES = {".jpg", ".jpeg", ".png", ".heic"}
|
||||
|
||||
|
||||
def _route_ip() -> str | None:
|
||||
"""The IPv4 address of this machine's default outbound interface — the
|
||||
single best guess for the address a phone on the same network dials.
|
||||
Multi-homed machines (VM bridges, Ethernet + Wi-Fi) have several
|
||||
addresses; this is the one the OS actually routes through."""
|
||||
try:
|
||||
probe = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
probe.connect(("192.0.2.1", 80)) # never sent; just picks the route
|
||||
address = probe.getsockname()[0]
|
||||
probe.close()
|
||||
return address
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
|
||||
def lan_hosts() -> set[str]:
|
||||
"""This machine's names and addresses on the local network — what a
|
||||
phone's browser will put in the Host header. An allowlist (never a
|
||||
@@ -256,13 +271,8 @@ def lan_hosts() -> set[str]:
|
||||
hostname = socket.gethostname()
|
||||
hosts.add(hostname.lower())
|
||||
hosts.add(hostname.split(".")[0].lower() + ".local")
|
||||
try:
|
||||
probe = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
probe.connect(("192.0.2.1", 80)) # never sent; just picks the route
|
||||
hosts.add(probe.getsockname()[0])
|
||||
probe.close()
|
||||
except OSError:
|
||||
pass
|
||||
if route := _route_ip():
|
||||
hosts.add(route)
|
||||
try:
|
||||
for info in socket.getaddrinfo(hostname, None):
|
||||
address = info[4][0]
|
||||
@@ -1091,27 +1101,38 @@ def run_web_review(
|
||||
# type it once; the cookie remembers it from then on.
|
||||
token = secrets.token_urlsafe(16) if lan else None
|
||||
if lan:
|
||||
hosts = lan_hosts()
|
||||
ips = sorted(
|
||||
h
|
||||
for h in hosts
|
||||
if h.replace(".", "").isdigit() and not h.startswith("127.")
|
||||
primary = _route_ip()
|
||||
spares = sorted(
|
||||
h for h in lan_hosts() if h != primary and not h.startswith("127.")
|
||||
)
|
||||
names = sorted(h for h in hosts if not h.replace(".", "").isdigit())
|
||||
addresses = ", ".join(f"http://{h}:{port}/?k={token}" for h in ips + names)
|
||||
typer.echo(f"bggpipe web UI: {url}?k={token}")
|
||||
typer.echo(f" from your phone, open: {addresses}")
|
||||
typer.echo(f"bggpipe web UI: {url} (this machine needs no key)")
|
||||
if primary:
|
||||
typer.echo(f" on your phone, open: http://{primary}:{port}/?k={token}")
|
||||
if spares:
|
||||
typer.echo(
|
||||
" (several network interfaces here — if that address "
|
||||
"doesn't answer, try: "
|
||||
+ ", ".join(f"http://{h}:{port}/?k={token}" for h in spares)
|
||||
+ ")"
|
||||
)
|
||||
else:
|
||||
typer.echo(
|
||||
" couldn't determine this machine's network address — find "
|
||||
"it in your network settings and open "
|
||||
f"http://<that-ip>:{port}/?k={token}"
|
||||
+ (
|
||||
" (or try: "
|
||||
+ ", ".join(f"http://{h}:{port}/?k={token}" for h in spares)
|
||||
+ ")"
|
||||
if spares
|
||||
else ""
|
||||
)
|
||||
)
|
||||
typer.echo(
|
||||
" --lan: no login beyond that key — anyone who has it can run "
|
||||
"stages, change your data, and (once unlocked) drive uploads "
|
||||
"to your BGG account. Use only on a network you trust."
|
||||
)
|
||||
if not ips:
|
||||
typer.echo(
|
||||
" couldn't determine this machine's network address — find "
|
||||
"it in your network settings and open "
|
||||
f"http://<that-ip>:{port}/?k={token}"
|
||||
)
|
||||
else:
|
||||
typer.echo(
|
||||
f"bggpipe web UI: {url} (localhost only; dashboard at /, review "
|
||||
|
||||
Reference in New Issue
Block a user