PeerNet.Connection (PeerNet v0.1.0)

Copy Markdown View Source

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

  1. Spawned with :inbound (from PeerNet.Acceptor) or :outbound (from PeerNet.connect/4) plus an open TCP socket.
  2. Handshake: drives PeerNet.Handshake in a tight loop until the peer's pubkey is verified against the trust list. Bad input → terminate.
  3. Registered: once authenticated, registers itself with PeerNet.Registry under the verified peer pubkey.
  4. Active: receives envelopes, dispatches :call and :send through PeerNet.Handlers, matches :reply envelopes to in-flight callers.
  5. 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.Handshake notes).
  • 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

direction()

@type direction() :: :inbound | :outbound

How the socket was created.

Functions

call(pid, name, args, timeout \\ 5000)

@spec call(pid(), atom(), term(), pos_integer()) :: {:ok, term()} | {:error, term()}

Send a :call envelope and await {:reply, _, result} (or timeout).

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

hand_off_socket(pid, socket)

@spec hand_off_socket(pid(), :gen_tcp.socket()) :: :ok

Take ownership of an inbound socket. Used by Acceptor after :gen_tcp.accept/1.

send(pid, name, args)

@spec send(pid(), atom(), term()) :: :ok

Send a fire-and-forget :send envelope. No reply expected.

start_link(opts)

@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).