mirror of
https://github.com/amineo/t2_server_query_elixir.git
synced 2026-01-19 18:14:44 +00:00
* Init ExDoc
This commit is contained in:
parent
3b22db761b
commit
6ab3e06e78
41
README.md
41
README.md
|
|
@ -1,11 +1,14 @@
|
||||||
# T2ServerQuery
|
# T2ServerQuery
|
||||||
|
|
||||||
**TODO: Add description**
|
Querying a Tribes 2 server actually requires sending 2 different packets to the server where the first byte is denoting the type of information we're asking for. The first is called the `info` packet which doesnt contain much more then the server name. The second is called the `status` packet which contains all the meat and potatoes.
|
||||||
|
|
||||||
|
The `T2ServerQuery.query/3` function makes requests for both `info` and `status` and combines them into a single response for easy consumption.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
|
The package can be installed by adding `t2_server_query` to your list of dependencies in `mix.exs`:
|
||||||
by adding `t2_server_query` to your list of dependencies in `mix.exs`:
|
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
def deps do
|
def deps do
|
||||||
|
|
@ -15,7 +18,33 @@ def deps do
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
|
|
||||||
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
|
## Usage
|
||||||
be found at [https://hexdocs.pm/t2_server_query](https://hexdocs.pm/t2_server_query).
|
|
||||||
|
```elixir
|
||||||
|
# T2ServerQuery.query("35.239.88.241", port // 28_000, timeout // 3_500)
|
||||||
|
T2ServerQuery.query("35.239.88.241")
|
||||||
|
|
||||||
|
{:ok,
|
||||||
|
%T2ServerQuery.QueryResult{
|
||||||
|
bot_count: 0,
|
||||||
|
game_type: "Classic",
|
||||||
|
map_name: "Canker",
|
||||||
|
max_player_count: 64,
|
||||||
|
mission_type: "LakRabbit",
|
||||||
|
player_count: 0,
|
||||||
|
players: [%{}],
|
||||||
|
server_description: "Celebrating 20 Years of Tribes2! More information in Discord. <a:playt2.com/discord>playt2.com/discord</a>",
|
||||||
|
server_name: "Discord PUB",
|
||||||
|
server_status: :online,
|
||||||
|
team_count: 1,
|
||||||
|
teams: [%{name: "Storm", score: 0}]
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Docs
|
||||||
|
The docs can be found at [https://hexdocs.pm/t2_server_query](https://hexdocs.pm/t2_server_query).
|
||||||
|
|
||||||
|
Documentation has been generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
|
||||||
|
and published on [HexDocs](https://hexdocs.pm).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,119 @@
|
||||||
defmodule T2ServerQuery do
|
defmodule T2ServerQuery do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Documentation for `T2ServerQuery`.
|
|
||||||
|
Querying a Tribes 2 server actually requires sending 2 different packets to the server where the first byte is denoting the type of information we're asking for. The first is called the `info` packet which doesnt contain much more then the server name. The second is called the `status` packet which contains all the meat and potatoes.
|
||||||
|
|
||||||
|
The `T2ServerQuery.query/3` function makes requests for both `info` and `status` and combines them into a single response for easy consumption.
|
||||||
|
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
def deps do
|
||||||
|
[
|
||||||
|
{:t2_server_query, "~> 0.1.0"}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
# T2ServerQuery.query("35.239.88.241", port // 28_000, timeout // 3_500)
|
||||||
|
T2ServerQuery.query("35.239.88.241")
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
# Just a simple debug logging util
|
alias T2ServerQuery.PacketParser
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Perform a server query. **Results should be in the form of a tuple with either `:ok` or `:error`**
|
||||||
|
|
||||||
|
{:ok, %T2ServerQuery.QueryResult{...} }
|
||||||
|
|
||||||
|
{:error, %T2ServerQuery.QueryResult{...} }
|
||||||
|
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> T2ServerQuery.query("35.239.88.241")
|
||||||
|
{:ok,
|
||||||
|
%T2ServerQuery.QueryResult{
|
||||||
|
bot_count: 0,
|
||||||
|
game_type: "Classic",
|
||||||
|
map_name: "Canker",
|
||||||
|
max_player_count: 64,
|
||||||
|
mission_type: "LakRabbit",
|
||||||
|
player_count: 0,
|
||||||
|
players: [%{}],
|
||||||
|
server_description: "Celebrating 20 Years of Tribes2! More information in Discord. <a:playt2.com/discord>playt2.com/discord</a>",
|
||||||
|
server_name: "Discord PUB",
|
||||||
|
server_status: :online,
|
||||||
|
team_count: 1,
|
||||||
|
teams: [%{name: "Storm", score: 0}]
|
||||||
|
}}
|
||||||
|
|
||||||
|
iex> T2ServerQuery.query("127.0.0.1")
|
||||||
|
{:error,
|
||||||
|
%T2ServerQuery.QueryResult{
|
||||||
|
bot_count: 0,
|
||||||
|
game_type: "",
|
||||||
|
map_name: "",
|
||||||
|
max_player_count: 0,
|
||||||
|
mission_type: "",
|
||||||
|
player_count: 0,
|
||||||
|
players: [],
|
||||||
|
server_description: "Host unreachable, timed out.",
|
||||||
|
server_name: "127.0.0.1:28000",
|
||||||
|
server_status: :offline,
|
||||||
|
team_count: 0,
|
||||||
|
teams: []
|
||||||
|
}}
|
||||||
|
|
||||||
|
"""
|
||||||
|
def query(server_ip, port \\ 28_000, timeout \\ 3_500) do
|
||||||
|
Logger.info "query: #{server_ip}"
|
||||||
|
|
||||||
|
{:ok, socket} = :gen_udp.open(0, [:binary, {:active, false}])
|
||||||
|
|
||||||
|
# Convert a string ip from "127.0.0.1" into {127, 0, 0, 1}
|
||||||
|
{:ok, s_ip} = server_ip
|
||||||
|
|> to_charlist()
|
||||||
|
|> :inet.parse_address()
|
||||||
|
|
||||||
|
|
||||||
|
qry_info_packet = <<14, 2, 1, 2, 3, 4>>
|
||||||
|
qry_status_packet = <<18, 2, 1, 2, 3, 4>>
|
||||||
|
|
||||||
|
# Requst info packet
|
||||||
|
:gen_udp.send(socket, s_ip, port, qry_info_packet)
|
||||||
|
hex_info_packet = :gen_udp.recv(socket, 0, timeout)
|
||||||
|
|> handle_udp_response(server_ip, port)
|
||||||
|
|
||||||
|
# Request status packet
|
||||||
|
:gen_udp.send(socket, s_ip, port, qry_status_packet)
|
||||||
|
hex_status_packet = :gen_udp.recv(socket, 0, timeout)
|
||||||
|
|> handle_udp_response(server_ip, port)
|
||||||
|
|
||||||
|
# Combine and parse results
|
||||||
|
PacketParser.init(hex_info_packet, hex_status_packet)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
defp handle_udp_response({:ok, {_ip, _port, packet}}, _server_ip, _port) do
|
||||||
|
packet
|
||||||
|
|> Base.encode16
|
||||||
|
end
|
||||||
|
|
||||||
|
defp handle_udp_response({:error, :timeout}, server_ip, port) do
|
||||||
|
Logger.error "TIMEOUT --> #{server_ip}:#{port}"
|
||||||
|
{:error, "#{server_ip}:#{port}"}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@doc false
|
||||||
def log(thing_to_log) do
|
def log(thing_to_log) do
|
||||||
|
# Just a simple debug logging util
|
||||||
Logger.info(inspect thing_to_log)
|
Logger.info(inspect thing_to_log)
|
||||||
IO.puts "\n____________________________________________\n"
|
IO.puts "\n____________________________________________\n"
|
||||||
thing_to_log
|
thing_to_log
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,58 @@
|
||||||
defmodule T2ServerQuery.PacketParser do
|
defmodule T2ServerQuery.PacketParser do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Documentation for `T2ServerQuery.PacketParser`.
|
This module does the heavy lifting with parsing a Tribes 2 query response packet.
|
||||||
|
|
||||||
|
## UDP Packet Anatomy
|
||||||
|
|
||||||
|
### Info Packet
|
||||||
|
<<
|
||||||
|
_header :: size(192),
|
||||||
|
server_name :: bitstring
|
||||||
|
>>
|
||||||
|
|
||||||
|
### Status Packet
|
||||||
|
<<
|
||||||
|
_header :: size(48),
|
||||||
|
|
||||||
|
game_type_length :: little-integer,
|
||||||
|
game_type :: binary-size(game_type_length),
|
||||||
|
mission_type_length :: little-integer,
|
||||||
|
mission_type :: binary-size(mission_type_length),
|
||||||
|
map_name_length :: little-integer,
|
||||||
|
map_name :: binary-size(map_name_length),
|
||||||
|
|
||||||
|
_skip_a :: size(8),
|
||||||
|
|
||||||
|
player_count :: little-integer,
|
||||||
|
max_player_count :: little-integer,
|
||||||
|
bot_count :: little-integer,
|
||||||
|
|
||||||
|
_skip_b :: size(16),
|
||||||
|
|
||||||
|
server_description_length :: little-integer,
|
||||||
|
server_description :: binary-size(server_description_length),
|
||||||
|
|
||||||
|
_skip_c :: size(16),
|
||||||
|
|
||||||
|
team_count :: binary-size(1),
|
||||||
|
|
||||||
|
rest :: bitstring
|
||||||
|
>>
|
||||||
|
|
||||||
|
Notice the `_skip_(a|b|c)` mappings. I havn't quite figured out what they refer to yet but they don't seem that important. They likely relate to a few server flags like `tournament_mode`, `cpu_speed`, `is_linux`.
|
||||||
|
|
||||||
|
Refer to `T2ServerQuery.QueryResult` for what a typical struct would look like.
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
alias T2ServerQuery.QueryResult
|
alias T2ServerQuery.QueryResult
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
This function expects both an `info` and `status` packet to be passed in that is in a `Base.encode16` format.
|
||||||
|
Normally you wouldn't need to run this function manually since it's called in a pipeline from the main `T2ServerQuery.query`
|
||||||
|
|
||||||
|
"""
|
||||||
def init({:error, host}, _) do
|
def init({:error, host}, _) do
|
||||||
results = %QueryResult{}
|
results = %QueryResult{}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,51 +1,51 @@
|
||||||
defmodule T2ServerQuery.QueryResult do
|
defmodule T2ServerQuery.QueryResult do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Shape of the server query result struct.
|
## Struct Shape
|
||||||
|
|
||||||
%T2ServerQuery.QueryResult{
|
%T2ServerQuery.QueryResult{
|
||||||
server_status: :online,
|
server_status: :online,
|
||||||
bot_count: 30,
|
bot_count: 30,
|
||||||
game_type: "Classic",
|
game_type: "Classic",
|
||||||
map_name: "Cold as Ice [b]",
|
map_name: "Cold as Ice [b]",
|
||||||
max_player_count: 64,
|
max_player_count: 64,
|
||||||
mission_type: "Capture the Flag",
|
mission_type: "Capture the Flag",
|
||||||
player_count: 29,
|
player_count: 29,
|
||||||
players: [
|
players: [
|
||||||
%{player: "Rooster128", score: "0", team: "Storm"},
|
%{player: "Rooster128", score: "0", team: "Storm"},
|
||||||
%{player: "sneakygnome", score: "0", team: "Inferno"},
|
%{player: "sneakygnome", score: "0", team: "Inferno"},
|
||||||
%{player: "Waldred ", score: "0", team: "Inferno"},
|
%{player: "Waldred ", score: "0", team: "Inferno"},
|
||||||
%{player: "HDPTetchy ", score: "0", team: "Storm"},
|
%{player: "HDPTetchy ", score: "0", team: "Storm"},
|
||||||
%{player: "0wnj0o", score: "0", team: "Inferno"},
|
%{player: "0wnj0o", score: "0", team: "Inferno"},
|
||||||
%{player: "idjit ", score: "0", team: "Storm"},
|
%{player: "idjit ", score: "0", team: "Storm"},
|
||||||
%{player: "JesusChrist ", score: "0", team: "Storm"},
|
%{player: "JesusChrist ", score: "0", team: "Storm"},
|
||||||
%{player: "Sofaking--bakeD ", score: "0", team: "Inferno"},
|
%{player: "Sofaking--bakeD ", score: "0", team: "Inferno"},
|
||||||
%{player: "saKe ", score: "0", team: "Inferno"},
|
%{player: "saKe ", score: "0", team: "Inferno"},
|
||||||
%{player: "ZurkinWood497", score: "0", team: "Storm"},
|
%{player: "ZurkinWood497", score: "0", team: "Storm"},
|
||||||
%{player: "TerryTC ", score: "0", team: "Inferno"},
|
%{player: "TerryTC ", score: "0", team: "Inferno"},
|
||||||
%{player: "WankBullet ", score: "0", team: "Storm"},
|
%{player: "WankBullet ", score: "0", team: "Storm"},
|
||||||
%{player: "CyClones", score: "0", team: "Inferno"},
|
%{player: "CyClones", score: "0", team: "Inferno"},
|
||||||
%{player: "huntergirl10", score: "0", team: "Storm"},
|
%{player: "huntergirl10", score: "0", team: "Storm"},
|
||||||
%{player: "ChocoTaco", score: "0", team: "Inferno"},
|
%{player: "ChocoTaco", score: "0", team: "Inferno"},
|
||||||
%{player: "Dirk", score: "0", team: "Storm"},
|
%{player: "Dirk", score: "0", team: "Storm"},
|
||||||
%{player: "Krell", score: "0", team: "Storm"},
|
%{player: "Krell", score: "0", team: "Storm"},
|
||||||
%{player: "high5slayer", score: "0", team: "Inferno"},
|
%{player: "high5slayer", score: "0", team: "Inferno"},
|
||||||
%{player: "Red Fraction ", score: "0", team: "Inferno"},
|
%{player: "Red Fraction ", score: "0", team: "Inferno"},
|
||||||
%{player: "-MaLice--", score: "0", team: "Storm"},
|
%{player: "-MaLice--", score: "0", team: "Storm"},
|
||||||
%{player: "wiltedflower ", score: "0", team: "Inferno"},
|
%{player: "wiltedflower ", score: "0", team: "Inferno"},
|
||||||
%{player: "Glarm ", score: "0", team: "Storm"},
|
%{player: "Glarm ", score: "0", team: "Storm"},
|
||||||
%{player: "AlphaSentinel", score: "0", team: "Inferno"},
|
%{player: "AlphaSentinel", score: "0", team: "Inferno"},
|
||||||
%{player: "The-Punisher ", score: "0", team: "Storm"},
|
%{player: "The-Punisher ", score: "0", team: "Storm"},
|
||||||
%{player: "2SmOkeD", score: "0", team: "Inferno"},
|
%{player: "2SmOkeD", score: "0", team: "Inferno"},
|
||||||
%{player: "iPrecision", score: "0", team: "Storm"},
|
%{player: "iPrecision", score: "0", team: "Storm"},
|
||||||
%{player: "Halo 2 ", score: "0", team: "Storm"},
|
%{player: "Halo 2 ", score: "0", team: "Storm"},
|
||||||
%{player: "Sami-FIN ", score: "0", team: "Inferno"},
|
%{player: "Sami-FIN ", score: "0", team: "Inferno"},
|
||||||
%{player: "rileygarbels", score: "0", team: "Storm"}
|
%{player: "rileygarbels", score: "0", team: "Storm"}
|
||||||
],
|
],
|
||||||
server_description: "This server is using bots that are adapted to playing Classic. http://tribes2bots.byethost4.com/forum/index.php?topic=57.msg234",
|
server_description: "This server is using bots that are adapted to playing Classic. http://tribes2bots.byethost4.com/forum/index.php?topic=57.msg234",
|
||||||
server_name: "Classic Bots Server",
|
server_name: "Classic Bots Server",
|
||||||
team_count: 2,
|
team_count: 2,
|
||||||
teams: [%{name: "Storm", score: "0"}, %{name: "Inferno", score: "0"}]
|
teams: [%{name: "Storm", score: "0"}, %{name: "Inferno", score: "0"}]
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
defstruct [
|
defstruct [
|
||||||
|
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
||||||
defmodule T2ServerQuery.UdpServer do
|
|
||||||
@moduledoc """
|
|
||||||
Documentation for `UdpServer`.
|
|
||||||
"""
|
|
||||||
require Logger
|
|
||||||
|
|
||||||
alias T2ServerQuery.PacketParser
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Perform a server query.
|
|
||||||
Results should be in the form of a tuple
|
|
||||||
- {:ok, %T2ServerQuery.QueryResult{}}
|
|
||||||
- {:error, %T2ServerQuery.QueryResult{}}
|
|
||||||
|
|
||||||
Querying a Tribes 2 server actually requires sending 2 different packets to the server where the first byte is denoting what we're asking for in response. The first is called the 'info' packet which doesnt contain much more then the server name. The second is called the 'status' packet which contains all the meat and potatoes.
|
|
||||||
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
iex> T2ServerQuery.UdpServer.query("35.239.88.241")
|
|
||||||
{:ok,
|
|
||||||
%T2ServerQuery.QueryResult{
|
|
||||||
bot_count: 0,
|
|
||||||
game_type: "Classic",
|
|
||||||
map_name: "Canker",
|
|
||||||
max_player_count: 64,
|
|
||||||
mission_type: "LakRabbit",
|
|
||||||
player_count: 0,
|
|
||||||
players: [%{}],
|
|
||||||
server_description: "Celebrating 20 Years of Tribes2! More information in Discord. <a:playt2.com/discord>playt2.com/discord</a>",
|
|
||||||
server_name: "Discord PUB",
|
|
||||||
server_status: :online,
|
|
||||||
team_count: 1,
|
|
||||||
teams: [%{name: "Storm", score: 0}]
|
|
||||||
}}
|
|
||||||
|
|
||||||
iex> T2ServerQuery.UdpServer.query("127.0.0.1")
|
|
||||||
{:error,
|
|
||||||
%T2ServerQuery.QueryResult{
|
|
||||||
bot_count: 0,
|
|
||||||
game_type: "",
|
|
||||||
map_name: "",
|
|
||||||
max_player_count: 0,
|
|
||||||
mission_type: "",
|
|
||||||
player_count: 0,
|
|
||||||
players: [],
|
|
||||||
server_description: "Host unreachable, timed out.",
|
|
||||||
server_name: "127.0.0.1:28000",
|
|
||||||
server_status: :offline,
|
|
||||||
team_count: 0,
|
|
||||||
teams: []
|
|
||||||
}}
|
|
||||||
|
|
||||||
"""
|
|
||||||
def query(server_ip, port \\ 28_000, timeout \\ 3_500) do
|
|
||||||
Logger.info "query: #{server_ip}"
|
|
||||||
|
|
||||||
{:ok, socket} = :gen_udp.open(0, [:binary, {:active, false}])
|
|
||||||
|
|
||||||
# Convert a string ip from "127.0.0.1" into {127, 0, 0, 1}
|
|
||||||
{:ok, s_ip} = server_ip
|
|
||||||
|> to_charlist()
|
|
||||||
|> :inet.parse_address()
|
|
||||||
|
|
||||||
|
|
||||||
qry_info_packet = <<14, 2, 1, 2, 3, 4>>
|
|
||||||
qry_status_packet = <<18, 2, 1, 2, 3, 4>>
|
|
||||||
|
|
||||||
# Requst info packet
|
|
||||||
:gen_udp.send(socket, s_ip, port, qry_info_packet)
|
|
||||||
hex_info_packet = :gen_udp.recv(socket, 0, timeout)
|
|
||||||
|> handle_udp_response(server_ip, port)
|
|
||||||
|
|
||||||
# Request status packet
|
|
||||||
:gen_udp.send(socket, s_ip, port, qry_status_packet)
|
|
||||||
hex_status_packet = :gen_udp.recv(socket, 0, timeout)
|
|
||||||
|> handle_udp_response(server_ip, port)
|
|
||||||
|
|
||||||
# Combine and parse results
|
|
||||||
PacketParser.init(hex_info_packet, hex_status_packet)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
defp handle_udp_response({:ok, {_ip, _port, packet}}, _server_ip, _port) do
|
|
||||||
packet
|
|
||||||
|> Base.encode16
|
|
||||||
end
|
|
||||||
|
|
||||||
defp handle_udp_response({:error, :timeout}, server_ip, port) do
|
|
||||||
Logger.error "TIMEOUT --> #{server_ip}:#{port}"
|
|
||||||
{:error, "#{server_ip}:#{port}"}
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
15
mix.exs
15
mix.exs
|
|
@ -7,7 +7,17 @@ defmodule T2ServerQuery.MixProject do
|
||||||
version: "0.1.0",
|
version: "0.1.0",
|
||||||
elixir: "~> 1.12",
|
elixir: "~> 1.12",
|
||||||
start_permanent: Mix.env() == :prod,
|
start_permanent: Mix.env() == :prod,
|
||||||
deps: deps()
|
deps: deps(),
|
||||||
|
|
||||||
|
# Docs
|
||||||
|
name: "T2ServerQuery",
|
||||||
|
description: "Query any Tribes 2 server and retrieve the current map, players, team scores and more!",
|
||||||
|
source_url: "https://github.com/amineo/t2_server_query_elixir",
|
||||||
|
homepage_url: "https://github.com/amineo/t2_server_query_elixir",
|
||||||
|
docs: [
|
||||||
|
main: "T2ServerQuery",
|
||||||
|
extras: ["README.md"]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -21,7 +31,8 @@ defmodule T2ServerQuery.MixProject do
|
||||||
# Run "mix help deps" to learn about dependencies.
|
# Run "mix help deps" to learn about dependencies.
|
||||||
defp deps do
|
defp deps do
|
||||||
[
|
[
|
||||||
{:credo, "~> 1.5"}
|
{:credo, "~> 1.5"},
|
||||||
|
{:ex_doc, "~> 0.24", only: :dev, runtime: false}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
6
mix.lock
6
mix.lock
|
|
@ -1,6 +1,12 @@
|
||||||
%{
|
%{
|
||||||
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
|
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
|
||||||
"credo": {:hex, :credo, "1.5.6", "e04cc0fdc236fefbb578e0c04bd01a471081616e741d386909e527ac146016c6", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "4b52a3e558bd64e30de62a648518a5ea2b6e3e5d2b164ef5296244753fc7eb17"},
|
"credo": {:hex, :credo, "1.5.6", "e04cc0fdc236fefbb578e0c04bd01a471081616e741d386909e527ac146016c6", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "4b52a3e558bd64e30de62a648518a5ea2b6e3e5d2b164ef5296244753fc7eb17"},
|
||||||
|
"earmark_parser": {:hex, :earmark_parser, "1.4.16", "607709303e1d4e3e02f1444df0c821529af1c03b8578dfc81bb9cf64553d02b9", [:mix], [], "hexpm", "69fcf696168f5a274dd012e3e305027010658b2d1630cef68421d6baaeaccead"},
|
||||||
|
"ex_doc": {:hex, :ex_doc, "0.25.3", "3edf6a0d70a39d2eafde030b8895501b1c93692effcbd21347296c18e47618ce", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "9ebebc2169ec732a38e9e779fd0418c9189b3ca93f4a676c961be6c1527913f5"},
|
||||||
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
||||||
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
|
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
|
||||||
|
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
|
||||||
|
"makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"},
|
||||||
|
"makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"},
|
||||||
|
"nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
defmodule T2ServerQueryTest do
|
defmodule T2ServerQueryTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
alias T2ServerQuery.UdpServer
|
|
||||||
|
|
||||||
doctest T2ServerQuery
|
# doctest T2ServerQuery
|
||||||
|
|
||||||
|
|
||||||
test "Gracefully handle timeouts and unreachable servers" do
|
test "Gracefully handle timeouts and unreachable servers" do
|
||||||
|
|
@ -10,7 +9,7 @@ defmodule T2ServerQueryTest do
|
||||||
timeout = 250
|
timeout = 250
|
||||||
|
|
||||||
port = Enum.random(28_000..28_999)
|
port = Enum.random(28_000..28_999)
|
||||||
{:error, result} = T2ServerQuery.UdpServer.query("127.0.0.1", port, timeout)
|
{:error, result} = T2ServerQuery.query("127.0.0.1", port, timeout)
|
||||||
|> T2ServerQuery.log
|
|> T2ServerQuery.log
|
||||||
|
|
||||||
assert result.server_status == :offline
|
assert result.server_status == :offline
|
||||||
|
|
@ -21,9 +20,9 @@ defmodule T2ServerQueryTest do
|
||||||
|
|
||||||
test "Live test a number of Tribes 2 servers" do
|
test "Live test a number of Tribes 2 servers" do
|
||||||
tasks = [
|
tasks = [
|
||||||
Task.async(T2ServerQuery.UdpServer, :query, ["35.239.88.241"]),
|
Task.async(T2ServerQuery, :query, ["35.239.88.241"]),
|
||||||
Task.async(T2ServerQuery.UdpServer, :query, ["97.99.172.12", 28_001]),
|
Task.async(T2ServerQuery, :query, ["97.99.172.12", 28_001]),
|
||||||
Task.async(T2ServerQuery.UdpServer, :query, ["67.222.138.13"])
|
Task.async(T2ServerQuery, :query, ["67.222.138.13"])
|
||||||
]
|
]
|
||||||
|
|
||||||
server_list = Task.yield_many(tasks)
|
server_list = Task.yield_many(tasks)
|
||||||
|
|
@ -50,28 +49,28 @@ end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#qry_test = T2ServerQuery.UdpServer.query("127.0.0.1")
|
#qry_test = T2ServerQuery.query("127.0.0.1")
|
||||||
#IO.inspect qry_test
|
#IO.inspect qry_test
|
||||||
|
|
||||||
#qry_test2 = T2ServerQuery.UdpServer.query("35.239.88.241")
|
#qry_test2 = T2ServerQuery.query("35.239.88.241")
|
||||||
#IO.inspect qry_test2
|
#IO.inspect qry_test2
|
||||||
|
|
||||||
|
|
||||||
# tasks = [
|
# tasks = [
|
||||||
# Task.async(T2ServerQuery.UdpServer, :query, ["127.0.0.1"]),
|
# Task.async(T2ServerQuery, :query, ["127.0.0.1"]),
|
||||||
# Task.async(T2ServerQuery.UdpServer, :query, ["35.239.88.241"]),
|
# Task.async(T2ServerQuery, :query, ["35.239.88.241"]),
|
||||||
# Task.async(T2ServerQuery.UdpServer, :query, ["97.99.172.12", 28001]),
|
# Task.async(T2ServerQuery, :query, ["97.99.172.12", 28001]),
|
||||||
# Task.async(T2ServerQuery.UdpServer, :query, ["67.222.138.13"]),
|
# Task.async(T2ServerQuery, :query, ["67.222.138.13"]),
|
||||||
# Task.async(T2ServerQuery.UdpServer, :query, ["91.55.51.94"]),
|
# Task.async(T2ServerQuery, :query, ["91.55.51.94"]),
|
||||||
# ]
|
# ]
|
||||||
|
|
||||||
# IO.inspect Task.yield_many(tasks)
|
# IO.inspect Task.yield_many(tasks)
|
||||||
|
|
||||||
# task0 = Task.async(T2ServerQuery.UdpServer, :query, ["127.0.0.1"])
|
# task0 = Task.async(T2ServerQuery, :query, ["127.0.0.1"])
|
||||||
# task1 = Task.async(T2ServerQuery.UdpServer, :query, ["35.239.88.241"])
|
# task1 = Task.async(T2ServerQuery, :query, ["35.239.88.241"])
|
||||||
# task2 = Task.async(T2ServerQuery.UdpServer, :query, ["97.99.172.12", 28001])
|
# task2 = Task.async(T2ServerQuery, :query, ["97.99.172.12", 28001])
|
||||||
# task3 = Task.async(T2ServerQuery.UdpServer, :query, ["67.222.138.13"])
|
# task3 = Task.async(T2ServerQuery, :query, ["67.222.138.13"])
|
||||||
# task4 = Task.async(T2ServerQuery.UdpServer, :query, ["91.55.51.94"])
|
# task4 = Task.async(T2ServerQuery, :query, ["91.55.51.94"])
|
||||||
# # res4 = Task.await(task4)
|
# # res4 = Task.await(task4)
|
||||||
# # IO.inspect res4.server_name
|
# # IO.inspect res4.server_name
|
||||||
|
|
||||||
|
|
@ -87,7 +86,7 @@ end
|
||||||
# IO.inspect res3.server_name
|
# IO.inspect res3.server_name
|
||||||
# IO.inspect res4.server_name
|
# IO.inspect res4.server_name
|
||||||
|
|
||||||
# T2ServerQuery.UdpServer.query("35.239.88.241")
|
# T2ServerQuery.query("35.239.88.241")
|
||||||
# T2ServerQuery.UdpServer.query("97.99.172.12", 28001)
|
# T2ServerQuery.query("97.99.172.12", 28001)
|
||||||
# T2ServerQuery.UdpServer.query("67.222.138.13")
|
# T2ServerQuery.query("67.222.138.13")
|
||||||
# T2ServerQuery.UdpServer.query("91.55.51.94")
|
# T2ServerQuery.query("91.55.51.94")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue