good_net_p2p 0.2.0 copy "good_net_p2p: ^0.2.0" to clipboard
good_net_p2p: ^0.2.0 copied to clipboard

Serverless peer-to-peer UDP backend for good_net: reliable and unreliable channels, LAN discovery, and join codes that carry the host address. No broker, relay or server to run.

good_net_p2p #

The serverless backend for good_net: peer-to-peer UDP with nothing in the middle. Add the dependency, declare it, and a game is networked.

descriptor.transport(P2PNetTransport());

Hosting binds a UDP socket and hands back a ten-character code that is the host's address. Joining decodes it and starts talking. There is no broker, no relay, no account, nothing to deploy and nothing that can go down.

final session = await network.host(SessionOptions(name: 'Kitchen table'));
print(session.id);          // 4KM2QX9P7T - read this out to a friend

await network.join(SessionId('4KM2QX9P7T'));

On a LAN nobody types anything: a host announces itself once a second, and network.discover() lists what is out there.

How far a code reaches #

What a code actually reaches, because "P2P" tends to promise more than it delivers:

Where Works Why
One machine Yes Nothing in the way
One LAN Yes The code carries a LAN address, and discovery means nobody has to type it
Across the internet Not yet A home router hands out a private address and drops unsolicited inbound packets

Crossing a router needs a peer's public address (STUN) and a moment of coordination so both sides punch at once (a rendezvous). That is the next landing. And the limit past it, worth signing off on before it is built: pure hole punching fails when both peers are behind symmetric NAT, so "free, no server" and "always connects" are not the same claim. A TURN-style relay fallback is a separate, clearly-scoped addition.

The protocol #

A lightweight UDP protocol implementing good_net's two channels directly, instead of emulating them over a TCP-shaped stream — and instead of pulling a DTLS and SCTP stack into a native game by binding WebRTC.

Mechanism How
Acknowledgement Every packet carries seq, ack and 32 ackBits, so one packet acknowledges 33 — losing an ack costs nothing
Reliability A reliable message is kept until a packet carrying it is acknowledged, then resent on a timer derived from the measured round trip
Ordering Reliable messages carry an id; the receiver delivers in order and buffers what arrives early
Batching A tick's worth of messages become one datagram, up to 1200 bytes
Fragmentation Anything larger is split and reassembled on the far side
Liveness A keepalive every 100 ms; a link silent for linkTimeout (5 s) is declared gone

Not here, and named instead of approximated: congestion control. A link sends what the game asks it to and reports packetLoss so the game can decide to send less.

Testing netcode that has only ever seen loopback #

simulatedLoss throws away a fraction of outgoing datagrams. It is a field on the shipped class, not a test helper on purpose: netcode that has only run over loopback has never had a packet lost, so every retransmission path in it is untested code that first runs on a player's hotel wifi.

final transport = P2PNetTransport(simulatedLoss: 0.3);
transport.simulatedLoss = 1;   // settable: the link that was fine, and then was not

At 30% loss the reliable channel still delivers everything in order — this package's tests assert exactly that, alongside good_net's conformance suite run over real sockets.

0
likes
150
points
123
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

Serverless peer-to-peer UDP backend for good_net: reliable and unreliable channels, LAN discovery, and join codes that carry the host address. No broker, relay or server to run.

Homepage
Repository (GitHub)
View/report issues

License

(pending) (license)

Dependencies

good_net

More

Packages that depend on good_net_p2p