This is the mail archive of the
cygwin-cvs@cygwin.com
mailing list for the Cygwin project.
[newlib-cygwin] Cygwin: fhandler_socket: Move shutdown and close methods into derived classes
- From: Corinna Vinschen <corinna at sourceware dot org>
- To: cygwin-cvs at sourceware dot org
- Date: 22 Feb 2018 16:00:56 -0000
- Subject: [newlib-cygwin] Cygwin: fhandler_socket: Move shutdown and close methods into derived classes
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=233bde312546ee60346588803570221389fd89f2
commit 233bde312546ee60346588803570221389fd89f2
Author: Corinna Vinschen <corinna@vinschen.de>
Date: Thu Feb 22 16:28:14 2018 +0100
Cygwin: fhandler_socket: Move shutdown and close methods into derived classes
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diff:
---
winsup/cygwin/fhandler.h | 8 +++-
winsup/cygwin/fhandler_socket.cc | 66 -------------------------
winsup/cygwin/fhandler_socket_inet.cc | 88 +++++++++++++++++++++++++++++-----
winsup/cygwin/fhandler_socket_local.cc | 88 +++++++++++++++++++++++++++++-----
4 files changed, 160 insertions(+), 90 deletions(-)
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 4b1d8dd..51a4a46 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 aafc09c..98c4467 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 0609197..d180841 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 c5e4bfb..4c8f334 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