From: Corinna Vinschen Date: Thu, 22 Feb 2018 15:28:14 +0000 (+0100) Subject: Cygwin: fhandler_socket: Move shutdown and close methods into derived classes X-Git-Tag: newlib-snapshot-20180226~19 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=233bde312546ee60346588803570221389fd89f2;p=newlib-cygwin.git Cygwin: fhandler_socket: Move shutdown and close methods into derived classes Signed-off-by: Corinna Vinschen --- diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 4b1d8ddaf..51a4a46da 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -580,6 +580,8 @@ class fhandler_socket: public fhandler_base virtual int connect (const struct sockaddr *name, int namelen) = 0; virtual int getsockname (struct sockaddr *name, int *namelen) = 0; virtual int getpeername (struct sockaddr *name, int *namelen) = 0; + virtual int shutdown (int how) = 0; + virtual int close () = 0; virtual int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid); virtual int setsockopt (int level, int optname, const void *optval, __socklen_t optlen) = 0; @@ -607,8 +609,6 @@ class fhandler_socket: public fhandler_base set_errno (ESPIPE); return -1; } - int shutdown (int how); - int close (); void hclose (HANDLE) {close ();} int dup (fhandler_base *child, int); @@ -654,6 +654,8 @@ class fhandler_socket_inet: public fhandler_socket int connect (const struct sockaddr *name, int namelen); int getsockname (struct sockaddr *name, int *namelen); int getpeername (struct sockaddr *name, int *namelen); + int shutdown (int how); + int close (); int setsockopt (int level, int optname, const void *optval, __socklen_t optlen); int getsockopt (int level, int optname, const void *optval, @@ -739,6 +741,8 @@ class fhandler_socket_local: public fhandler_socket int connect (const struct sockaddr *name, int namelen); int getsockname (struct sockaddr *name, int *namelen); int getpeername (struct sockaddr *name, int *namelen); + int shutdown (int how); + int close (); int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid); int setsockopt (int level, int optname, const void *optval, __socklen_t optlen); diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index aafc09c43..98c4467fa 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -720,72 +720,6 @@ fhandler_socket::link (const char *newpath) return fhandler_base::link (newpath); } -int -fhandler_socket::shutdown (int how) -{ - int res = ::shutdown (get_socket (), how); - - /* Linux allows to call shutdown for any socket, even if it's not connected. - This also disables to call accept on this socket, if shutdown has been - called with the SHUT_RD or SHUT_RDWR parameter. In contrast, WinSock - only allows to call shutdown on a connected socket. The accept function - is in no way affected. So, what we do here is to fake success, and to - change the event settings so that an FD_CLOSE event is triggered for the - calling Cygwin function. The evaluate_events method handles the call - from accept specially to generate a Linux-compatible behaviour. */ - if (res && WSAGetLastError () != WSAENOTCONN) - set_winsock_errno (); - else - { - res = 0; - switch (how) - { - case SHUT_RD: - saw_shutdown_read (true); - wsock_events->events |= FD_CLOSE; - SetEvent (wsock_evt); - break; - case SHUT_WR: - saw_shutdown_write (true); - break; - case SHUT_RDWR: - saw_shutdown_read (true); - saw_shutdown_write (true); - wsock_events->events |= FD_CLOSE; - SetEvent (wsock_evt); - break; - } - } - return res; -} - -int -fhandler_socket::close () -{ - int res = 0; - - release_events (); - while ((res = ::closesocket (get_socket ())) != 0) - { - if (WSAGetLastError () != WSAEWOULDBLOCK) - { - set_winsock_errno (); - res = -1; - break; - } - if (cygwait (10) == WAIT_SIGNALED) - { - set_errno (EINTR); - res = -1; - break; - } - WSASetLastError (0); - } - - debug_printf ("%d = fhandler_socket::close()", res); - return res; -} - /* Definitions of old ifreq stuff used prior to Cygwin 1.7.0. */ #define OLD_SIOCGIFFLAGS _IOW('s', 101, struct __old_ifreq) #define OLD_SIOCGIFADDR _IOW('s', 102, struct __old_ifreq) diff --git a/winsup/cygwin/fhandler_socket_inet.cc b/winsup/cygwin/fhandler_socket_inet.cc index 06091973f..d1808414a 100644 --- a/winsup/cygwin/fhandler_socket_inet.cc +++ b/winsup/cygwin/fhandler_socket_inet.cc @@ -88,6 +88,20 @@ get_inet_addr_inet (const struct sockaddr *in, int inlen, } } +/* There's no DLL which exports the symbol WSARecvMsg. One has to call + WSAIoctl as below to fetch the function pointer. Why on earth did the + MS developers decide not to export a normal symbol for these extension + functions? */ +inline int +get_ext_funcptr (SOCKET sock, void *funcptr) +{ + DWORD bret; + const GUID guid = WSAID_WSARECVMSG; + return WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER, + (void *) &guid, sizeof (GUID), funcptr, sizeof (void *), + &bret, NULL, NULL); +} + static int convert_ws1_ip_optname (int optname) { @@ -383,18 +397,70 @@ fhandler_socket_inet::getpeername (struct sockaddr *name, int *namelen) return res; } -/* There's no DLL which exports the symbol WSARecvMsg. One has to call - WSAIoctl as below to fetch the function pointer. Why on earth did the - MS developers decide not to export a normal symbol for these extension - functions? */ -inline int -get_ext_funcptr (SOCKET sock, void *funcptr) +int +fhandler_socket_inet::shutdown (int how) { - DWORD bret; - const GUID guid = WSAID_WSARECVMSG; - return WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER, - (void *) &guid, sizeof (GUID), funcptr, sizeof (void *), - &bret, NULL, NULL); + int res = ::shutdown (get_socket (), how); + + /* Linux allows to call shutdown for any socket, even if it's not connected. + This also disables to call accept on this socket, if shutdown has been + called with the SHUT_RD or SHUT_RDWR parameter. In contrast, WinSock + only allows to call shutdown on a connected socket. The accept function + is in no way affected. So, what we do here is to fake success, and to + change the event settings so that an FD_CLOSE event is triggered for the + calling Cygwin function. The evaluate_events method handles the call + from accept specially to generate a Linux-compatible behaviour. */ + if (res && WSAGetLastError () != WSAENOTCONN) + set_winsock_errno (); + else + { + res = 0; + switch (how) + { + case SHUT_RD: + saw_shutdown_read (true); + wsock_events->events |= FD_CLOSE; + SetEvent (wsock_evt); + break; + case SHUT_WR: + saw_shutdown_write (true); + break; + case SHUT_RDWR: + saw_shutdown_read (true); + saw_shutdown_write (true); + wsock_events->events |= FD_CLOSE; + SetEvent (wsock_evt); + break; + } + } + return res; +} + +int +fhandler_socket_inet::close () +{ + int res = 0; + + release_events (); + while ((res = ::closesocket (get_socket ())) != 0) + { + if (WSAGetLastError () != WSAEWOULDBLOCK) + { + set_winsock_errno (); + res = -1; + break; + } + if (cygwait (10) == WAIT_SIGNALED) + { + set_errno (EINTR); + res = -1; + break; + } + WSASetLastError (0); + } + + debug_printf ("%d = fhandler_socket::close()", res); + return res; } inline ssize_t diff --git a/winsup/cygwin/fhandler_socket_local.cc b/winsup/cygwin/fhandler_socket_local.cc index c5e4bfb67..4c8f3340b 100644 --- a/winsup/cygwin/fhandler_socket_local.cc +++ b/winsup/cygwin/fhandler_socket_local.cc @@ -206,6 +206,20 @@ get_inet_addr_local (const struct sockaddr *in, int inlen, return SOCKET_ERROR; } +/* There's no DLL which exports the symbol WSARecvMsg. One has to call + WSAIoctl as below to fetch the function pointer. Why on earth did the + MS developers decide not to export a normal symbol for these extension + functions? */ +inline int +get_ext_funcptr (SOCKET sock, void *funcptr) +{ + DWORD bret; + const GUID guid = WSAID_WSARECVMSG; + return WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER, + (void *) &guid, sizeof (GUID), funcptr, sizeof (void *), + &bret, NULL, NULL); +} + fhandler_socket_local::fhandler_socket_local () : fhandler_socket (), sun_path (NULL), @@ -1030,18 +1044,70 @@ fhandler_socket_local::getpeername (struct sockaddr *name, int *namelen) return res; } -/* There's no DLL which exports the symbol WSARecvMsg. One has to call - WSAIoctl as below to fetch the function pointer. Why on earth did the - MS developers decide not to export a normal symbol for these extension - functions? */ -inline int -get_ext_funcptr (SOCKET sock, void *funcptr) +int +fhandler_socket_local::shutdown (int how) { - DWORD bret; - const GUID guid = WSAID_WSARECVMSG; - return WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER, - (void *) &guid, sizeof (GUID), funcptr, sizeof (void *), - &bret, NULL, NULL); + int res = ::shutdown (get_socket (), how); + + /* Linux allows to call shutdown for any socket, even if it's not connected. + This also disables to call accept on this socket, if shutdown has been + called with the SHUT_RD or SHUT_RDWR parameter. In contrast, WinSock + only allows to call shutdown on a connected socket. The accept function + is in no way affected. So, what we do here is to fake success, and to + change the event settings so that an FD_CLOSE event is triggered for the + calling Cygwin function. The evaluate_events method handles the call + from accept specially to generate a Linux-compatible behaviour. */ + if (res && WSAGetLastError () != WSAENOTCONN) + set_winsock_errno (); + else + { + res = 0; + switch (how) + { + case SHUT_RD: + saw_shutdown_read (true); + wsock_events->events |= FD_CLOSE; + SetEvent (wsock_evt); + break; + case SHUT_WR: + saw_shutdown_write (true); + break; + case SHUT_RDWR: + saw_shutdown_read (true); + saw_shutdown_write (true); + wsock_events->events |= FD_CLOSE; + SetEvent (wsock_evt); + break; + } + } + return res; +} + +int +fhandler_socket_local::close () +{ + int res = 0; + + release_events (); + while ((res = ::closesocket (get_socket ())) != 0) + { + if (WSAGetLastError () != WSAEWOULDBLOCK) + { + set_winsock_errno (); + res = -1; + break; + } + if (cygwait (10) == WAIT_SIGNALED) + { + set_errno (EINTR); + res = -1; + break; + } + WSASetLastError (0); + } + + debug_printf ("%d = fhandler_socket::close()", res); + return res; } inline ssize_t