141 lines
8.0 KiB
Markdown
141 lines
8.0 KiB
Markdown
# Rendezvous
|
|
|
|
Rendezvous is shared discovery and connection-coordination infrastructure for Final Factory multiplayer games. It gives games such as **SpaceGame** and **Unscouted** a common way to publish available servers, browse sessions, authorize joins, and establish direct peer-to-peer UDP connections through NAT where possible.
|
|
|
|
Rendezvous is not a game server. It does not simulate gameplay, own match state, or carry normal gameplay traffic. Once two peers establish a direct connection, the service leaves the gameplay path.
|
|
|
|
## Responsibilities
|
|
|
|
Rendezvous is intended to provide:
|
|
|
|
- Server registration with renewable heartbeat leases.
|
|
- Server and session browsing with bounded, game-specific metadata.
|
|
- Public endpoint observation for hosts and clients.
|
|
- LiteNetLib NAT introduction and UDP hole punching.
|
|
- Short-lived, authenticated join and punch tokens.
|
|
- Clear timeouts and failure results when a direct connection cannot be established.
|
|
- Isolation by game, environment, protocol version, and region.
|
|
- Operational health, metrics, logging, administration, and rate limiting.
|
|
|
|
UDP hole punching cannot guarantee a direct connection through every network. Symmetric NAT, carrier-grade NAT, restrictive firewalls, and platform policies can prevent it. Consumers must therefore support a defined fallback, such as a dedicated server. The v1 SDK returns an optional game-configured endpoint for an explicit caller decision; it never routes automatically, and v1 does not provide a relay.
|
|
|
|
## Connection flow
|
|
|
|
1. A host registers a server or session and renews its lease with heartbeats.
|
|
2. A client queries Rendezvous and selects a compatible session.
|
|
3. Rendezvous validates the join request and issues short-lived credentials.
|
|
4. The host and client contact the mediator from their gameplay UDP sockets.
|
|
5. The mediator introduces their observed public and reported local endpoints.
|
|
6. Both peers attempt LiteNetLib UDP hole punching.
|
|
7. On success, they establish a direct authenticated connection.
|
|
8. On timeout or failure, the game selects or reports its configured fallback.
|
|
|
|
## Planned components
|
|
|
|
- `FinalFactory.Rendezvous.Server` — deployable service hosting the server directory, HTTP API, and UDP NAT mediator.
|
|
- `FinalFactory.Rendezvous.Contracts` — versioned wire contracts and shared protocol definitions.
|
|
- `FinalFactory.Rendezvous.Client` — .NET client library used by participating games.
|
|
- `FinalFactory.Rendezvous.TestClient` — thin interactive and scriptable host/browser/join diagnostic built only on the public SDK.
|
|
- `FinalFactory.Rendezvous.Tests` — unit, integration, security, and connection-lifecycle tests.
|
|
|
|
The server directory and NAT mediator are separate modules in one single-active
|
|
deployable service because they share ephemeral session, lease, authorization,
|
|
replay, and endpoint state. Their internal boundary can support a future
|
|
explicitly designed shared-state architecture; operators must not create
|
|
multiple active v1 replicas.
|
|
|
|
## Service boundaries
|
|
|
|
Rendezvous must remain independent of game simulation and transport payloads. Each game supplies only the information required for discovery and compatibility, including:
|
|
|
|
- A stable game identifier and environment.
|
|
- Build and network-protocol compatibility versions.
|
|
- Region and capacity information.
|
|
- A bounded, validated metadata document for browser presentation.
|
|
|
|
Canonical player, world, inventory, combat, and persistence state remains owned by each game's authoritative server. Rendezvous identifiers must never become canonical entity or player identities.
|
|
|
|
## Security model
|
|
|
|
The service is designed as public Internet infrastructure. Implementations should assume all registrations, searches, metadata, and UDP packets are hostile. At minimum, the production service will require:
|
|
|
|
- Per-game credentials and signing keys.
|
|
- Short-lived, single-purpose tokens resistant to replay.
|
|
- Strict payload, metadata, and token size limits.
|
|
- Registration, query, and introduction rate limits.
|
|
- Lease expiry so abandoned or crashed servers disappear automatically.
|
|
- Validation of game, environment, room, and protocol-version boundaries.
|
|
- Structured audit events without logging secrets or reusable credentials.
|
|
|
|
## Non-goals
|
|
|
|
The initial service does not provide:
|
|
|
|
- Gameplay hosting or authoritative simulation.
|
|
- General-purpose user accounts, social features, or chat.
|
|
- Skill-based matchmaking.
|
|
- Guaranteed traversal through every NAT or firewall.
|
|
- Gameplay relaying; a relay may be designed as a separate future component.
|
|
|
|
## Project status
|
|
|
|
Rendezvous is under active roadmap development. The versioned contracts,
|
|
directory leases, authenticated join attempts, LiteNetLib mediator, caller-owned
|
|
SDK coordination, typed connection outcomes, thin public-SDK diagnostic client,
|
|
deterministic NAT topology harness, hostile-input controls,
|
|
observability/operator surface, secure single-active Linux deployment, and
|
|
numeric capacity/resilience gates, and reproducible signed release pipeline are
|
|
implemented. Consumer pilots and final production-readiness gates remain in progress;
|
|
participating games must not treat the current repository as a finished production
|
|
service until those gates land.
|
|
|
|
The ratified v1 boundaries, trust decisions, privacy rules, safety budgets, and
|
|
threat model are indexed in [the architecture documentation](docs/architecture/README.md).
|
|
The frozen v1 wire surface is documented in the
|
|
[HTTP, UDP, and generated OpenAPI contracts](docs/contracts/README.md).
|
|
Tenant policy, publisher/operator principals, and production key custody are
|
|
defined in [game provisioning and signing-key lifecycle](docs/security/provisioning.md).
|
|
Layered HTTP/UDP budgets, overload behavior, and safe operational tuning are
|
|
defined in [hostile-input and overload protection](docs/security/abuse-protection.md).
|
|
Health semantics, bounded telemetry, alerting, audit privacy, and the authenticated
|
|
operator controls are defined in the
|
|
[observability and operator runbook](docs/operations/observability-and-operator-runbook.md).
|
|
The pinned non-root container, production topology, graceful drain, Linux
|
|
hardening, smoke procedure, and recovery lifecycle are documented in
|
|
[secure single-active Linux deployment](docs/deployment/linux.md).
|
|
The numeric core-state candidate profile, public launch objectives, accelerated
|
|
soak, resilience matrix, and single-active scaling decision are recorded in
|
|
[capacity and resilience gates](docs/operations/capacity-and-resilience.md).
|
|
Release versions, compatibility windows, immutable artifact construction,
|
|
signing, staged promotion, rollback, and migration are defined in
|
|
[releases and compatibility](docs/releases/README.md).
|
|
The scriptable host/browser/join diagnostic and its stable automation contract are
|
|
documented in the [TestClient integration guide](docs/integration/test-client.md).
|
|
The always-on three-party scenarios, optional Linux namespace topology, and
|
|
simulation limits are documented in the
|
|
[deterministic topology harness](docs/integration/topology-harness.md).
|
|
|
|
## Development
|
|
|
|
The repository pins .NET SDK 10.0.301. From a clean clone, run the same gates as
|
|
CI from the repository root:
|
|
|
|
```bash
|
|
dotnet restore Rendezvous.slnx --locked-mode
|
|
dotnet format Rendezvous.slnx --verify-no-changes --no-restore
|
|
dotnet build Rendezvous.slnx --configuration Release --no-restore
|
|
dotnet test Rendezvous.slnx --configuration Release --no-build
|
|
```
|
|
|
|
Run the bootstrap server with
|
|
`dotnet run --project src/FinalFactory.Rendezvous.Server`. It serves HTTP health endpoints and binds
|
|
the configured UDP mediator port; both stop through normal host cancellation.
|
|
The launch profile uses separate ephemeral development-only publisher and operator
|
|
signing keys. Production
|
|
startup fails closed until its advertised endpoints, proxy trust boundary,
|
|
externally supplied game policies, and `env:` (base64) or `file:` (raw,
|
|
absolute, non-symlink) signing-key references resolve safely; no reusable game secret is stored
|
|
in this repository or the public Client package.
|
|
The project dependency rules and supported runtime choices are documented in
|
|
[project and dependency boundaries](docs/architecture/project-boundaries.md).
|