File 5782-enet-Add-net-getservbyname.patch of Package erlang

From 7f86a1e5c57ac47a368b092d766465fc44f07a96 Mon Sep 17 00:00:00 2001
From: Micael Karlberg <bmk@erlang.org>
Date: Mon, 15 Apr 2024 16:55:18 +0200
Subject: [PATCH 02/18] [enet] Add net:getservbyname

---
 erts/emulator/nifs/common/prim_net_nif.c | 111 ++++++++++++++++++++++-
 lib/kernel/src/net.erl                   |  47 +++++++++-
 2 files changed, 150 insertions(+), 8 deletions(-)

diff --git a/erts/emulator/nifs/common/prim_net_nif.c b/erts/emulator/nifs/common/prim_net_nif.c
index 8655c561e3..ed088aaed6 100644
--- a/erts/emulator/nifs/common/prim_net_nif.c
+++ b/erts/emulator/nifs/common/prim_net_nif.c
@@ -203,9 +203,23 @@ ERL_NIF_INIT(prim_net, net_funcs, on_load, NULL, NULL, NULL)
 
 
 #ifdef __WIN32__
-#define net_gethostname(__buf__, __bufSz__) gethostname((__buf__), (__bufSz__))
+
+#define net_gethostname(__buf__, __bufSz__)     \
+    gethostname((__buf__), (__bufSz__))
+#define net_getservbyname(__name__, __proto__)  \
+    getservbyname((__name__), (__proto__))
+#define net_ntohs(x)                            \
+    ntohs((x))
+
 #else
-#define net_gethostname(__buf__, __bufSz__) gethostname((__buf__), (__bufSz__))
+
+#define net_gethostname(__buf__, __bufSz__)     \
+    gethostname((__buf__), (__bufSz__))
+#define net_getservbyname(__name__, __proto__)  \
+    getservbyname((__name__), (__proto__))
+#define net_ntohs(x)                            \
+    ntohs((x))
+
 #endif // __WIN32__
 
 
@@ -266,7 +280,7 @@ static NetData data;
  * ----------------------------------------------------------------------
  */
 
-/* THIS IS JUST TEMPORARY */
+/* THIS IS JUST TEMPORARY...maybe */
 extern char* erl_errno_id(int error);
 
 /* All the nif "callback" functions for the net API has
@@ -292,6 +306,7 @@ extern char* erl_errno_id(int error);
     ENET_NIF_FUNC_DEF(get_if_entry);         \
     ENET_NIF_FUNC_DEF(get_interface_info);   \
     ENET_NIF_FUNC_DEF(get_ip_address_table); \
+    ENET_NIF_FUNC_DEF(getservbyname);        \
     ENET_NIF_FUNC_DEF(if_name2index);        \
     ENET_NIF_FUNC_DEF(if_index2name);        \
     ENET_NIF_FUNC_DEF(if_names);
@@ -467,7 +482,11 @@ static void make_ip_address_row(ErlNifEnv*    env,
                                 ERL_NIF_TERM  eReasmSize,
                                 ERL_NIF_TERM* iar);
 
-#endif
+#endif // defined(__WIN32__)
+
+static ERL_NIF_TERM enet_getservbyname(ErlNifEnv*   env,
+                                       ERL_NIF_TERM ename,
+                                       ERL_NIF_TERM eproto);
 
 #if defined(HAVE_IF_NAMETOINDEX)
 static ERL_NIF_TERM enet_if_name2index(ErlNifEnv* env,
@@ -791,6 +810,7 @@ static ErlNifResourceTypeInit netInit = {
  * nif_get_if_entry/1
  * nif_get_interface_info/1
  * nif_get_ip_address_table/1
+ * nif_getservbyname/2
  * nif_if_name2index/1
  * nif_if_index2name/1
  * nif_if_names/0
@@ -3932,6 +3952,86 @@ void make_ip_address_row(ErlNifEnv*    env,
 
 
 
+/* ----------------------------------------------------------------------
+ * nif_getservbyname
+ *
+ * Description:
+ * Get service by name.
+ * This is a lookup function that translates a service name to its
+ * registered port number.
+ *
+ * Arguments:
+ * Name - The name of the service.
+ * Protocol - The name of the service.
+ *
+ * Returns:
+ * {ok, PortNumber :: port_number()} | {error, Reason :: term()}
+ */
+
+static
+ERL_NIF_TERM nif_getservbyname(ErlNifEnv*         env,
+                               int                argc,
+                               const ERL_NIF_TERM argv[])
+{
+    ERL_NIF_TERM result, ename, eproto;
+    BOOLEAN_T    dbg = FALSE;
+
+    NDBG( ("NET", "nif_get_ip_address_table -> entry (%d)\r\n", argc) );
+
+    if (argc != 2)
+        return enif_make_badarg(env);
+
+    ename  = argv[0];
+    eproto = argv[1];
+
+    NDBG2( dbg,
+           ("NET",
+            "nif_getservbyname -> args: "
+            "\r\n   ename:  %T"
+            "\r\n   eproto: %T"
+            "\r\n", ename, eproto) );
+
+    result = enet_getservbyname(env, ename, eproto);
+
+    NDBG2( dbg,
+           ("NET",
+            "nif_getservbyname -> done when result: "
+            "\r\n   %T\r\n", result) );
+
+    return result;
+}
+
+
+static
+ERL_NIF_TERM enet_getservbyname(ErlNifEnv*   env,
+                                ERL_NIF_TERM ename,
+                                ERL_NIF_TERM eproto)
+{
+    char            name[256];
+    char            proto[256];
+    struct servent* srv;
+    short           port;
+
+    if (0 >= GET_STR(env, ename, name, sizeof(name)))
+        return esock_make_error(env, esock_atom_einval);
+
+    if (0 >= GET_STR(env, eproto, proto, sizeof(proto)))
+        return esock_make_error(env, esock_atom_einval);
+
+    if ( strcmp(proto, "any") == 0 )
+        srv = net_getservbyname(name, NULL);
+    else
+        srv = net_getservbyname(name, proto);
+
+    if (srv == NULL)
+        return esock_make_error(env, esock_atom_einval);
+
+    port = net_ntohs(srv->s_port);
+
+    return esock_make_ok2(env, MKI(env, port));
+}
+
+
 
 /* ----------------------------------------------------------------------
  * nif_if_name2index
@@ -4697,6 +4797,7 @@ ErlNifFunc net_funcs[] =
     {"nif_get_if_entry",       1, nif_get_if_entry,       ERL_NIF_DIRTY_JOB_IO_BOUND},
     {"nif_get_interface_info", 1, nif_get_interface_info, ERL_NIF_DIRTY_JOB_IO_BOUND},
     {"nif_get_ip_address_table", 1, nif_get_ip_address_table, ERL_NIF_DIRTY_JOB_IO_BOUND},
+    {"nif_getservbyname", 2, nif_getservbyname, ERL_NIF_DIRTY_JOB_IO_BOUND},
 
     /* Network interface (name and/or index) functions */
     {"nif_if_name2index",    1, nif_if_name2index, 0},
