CultLib/src/GameCult.Mesh.Quic
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Meta Vens 5c6398473f Document latest-only retention for newly attached QUIC peers
One sentence each in the C# QUIC README and the transport-planes doc: a
provider retains the newest latest-only frame per (channel, body) and
delivers it to a peer as soon as it attaches, bounded by the number of
distinct keys.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 18:17:37 +02:00
..
CultMeshQuicRealtimeTransport.cs C# QUIC server: retain the newest latest-only frame per (channel, body) 2026-09-23 18:17:28 +02:00
GameCult.Mesh.Quic.csproj Add MsQuic realtime transport package 2026-07-19 18:36:50 +01:00
README.md Document latest-only retention for newly attached QUIC peers 2026-09-23 18:17:37 +02:00

GameCult.Mesh.Quic

GameCult.Mesh.Quic is the optional MsQuic-backed realtime state plane for CultMesh daemons and .NET tools. It implements the transport-neutral contracts from GameCult.Mesh; it does not own discovery, provider authorization, state meaning, commands, receipts, schemas, or immutable content.

The package targets .NET 10. It uses System.Net.Quic, which requires a supported MsQuic runtime and TLS 1.3. Unity runtimes do not consume this package; their generic CultMesh lowerer needs a native MsQuic connector implementing the same ICultMeshRealtimeTransportConnector contract.

Provider

using GameCult.Mesh.Quic;

await using var server = await CultMeshQuicRealtimeServer.ListenAsync(
    new CultMeshQuicRealtimeServerOptions
    {
        ListenEndPoint = new IPEndPoint(IPAddress.Any, 7443),
        ServerCertificate = providerCertificate
    });

await server.BroadcastAsync(new CultMeshRealtimeFrame
{
    ChannelId = "aetheria.entities",
    SchemaId = "eve.entity_soa.v1",
    BodyId = "body:aetheria:entities",
    ProducerEpoch = epoch,
    Sequence = sequence,
    Delivery = CultMeshRealtimeDelivery.LatestOnly,
    Payload = encodedSoa
});

Advertise the listener as cultmesh-state+quic://host:port. Certificate identity and provider identity must be bound by the application trust policy; accepting every certificate is appropriate only in isolated tests. For directly trusted discovery records, a provider may append its uppercase SHA-256 certificate fingerprint as ?cert-sha256=.... The default connector accepts a self-signed certificate only when its raw certificate bytes match that advertised pin. A caller-supplied validator remains authoritative when present.

Consumer

var connector = new CultMeshQuicRealtimeTransportConnector(
    new CultMeshQuicRealtimeConnectorOptions
    {
        ValidateProviderCertificate = ValidateAdvertisedProvider
    });

using var sessions = new CultMeshSessionManager(
    discovery,
    schemaConnectors,
    contentConnectors,
    new ICultMeshRealtimeTransportConnector[] { connector });

var session = await sessions.ConnectRealtimeAsync(providerId);
var frame = await session.ReceiveAsync(cancellationToken);

Delivery modes

  • ReliableOrdered uses one ordered QUIC stream.
  • LatestOnly uses independent streams and keeps at most one pending frame per channel and body. A newer (producer epoch, sequence) generation replaces queued state. The provider also retains the newest LatestOnly frame per (channel, body) and delivers it to each client as soon as it attaches.
  • Unreliable fails closed in this adapter because System.Net.Quic does not expose QUIC datagrams. Use a native MsQuic connector when datagram semantics are required.

Schemas, commands, receipts, manifests, and immutable content remain on their TCP planes. Same-machine SoA should negotiate mapped/shared memory instead of crossing QUIC.