/* 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
* 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"
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)
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);
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);
}
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;
}