File 2433-erts-enet-Miscellanous-improvements-to-the-net-nif.patch of Package erlang

From a95d7aee0fe5ac732dbe031d50d993af8b2d11d0 Mon Sep 17 00:00:00 2001
From: Micael Karlberg <bmk@erlang.org>
Date: Thu, 19 Jun 2025 15:03:39 +0200
Subject: [PATCH 13/14] [erts|enet] Miscellanous improvements to the net nif

Improve getifaddrs handling of netns (string handkling).
Also introduced debug to that function call (part of the extra
argument).
Also improved the net info function (add info about if netns
is supported or not).

OTP-19674
---
 erts/emulator/nifs/common/prim_net_nif.c | 150 ++++++++++-------------
 erts/emulator/nifs/common/socket_util.c  |  59 +++++++++
 erts/emulator/nifs/common/socket_util.h  |   7 ++
 3 files changed, 133 insertions(+), 83 deletions(-)

diff --git a/erts/emulator/nifs/common/prim_net_nif.c b/erts/emulator/nifs/common/prim_net_nif.c
index 33c805a68c..83a5167861 100644
--- a/erts/emulator/nifs/common/prim_net_nif.c
+++ b/erts/emulator/nifs/common/prim_net_nif.c
@@ -352,6 +352,7 @@ static ERL_NIF_TERM enet_getaddrinfo(ErlNifEnv* env,
 
 #if defined(HAVE_GETIFADDRS) || defined(__PASE__)
 static ERL_NIF_TERM enet_getifaddrs(ErlNifEnv* env,
+                                    BOOLEAN_T  dbg,
                                     char*      netns);
 #endif
 
@@ -533,8 +534,10 @@ static void net_down(ErlNifEnv*           env,
 */
 
 static ERL_NIF_TERM enet_getifaddrs(ErlNifEnv* env,
+                                    BOOLEAN_T  dbg,
                                     char*      netns);
 static ERL_NIF_TERM enet_getifaddrs_process(ErlNifEnv*      env,
+                                            BOOLEAN_T       dbg,
                                             struct ifaddrs* ifap);
 static unsigned int enet_getifaddrs_length(struct ifaddrs* ifap);
 static void encode_ifaddrs(ErlNifEnv*      env,
@@ -555,6 +558,8 @@ static void make_ifaddrs(ErlNifEnv*    env,
                          ERL_NIF_TERM  ifu_value,
                          ERL_NIF_TERM  data,
                          ERL_NIF_TERM* ifAddrs);
+static BOOLEAN_T enet_getifaddrs_debug(ErlNifEnv*   env,
+                                       ERL_NIF_TERM map);
 #ifdef HAVE_SETNS
 static BOOLEAN_T enet_getifaddrs_netns(ErlNifEnv*   env,
                                        ERL_NIF_TERM map,
@@ -837,22 +842,29 @@ static ErlNifResourceTypeInit netInit = {
  * nif_info
  *
  * Description:
- * This is currently just a placeholder...
+ * Provide miscellaneous information about the net nif.
  */
 static
 ERL_NIF_TERM nif_info(ErlNifEnv*         env,
                       int                argc,
                       const ERL_NIF_TERM argv[])
 {
-    ERL_NIF_TERM info, tmp;
-
-    NDBG( ("NET", "info -> entry\r\n") );
+    BOOLEAN_T    dbg     = data.debug;
+#ifdef HAVE_NETNS
+    BOOLEAN_T    netns   = TRUE;
+#else
+    BOOLEAN_T    netns   = FALSE;
+#endif
+    ERL_NIF_TERM vals[]  = {BOOL2ATOM(dbg), BOOL2ATOM(netns)};
+    ERL_NIF_TERM keys[]  = {atom_debug, enif_make_atom(env, "netns")};
+    unsigned int numVals = NUM(vals);
+    unsigned int numKeys = NUM(keys);
+    ERL_NIF_TERM info;
 
-    tmp  = enif_make_new_map(env);
-    if (!enif_make_map_put(env, tmp, atom_debug, BOOL2ATOM(data.debug), &info))
-        info = tmp;
+    ESOCK_ASSERT( numKeys == numVals );
+    ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, &info) );
 
-    NDBG( ("NET", "info -> done: %T\r\n", info) );
+    NDBG( ("NET", "info -> done\r\n") );
 
     return info;
 }
@@ -1360,7 +1372,9 @@ ERL_NIF_TERM enet_getaddrinfo(ErlNifEnv* env,
  *
  * Arguments:
  * Extra - A way to pass 'extra' arguments.
- *         Currently only used for netns (name space).
+ *         Currently only used for:
+ *            * debug (for this call only)
+ *            * netns (name space).
  */
 
 static
@@ -1371,9 +1385,8 @@ ERL_NIF_TERM nif_getifaddrs(ErlNifEnv*         env,
 #if defined(__WIN32__)
     return enif_raise_exception(env, MKA(env, "notsup"));
 #elif defined(HAVE_GETIFADDRS) || defined(__PASE__)
-#ifdef HAVE_SETNS
     ERL_NIF_TERM extra;
-#endif
+    BOOLEAN_T    dbg;
     char*        netns;
     ERL_NIF_TERM result;
 
@@ -1383,26 +1396,23 @@ ERL_NIF_TERM nif_getifaddrs(ErlNifEnv*         env,
         !IS_MAP(env,  argv[0])) {
         return enif_make_badarg(env);
     }
-#ifdef HAVE_SETNS
     extra = argv[0];
-#endif
 
+    dbg = enet_getifaddrs_debug(env, extra);
 
 #ifdef HAVE_SETNS
     /* We *currently* only support one extra option: netns */
     if (!enet_getifaddrs_netns(env, extra, &netns)) {
-        NDBG( ("NET", "nif_getifaddrs -> namespace: %s\r\n", netns) );
+        NDBG2( dbg, ("NET", "nif_getifaddrs -> namespace: %s\r\n", netns) );
         return enif_make_badarg(env);
     }
 #else
     netns = NULL;
 #endif
 
-    result = enet_getifaddrs(env, netns);
+    result = enet_getifaddrs(env, dbg, netns);
 
-    NDBG( ("NET",
-           "nif_getifaddrs -> done when result: "
-           "\r\n   %T\r\n", result) );
+    NDBG2( dbg, ("NET", "nif_getifaddrs -> done\r\n") );
 
     return result;
 #else // HAVE_GETIFADDRS
@@ -1411,68 +1421,38 @@ ERL_NIF_TERM nif_getifaddrs(ErlNifEnv*         env,
 }
 
 
+static
+BOOLEAN_T enet_getifaddrs_debug(ErlNifEnv* env, ERL_NIF_TERM map)
+{
+    ERL_NIF_TERM key = enif_make_atom(env, "debug");
+
+    return esock_get_bool_from_map(env, map, key, FALSE);
+
+}
+
+
 #if defined(HAVE_GETIFADDRS) || defined(__PASE__)
 #ifdef HAVE_SETNS
 /* enet_getifaddrs_netns - extract the netns field from the 'extra' map
  *
- * Note that the 'extra' map *may* contain other options, but here we
+ * Note that the 'extra' map may contain other options, but here we
  * only care about 'netns'.
  */
 static
 BOOLEAN_T enet_getifaddrs_netns(ErlNifEnv* env, ERL_NIF_TERM map, char** netns)
 {
-    size_t       sz;
-    ERL_NIF_TERM key;
-    ERL_NIF_TERM value;
-    unsigned int len;
-    char*        buf;
-    int          written;
-
-    /* Note that its acceptable that the extra map is empty */
-    if (!enif_get_map_size(env, map, &sz) ||
-        (sz != 1)) {
-        *netns = NULL;
-        return TRUE;
-    }
+    ERL_NIF_TERM       key      = enif_make_atom(env, "netns");
+    ErlNifCharEncoding encoding = ERL_NIF_LATIN1;
 
-    /* Regardless of the content of the 'extra' map, we only care about 'netns' */
-    key = enif_make_atom(env, "netns");
-    if (!GET_MAP_VAL(env, map, key, &value)) {
-        *netns = NULL;
-        return TRUE;
-    }
+    return esock_get_string_from_map(env, map, key, encoding, netns);
 
-    /* So far so good. The value should be a string, check. */
-    if (!enif_is_list(env, value)) {
-        *netns = NULL; // Just in case...
-        return FALSE;
-    }
-
-    if (!enif_get_list_length(env, value, &len)) {
-        *netns = NULL; // Just in case...
-        return FALSE;
-    }
-
-    if ((buf = MALLOC(len+1)) == NULL) {
-        *netns = NULL; // Just in case...
-        return FALSE;
-    }
-
-    written = enif_get_string(env, value, buf, len+1, ERL_NIF_LATIN1);
-    if (written == (len+1)) {
-        *netns = buf;
-        return TRUE;
-    } else {
-        *netns = NULL; // Just in case...
-        return FALSE;
-    }
 }
 #endif
 
 
 
 static
-ERL_NIF_TERM enet_getifaddrs(ErlNifEnv* env, char* netns)
+ERL_NIF_TERM enet_getifaddrs(ErlNifEnv* env, BOOLEAN_T dbg, char* netns)
 {
     ERL_NIF_TERM    result;
     struct ifaddrs* ifap;
@@ -1481,9 +1461,10 @@ ERL_NIF_TERM enet_getifaddrs(ErlNifEnv* env, char* netns)
     int             current_ns = 0;
 #endif
 
-    NDBG( ("NET", "enet_getifaddrs -> entry with"
-           "\r\n   netns: %s"
-           "\r\n", ((netns == NULL) ? "NULL" : netns)) );
+    NDBG2( dbg,
+           ("NET", "enet_getifaddrs -> entry with"
+            "\r\n   netns: %s"
+            "\r\n", ((netns == NULL) ? "NULL" : netns)) );
 
 #ifdef HAVE_SETNS
     if ((netns != NULL) &&
@@ -1496,7 +1477,7 @@ ERL_NIF_TERM enet_getifaddrs(ErlNifEnv* env, char* netns)
 #else
     if (0 == getifaddrs(&ifap)) {
 #endif
-        result = enet_getifaddrs_process(env, ifap);
+        result = enet_getifaddrs_process(env, dbg, ifap);
 #ifdef __PASE__
         Qp2freeifaddrs(ifap);
 #else
@@ -1505,7 +1486,8 @@ ERL_NIF_TERM enet_getifaddrs(ErlNifEnv* env, char* netns)
     } else {
         save_errno = get_errno();
 
-        NDBG( ("NET", "enet_getifaddrs -> failed get addrs: %d", save_errno) );
+        NDBG2( dbg,
+               ("NET", "enet_getifaddrs -> failed get addrs: %d", save_errno) );
 
         result = esock_make_error_errno(env, save_errno);
     }
@@ -1520,21 +1502,21 @@ ERL_NIF_TERM enet_getifaddrs(ErlNifEnv* env, char* netns)
         FREE(netns);
 #endif
 
-    NDBG( ("NET", "enet_getifaddrs -> done when"
-           "\r\n   result: %T"
-           "\r\n", result) );
+    NDBG2( dbg, ("NET", "enet_getifaddrs -> done\r\n") );
 
     return result;
 }
 
 
 static
-ERL_NIF_TERM enet_getifaddrs_process(ErlNifEnv* env, struct ifaddrs* ifap)
+ERL_NIF_TERM enet_getifaddrs_process(ErlNifEnv*      env,
+                                     BOOLEAN_T       dbg,
+                                     struct ifaddrs* ifap)
 {
     ERL_NIF_TERM result;
     unsigned int len = ((ifap == NULL) ? 0 : enet_getifaddrs_length(ifap));
 
-    NDBG( ("NET", "enet_getifaddrs_process -> len: %d\r\n", len) );
+    NDBG2( dbg, ("NET", "enet_getifaddrs_process -> len: %d\r\n", len) );
 
     if (len > 0) {
       ERL_NIF_TERM*   array = MALLOC(len * sizeof(ERL_NIF_TERM));
@@ -1544,23 +1526,26 @@ ERL_NIF_TERM enet_getifaddrs_process(ErlNifEnv* env, struct ifaddrs* ifap)
         while (i < len) {
             ERL_NIF_TERM entry;
 
-            NDBG( ("NET",
-                   "enet_getifaddrs_process -> encode entry %d\r\n", i) );
+            NDBG2( dbg,
+                   ("NET",
+                    "enet_getifaddrs_process -> encode entry %d\r\n", i) );
 
             encode_ifaddrs(env, p, &entry);
 
-            NDBG( ("NET", "enet_getifaddrs_process -> new entry (%d):"
-                   "\r\n   %T"
-                   "\r\n", i, entry) );
+            NDBG2( dbg,
+                   ("NET", "enet_getifaddrs_process -> new entry (%d):"
+                    "\r\n   %T"
+                    "\r\n", i, entry) );
 
             array[i] = entry;
             p = p->ifa_next;
             i++;
         }
 
-        NDBG( ("NET",
-               "enet_getifaddrs_process -> all (%d) entries processed\r\n",
-               len) );
+        NDBG2( dbg,
+               ("NET",
+                "enet_getifaddrs_process -> all (%d) entries processed\r\n",
+                len) );
 
         result = esock_make_ok2(env, MKLA(env, array, len));
         FREE(array);        
@@ -1569,8 +1554,7 @@ ERL_NIF_TERM enet_getifaddrs_process(ErlNifEnv* env, struct ifaddrs* ifap)
         result = esock_make_ok2(env, MKEL(env));
     }
 
-    NDBG( ("NET", "enet_getifaddrs_process -> result: "
-           "\r\n   %T\r\n", result) );
+    NDBG2( dbg, ("NET", "enet_getifaddrs_process -> done\r\n") );
 
     return result;
 }
diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c
index 68f689ac74..ef832f059e 100644
--- a/erts/emulator/nifs/common/socket_util.c
+++ b/erts/emulator/nifs/common/socket_util.c
@@ -236,6 +236,65 @@ BOOLEAN_T esock_get_bool_from_map(ErlNifEnv*   env,
 }
 
 
+/* *** esock_get_string_from_map ***
+ *
+ * Simple utility function used to extract a string value from a map.
+ * If the map does not contain the map value, the string is set to NULL
+ * and TRUE is returned (its acceptible to not provide a value).
+ * If it fails to extract the value (for whatever reason) the string
+ * is set to NULL and FALSE is returned.
+ */
+
+extern
+BOOLEAN_T esock_get_string_from_map(ErlNifEnv*         env,
+                                    ERL_NIF_TERM       map,
+                                    ERL_NIF_TERM       key,
+                                    ErlNifCharEncoding encoding,
+                                    char**             str)
+{
+    ERL_NIF_TERM eval;
+    unsigned int len;
+    char*        buf;
+    int          written;
+
+    /* Try extract the string in erlang form from the map */
+    if (!GET_MAP_VAL(env, map, key, &eval)) {
+        *str = NULL;
+        return TRUE;
+    }
+
+    /* Check if its a list */
+    if (!enif_is_list(env, eval)) {
+        *str = NULL;
+        return FALSE;
+    }
+
+    /* Get the string length */
+    if (!enif_get_string_length(env, eval, &len, encoding)) {
+        *str = NULL;
+        return FALSE;
+    }
+
+    /* Allocate the string */
+    if ((buf = MALLOC(len+1)) == NULL) {
+        *str = NULL;
+        return FALSE;
+    }
+
+    /* And finally copy it out */
+    written = enif_get_string(env, eval, buf, len+1, encoding);
+    if (written == (len+1)) {
+        *str = buf;
+        return TRUE;
+    } else {
+        FREE( buf );
+        *str = NULL;
+        return FALSE;
+    }
+
+}
+
+
 /* +++ esock_encode_iov +++
  *
  * Encode an IO Vector. In erlang we represented this as a list of binaries.
diff --git a/erts/emulator/nifs/common/socket_util.h b/erts/emulator/nifs/common/socket_util.h
index 37f8a4b5bd..8c0f40eb92 100644
--- a/erts/emulator/nifs/common/socket_util.h
+++ b/erts/emulator/nifs/common/socket_util.h
@@ -87,6 +87,13 @@ BOOLEAN_T esock_get_bool_from_map(ErlNifEnv*   env,
                                   ERL_NIF_TERM key,
                                   BOOLEAN_T    def);
 
+extern
+BOOLEAN_T esock_get_string_from_map(ErlNifEnv*         env,
+                                    ERL_NIF_TERM       map,
+                                    ERL_NIF_TERM       key,
+                                    ErlNifCharEncoding encoding,
+                                    char**             str);
+
 extern
 BOOLEAN_T esock_decode_iov(ErlNifEnv*    env,
                            ERL_NIF_TERM  eIOV,
-- 
2.43.0

openSUSE Build Service is sponsored by