feat(punktfunk1): configurable data-plane UDP port (--data-port)

The native data plane used a random ephemeral UDP port (hole-punched), which a
strict firewall can't pre-open — so remote clients behind one couldn't connect.
Add an optional fixed data port:

- `Punktfunk1Options`/`NativeServe` gain `data_port`; `bind_data_socket` binds the
  fixed port (→ direct, no hole-punch) or falls back to a random port + hole-punch
  when unset or the fixed port is busy (a concurrent session already holds it).
- `UdpTransport::from_socket`/`from_socket_punch` adopt an already-bound socket, so
  the host keeps the SAME data socket from handshake through streaming — no
  drop-then-rebind window in which a concurrent session could steal a fixed port.
- `main.rs` wires the CLI flag through to `NativeServe`.
- Firewall docs updated (troubleshooting.md + apt/pacman/bazzite READMEs): control
  plane is the fixed UDP 9777; the data plane is a separate random port that usually
  needs no rule, with the fixed-port option for strict firewalls.

Unit-tested: default random+hole-punch, and fixed-port-then-fallback-when-busy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-05 13:53:54 +00:00
parent 677a4f4cf5
commit 62e0367f4b
7 changed files with 238 additions and 37 deletions
+8 -3
View File
@@ -361,9 +361,14 @@ sudo firewall-cmd --reload
default unit):
- **QUIC control plane: UDP 9777** (default `--port`; change with `--port N`).
- **Data plane: an *ephemeral* UDP port** — `punktfunk1-host` binds `0.0.0.0:0` and tells the client which
port it got, so there is **no fixed data port to open**. For a restrictive firewall you'd need to
allow the ephemeral UDP range; the repo does not pin one.
- **Data plane: a separate UDP port** — by default *random* (`0.0.0.0:0`), so there is **no fixed
port to open**. Video flows host → client, but the client sends the first packet (a hole-punch): if
firewalld drops it, the host waits ~2.5 s and falls back to the client-reported address and streams
anyway, so you normally **leave the data port closed**. To skip that ~2.5 s fallback, pin it with
`serve --data-port <PORT>` (or `PUNKTFUNK_DATA_PORT`) and open exactly that one port with
`firewall-cmd --add-port=<PORT>/udp`. A fixed port serves one session at a time (concurrent ones
fall back to random + hole-punch) and streams to the client's reported address (flat LAN /
non-remapping forward only).
```sh
# Only if you run `punktfunk1-host`: