X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fsockets.c;h=42b8f9ea58e19b1ef06d4c8e66e55c2b998f9a10;hb=83b1d6414af952ac03022bf956d84a21f6132d0e;hp=9d5c54792888eca80025f9123d2c1db7fa4fa52b;hpb=d9576a558fefb2660292e7d4baccd23ea67ecf47;p=gnulib.git diff --git a/lib/sockets.c b/lib/sockets.c index 9d5c54792..42b8f9ea5 100644 --- a/lib/sockets.c +++ b/lib/sockets.c @@ -1,6 +1,6 @@ /* sockets.c --- wrappers for Windows socket functions - Copyright (C) 2008-2009 Free Software Foundation, Inc. + Copyright (C) 2008-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,15 +25,17 @@ #if WINDOWS_SOCKETS /* This includes winsock2.h on MinGW. */ -#include +# include -#include "close-hook.h" +# include "fd-hook.h" /* Get set_winsock_errno, FD_TO_SOCKET etc. */ -#include "w32sock.h" +# include "w32sock.h" static int -close_fd_maybe_socket (int fd, const struct close_hook *remaining_list) +close_fd_maybe_socket (const struct fd_hook *remaining_list, + gl_close_fn primary, + int fd) { SOCKET sock; WSANETWORKEVENTS ev; @@ -46,46 +48,83 @@ close_fd_maybe_socket (int fd, const struct close_hook *remaining_list) { /* fd refers to a socket. */ /* FIXME: other applications, like squid, use an undocumented - _free_osfhnd free function. But this is not enough: The 'osfile' - flags for fd also needs to be cleared, but it is hard to access it. - Instead, here we just close twice the file descriptor. */ + _free_osfhnd free function. But this is not enough: The 'osfile' + flags for fd also needs to be cleared, but it is hard to access it. + Instead, here we just close twice the file descriptor. */ if (closesocket (sock)) - { - set_winsock_errno (); - return -1; - } + { + set_winsock_errno (); + return -1; + } else - { - /* This call frees the file descriptor and does a - CloseHandle ((HANDLE) _get_osfhandle (fd)), which fails. */ - _close (fd); - return 0; - } + { + /* This call frees the file descriptor and does a + CloseHandle ((HANDLE) _get_osfhandle (fd)), which fails. */ + _close (fd); + return 0; + } } else /* Some other type of file descriptor. */ - return execute_close_hooks (fd, remaining_list); + return execute_close_hooks (remaining_list, primary, fd); } -static struct close_hook close_sockets_hook; +static int +ioctl_fd_maybe_socket (const struct fd_hook *remaining_list, + gl_ioctl_fn primary, + int fd, int request, void *arg) +{ + SOCKET sock; + WSANETWORKEVENTS ev; -#endif + /* Test whether fd refers to a socket. */ + sock = FD_TO_SOCKET (fd); + ev.lNetworkEvents = 0xDEADBEEF; + WSAEnumNetworkEvents (sock, NULL, &ev); + if (ev.lNetworkEvents != 0xDEADBEEF) + { + /* fd refers to a socket. */ + if (ioctlsocket (sock, request, arg) < 0) + { + set_winsock_errno (); + return -1; + } + else + return 0; + } + else + /* Some other type of file descriptor. */ + return execute_ioctl_hooks (remaining_list, primary, fd, request, arg); +} + +static struct fd_hook fd_sockets_hook; + +static int initialized_sockets_version /* = 0 */; + +#endif /* WINDOWS_SOCKETS */ int -gl_sockets_startup (int version) +gl_sockets_startup (int version _GL_UNUSED) { #if WINDOWS_SOCKETS - WSADATA data; - int err; + if (version > initialized_sockets_version) + { + WSADATA data; + int err; - err = WSAStartup (version, &data); - if (err != 0) - return 1; + err = WSAStartup (version, &data); + if (err != 0) + return 1; - if (data.wVersion < version) - return 2; + if (data.wVersion < version) + return 2; - register_close_hook (close_fd_maybe_socket, &close_sockets_hook); + if (initialized_sockets_version == 0) + register_fd_hook (close_fd_maybe_socket, ioctl_fd_maybe_socket, + &fd_sockets_hook); + + initialized_sockets_version = version; + } #endif return 0; @@ -97,7 +136,9 @@ gl_sockets_cleanup (void) #if WINDOWS_SOCKETS int err; - unregister_close_hook (&close_sockets_hook); + initialized_sockets_version = 0; + + unregister_fd_hook (&fd_sockets_hook); err = WSACleanup (); if (err != 0)