defmodule A2S.UDP do
@moduledoc """
GenServer wrapping a UDP socket that sends packets and routes recevied ones to the proper A2S_statem.
"""
use GenServer
## API
def start_link(args) do
GenServer.start_link(__MODULE__, args, [])
end
## Callbacks
@impl true
def init([port: port]) do
Process.register(self(), __MODULE__) # singleton
case :gen_udp.open(port, [:binary, active: true]) do
{:error, reason} -> {:stop, reason}
{:ok, socket} -> {:ok, socket}
end
end
@doc """
Forward received packets to the appropriate `A2S.Statem`.
"""
@impl true
def handle_info({:udp, _socket, ip, port, packet}, socket) do
GenServer.cast(via_registry({ip, port}), packet)
{:noreply, socket}
end
@doc """
Send the given packet to the game server.
"""
@impl true
def handle_call({address, packet}, _from, socket) do
with :ok <- :gen_udp.send(socket, address, packet) do
{:reply, :ok, socket}
else
err -> {:reply, err, socket}
end
end
## Functions
defp via_registry(name), do: {:via, Registry, {:a2s_registry, name}}
end