2003-03-27 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (class sock_event): New class managing Winsock events for interruptible socket calls. (fhandler_socket::connect): Move support for interruptible call to class sock_event. Use class object instead. (fhandler_socket::accept): Ditto. Remove useless casts. 2003-03-27 Thomas Pfaff <tpfaff@gmx.net> * fhandler_socket.cc (fhandler_socket::connect): Add support for an interruptable connect.
This commit is contained in:
parent
7d82e7bf32
commit
5777b970bb
|
@ -1,3 +1,16 @@
|
||||||
|
2003-03-27 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* fhandler_socket.cc (class sock_event): New class managing Winsock
|
||||||
|
events for interruptible socket calls.
|
||||||
|
(fhandler_socket::connect): Move support for interruptible call to
|
||||||
|
class sock_event. Use class object instead.
|
||||||
|
(fhandler_socket::accept): Ditto. Remove useless casts.
|
||||||
|
|
||||||
|
2003-03-27 Thomas Pfaff <tpfaff@gmx.net>
|
||||||
|
|
||||||
|
* fhandler_socket.cc (fhandler_socket::connect): Add support for
|
||||||
|
an interruptable connect.
|
||||||
|
|
||||||
2003-02-27 Pierre Humblet <pierre.humblet@ieee.org>
|
2003-02-27 Pierre Humblet <pierre.humblet@ieee.org>
|
||||||
|
|
||||||
* uinfo.cc (internal_getlogin): Only update user.groups.pgsid
|
* uinfo.cc (internal_getlogin): Only update user.groups.pgsid
|
||||||
|
|
|
@ -91,6 +91,73 @@ get_inet_addr (const struct sockaddr *in, int inlen,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class sock_event
|
||||||
|
{
|
||||||
|
WSAEVENT ev[2];
|
||||||
|
SOCKET evt_sock;
|
||||||
|
int evt_type_bit;
|
||||||
|
|
||||||
|
public:
|
||||||
|
sock_event ()
|
||||||
|
{
|
||||||
|
ev[0] = WSA_INVALID_EVENT;
|
||||||
|
ev[1] = signal_arrived;
|
||||||
|
}
|
||||||
|
bool load (SOCKET sock, int type_bit)
|
||||||
|
{
|
||||||
|
if ((ev[0] = WSACreateEvent ()) == WSA_INVALID_EVENT)
|
||||||
|
return false;
|
||||||
|
evt_sock = sock;
|
||||||
|
evt_type_bit = type_bit;
|
||||||
|
if (WSAEventSelect (evt_sock, ev[0], 1 << evt_type_bit))
|
||||||
|
{
|
||||||
|
WSACloseEvent (ev[0]);
|
||||||
|
ev[0] = WSA_INVALID_EVENT;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int wait ()
|
||||||
|
{
|
||||||
|
WSANETWORKEVENTS sock_event;
|
||||||
|
int wait_result = WSAWaitForMultipleEvents (2, ev, FALSE, WSA_INFINITE,
|
||||||
|
FALSE);
|
||||||
|
if (wait_result == WSA_WAIT_EVENT_0)
|
||||||
|
WSAEnumNetworkEvents (evt_sock, ev[0], &sock_event);
|
||||||
|
|
||||||
|
/* Cleanup, Revert to blocking. */
|
||||||
|
WSAEventSelect (evt_sock, ev[0], 0);
|
||||||
|
WSACloseEvent (ev[0]);
|
||||||
|
unsigned long nonblocking = 0;
|
||||||
|
ioctlsocket (evt_sock, FIONBIO, &nonblocking);
|
||||||
|
|
||||||
|
switch (wait_result)
|
||||||
|
{
|
||||||
|
case WSA_WAIT_EVENT_0:
|
||||||
|
if ((sock_event.lNetworkEvents & (1 << evt_type_bit))
|
||||||
|
&& sock_event.iErrorCode[evt_type_bit])
|
||||||
|
{
|
||||||
|
WSASetLastError (sock_event.iErrorCode[evt_type_bit]);
|
||||||
|
set_winsock_errno ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSA_WAIT_EVENT_0 + 1:
|
||||||
|
debug_printf ("signal received");
|
||||||
|
set_errno (EINTR);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case WSA_WAIT_FAILED:
|
||||||
|
default:
|
||||||
|
WSASetLastError (WSAEFAULT);
|
||||||
|
set_winsock_errno ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
/* fhandler_socket */
|
/* fhandler_socket */
|
||||||
|
|
||||||
|
@ -431,6 +498,8 @@ out:
|
||||||
int
|
int
|
||||||
fhandler_socket::connect (const struct sockaddr *name, int namelen)
|
fhandler_socket::connect (const struct sockaddr *name, int namelen)
|
||||||
{
|
{
|
||||||
|
sock_event evt;
|
||||||
|
BOOL interrupted = FALSE;
|
||||||
int res = -1;
|
int res = -1;
|
||||||
BOOL secret_check_failed = FALSE;
|
BOOL secret_check_failed = FALSE;
|
||||||
BOOL in_progress = FALSE;
|
BOOL in_progress = FALSE;
|
||||||
|
@ -440,12 +509,36 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
|
||||||
if (!get_inet_addr (name, namelen, &sin, &namelen, secret))
|
if (!get_inet_addr (name, namelen, &sin, &namelen, secret))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (!is_nonblocking () && !is_connect_pending ())
|
||||||
|
if (!evt.load (get_socket (), FD_CONNECT_BIT))
|
||||||
|
{
|
||||||
|
set_winsock_errno ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
res = ::connect (get_socket (), (sockaddr *) &sin, namelen);
|
res = ::connect (get_socket (), (sockaddr *) &sin, namelen);
|
||||||
|
|
||||||
|
if (res && !is_nonblocking () && !is_connect_pending () &&
|
||||||
|
WSAGetLastError () == WSAEWOULDBLOCK)
|
||||||
|
switch (evt.wait ())
|
||||||
|
{
|
||||||
|
case 1: /* Signal */
|
||||||
|
WSASetLastError (WSAEINPROGRESS);
|
||||||
|
interrupted = TRUE;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
res = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
res = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
/* Special handling for connect to return the correct error code
|
/* Special handling for connect to return the correct error code
|
||||||
when called on a non-blocking socket. */
|
when called on a non-blocking socket. */
|
||||||
if (is_nonblocking ())
|
if (is_nonblocking () || is_connect_pending ())
|
||||||
{
|
{
|
||||||
DWORD err = WSAGetLastError ();
|
DWORD err = WSAGetLastError ();
|
||||||
if (err == WSAEWOULDBLOCK || err == WSAEALREADY)
|
if (err == WSAEWOULDBLOCK || err == WSAEALREADY)
|
||||||
|
@ -493,6 +586,10 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
|
||||||
set_connect_state (CONNECT_PENDING);
|
set_connect_state (CONNECT_PENDING);
|
||||||
else
|
else
|
||||||
set_connect_state (CONNECTED);
|
set_connect_state (CONNECTED);
|
||||||
|
|
||||||
|
if (interrupted)
|
||||||
|
set_errno (EINTR);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,7 +608,6 @@ int
|
||||||
fhandler_socket::accept (struct sockaddr *peer, int *len)
|
fhandler_socket::accept (struct sockaddr *peer, int *len)
|
||||||
{
|
{
|
||||||
int res = -1;
|
int res = -1;
|
||||||
WSAEVENT ev[2] = { WSA_INVALID_EVENT, signal_arrived };
|
|
||||||
BOOL secret_check_failed = FALSE;
|
BOOL secret_check_failed = FALSE;
|
||||||
BOOL in_progress = FALSE;
|
BOOL in_progress = FALSE;
|
||||||
|
|
||||||
|
@ -535,65 +631,31 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
|
||||||
|
|
||||||
if (!is_nonblocking ())
|
if (!is_nonblocking ())
|
||||||
{
|
{
|
||||||
ev[0] = WSACreateEvent ();
|
sock_event evt;
|
||||||
|
if (!evt.load (get_socket (), FD_ACCEPT_BIT))
|
||||||
if (ev[0] != WSA_INVALID_EVENT &&
|
{
|
||||||
!WSAEventSelect (get_socket (), ev[0], FD_ACCEPT))
|
set_winsock_errno ();
|
||||||
{
|
return -1;
|
||||||
WSANETWORKEVENTS sock_event;
|
}
|
||||||
int wait_result;
|
switch (evt.wait ())
|
||||||
|
{
|
||||||
wait_result = WSAWaitForMultipleEvents (2, ev, FALSE, WSA_INFINITE,
|
case 1: /* Signal */
|
||||||
FALSE);
|
return -1;
|
||||||
if (wait_result == WSA_WAIT_EVENT_0)
|
case 0:
|
||||||
WSAEnumNetworkEvents (get_socket (), ev[0], &sock_event);
|
break;
|
||||||
|
case -1:
|
||||||
/* Unset events for listening socket and
|
return -1;
|
||||||
switch back to blocking mode */
|
|
||||||
WSAEventSelect (get_socket (), ev[0], 0);
|
|
||||||
unsigned long nonblocking = 0;
|
|
||||||
ioctlsocket (get_socket (), FIONBIO, &nonblocking);
|
|
||||||
|
|
||||||
switch (wait_result)
|
|
||||||
{
|
|
||||||
case WSA_WAIT_EVENT_0:
|
|
||||||
if (sock_event.lNetworkEvents & FD_ACCEPT)
|
|
||||||
{
|
|
||||||
if (sock_event.iErrorCode[FD_ACCEPT_BIT])
|
|
||||||
{
|
|
||||||
WSASetLastError (sock_event.iErrorCode[FD_ACCEPT_BIT]);
|
|
||||||
set_winsock_errno ();
|
|
||||||
res = -1;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* else; : Should never happen since FD_ACCEPT is the only event
|
|
||||||
that has been selected */
|
|
||||||
break;
|
|
||||||
case WSA_WAIT_EVENT_0 + 1:
|
|
||||||
debug_printf ("signal received during accept");
|
|
||||||
set_errno (EINTR);
|
|
||||||
res = -1;
|
|
||||||
goto done;
|
|
||||||
case WSA_WAIT_FAILED:
|
|
||||||
default: /* Should never happen */
|
|
||||||
WSASetLastError (WSAEFAULT);
|
|
||||||
set_winsock_errno ();
|
|
||||||
res = -1;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res = ::accept (get_socket (), peer, len);
|
res = ::accept (get_socket (), peer, len);
|
||||||
|
|
||||||
if ((SOCKET) res == (SOCKET) INVALID_SOCKET &&
|
if ((SOCKET) res == INVALID_SOCKET && WSAGetLastError () == WSAEWOULDBLOCK)
|
||||||
WSAGetLastError () == WSAEWOULDBLOCK)
|
|
||||||
in_progress = TRUE;
|
in_progress = TRUE;
|
||||||
|
|
||||||
if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
|
if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
|
||||||
{
|
{
|
||||||
if ((SOCKET) res != (SOCKET) INVALID_SOCKET || in_progress)
|
if ((SOCKET) res != INVALID_SOCKET || in_progress)
|
||||||
{
|
{
|
||||||
if (!create_secret_event ())
|
if (!create_secret_event ())
|
||||||
secret_check_failed = TRUE;
|
secret_check_failed = TRUE;
|
||||||
|
@ -602,7 +664,7 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!secret_check_failed &&
|
if (!secret_check_failed &&
|
||||||
(SOCKET) res != (SOCKET) INVALID_SOCKET)
|
(SOCKET) res != INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
if (!check_peer_secret_event ((struct sockaddr_in*) peer))
|
if (!check_peer_secret_event ((struct sockaddr_in*) peer))
|
||||||
{
|
{
|
||||||
|
@ -614,15 +676,14 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
|
||||||
if (secret_check_failed)
|
if (secret_check_failed)
|
||||||
{
|
{
|
||||||
close_secret_event ();
|
close_secret_event ();
|
||||||
if ((SOCKET) res != (SOCKET) INVALID_SOCKET)
|
if ((SOCKET) res != INVALID_SOCKET)
|
||||||
closesocket (res);
|
closesocket (res);
|
||||||
set_errno (ECONNABORTED);
|
set_errno (ECONNABORTED);
|
||||||
res = -1;
|
return -1;
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((SOCKET) res == (SOCKET) INVALID_SOCKET)
|
if ((SOCKET) res == INVALID_SOCKET)
|
||||||
set_winsock_errno ();
|
set_winsock_errno ();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -646,10 +707,6 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
|
||||||
if (ev[0] != WSA_INVALID_EVENT)
|
|
||||||
WSACloseEvent (ev[0]);
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue