netfishing-discovery-server/README.md

100 lines
4 KiB
Markdown

# NETfishing Discovery Server
An ephemeral public-room directory for NETfishing. It complements the game's existing direct ENet
transport: hosts advertise a room through HTTPS, browsers retrieve compatible rooms, and joining
still uses the authoritative host's UDP endpoint.
The service also runs a small UDP rendezvous. It observes packets sent from the exact ENet sockets
used by hosts and joiners, then lets an authenticated room host retrieve pending endpoints and send
hole-punch packets. Gameplay remains direct and never passes through this service.
## Requirements
- Python 3.11 or newer
- A TLS reverse proxy for public deployment
There are no runtime Python package dependencies.
## Run locally
```bash
python3 -m netfishing_discovery
```
The default listener is `127.0.0.1:7770`.
```bash
curl http://127.0.0.1:7770/health
```
Set `NETFISHING_DISCOVERY_BUILD_REVISION` to the deployed Git commit. The health response reports
both the package version and that build revision, which makes production/source drift visible.
Run the focused tests with:
```bash
python3 -m unittest discover -v
```
## Configuration
Environment variables are documented in
[`deploy/netfishing-discovery.env.example`](deploy/netfishing-discovery.env.example).
The intended public topology is:
```text
NETfishing client -> HTTPS reverse proxy -> 127.0.0.1:7770 discovery service
NETfishing client -----------------------> public UDP rendezvous:7771
NETfishing client -----------------------> advertised ENet/UDP host:port
```
Configure the Godot client with the reverse proxy's HTTPS origin through
`network/discovery/base_url` in `project.godot`. For local development, the
same value can be overridden without modifying the project by setting
`NETFISHING_DISCOVERY_URL` before launching the game.
The reverse proxy must preserve the client address in `X-Forwarded-For`, and
its own address must be listed in `NETFISHING_DISCOVERY_TRUSTED_PROXY_CIDRS`.
Apply ordinary request-rate limits to the write endpoints at the proxy. Do not
expose the Python listener directly to the public Internet.
Use the sample systemd unit in [`deploy/netfishing-discovery.service`](deploy/netfishing-discovery.service)
as a deployment starting point. The service keeps only active leases in memory, so it requires no
database, backups, or schema migrations.
## Connectivity boundary
The game first requests UPnP forwarding, then uses same-socket UDP rendezvous and hole punching.
This covers common home NAT configurations without changing ENet gameplay authority. Symmetric
NAT and some carrier-grade networks can still require a future ENet-compatible relay fallback.
Expose the configured traversal port over UDP in both the host firewall and provider firewall.
The rendezvous listener intentionally processes its small, bounded packets serially so arbitrary
datagrams cannot create unbounded worker threads. Apply conservative edge rate limits as an
additional deployment control.
## API
See [`docs/API.md`](docs/API.md) for the versioned HTTP contract.
## Repository relationship
This is deliberately a separate repository from the Godot game so the service can deploy and roll
back independently. Production tags follow the coordinated NETfishing release train: a
`vX.Y.Z-alpha` tag identifies the discovery snapshot tested for the same game and dedicated-server
release. The versioned HTTP contract remains independent from NETfishing's save schema and gameplay
network protocol. Each tagged deployment accepts room advertisements only from its matching game
release so incompatible rooms are never presented as publicly available.
## Licensing
Project-owned source code is licensed under the GNU General Public License,
version 3 or, at your option, any later version
([GPL-3.0-or-later](LICENSE)).
NETfishing and Woofmeow branding is not granted under the GPL; see
[`TRADEMARKS.md`](TRADEMARKS.md). Contributions are accepted under
[`CONTRIBUTING.md`](CONTRIBUTING.md) and
[`CONTRIBUTOR-TERMS.md`](CONTRIBUTOR-TERMS.md).
Copyright © 2026 Woofmeow.