Map an incoming Tahr.RPC.Message.Call to the registered
handler for its {program, version} pair, then wrap the result in
the appropriate Tahr.RPC.Message.AcceptedReply /
DeniedReply.
The dispatcher is stateless — handlers are passed in via the
programs map. The TCP server holds the registry; this module
is pure-function so it's trivial to unit-test.
RPC error mapping
- RPC version != 2 →
RPC_MISMATCH(denied) - Unknown program →
PROG_UNAVAIL - Wrong version of a known program →
PROG_MISMATCH - Handler returns
:proc_unavail→PROC_UNAVAIL - Handler returns
:garbage_args→GARBAGE_ARGS - Handler returns
:system_error raises →SYSTEM_ERR - Handler returns
{:ok, body}→SUCCESSwithbody
Summary
Types
Registry of installed handlers
Functions
Dispatch a single call. Returns a Message.reply() ready to be
encoded with Message.encode_reply/1.
Types
@type programs() :: %{ required(non_neg_integer()) => %{required(non_neg_integer()) => module()} }
Registry of installed handlers:
%{
100000 => %{2 => SomeModule}, # portmapper
100003 => %{3 => Nfs3Handler} # NFSv3
}
Functions
@spec dispatch(Tahr.RPC.Message.Call.t(), programs(), map()) :: Tahr.RPC.Message.reply()
Dispatch a single call. Returns a Message.reply() ready to be
encoded with Message.encode_reply/1.
extras is merged into the handler ctx map — the TCP server uses
it to surface the connection's client address as ctx.peer so
handlers can apply per-export host filtering.