diff --git a/lib/kernel/src/net.erl b/lib/kernel/src/net.erl
index e642b89d5a..f51f4fb51a 100644
--- a/lib/kernel/src/net.erl
+++ b/lib/kernel/src/net.erl
@@ -34,9 +34,10 @@ This module provides an API for the network interface.
 
 -export([
          gethostname/0,
-         getnameinfo/1, getnameinfo/2,
-         getaddrinfo/1, getaddrinfo/2,
-         getifaddrs/0,  getifaddrs/1, getifaddrs/2,
+         getnameinfo/1,   getnameinfo/2,
+         getaddrinfo/1,   getaddrinfo/2,
+         getifaddrs/0,    getifaddrs/1, getifaddrs/2,
+         getservbyname/1, getservbyname/2,
 
          if_name2index/1,
          if_index2name/1,
@@ -320,6 +321,7 @@ getaddrinfo(Host, Service)
        (not ((Service =:= undefined) andalso (Host =:= undefined))) ->
     prim_net:getaddrinfo(Host, Service).
 
+
 %% ===========================================================================
 %%
 %% getifaddrs - Get interface addresses
@@ -893,6 +895,45 @@ iat_broadaddr({A1, A2, A3, A4}, {M1, M2, M3, M4}) ->
       addr   => {BA1, BA2, BA3, BA4},
       port   => 0}.    
 
+
+%% ===========================================================================
+%%
+%% getservbyname - Get service by name
+%%
+%% Get the port number for the named service.
+%%
+
+-doc(#{equiv => getservbyname(Name, any)}).
+-doc(#{since => <<"OTP FOOBAR">>}).
+-spec getservbyname(Name) ->
+          {ok, PortNumber} | {error, Reason} when
+      Name       :: atom() | string(),
+      PortNumber :: socket:port_number(),
+      Reason     :: term().
+getservbyname(Name) ->
+    getservbyname(Name, any).
+
+-doc """
+Get service by name.
+
+This function is used to get the port number of the specified protocol
+for the named service.
+""".
+-doc(#{since => <<"OTP FOOBAR">>}).
+-spec getservbyname(Name, Protocol) ->
+          {ok, PortNumber} | {error, Reason} when
+      Name       :: atom() | string(),
+      PortNumber :: socket:port_number(),
+      Protocol   :: any | socket:protocol(),
+      Reason     :: term().
+getservbyname(Name, Protocol)
+  when is_atom(Name) ->
+    getservbyname(atom_to_list(Name), Protocol);
+getservbyname(Name, Protocol)
+  when is_list(Name) andalso is_atom(Protocol) ->
+    prim_net:getservbyname(Name, atom_to_list(Protocol)).
+
+
 %% ===========================================================================
 %%
 %% if_name2index - Mappings between network interface names and indexes:
-- 
2.35.3

openSUSE Build Service is sponsored by