Browse Source

improve IPv4/IPv6 resolution and printing

This is only a proposal, this code needs to be beautified/structured more
OptoCloud 3 years ago
parent
commit
81e212c784
1 changed files with 73 additions and 30 deletions
  1. 73 30
      include/enet.h

+ 73 - 30
include/enet.h

@@ -202,6 +202,9 @@
 #define ENET_MIN(x, y) ((x) < (y) ? (x) : (y))
 
 #define ENET_IPV6           1
+const struct in6_addr enet_v6_anyaddr   = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}};
+const struct in6_addr enet_v6_noaddr    = {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}};
+const struct in6_addr enet_v6_localhost = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}};
 #define ENET_HOST_ANY       in6addr_any
 #define ENET_HOST_BROADCAST 0xFFFFFFFFU
 #define ENET_PORT_ANY       0
@@ -1198,6 +1201,31 @@ extern "C" {
 
 #endif /* defined(_MSC_VER) */
 
+    inline void enet_inaddr_map4to6(struct in_addr in, struct in6_addr *out)
+    {
+        if (in.s_addr == 0x00000000) {
+            *out = enet_v6_anyaddr;
+        } else if (in.s_addr == 0xFFFFFFFF) {
+            *out = enet_v6_noaddr;
+        } else {
+            *out = enet_v6_anyaddr;
+            out->s6_addr[10] = 0xFF;
+            out->s6_addr[11] = 0xFF;
+            out->s6_addr[12] = ((uint8_t *)&in.s_addr)[0];
+            out->s6_addr[13] = ((uint8_t *)&in.s_addr)[1];
+            out->s6_addr[14] = ((uint8_t *)&in.s_addr)[2];
+            out->s6_addr[15] = ((uint8_t *)&in.s_addr)[3];
+        }
+    }
+    inline void enet_inaddr_map6to4(const struct in6_addr *in, struct in_addr *out)
+    {
+        memset(out, 0, sizeof(struct in_addr));
+        ((uint8_t *)&out->s_addr)[0] = in->s6_addr[12];
+        ((uint8_t *)&out->s_addr)[1] = in->s6_addr[13];
+        ((uint8_t *)&out->s_addr)[2] = in->s6_addr[14];
+        ((uint8_t *)&out->s_addr)[3] = in->s6_addr[15];
+    }
+
 
 // =======================================================================//
 // !
@@ -5175,62 +5203,77 @@ extern "C" {
         return (enet_uint64) time(NULL);
     }
 
-    int enet_address_set_host_ip(ENetAddress *address, const char *name) {
-        if (!inet_pton(AF_INET6, name, &address->host)) {
-            return -1;
-        }
-
-        return 0;
-    }
-
-    int enet_address_set_host(ENetAddress *address, const char *name) {
+    int enet_in6addr_lookup_host(const char *name, bool nodns, struct in6_addr *out) {
         struct addrinfo hints, *resultList = NULL, *result = NULL;
 
         memset(&hints, 0, sizeof(hints));
         hints.ai_family = AF_UNSPEC;
 
+        if (nodns)
+        {
+            hints.ai_flags = AI_NUMERICHOST; /* prevent actual DNS lookups! */
+        }
+
         if (getaddrinfo(name, NULL, &hints, &resultList) != 0) {
+            if (resultList != NULL) {
+                freeaddrinfo(resultList);
+            }
+
             return -1;
         }
 
         for (result = resultList; result != NULL; result = result->ai_next) {
-            if (result->ai_addr != NULL && result->ai_addrlen >= sizeof(struct sockaddr_in)) {
-                if (result->ai_family == AF_INET) {
-                    struct sockaddr_in * sin = (struct sockaddr_in *) result->ai_addr;
+            if (result->ai_addr != NULL) {
+                if (result->ai_family == AF_INET || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in))) {
+                    enet_inaddr_map4to6(((struct sockaddr_in*)result->ai_addr)->sin_addr, out);
 
-                    ((uint32_t *)&address->host.s6_addr)[0] = 0;
-                    ((uint32_t *)&address->host.s6_addr)[1] = 0;
-                    ((uint32_t *)&address->host.s6_addr)[2] = htonl(0xffff);
-                    ((uint32_t *)&address->host.s6_addr)[3] = sin->sin_addr.s_addr;
-
-                    freeaddrinfo(resultList);
+                    if (resultList != NULL) {
+                        freeaddrinfo(resultList);
+                    }
 
                     return 0;
-                }
-                else if(result->ai_family == AF_INET6) {
-                    struct sockaddr_in6 * sin = (struct sockaddr_in6 *)result->ai_addr;
-
-                    address->host = sin->sin6_addr;
-                    address->sin6_scope_id = sin->sin6_scope_id;
+                } else if (result->ai_family == AF_INET6 || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in6))) {
+                    memcpy(out, &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, sizeof(struct sockaddr_in6));
 
-                    freeaddrinfo(resultList);
+                    if (resultList != NULL) {
+                        freeaddrinfo(resultList);
+                    }
 
                     return 0;
                 }
             }
         }
 
-
         if (resultList != NULL) {
             freeaddrinfo(resultList);
         }
 
-        return enet_address_set_host_ip(address, name);
-    } /* enet_address_set_host */
+        return -1;
+    }
+
+    int enet_address_set_host_ip(ENetAddress *address, const char *name) {
+        return enet_in6addr_lookup_host(name, true, &address->host);
+    }
+
+    int enet_address_set_host(ENetAddress *address, const char *name) {
+        return enet_in6addr_lookup_host(name, false, &address->host);
+    }
 
     int enet_address_get_host_ip(const ENetAddress *address, char *name, size_t nameLength) {
-        if (inet_ntop(AF_INET6, &address->host, name, nameLength) == NULL) {
-            return -1;
+        if (IN6_IS_ADDR_V4MAPPED(&address->host))
+        {
+            struct in_addr buf;
+            enet_inaddr_map6to4(&address->host, &buf);
+
+            if (inet_ntop(AF_INET, &buf, name, nameLength) == NULL) {
+                return -1;
+            }
+        }
+        else
+        {
+            if (inet_ntop(AF_INET6, &address->host, name, nameLength) == NULL) {
+                return -1;
+            }
         }
 
         return 0;