macula_dist_relay_protocol (macula v13.2.2)

View Source

Control protocol encoder/decoder for dist relay.

Stream 0 carries CBOR control messages. Each frame:

+----------+---------+ | Len (4B) | MsgPack | +----------+---------+

Len is big-endian uint32 of the msgpack payload size.

Message types: identify → identified tunnel_request → tunnel_ok | tunnel_error tunnel_close → (no reply) tunnel_notify → (relay → target, informs of incoming tunnel)

⚠ A reader refuses rather than carries on, on both counts, because what is at the far end of this channel is a relay: a forwarder, and not a thing to be trusted with the reader's memory or with where frames begin.

A LENGTH IS A PROMISE ABOUT BYTES THAT HAVE NOT ARRIVED. Without a cap, a length of 4 GiB is a reader that waits, holding everything that arrives meanwhile, and grows until the node dies. A control frame here carries at most a node name.

A FRAME THAT DOES NOT DECODE MEANS THE TWO ENDS NO LONGER AGREE WHERE FRAMES BEGIN. Skipping it and reading on takes the middle of something else for a length, so one bad frame becomes an endless run of them while the channel looks alive. The connection ends instead.

Summary

Functions

Extract zero or more complete frames from a buffer. {ok, Messages, Remaining} where Remaining is what is left of a frame that has not all arrived, or {error, Reason}, which ends the connection: a frame too large to be one of ours, or one whose bytes do not decode to a frame this protocol knows.

The largest control frame a reader accepts.

Types

control_msg/0

identified_msg/0

-type identified_msg() :: #{type := identified, status := ok}.

identify_msg/0

-type identify_msg() :: #{type := identify, node_name := binary()}.

tunnel_close_msg/0

-type tunnel_close_msg() :: #{type := tunnel_close, tunnel_id := binary()}.

tunnel_error_msg/0

-type tunnel_error_msg() :: #{type := tunnel_error, reason := binary()}.

tunnel_notify_msg/0

-type tunnel_notify_msg() :: #{type := tunnel_notify, tunnel_id := binary(), source := binary()}.

tunnel_ok_msg/0

-type tunnel_ok_msg() :: #{type := tunnel_ok, tunnel_id := binary()}.

tunnel_request_msg/0

-type tunnel_request_msg() :: #{type := tunnel_request, target := binary()}.

Functions

decode_buffer(Buffer)

-spec decode_buffer(binary()) -> {ok, [control_msg()], binary()} | {error, term()}.

Extract zero or more complete frames from a buffer. {ok, Messages, Remaining} where Remaining is what is left of a frame that has not all arrived, or {error, Reason}, which ends the connection: a frame too large to be one of ours, or one whose bytes do not decode to a frame this protocol knows.

encode(Msg)

-spec encode(control_msg()) -> binary().

max_frame_bytes()

-spec max_frame_bytes() -> pos_integer().

The largest control frame a reader accepts.