March Docs

ClusterConn

ClusterConn: the net-kernel connection lifecycle (distributed P1, L2).

Ties the transport (NetKernel.handshake) to the peer table (PeerRegistry): dial out to a peer, or accept an inbound connection, run the authenticated handshake, and on success register the peer (one connection per NodeId). A handshake failure closes the socket and returns the reason.

Socket glue, runtime-exercised — the eval-based stdlib test harness does not run sockets (same convention as NetKernel/ChannelServer). It composes only already-unit-tested logic (NetKernel byte bridge + Handshake + ClusterAuth + PeerRegistry) over the available Socket.* / tcp_listen / tcp_accept APIs. (Type annotations are omitted so the qualified PeerRegistry.Registry/Peer type paths are resolved by inference against the bare definitions.)

Functions

fnaccept_oneaccept_one(reg, listen_fd, my_id, secret)#

Single-connection (pre-split) accept: wait for one inbound connection on [listen_fd], run the shared-[secret] handshake as [my_id], and register the peer in [reg] with no data connection. Returns Ok((reg2, peer)) or Err(message); the socket is closed on a handshake failure. Blocks until a peer connects and completes the handshake. The counterpart of connect_to_peer.

fnaccept_splitaccept_split(reg, listen_fd, my_id, secret)#

Accept one peer's TWO connections on [listen_fd], in the order the peer dials them (control, then data), run the shared-[secret] handshake as [my_id] on each, and register the peer in [reg] with both fds. Returns Ok((reg2, peer)), or Err(message) when an accept or handshake fails or the connections arrive out of role order or from different nodes. Blocks until both connections arrive; see accept_split_within for a bound.

fnaccept_split_authaccept_split_auth(reg, listen_fd, my_id, auth, timeout_ms)#

accept_split_within in either authentication mode; see connect_split_auth.

fnaccept_split_withinaccept_split_within(reg, listen_fd, my_id, secret, timeout_ms)#

accept_split, giving up when [timeout_ms] (<= 0: no bound) passes with no connection pending, or with a handshake unfinished: Err("tcp_accept: timed out") for the first, the handshake's own error for the second. The bound applies to each accept and each handshake separately, so the whole call can take up to about four times [timeout_ms].

fnconnect_splitconnect_split(reg, host, port, my_id, secret)#

Dial [host]:[port] twice, control connection first and then data, run the shared-[secret] handshake as [my_id] on each, and register the peer in [reg] with both fds. Returns Ok((reg2, peer)) or Err(message) (connect failure, handshake failure, or the two connections reaching different nodes); on failure every socket it opened is closed. The handshakes are unbounded: blocks until the peer answers. See connect_split_within.

fnconnect_split_authconnect_split_auth(reg, host, port, my_id, auth, timeout_ms)#

connect_split_within in either authentication mode ([auth], a ClusterAuth.Auth): also returns the peer's verified certificate (certificate mode; None with a shared secret) and remembers it for peer_cert. Both connections must reach the same node.

fnconnect_split_withinconnect_split_within(reg, host, port, my_id, secret, timeout_ms)#

connect_split, with each handshake's reads bounded by [timeout_ms] (<= 0: no bound), so a peer that accepts and then says nothing fails with the handshake's error instead of blocking the caller for ever. The TCP connect itself is not bounded by [timeout_ms].

fnconnect_to_peerconnect_to_peer(reg, host, port, my_id, secret)#

Single-connection (pre-split) dial: connect to [host]:[port], run the shared-[secret] handshake as [my_id], and register the peer in [reg] with no data connection (data_fd is PeerRegistry.no_fd()). Returns Ok((reg2, peer)) or Err(message); the socket is closed on a handshake failure. Unbounded: blocks until the peer completes the handshake. Kept for pre-split peers and fixtures; new code uses connect_split_auth.

fnlistenlisten(port : Int) : Result(Int, String)#

Open a TCP listening socket on [port] (tcp_listen). Returns Ok(fd), or Err(message) when the port cannot be bound (e.g. already in use). Pass the fd to accept_split / accept_split_auth / accept_one.

match ClusterConn.listen(9100) do
  Ok(lfd) -> serve(lfd)
  Err(e) -> println("listen failed: " ++ e)
end
fnpeer_certpeer_cert(node_id : String) : Option(NodeCert.Cert) do Vault.get(certs(), node_id) end#

The verified certificate of peer [node_id] (certificate mode), if it presented one.