]> git.sesse.net Git - vlc/blobdiff - src/network/getaddrinfo.c
Use replacement API for obsolete systems. Not tested.
[vlc] / src / network / getaddrinfo.c
index 62060b164805cb2a778f704e57b000d4dbf9c96d..70183d6b141cf80349c8018d354959dfcce9c3be 100644 (file)
@@ -102,36 +102,6 @@ const char *vlc_gai_strerror (int errnum)
 }
 #endif
 
-#ifndef WIN32
-#if !(defined (HAVE_GETNAMEINFO) && defined (HAVE_GETADDRINFO))
-/*
- * Converts the current herrno error value into an EAI_* error code.
- * That error code is normally returned by getnameinfo() or getaddrinfo().
- */
-static int
-gai_error_from_herrno (void)
-{
-    switch (h_errno)
-    {
-        case HOST_NOT_FOUND:
-            return EAI_NONAME;
-
-        case NO_ADDRESS:
-# if (NO_ADDRESS != NO_DATA)
-        case NO_DATA:
-# endif
-            return EAI_NODATA;
-
-        case NO_RECOVERY:
-            return EAI_FAIL;
-
-        case TRY_AGAIN:
-            return EAI_AGAIN;
-    }
-    return EAI_SYSTEM;
-}
-#endif /* if !(HAVE_GETNAMEINFO && HAVE_GETADDRINFO) */
-
 #ifndef HAVE_GETNAMEINFO
 /*
  * getnameinfo() non-thread-safe IPv4-only implementation,
@@ -191,6 +161,33 @@ getnameinfo (const struct sockaddr *sa, socklen_t salen,
 #endif /* if !HAVE_GETNAMEINFO */
 
 #ifndef HAVE_GETADDRINFO
+/*
+ * Converts the current herrno error value into an EAI_* error code.
+ * That error code is normally returned by getnameinfo() or getaddrinfo().
+ */
+static int
+gai_error_from_herrno (void)
+{
+    switch (h_errno)
+    {
+        case HOST_NOT_FOUND:
+            return EAI_NONAME;
+
+        case NO_ADDRESS:
+# if (NO_ADDRESS != NO_DATA)
+        case NO_DATA:
+# endif
+            return EAI_NODATA;
+
+        case NO_RECOVERY:
+            return EAI_FAIL;
+
+        case TRY_AGAIN:
+            return EAI_AGAIN;
+    }
+    return EAI_SYSTEM;
+}
+
 /*
  * This functions must be used to free the memory allocated by getaddrinfo().
  */
