-module(barnacle@dns). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([dns_lookup/2, discover_nodes/3]). -export_type([lookup_error/0, ip_address/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type lookup_error() :: format_error | query_format_error | server_failure | no_such_domain | timeout | not_implemented | refused | bad_version | {posix_error, binary()} | unknown. -type ip_address() :: {ip_v4, integer(), integer(), integer(), integer()} | {ip_v6, integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer()}. -file("src/barnacle/dns.gleam", 40). ?DOC( " Perform a DNS lookup against a hostname. This will return a list of IP\n" " addresses. Queries will be performed using the `A` and `AAAA` record types.\n" ). -spec dns_lookup(binary(), integer()) -> {ok, list(ip_address())} | {error, lookup_error()}. dns_lookup(Hostname, Timeout) -> gleam@result:'try'( barnacle_ffi:lookup_a(Hostname, Timeout), fun(A_records) -> A_records@1 = begin _pipe = A_records, gleam@list:map( _pipe, fun(Ip) -> {A, B, C, D} = Ip, {ip_v4, A, B, C, D} end ) end, gleam@result:'try'( barnacle_ffi:lookup_aaaa(Hostname, Timeout), fun(Aaaa_records) -> Aaaa_records@1 = begin _pipe@1 = Aaaa_records, gleam@list:map( _pipe@1, fun(Ip@1) -> {A@1, B@1, C@1, D@1, E, F, G, H} = Ip@1, {ip_v6, A@1, B@1, C@1, D@1, E, F, G, H} end ) end, {ok, lists:append(A_records@1, Aaaa_records@1)} end ) end ). -file("src/barnacle/dns.gleam", 65). -spec format_ip_address(ip_address()) -> binary(). format_ip_address(Ip) -> case Ip of {ip_v4, A, B, C, D} -> _pipe = [A, B, C, D], _pipe@1 = gleam@list:map(_pipe, fun erlang:integer_to_binary/1), gleam@string:join(_pipe@1, <<"."/utf8>>); {ip_v6, A@1, B@1, C@1, D@1, E, F, G, H} -> _pipe@2 = [A@1, B@1, C@1, D@1, E, F, G, H], _pipe@3 = gleam@list:map(_pipe@2, fun(Value) -> case Value of 0 -> <<""/utf8>>; _ -> gleam@int:to_base16(Value) end end), _pipe@4 = gleam@string:join(_pipe@3, <<":"/utf8>>), string:lowercase(_pipe@4) end. -file("src/barnacle/dns.gleam", 92). ?DOC( " Discover nodes using DNS. The first argument is the basename of the nodes.\n" " Currently, Barnacle only supports connecting to nodes with the same basename.\n" "\n" " The second argument is the hostname to query against. Both A and AAAA records\n" " will be queried. The final argument is an optional timeout for the DNS\n" " lookup. This defaults to 5000ms if not supplied.\n" ). -spec discover_nodes(binary(), binary(), integer()) -> {ok, list(gleam@erlang@atom:atom_())} | {error, lookup_error()}. discover_nodes(Basename, Hostname_query, Timeout) -> gleam@result:'try'( dns_lookup(Hostname_query, Timeout), fun(Ip_addresses) -> _pipe = Ip_addresses, _pipe@2 = gleam@list:map( _pipe, fun(Ip) -> Ip_string = format_ip_address(Ip), _pipe@1 = (<<<>/binary, Ip_string/binary>>), erlang:binary_to_atom(_pipe@1) end ), {ok, _pipe@2} end ).