One connection to one peer — a GenServer that owns a TCP socket, drives
the PeerNet.Handshake to completion, and then multiplexes
:call/:reply/:send envelopes over the wire.
Lifecycle
- Spawned with
:inbound(fromPeerNet.Acceptor) or:outbound(fromPeerNet.connect/4) plus an open TCP socket. - Handshake: drives
PeerNet.Handshakein a tight loop until the peer's pubkey is verified against the trust list. Bad input → terminate. - Registered: once authenticated, registers itself with
PeerNet.Registryunder the verified peer pubkey. - Active: receives envelopes, dispatches
:calland:sendthroughPeerNet.Handlers, matches:replyenvelopes to in-flight callers. - Terminated: socket close, peer revoke, or supersede event.
Caller registration
An outbound PeerNet.call/4 arrives here as a GenServer.call. Each call
is assigned a 64-bit non-zero request_id; the GenServer stores
{request_id => GenServer.from} and replies asynchronously when the
matching :reply envelope arrives. Unknown reply IDs are dropped — they
may be late replies for already-timed-out calls.
v0 limitations
- Plaintext over TCP (no Noise yet — see
PeerNet.Handshakenotes). - No reconnect logic. If the socket dies, the connection terminates and
the peer must be re-
connect/4'd. - No application-level liveness ping. Detection of dead peers waits on TCP-level events.
Summary
Types
How the socket was created.
Functions
Send a :call envelope and await {:reply, _, result} (or timeout).
Returns a specification to start this module under a supervisor.
Take ownership of an inbound socket. Used by Acceptor after :gen_tcp.accept/1.
Send a fire-and-forget :send envelope. No reply expected.
Start a connection process owning socket.
Types
Functions
Send a :call envelope and await {:reply, _, result} (or timeout).
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec hand_off_socket(pid(), :gen_tcp.socket()) :: :ok
Take ownership of an inbound socket. Used by Acceptor after :gen_tcp.accept/1.
Send a fire-and-forget :send envelope. No reply expected.
@spec start_link(keyword()) :: GenServer.on_start()
Start a connection process owning socket.
After this call the GenServer takes ownership: the caller must not read
or write socket afterwards. Usually called by Acceptor or via
PeerNet.connect/4.
Required opts: :identity, :trust, :handlers, :peer_index,
:direction. Optional: :expected_peer (the pubkey the dialer expects
on the other end of an outbound connection).