@@ -368,7 +365,7 @@ getaddrinfo (const char *node, const char *service,
             entry = gethostbyname (node);
 
         if (entry == NULL)
-            return EAI_NONAME;
+            return gai_error_from_herrno ();
 
         if ((entry->h_length != 4) || (entry->h_addrtype != AF_INET))
             return EAI_FAMILY;
@@ -450,101 +447,96 @@ getaddrinfo (const char *node, const char *service,
     return 0;
 }
 #endif /* if !HAVE_GETADDRINFO */
-#endif
 
 #if defined( WIN32 ) && !defined( UNDER_CE )
     /*
      * Here is the kind of kludge you need to keep binary compatibility among
      * varying OS versions...
      */
-typedef int (CALLBACK * GETNAMEINFO) ( const struct sockaddr*, socklen_t,
-                                           char*, DWORD, char*, DWORD, int );
-typedef int (CALLBACK * GETADDRINFO) (const char *, const char *,
-                                          const struct addrinfo *,
-                                          struct addrinfo **);
+typedef int (WSAAPI * GETNAMEINFO) ( const struct sockaddr FAR *, socklen_t,
+                                           char FAR *, DWORD, char FAR *, DWORD, int );
+typedef int (WSAAPI * GETADDRINFO) (const char FAR *, const char FAR *,
+                                          const struct addrinfo FAR *,
+                                          struct addrinfo FAR * FAR *);
 
-typedef void (CALLBACK * FREEADDRINFO) ( struct addrinfo * );
+typedef void (WSAAPI * FREEADDRINFO) ( struct addrinfo FAR * );
 
-
-static WINAPI int _ws2_getnameinfo_bind( const struct sockaddr *sa, socklen_t salen,
-               char *host, DWORD hostlen, char *serv, DWORD servlen, int flags );
-
-static WINAPI int _ws2_getaddrinfo_bind(const char *node, const char *service,
-               const struct addrinfo *hints, struct addrinfo **res);
-
-static WINAPI void _ws2_freeaddrinfo_bind( struct addrinfo *infos );
+static int WSAAPI _ws2_getnameinfo_bind ( const struct sockaddr FAR *, socklen_t,
+                                           char FAR *, DWORD, char FAR *, DWORD, int );
+static int WSAAPI _ws2_getaddrinfo_bind (const char FAR *, const char FAR *,
+                                          const struct addrinfo FAR *,
+                                          struct addrinfo FAR * FAR *);
 
 static GETNAMEINFO ws2_getnameinfo = _ws2_getnameinfo_bind;
 static GETADDRINFO ws2_getaddrinfo = _ws2_getaddrinfo_bind;
-static FREEADDRINFO ws2_freeaddrinfo = _ws2_freeaddrinfo_bind;
+static FREEADDRINFO ws2_freeaddrinfo;
 
-static int _ws2_find_ipv6_api(void)
+static FARPROC ws2_find_api (LPCTSTR name)
 {
-    /* For Windows XP and above, IPv6 stack is in WS2_32.DLL */
-    HINSTANCE module = LoadLibrary( "ws2_32.dll" );
-    if( module != NULL )
-    {
-        ws2_getnameinfo = (GETNAMEINFO)GetProcAddress( module, "getnameinfo" );
-        ws2_getaddrinfo = (GETADDRINFO)GetProcAddress( module, "getaddrinfo" );
-        ws2_freeaddrinfo = (FREEADDRINFO)GetProcAddress( module, "freeaddrinfo" );
-        if( ws2_getnameinfo && ws2_getaddrinfo && ws2_freeaddrinfo )
-        {
-            /* got them */
-            return 1;
-        }
-        FreeLibrary( module );
+    FARPROC f = NULL;
 
-        /* For Windows 2000 and below, try IPv6 stack in in WSHIP6.DLL */
-        module = LoadLibrary( "wship6.dll" );
-        if( module != NULL )
-        {
-            ws2_getnameinfo = (GETNAMEINFO)GetProcAddress( module, "getnameinfo" );
-            ws2_getaddrinfo = (GETADDRINFO)GetProcAddress( module, "getaddrinfo" );
-            ws2_freeaddrinfo = (FREEADDRINFO)GetProcAddress( module, "freeaddrinfo" );
-            if( ws2_getnameinfo && ws2_getaddrinfo && ws2_freeaddrinfo )
-            {
-                /* got them */
-                return 1;
-            }
-            FreeLibrary( module );
-        }
+    HMODULE m = GetModuleHandle (TEXT("WS2_32"));
+    if (m != NULL)
+        f = GetProcAddress (m, name);
+
+    if (f == NULL)
+    {
+        /* Windows 2K IPv6 preview */
+        m = LoadLibrary (TEXT("WSHIP6"));
+        if (m != NULL)
+            f = GetProcAddress (m, name);
     }
-    /* no API */
-    return 0;
+
+    return f;
 }
 
-static WINAPI int _ws2_getnameinfo_bind( const struct sockaddr *sa, socklen_t salen,
-               char *host, DWORD hostlen, char *serv, DWORD servlen, int flags )
+static WSAAPI int _ws2_getnameinfo_bind( const struct sockaddr FAR * sa, socklen_t salen,
+               char FAR *host, DWORD hostlen, char FAR *serv, DWORD servlen, int flags )
 {
-    if( _ws2_find_ipv6_api() )
+    GETNAMEINFO entry = (GETNAMEINFO)ws2_find_api (TEXT("getnameinfo"));
+    if (entry != NULL)
     {
-        return ws2_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+        /* call API before replacing function pointer to avoid crash */
+        int result = entry (sa, salen, host, hostlen, serv, servlen, flags);
+        ws2_getnameinfo = entry;
+        return result;
     }
-    /* return a possible error if API is not found */
-    WSASetLastError(WSAHOST_NOT_FOUND);
-    return WSAHOST_NOT_FOUND;
+    return getnameinfo (sa, salen, host, hostlen, serv, servlen, flags);
 }
+#undef getnameinfo
+#define getnameinfo ws2_getnameinfo
 
-static WINAPI int _ws2_getaddrinfo_bind(const char *node, const char *service,
-               const struct addrinfo *hints, struct addrinfo **res)
+/* So much for using different calling conventions */
+static WSAAPI void call_freeaddrinfo (struct addrinfo *infos)
 {
-    if( _ws2_find_ipv6_api() )
-    {
-        return ws2_getaddrinfo(node, service, hints, res);
-    }
-    /* return a possible error if API is not found */
-    WSASetLastError(WSAHOST_NOT_FOUND);
-    return WSAHOST_NOT_FOUND;
+    freeaddrinfo (infos);
 }
 
-static WINAPI void _ws2_freeaddrinfo_bind( struct addrinfo *infos )
+static WSAAPI int _ws2_getaddrinfo_bind(const char FAR *node, const char FAR *service,
+               const struct addrinfo FAR *hints, struct addrinfo FAR * FAR *res)
 {
-    if( _ws2_find_ipv6_api() )
+    GETADDRINFO entry;
+    FREEADDRINFO freentry;
+
+    entry = (GETADDRINFO)ws2_find_api (TEXT("getaddrinfo"));
+    freentry = (FREEADDRINFO)ws2_find_api (TEXT("freeaddrinfo"));
+
+    if ((entry != NULL) && (freentry != NULL))
     {
-        ws2_freeaddrinfo(infos);
+        /* call API before replacing function pointer to avoid crash */
+        int result = entry (node, service, hints, res);
+        ws2_freeaddrinfo = freentry;
+        ws2_getaddrinfo = entry;
+        return result;
     }
+    ws2_freeaddrinfo = call_freeaddrinfo;
+    return getaddrinfo (node, service, hints, res);
 }
-
+#undef getaddrinfo
+#undef freeaddrinfo
+#define getaddrinfo ws2_getaddrinfo
+#define freeaddrinfo ws2_freeaddrinfo
+#define HAVE_GETADDRINFO
 #endif
 
 
@@ -567,13 +559,7 @@ int vlc_getnameinfo( const struct sockaddr *sa, int salen,
         i_servlen = 0;
     }
 
-#if defined (HAVE_GETNAMEINFO)
     i_val = getnameinfo(sa, salen, host, hostlen, psz_serv, i_servlen, flags);
-#elif defined (WIN32)
-    i_val = ws2_getnameinfo (sa, salen, host, hostlen, psz_serv, i_servlen, flags);
-#else
-    i_val = __getnameinfo (sa, salen, host, hostlen, psz_serv, i_servlen, flags);
-#endif
 
     if( portnum != NULL )
         *portnum = atoi( psz_serv );
@@ -582,7 +568,6 @@ int vlc_getnameinfo( const struct sockaddr *sa, int salen,
 }
 
 
-/* TODO: support for setting sin6_scope_id */
 int vlc_getaddrinfo( vlc_object_t *p_this, const char *node,
                      int i_port, const struct addrinfo *p_hints,
                      struct addrinfo **res )
@@ -657,13 +642,13 @@ int vlc_getaddrinfo( vlc_object_t *p_this, const char *node,
 #ifdef WIN32
     /*
      * Winsock tries to resolve numerical IPv4 addresses as AAAA
-     * and IPv6 addresses as A... There comes the work around.
+     * and IPv6 addresses as A... There comes the bug-to-bug fix.
      */
     if ((hints.ai_flags & AI_NUMERICHOST) == 0)
     {
         hints.ai_flags |= AI_NUMERICHOST;
 
-        if (ws2_getaddrinfo (psz_node, psz_service, &hints, res) == 0)
+        if (getaddrinfo (psz_node, psz_service, &hints, res) == 0)
             return 0;
 
         hints.ai_flags &= ~AI_NUMERICHOST;
@@ -689,8 +674,6 @@ int vlc_getaddrinfo( vlc_object_t *p_this, const char *node,
     }
 # endif
     return getaddrinfo (psz_node, psz_service, &hints, res);
-#elif defined (WIN32)
-    return ws2_getaddrinfo (psz_node, psz_service, &hints, res);
 #else
     int ret;
     vlc_value_t lock;
@@ -699,7 +682,7 @@ int vlc_getaddrinfo( vlc_object_t *p_this, const char *node,
     var_Get (p_this->p_libvlc, "getaddrinfo_mutex", &lock);
     vlc_mutex_lock (lock.p_address);
 
-    int ret = __getaddrinfo (psz_node, psz_service, &hints, res);
+    ret = getaddrinfo (psz_node, psz_service, &hints, res);
     vlc_mutex_unlock (lock.p_address);
     return ret;
 #endif
@@ -708,11 +691,5 @@ int vlc_getaddrinfo( vlc_object_t *p_this, const char *node,
 
 void vlc_freeaddrinfo( struct addrinfo *infos )
 {
-#if defined (HAVE_GETADDRINFO)
     freeaddrinfo (infos);
-#elif defined (WIN32)
-    ws2_freeaddrinfo (infos);
-#else
-    __freeaddrinfo( infos );
-#endif
 }