Cygwin: fhandler_socket: Move shutdown and close methods into derived classes
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
84c5e0fd3d
commit
233bde3125
@ -580,6 +580,8 @@ class fhandler_socket: public fhandler_base
|
|||||||
virtual int connect (const struct sockaddr *name, int namelen) = 0;
|
virtual int connect (const struct sockaddr *name, int namelen) = 0;
|
||||||
virtual int getsockname (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 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 getpeereid (pid_t *pid, uid_t *euid, gid_t *egid);
|
||||||
virtual int setsockopt (int level, int optname, const void *optval,
|
virtual int setsockopt (int level, int optname, const void *optval,
|
||||||
__socklen_t optlen) = 0;
|
__socklen_t optlen) = 0;
|
||||||
@ -607,8 +609,6 @@ class fhandler_socket: public fhandler_base
|
|||||||
set_errno (ESPIPE);
|
set_errno (ESPIPE);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int shutdown (int how);
|
|
||||||
int close ();
|
|
||||||
void hclose (HANDLE) {close ();}
|
void hclose (HANDLE) {close ();}
|
||||||
int dup (fhandler_base *child, int);
|
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 connect (const struct sockaddr *name, int namelen);
|
||||||
int getsockname (struct sockaddr *name, int *namelen);
|
int getsockname (struct sockaddr *name, int *namelen);
|
||||||
int getpeername (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,
|
int setsockopt (int level, int optname, const void *optval,
|
||||||
__socklen_t optlen);
|
__socklen_t optlen);
|
||||||
int getsockopt (int level, int optname, const void *optval,
|
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 connect (const struct sockaddr *name, int namelen);
|
||||||
int getsockname (struct sockaddr *name, int *namelen);
|
int getsockname (struct sockaddr *name, int *namelen);
|
||||||
int getpeername (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 getpeereid (pid_t *pid, uid_t *euid, gid_t *egid);
|
||||||
int setsockopt (int level, int optname, const void *optval,
|
int setsockopt (int level, int optname, const void *optval,
|
||||||
__socklen_t optlen);
|
__socklen_t optlen);
|
||||||
|
@ -720,72 +720,6 @@ fhandler_socket::link (const char *newpath)
|
|||||||
return fhandler_base::link (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. */
|
/* Definitions of old ifreq stuff used prior to Cygwin 1.7.0. */
|
||||||
#define OLD_SIOCGIFFLAGS _IOW('s', 101, struct __old_ifreq)
|
#define OLD_SIOCGIFFLAGS _IOW('s', 101, struct __old_ifreq)
|
||||||
#define OLD_SIOCGIFADDR _IOW('s', 102, struct __old_ifreq)
|
#define OLD_SIOCGIFADDR _IOW('s', 102, struct __old_ifreq)
|
||||||
|
@ -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
|
static int
|
||||||
convert_ws1_ip_optname (int optname)
|
convert_ws1_ip_optname (int optname)
|
||||||
{
|
{
|
||||||
@ -383,18 +397,70 @@ fhandler_socket_inet::getpeername (struct sockaddr *name, int *namelen)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* There's no DLL which exports the symbol WSARecvMsg. One has to call
|
int
|
||||||
WSAIoctl as below to fetch the function pointer. Why on earth did the
|
fhandler_socket_inet::shutdown (int how)
|
||||||
MS developers decide not to export a normal symbol for these extension
|
|
||||||
functions? */
|
|
||||||
inline int
|
|
||||||
get_ext_funcptr (SOCKET sock, void *funcptr)
|
|
||||||
{
|
{
|
||||||
DWORD bret;
|
int res = ::shutdown (get_socket (), how);
|
||||||
const GUID guid = WSAID_WSARECVMSG;
|
|
||||||
return WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
|
/* Linux allows to call shutdown for any socket, even if it's not connected.
|
||||||
(void *) &guid, sizeof (GUID), funcptr, sizeof (void *),
|
This also disables to call accept on this socket, if shutdown has been
|
||||||
&bret, NULL, NULL);
|
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
|
inline ssize_t
|
||||||
|
@ -206,6 +206,20 @@ get_inet_addr_local (const struct sockaddr *in, int inlen,
|
|||||||
return SOCKET_ERROR;
|
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_local::fhandler_socket_local () :
|
||||||
fhandler_socket (),
|
fhandler_socket (),
|
||||||
sun_path (NULL),
|
sun_path (NULL),
|
||||||
@ -1030,18 +1044,70 @@ fhandler_socket_local::getpeername (struct sockaddr *name, int *namelen)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* There's no DLL which exports the symbol WSARecvMsg. One has to call
|
int
|
||||||
WSAIoctl as below to fetch the function pointer. Why on earth did the
|
fhandler_socket_local::shutdown (int how)
|
||||||
MS developers decide not to export a normal symbol for these extension
|
|
||||||
functions? */
|
|
||||||
inline int
|
|
||||||
get_ext_funcptr (SOCKET sock, void *funcptr)
|
|
||||||
{
|
{
|
||||||
DWORD bret;
|
int res = ::shutdown (get_socket (), how);
|
||||||
const GUID guid = WSAID_WSARECVMSG;
|
|
||||||
return WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
|
/* Linux allows to call shutdown for any socket, even if it's not connected.
|
||||||
(void *) &guid, sizeof (GUID), funcptr, sizeof (void *),
|
This also disables to call accept on this socket, if shutdown has been
|
||||||
&bret, NULL, NULL);
|
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
|
inline ssize_t
|
||||||
|
Loading…
x
Reference in New Issue
Block a user