Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Magnet

A generic, zero-allocation UDP game-networking stack in Zig.

Magnet combines typed channels, reliable delivery, congestion control, optional encryption, streaming, and game-state replication behind one comptime Config. Its protocol core is sans-IO, so applications retain control of sockets, clocks, scheduling, and memory placement.

Why Magnet

  • Deterministic memory. Connection tables, queues, pools, and transfer state are fixed by the compile-time configuration. magnet.memoryPlan(config) reports exact storage needs.
  • Typed channels. Each channel binds a delivery mode to a message type, with compile-time checking at application boundaries and raw-byte paths when needed.
  • Sans-IO transport. Feed received datagrams into the protocol and poll outgoing datagrams. The same core works in a game loop, a sharded server, or the deterministic simulator.
  • Integrated game replication. Prediction, rollback, interpolation, interest management, authority, lag compensation, and large transfers share one configurable stack.

Magnet is currently a 0.x project. Its API and wire format may change before v1, and it should be treated as pre-production software. See Status for details.

Quick start

Requires Zig 0.16:

zig fetch --save=magnet git+https://github.com/zigsel/magnet.git

In build.zig:

const dep = b.dependency("magnet", .{
    .target = target,
    .optimize = optimize,
});
exe.root_module.addImport("magnet", dep.module("magnet"));

One configuration selects the message schema, delivery behavior, congestion controller, security, and resource limits:

const magnet = @import("magnet");

const PlayerInput = struct { tick: u32, move_x: i8, move_y: i8 };
const GameEvent = union(enum) {
    spawned: struct { entity: u32 },
    damaged: struct { entity: u32, amount: u16 },
};

const Channels = magnet.proto.channels(.{
    .input = .{ .mode = .unreliable_sequenced, .Message = PlayerInput },
    .events = .{ .mode = .reliable_ordered, .Message = GameEvent },
    .bulk = .{ .mode = .reliable_unordered, .Message = void },
});

const Cfg = magnet.Config{
    .channels = Channels,
    .protocol_id = 0x4D41474E4554,
    .app_version = 1,
    .congestion = magnet.proto.delivery.cc.Cubic,
    .security = .{ .mode = .aead, .connection_ids = true },
    .delivery = .{ .fragmentation = true },
    .enable_pmtud = true,
};
const Endpoint = magnet.Endpoint(Cfg);
comptime magnet.validateProduction(Cfg);

After connection setup, the application-facing loop stays small:

try client.sendTo(server_addr, .input, input);

while (client.pollTransmit(&datagram, now)) |out| {
    // Send datagram[0..out.len] to out.addr through an IPv4 or IPv6 UDP driver.
}

// Feed each received UDP datagram back into the same endpoint.
client.feedFrom(from_addr, received_datagram, now);

Acknowledgements, loss recovery, retransmission, pacing, congestion control, encryption, and migration run inside that loop. The rest of the stack composes around the same endpoint:

Area Included API and behavior
Transport Six reliability modes, typed messages, AEAD, forward secrecy, recovery, congestion control, STUN, ICE, relay, and multipath
Replication magnet.replication and magnet.host.Bridge for prediction, rollback, interpolation, interest, authority, and lag compensation
Streaming magnet.proto.stream for raw bytes, files, live sources, progress, integrity, resume, and flexible storage
Runtime magnet.runtime for IPv4, IPv6, game-loop, sharded, Linux-optimized, simulated, and observable drivers

Continue with Getting started or browse the runnable examples.

Architecture

Each layer is usable independently. Unused declarations are not analyzed or linked:

L5  replication/    snapshots, prediction, rollback, interpolation, interest, lag compensation
L4  wire/           derived serialization, bit packing, quantization, delta coding
L3  proto/channel/  reliability modes, ordering streams, WFQ scheduling, packet packing
L2  proto/delivery/ packet numbers, ACK ranges, RACK, RTT/PTO, congestion, fragmentation
L1  proto/conn/     handshake, tokens, AEAD, replay defense, connection IDs, migration
L0  runtime/        std.Io drivers, poll/reactor/sharded/task loops, network simulation
    core/           sequence buffers, pools, rings, bitsets, fixed-point helpers

The compiler-enforced dependency graph keeps the protocol and replication layers independent of runtime IO. See Layering and Sans-IO for the design constraints.

Documentation

Run zig build docs to generate the API reference in zig-out/docs/.

Status

All six layers described above are implemented and exercised in the repository. Magnet is still a 0.x library, so no API or wire compatibility guarantee is currently offered.

The repository includes deterministic impairment tests, fuzz and soak cases, invariant checks, and real-socket validation. Independent security review and completed, recorded Internet soaks remain external release evidence. A v1 release also requires a frozen wire specification, an explicit compatibility policy, and an owner-selected software license.

Applications remain responsible for account identity, matchmaking, durable game state, deployment orchestration, and abuse response.

Validation

zig build test             # unit, integration, and conformance tests
zig build examples         # build every example
zig build ci               # optimization matrix, examples, and API audit
zig build hardening        # impairments, fuzz/soak, and invariant checks
zig build security-review  # reproducible audit-preparation package
zig build bench            # local ReleaseFast microbenchmarks

Acknowledgements

Magnet is informed by established game-networking systems and Internet transport research:

  • reliable.io, netcode.io, and yojimbo by Glenn Fiedler for fixed-capacity networking structures, acknowledgements, tokens, and serialization ideas.
  • RakNet for reliability modes, ordering streams, path-MTU probing, and fragment management.
  • Valve GameNetworkingSockets for scheduling, pacing, authenticated setup, and key-scheduling ideas.
  • quinn and QUIC for loss recovery, RTT/PTO estimation, migration, anti-amplification, and sans-IO architecture.
  • laminar for module boundaries and injectable transport seams.
  • Bevy lightyear for prediction, rollback, interpolation, interest management, and reconciliation ideas.

The borrowed ideas are theirs; the bugs are ours.