An Erlang/OTP library implementing Sun RPC (ONC RPC) protocol as defined in RFC 1057 and RFC 1831.
nfs_rpc_server provides a complete implementation of the Sun RPC protocol for Erlang applications, including:
- RPC Server: TCP-based RPC server using Ranch for connection management
- RPC Client: Full-featured client with timeout handling, retry logic, and statistics
- XDR Encoding/Decoding: Auto-generated XDR codec from
.xspecification files - Port Mapper Integration: Client interface for rpcbind/portmap daemon (port 111)
This library is designed to be used as a foundation for building NFS servers and other RPC-based services in Erlang.
- Erlang/OTP 24 or later (tested up to OTP 28)
- rebar3
# Get dependencies and compile
rebar3 compile
# Generate XDR code from .x files and build
make all
# Run tests
rebar3 eunit
# Run cross-reference analysis
rebar3 xref
# Run dialyzer
rebar3 dialyzer| Module | Description |
|---|---|
nfs_rpc_app |
Application module, manages RPC server lifecycle |
nfs_rpc_server_sup |
Supervisor for the RPC server |
nfs_rpc_proto |
Ranch protocol handler for incoming RPC requests |
nfs_rpc_client |
gen_server-based RPC client implementation |
nfs_rpc_xdr |
XDR encoder/decoder for RPC messages (generated) |
pmap |
Port mapper client interface |
pmap_xdr |
XDR encoder/decoder for port mapper (generated) |
src/nfs_rpc.x- RPC message format (RFC 1831)src/pmap.x- Port mapper protocol (RFC 1057)
%% Configure the server in sys.config or programmatically
application:set_env(nfs_rpc_server, args, [
{nfs_rpc_app_arg,
my_server_ref, % Unique reference
128, % Number of acceptors
[{port, 2049}], % Transport options
100003, % RPC program number (NFS)
nfs, % Program name for callbacks
[], % Version list (auto-generated)
3, % Lowest version
3, % Highest version
true, % Register with portmapper
my_nfs_impl, % Callback module
[], % Init arguments
[] % Initial state
}
]),
%% Start the application
application:ensure_all_started(nfs_rpc_server).Your callback module should implement functions named {program_name}_{version}:
-module(my_nfs_impl).
-export([init/1, nfs_3/5]).
init(Args) ->
{ok, #state{}}.
%% Called for each RPC procedure call
%% nfs_3(Proc, Msg, Offset, Client, State) -> {success, Reply, NewState}
%% | {noreply, NewState}
%% | {garbage_args, NewState}
%% | {error, NewState}
nfs_3(Proc, Msg, Offset, Client, State) ->
%% Decode arguments from Msg at Offset
%% Process the request
%% Return XDR-encoded reply
{success, <<Reply/binary>>, State}.%% Connect to an RPC server (using portmapper)
{ok, Clnt} = nfs_rpc_client:open("server.example.com", 100003, 3, tcp),
%% Or connect directly to a known port
{ok, Clnt} = nfs_rpc_client:open("server.example.com", 100003, 3, tcp, 2049),
%% Make an RPC call
Params = encode_my_params(...),
case nfs_rpc_client:call(Clnt, ProcNum, Params) of
{ok, Reply} ->
decode_my_reply(Reply);
{error, Reason} ->
handle_error(Reason)
end,
%% Close the client
nfs_rpc_client:close(Clnt).%% Set authentication
nfs_rpc_client:set_auth(Clnt, auth_null),
nfs_rpc_client:set_auth(Clnt, {auth_sys, Stamp, Hostname, Uid, Gid, Gids}),
%% Configure timeouts (in seconds)
nfs_rpc_client:set_timeout(Clnt, 30),
nfs_rpc_client:set_retry_timeout(Clnt, 5),
%% Configure queue limits
nfs_rpc_client:set_queue_limit(Clnt, 200),
%% Get statistics
{ok, Stats} = nfs_rpc_client:get_stats(Clnt).%% Connect to local portmapper
{ok, PClnt} = pmap:open({127, 0, 0, 1}),
%% Look up a service port
{ok, Port} = pmap:getport(PClnt, Program, Version, tcp),
%% Register a service
{ok, true} = pmap:set(PClnt, Program, Version, tcp, Port),
%% Unregister a service
{ok, true} = pmap:unset(PClnt, Program, Version, tcp, Port),
%% List all registered services
{ok, Mappings} = pmap:dump(PClnt),
pmap:close(PClnt).- RPC Version: 2 (RFC 1831)
- Transport: TCP (primary), UDP (client only)
- Authentication: AUTH_NONE, AUTH_SYS
- Port Mapper: Version 2 (RFC 1057)
Apache License, Version 2.0
- Copyright (c) 2012-2018 Rakuten, Inc.
- Copyright (c) 2019-2025 Lions Data, Ltd.