Packages

ENet - Reliable UDP networking library

Current section

Files

Jump to
enet src enet.erl
Raw

src/enet.erl

-module(enet).
-export([
start_host/3,
stop_host/1,
connect_peer/4,
await_connect/0,
disconnect_peer/1,
disconnect_peer_now/1,
send_unsequenced/2,
send_unreliable/2,
send_reliable/2,
broadcast_unsequenced/3,
broadcast_unreliable/3,
broadcast_reliable/3
]).
-type port_number() :: 0..65535.
-type mfargs() :: {module(),atom(),[term()]}.
%%%===================================================================
%%% API
%%%===================================================================
-spec start_host(
Port :: port_number(),
ConnectFun ::
mfargs()
| fun((map()) -> {ok, pid()} | {error, term()}),
Options :: [{atom(), term()}, ...]
) ->
{ok, port_number()} | {error, term()}.
start_host(Port, ConnectFun, Options) ->
{ok, Socket} = gen_udp:open(Port, enet_host:socket_options()),
{ok, AssignedPort} = inet:port(Socket),
case enet_sup:start_host_supervisor(AssignedPort, ConnectFun, Options) of
{error, Reason} ->
{error, Reason};
{ok, _HostSup} ->
Host = gproc:where({n, l, {enet_host, AssignedPort}}),
enet_host:give_socket(Host, Socket),
{ok, AssignedPort}
end.
-spec stop_host(HostPort :: port_number()) -> ok.
stop_host(HostPort) ->
enet_sup:stop_host_supervisor(HostPort).
-spec connect_peer(
HostPort :: port_number(),
IP :: string(),
RemotePort :: port_number(),
ChannelCount :: pos_integer()
) ->
{ok, pid()} | {error, atom()}.
connect_peer(HostPort, IP, RemotePort, ChannelCount) ->
Host = gproc:where({n, l, {enet_host, HostPort}}),
enet_host:connect(Host, IP, RemotePort, ChannelCount).
await_connect() ->
receive
C = {enet, connect, _LocalOrRemote, _PC, _ConnectID} -> {ok, C}
after 1000 -> {error, timeout}
end.
-spec disconnect_peer(Peer :: pid()) -> ok.
disconnect_peer(Peer) ->
enet_peer:disconnect(Peer).
-spec disconnect_peer_now(Peer :: pid()) -> ok.
disconnect_peer_now(Peer) ->
enet_peer:disconnect_now(Peer).
-spec send_unsequenced(Channel :: pid(), Data :: iodata()) -> ok.
send_unsequenced(Channel, Data) ->
enet_channel_srv:send_unsequenced(Channel, Data).
-spec send_unreliable(Channel :: pid(), Data :: iodata()) -> ok.
send_unreliable(Channel, Data) ->
enet_channel_srv:send_unreliable(Channel, Data).
-spec send_reliable(Channel :: pid(), Data :: iodata()) -> ok.
send_reliable(Channel, Data) ->
enet_channel_srv:send_reliable(Channel, Data).
-spec broadcast_unsequenced(
HostPort :: port_number(),
ChannelID :: integer(),
Data :: iodata()
) -> ok.
broadcast_unsequenced(HostPort, ChannelID, Data) ->
broadcast(HostPort, ChannelID, Data, fun send_unsequenced/2).
-spec broadcast_unreliable(
HostPort :: port_number(),
ChannelID :: integer(),
Data :: iodata()
) -> ok.
broadcast_unreliable(HostPort, ChannelID, Data) ->
broadcast(HostPort, ChannelID, Data, fun send_unreliable/2).
-spec broadcast_reliable(
HostPort :: port_number(),
ChannelID :: integer(),
Data :: iodata()
) -> ok.
broadcast_reliable(HostPort, ChannelID, Data) ->
broadcast(HostPort, ChannelID, Data, fun send_reliable/2).
%%%===================================================================
%%% Internal functions
%%%===================================================================
broadcast(HostPort, ChannelID, Data, SendFun) ->
Peers = enet_pool:active_peers(HostPort),
lists:foreach(
fun({_Name, Peer}) ->
Channel = enet_peer:channel(Peer, ChannelID),
SendFun(Channel, Data)
end,
Peers
).