PeerNet (PeerNet v0.1.0)

Copy Markdown View Source

Public API for the PeerNet library and the per-instance supervisor.

See README for an overview, PLAN for the v1 roadmap and module breakdown, and guides/protocol.md for the wire-format specification.

Starting an instance

children = [
  {PeerNet, [name: :my_node, data_dir: "/var/lib/myapp/peer_net", port: 4040]}
]

Options:

  • :name (required) — atom; root name for this instance's processes. All public API functions take this name as their first argument.
  • :data_dir (required) — directory where the identity keyfile and trust list are persisted.
  • :port (required) — TCP port to listen on; pass 0 for an OS-assigned ephemeral port.

Multiple instances

More than one PeerNet instance can run inside the same BEAM (used in tests and in apps that need to expose multiple identities). Each takes a unique :name, and its child processes derive their names from it (e.g. :my_node.trust, :my_node.handlers).

Threat model

See README. v0 (the current state) speaks authenticated-but-plaintext TCP — the channel is not encrypted yet. Use on local trusted networks only until Noise XX lands.

Summary

Types

A peer's permanent address — a 32-byte Ed25519 public key.

Functions

Call handle on pubkey with args. Awaits a reply.

Open a new outbound connection to pubkey at host:port.

True iff a live, authenticated connection to pubkey exists.

Register a handler for inbound calls/sends from peers.

Return all known peers' pubkeys (currently just the trust list).

Add pubkey to this instance's trust list.

Return the OS-assigned listen port for this instance.

Revoke a previously-exposed handle.

Send args to handle on pubkey. Fire-and-forget.

Start a PeerNet instance. See module docs for options.

Remove pubkey from this instance's trust list.

Types

pubkey()

@type pubkey() :: <<_::256>>

A peer's permanent address — a 32-byte Ed25519 public key.

Functions

call(name \\ __MODULE__, pubkey, handle, args, timeout \\ 5000)

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

Call handle on pubkey with args. Awaits a reply.

Returns {:ok, result}, {:error, :not_connected} if no live connection exists, or {:error, reason} for transport/handler errors.

connect(name \\ __MODULE__, pubkey, host, port)

@spec connect(
  atom(),
  pubkey(),
  :inet.ip_address() | charlist() | binary(),
  :inet.port_number()
) ::
  :ok | {:error, term()}

Open a new outbound connection to pubkey at host:port.

This is the manual-pairing path used in tests and in setups without mDNS discovery. Once mDNS discovery (M3) lands, peers will be auto-connected on detection.

Returns :ok once the socket is open and the connection process is spawned. Use connected?/2 to wait for handshake completion before issuing calls.

connected?(name \\ __MODULE__, pubkey)

@spec connected?(atom(), pubkey()) :: boolean()

True iff a live, authenticated connection to pubkey exists.

expose(name \\ __MODULE__, handle, fun, opts \\ [])

@spec expose(
  atom(),
  atom(),
  PeerNet.Handlers.handler(),
  PeerNet.Handlers.expose_opts()
) ::
  :ok | {:error, term()}

Register a handler for inbound calls/sends from peers.

See PeerNet.Handlers.expose/4 for option details.

identity(name \\ __MODULE__)

@spec identity(atom()) :: PeerNet.Identity.t()

Return this instance's PeerNet.Identity.

list_peers(name \\ __MODULE__)

@spec list_peers(atom()) :: [map()]

Return all known peers' pubkeys (currently just the trust list).

pair(name \\ __MODULE__, pubkey, opts \\ [])

@spec pair(atom(), pubkey(), keyword()) :: :ok | {:error, :invalid_pubkey}

Add pubkey to this instance's trust list.

port(name \\ __MODULE__)

@spec port(atom()) :: :inet.port_number()

Return the OS-assigned listen port for this instance.

revoke(name \\ __MODULE__, handle)

@spec revoke(atom(), atom()) :: :ok

Revoke a previously-exposed handle.

send(name \\ __MODULE__, pubkey, handle, args)

@spec send(atom(), pubkey(), atom(), term()) :: :ok | {:error, :not_connected}

Send args to handle on pubkey. Fire-and-forget.

start_link(opts)

@spec start_link(keyword()) :: Supervisor.on_start()

Start a PeerNet instance. See module docs for options.

unpair(name \\ __MODULE__, pubkey)

@spec unpair(atom(), pubkey()) :: :ok

Remove pubkey from this instance's trust list.