From 63e3961e1c2692d974f15ac51f32f0aeed187617 Mon Sep 17 00:00:00 2001 From: Paul Guyot Date: Sat, 14 Dec 2024 15:10:09 +0100 Subject: [PATCH] Add `inet:getaddr/2` Signed-off-by: Paul Guyot --- CHANGELOG.md | 1 + libs/estdlib/src/inet.erl | 33 +++++++++++++++++++++++++-- tests/libs/estdlib/CMakeLists.txt | 1 + tests/libs/estdlib/test_inet.erl | 38 +++++++++++++++++++++++++++++++ tests/libs/estdlib/tests.erl | 1 + 5 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 tests/libs/estdlib/test_inet.erl diff --git a/CHANGELOG.md b/CHANGELOG.md index a55020586..ec553b896 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added a limited implementation of the OTP `ets` interface - Added `code:all_loaded/0` and `code:all_available/0` - Added `erlang:split_binary/2` +- Added `inet:getaddr/2` ## [0.6.6] - Unreleased diff --git a/libs/estdlib/src/inet.erl b/libs/estdlib/src/inet.erl index 6af6c9a60..8eb3b2b61 100644 --- a/libs/estdlib/src/inet.erl +++ b/libs/estdlib/src/inet.erl @@ -20,7 +20,7 @@ -module(inet). --export([port/1, close/1, sockname/1, peername/1]). +-export([port/1, close/1, sockname/1, peername/1, getaddr/2]). -include("inet-priv.hrl"). @@ -30,7 +30,8 @@ -type port_number() :: 0..65535. -type ip_address() :: ip4_address(). -type ip4_address() :: {0..255, 0..255, 0..255, 0..255}. --type hostname() :: iodata(). +-type hostname() :: atom() | string(). +-type address_family() :: inet. -export_type([socket/0, port_number/0, ip_address/0, ip4_address/0, hostname/0]). @@ -85,3 +86,31 @@ sockname({Moniker, Socket, Module}) when {ok, {ip_address(), port_number()}} | {error, Reason :: term()}. peername({?GEN_TCP_MONIKER, Socket, Module}) -> Module:peername(Socket). + +%%----------------------------------------------------------------------------- +%% @param Name the name to resolve +%% @param Family the family to resolve it to +%% @returns The address or an error tuple. +%% @doc Get the IP address associated with a given name. +%% @end +%%----------------------------------------------------------------------------- +-spec getaddr(Name :: ip_address() | hostname(), Family :: address_family()) -> + {ok, ip_address()} | {error, Reason :: term()}. +getaddr(Name, _Family) when is_tuple(Name) -> + {ok, Name}; +getaddr(Name, Family) when is_atom(Name) -> + getaddr(atom_to_list(Name), Family); +getaddr(Name, Family) -> + try net:getaddrinfo(Name) of + {ok, Results} -> + Filtered = [Addr || #{family := F, addr := #{addr := Addr}} <- Results, F =:= Family], + case Filtered of + [] -> {error, nxdomain}; + [IPAddr | _] -> {ok, IPAddr} + end; + {error, _} = Err -> + Err + catch + error:function_clause -> + {error, einval} + end. diff --git a/tests/libs/estdlib/CMakeLists.txt b/tests/libs/estdlib/CMakeLists.txt index ebc4754f4..3e63834b6 100644 --- a/tests/libs/estdlib/CMakeLists.txt +++ b/tests/libs/estdlib/CMakeLists.txt @@ -31,6 +31,7 @@ set(ERLANG_MODULES test_gen_statem test_gen_udp test_gen_tcp + test_inet test_io_lib test_lists test_logger diff --git a/tests/libs/estdlib/test_inet.erl b/tests/libs/estdlib/test_inet.erl new file mode 100644 index 000000000..6703aaa35 --- /dev/null +++ b/tests/libs/estdlib/test_inet.erl @@ -0,0 +1,38 @@ +% +% This file is part of AtomVM. +% +% Copyright 2024 Paul Guyot +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. +% +% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later +% + +-module(test_inet). + +-export([test/0]). + +test() -> + ok = test_getaddr(), + ok. + +test_getaddr() -> + {ok, {127, 0, 0, 1}} = inet:getaddr(localhost, inet), + {ok, {127, 0, 0, 1}} = inet:getaddr("localhost", inet), + {ok, {_, _, _, _}} = inet:getaddr("www.atomvm.net", inet), + % RFC8880 + {ok, {192, 0, 0, LastByte}} = inet:getaddr("ipv4only.arpa", inet), + true = LastByte =:= 170 orelse LastByte =:= 171, + {error, einval} = inet:getaddr(<<"localhost">>, inet), + {error, _} = inet:getaddr("localhost.invalid", inet), + ok. diff --git a/tests/libs/estdlib/tests.erl b/tests/libs/estdlib/tests.erl index 21de828b8..ae70db2fd 100644 --- a/tests/libs/estdlib/tests.erl +++ b/tests/libs/estdlib/tests.erl @@ -52,6 +52,7 @@ get_tests(_OTPVersion) -> test_gen_statem, test_gen_udp, test_gen_tcp, + test_inet, test_io_lib, test_logger, test_maps,