macula_dist (macula v1.4.30)

View Source

QUIC Distribution Carrier for Erlang.

This module implements the Erlang distribution carrier interface using QUIC transport via quicer. It replaces inet_tcp_dist to enable distributed Erlang over QUIC with:

- Built-in TLS 1.3 encryption (mandatory) - NAT-friendly UDP-based transport - Connection migration support - Stream multiplexing for message priorities - Decentralized discovery (no EPMD required)

When MACULA_DIST_MODE=relay, distribution is tunneled through the Macula relay mesh via gen_tcp loopback pairs bridged to pub/sub. See macula_dist_relay for relay tunnel details.

Usage

Start the VM with: erl -proto_dist macula -no_epmd -start_epmd false

Or in vm.args: -proto_dist macula -no_epmd -start_epmd false -macula_dist_port 4433

Summary

Functions

Accept incoming connections. Called in a loop by net_kernel.

Accept a distribution connection from a remote node. Socket is either {QuicConn, Stream} (direct QUIC) or a gen_tcp port (relay).

Return address information for this distribution.

Return child specifications for the distribution supervisor.

Close a distribution connection.

Check if a string is a valid node name.

Listen for incoming distribution connections.

Check if this module should handle distribution to the given node.

Setup an outgoing distribution connection. self() here is net_kernel — captured as Kernel for the spawned process.

Split a node name into port and host. Supports two formats: - port@host (e.g., 4433@192.168.1.100) — explicit port - name@host (e.g., test@nanode1.example.com) — uses default port

Functions

accept(Sentinel)

-spec accept(term()) -> pid().

Accept incoming connections. Called in a loop by net_kernel.

In direct-QUIC mode: acceptor_loop runs accept on the listener handle. In relay (pub/sub) / dist_relay modes: acceptor_loop blocks — inbound connections arrive via the respective client which delivers the {accept, ...} messages directly to net_kernel.

accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime)

-spec accept_connection(pid(), term(), node(), term(), term()) -> pid().

Accept a distribution connection from a remote node. Socket is either {QuicConn, Stream} (direct QUIC) or a gen_tcp port (relay).

address()

-spec address() -> #net_address{address :: term(), host :: term(), protocol :: term(), family :: term()}.

Return address information for this distribution.

childspecs()

-spec childspecs() -> [supervisor:child_spec()].

Return child specifications for the distribution supervisor.

close(Socket)

-spec close(term()) -> ok.

Close a distribution connection.

is_node_name(Name)

-spec is_node_name(string()) -> boolean().

Check if a string is a valid node name.

listen(NodeName)

-spec listen(atom()) ->
                {ok,
                 {term(),
                  #net_address{address :: term(), host :: term(), protocol :: term(), family :: term()},
                  1..3}} |
                {error, term()}.

Listen for incoming distribution connections.

Dispatches on the current mode (set via MACULA_DIST_MODE env var): - relay (legacy): pub/sub bridge through the station — no local listener - dist_relay: tunnels via the dedicated dist relay — no local listener - direct (default): raw QUIC listener on the dist port

select(Node)

-spec select(atom()) -> boolean().

Check if this module should handle distribution to the given node.

setup(Node, Type, MyNode, LongOrShortNames, SetupTime)

-spec setup(node(), term(), atom(), term(), term()) -> pid().

Setup an outgoing distribution connection. self() here is net_kernel — captured as Kernel for the spawned process.

splitname(NodeName)

-spec splitname(atom() | string()) -> {integer(), string()} | false.

Split a node name into port and host. Supports two formats: - port@host (e.g., 4433@192.168.1.100) — explicit port - name@host (e.g., test@nanode1.example.com) — uses default port