Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Passive Mode Example

notebooks/passive_example.livemd

Passive Mode Example

Setup

This LiveBook demonstrates the minimal viable code to query a game server using :gen_udp in passive mode and the A2S module.

Mix.install(
  [
    {:elixir_a2s, path: Path.join(__DIR__, "../"), env: :dev}
  ],
  lockfile: :elixir_a2s
)

parse_ip = fn addr when is_list(addr) ->
  [rest, port] = :string.split(addr, ~c":")
  {:ok, ip} = :inet.parse_ipv4_address(rest)
  {port, []} = :string.to_integer(port)
  {ip, port}
end

Parameters

# target server
game_server = ~c"216.52.148.47:27015"
game_server = ~c"127.0.0.1:27015"
# timeout
timeout = 3000
# udp port (probably dont need to change this)
source_port = 20850

address = parse_ip.(game_server)

Query the server

try/rescue‘s used to ensure the :gen_udp socket is closed even if an exception occurs.

{:ok, socket} = :gen_udp.open(source_port, [:binary, {:active, false}])

try do
  :ok = :gen_udp.send(socket, address, A2S.challenge_request(:info))

  {:ok, {_addr, _port, challenge}} = :gen_udp.recv(socket, 0, timeout)

  case A2S.parse_challenge(challenge) do
    {:immediate, {:info, info}} ->
      IO.inspect(info, label: "info", limit: :infinity)

    {:challenge, challenge} ->
      :ok = :gen_udp.send(socket, address, A2S.sign_challenge(:info, challenge))
      {:ok, {_addr, _port, data}} = :gen_udp.recv(socket, 0, timeout)
      {:info, info} = A2S.parse_response(data)
      IO.inspect(info, label: "info", limit: :infinity)
  end
rescue
  e -> IO.puts(Exception.format(:error, e, __STACKTRACE__))
end

:gen_udp.close(socket)