First set of changes for windows
[cascardo/gnio.git] / gnio / gresolver.c
index af46ae9..c5ff2e7 100644 (file)
@@ -1,6 +1,6 @@
 /* GNIO - GLib Network Layer of GIO
- * 
- * Copyright (C) 2008 Christian Kellner 
+ *
+ * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -17,7 +17,8 @@
  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  * Boston, MA 02111-1307, USA.
  *
- * Author: Christian Kellner <gicmo@gnome.org>
+ * Authors: Christian Kellner <gicmo@gnome.org>
+ *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
  */
 
 #include <config.h>
 #include <gio/gio.h>
 
 #include <string.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
+#ifndef G_OS_WIN32
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+#else
+# include <winsock2.h>
+# include <winerror.h>
+# include <ws2tcpip.h>
+# undef HAVE_GETADDRINFO
+# define HAVE_GETHOSTBYNAME_THREADSAFE 1
+#endif
 #include <errno.h>
 
 #include "ginetaddress.h"
@@ -45,6 +54,126 @@ G_DEFINE_TYPE (GResolver, g_resolver, G_TYPE_OBJECT);
 G_LOCK_DEFINE (dnslock);
 #endif
 
+#ifdef G_OS_WIN32
+/* This is copied straight from giowin32.c, but its static there... */
+/* Is there another way to get this functionality? */
+static char *
+winsock_error_message (int number)
+{
+  static char unk[100];
+
+  switch (number) {
+  case WSAEINTR:
+    return "Interrupted function call";
+  case WSAEACCES:
+    return "Permission denied";
+  case WSAEFAULT:
+    return "Bad address";
+  case WSAEINVAL:
+    return "Invalid argument";
+  case WSAEMFILE:
+    return "Too many open sockets";
+  case WSAEWOULDBLOCK:
+    return "Resource temporarily unavailable";
+  case WSAEINPROGRESS:
+    return "Operation now in progress";
+  case WSAEALREADY:
+    return "Operation already in progress";
+  case WSAENOTSOCK:
+    return "Socket operation on nonsocket";
+  case WSAEDESTADDRREQ:
+    return "Destination address required";
+  case WSAEMSGSIZE:
+    return "Message too long";
+  case WSAEPROTOTYPE:
+    return "Protocol wrong type for socket";
+  case WSAENOPROTOOPT:
+    return "Bad protocol option";
+  case WSAEPROTONOSUPPORT:
+    return "Protocol not supported";
+  case WSAESOCKTNOSUPPORT:
+    return "Socket type not supported";
+  case WSAEOPNOTSUPP:
+    return "Operation not supported on transport endpoint";
+  case WSAEPFNOSUPPORT:
+    return "Protocol family not supported";
+  case WSAEAFNOSUPPORT:
+    return "Address family not supported by protocol family";
+  case WSAEADDRINUSE:
+    return "Address already in use";
+  case WSAEADDRNOTAVAIL:
+    return "Address not available";
+  case WSAENETDOWN:
+    return "Network interface is not configured";
+  case WSAENETUNREACH:
+    return "Network is unreachable";
+  case WSAENETRESET:
+    return "Network dropped connection on reset";
+  case WSAECONNABORTED:
+    return "Software caused connection abort";
+  case WSAECONNRESET:
+    return "Connection reset by peer";
+  case WSAENOBUFS:
+    return "No buffer space available";
+  case WSAEISCONN:
+    return "Socket is already connected";
+  case WSAENOTCONN:
+    return "Socket is not connected";
+  case WSAESHUTDOWN:
+    return "Can't send after socket shutdown";
+  case WSAETIMEDOUT:
+    return "Connection timed out";
+  case WSAECONNREFUSED:
+    return "Connection refused";
+  case WSAEHOSTDOWN:
+    return "Host is down";
+  case WSAEHOSTUNREACH:
+    return "Host is unreachable";
+  case WSAEPROCLIM:
+    return "Too many processes";
+  case WSASYSNOTREADY:
+    return "Network subsystem is unavailable";
+  case WSAVERNOTSUPPORTED:
+    return "Winsock.dll version out of range";
+  case WSANOTINITIALISED:
+    return "Successful WSAStartup not yet performed";
+  case WSAEDISCON:
+    return "Graceful shutdown in progress";
+  case WSATYPE_NOT_FOUND:
+    return "Class type not found";
+  case WSAHOST_NOT_FOUND:
+    return "Host not found";
+  case WSATRY_AGAIN:
+    return "Nonauthoritative host not found";
+  case WSANO_RECOVERY:
+    return "This is a nonrecoverable error";
+  case WSANO_DATA:
+    return "Valid name, no data record of requested type";
+  case WSA_INVALID_HANDLE:
+    return "Specified event object handle is invalid";
+  case WSA_INVALID_PARAMETER:
+    return "One or more parameters are invalid";
+  case WSA_IO_INCOMPLETE:
+    return "Overlapped I/O event object not in signaled state";
+  case WSA_NOT_ENOUGH_MEMORY:
+    return "Insufficient memory available";
+  case WSA_OPERATION_ABORTED:
+    return "Overlapped operation aborted";
+  case WSAEINVALIDPROCTABLE:
+    return "Invalid procedure table from service provider";
+  case WSAEINVALIDPROVIDER:
+    return "Invalid service provider version number";
+  case WSAEPROVIDERFAILEDINIT:
+    return "Unable to initialize a service provider";
+  case WSASYSCALLFAILURE:
+    return "System call failure";
+  default:
+    sprintf (unk, "Unknown WinSock error %d", number);
+    return unk;
+  }
+}
+#endif
+
 #if !defined(HAVE_GETADDRINFO)
 static GList *
 hostent2list (const struct hostent *he)
@@ -94,8 +223,12 @@ g_io_error_from_addrinfo (GError** error, int err)
 
   if (message == NULL)
     {
+#ifndef G_OS_WIN32
       /* FIXME: is gai_strerror() thread-safe? */
       message = gai_strerror (err);
+#else
+      message = winsock_error_message (WSAGetLastError ());
+#endif
     }
 
   *error = g_error_new_literal (G_IO_ERROR, code, message);
@@ -143,7 +276,10 @@ g_resolver_get_host_by_name (GResolver *resolver, const gchar *hostname, GError
     struct hostent *he = gethostbyname (hostname);
 
     if (!he)
-      g_io_error_from_errno (error);
+      {
+        if (error)
+          *error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, winsock_error_message (WSAGetLastError ()));
+      }
     else
       list = hostent2list (he);
   }
@@ -216,6 +352,9 @@ g_resolver_get_host_by_name (GResolver *resolver, const gchar *hostname, GError
   if (list)
     list = g_list_reverse (list);
 
+  if (!list && error)
+    *error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, winsock_error_message (WSAGetLastError ()));
+
   return list;
 }