01 · Problem
What is it for?
A peer coordinator must own sockets and discovery records throughout its lifecycle.
02 · Mental model
How should you think about it?
Separate address discovery, byte transport, message framing and authentication into explicit contracts.
Starts TCP peers explicitly and transports bounded, length-prefixed frames. Local discovery is the default; NetworkMDNS can be injected with an advertised network hostname. TCP data is unencrypted; trust establishment, authentication and replay protection need a full protocol.
03 · Control flow
What happens in which order?
- Start a TCP listener explicitly.
- Announce its actual port.
- Discover service records.
- Create peer connection state.
- Close peers, listener and discovery records on destroy.
04 · Building blocks
The important contracts
P2P.start / discoverPeers / destroyOwn the TCP server and discovery lifecycle.Peer.connect / send / disconnectTransport bounded plaintext frames over TCP.KeyPairEncryptionDemonstrate RSA encryption and signing as separate primitives.05 · Build it yourself
Implement a small core
Start with this small independent implementation, then use the steps below to make its contract explicit.
- Start a TCP listener explicitly.
- Announce its actual port.
- Discover service records.
- Create peer connection state.
- Close peers, listener and discovery records on destroy.
type Frame = { type: number; sequence: number; payload: Uint8Array };
function encodeFrame(frame: Frame) {
const body = encodeBody(frame);
if (body.length > 1_048_576) throw new RangeError("Frame too large");
const output = new Uint8Array(4 + body.length);
new DataView(output.buffer).setUint32(0, body.length);
output.set(body, 4);
return output;
}
function acceptSequence(last: number, next: number) {
if (next !== last + 1) throw new Error("Invalid sequence");
}06 · Verify
What should you test?
- Start on an ephemeral port and verify the announcement.
- Ensure destroy removes its discovery record.
- Test split messages, disconnections and shutdown with active sockets.
Try it yourself
Turn the first verification claim into a failing test, implement the smallest fix, then add a boundary case.
Start on an ephemeral port and verify the announcement.
Compare your approach
Your check should fail when the stated invariant is deliberately broken, and pass again after the fix. Keep setup deterministic and assert an observable result.
07 · Limits
Trade-offs and failure modes
- Real multicast transport remains incomplete.
- TCP needs explicit framing.
- Authentication and replay protection require a complete protocol.
Local discovery is the default; NetworkMDNS can be injected with an advertised network hostname. TCP data is unencrypted; trust establishment, authentication and replay protection need a full protocol.
08 · Keep exploring
Source code and related ideas
yarn tsx packages/p2p/examples/basic.ts