/* fhandler_socket */
fhandler_socket::fhandler_socket ()
- : fhandler_base (), sun_path (NULL), has_been_closed (0)
+ : fhandler_base (), sun_path (NULL)
{
set_need_fork_fixup ();
prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF,
fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
struct sockaddr *from, int *fromlen)
{
- int res = SOCKET_ERROR;
+ int res;
DWORD ret;
flags &= MSG_WINMASK;
{
WSABUF wsabuf = { len, (char *) ptr };
- if (is_nonblocking () || has_been_closed)
- res = WSARecvFrom (get_socket (), &wsabuf, 1, (ret = 0, &ret),
- (DWORD *) &flags, from, fromlen, NULL, NULL);
+ if (is_nonblocking ())
+ res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *) &flags,
+ from, fromlen,
+ NULL, NULL);
else
{
wsock_event wsock_evt;
- long evt = (FD_CLOSE | ((flags & MSG_OOB) ? FD_OOB : FD_READ));
- if (wsock_evt.prepare (get_socket (), evt))
- {
- do
- {
- res = WSARecvFrom (get_socket (), &wsabuf, 1,
- (ret = 0, &ret), (DWORD *) &flags,
- from, fromlen, NULL, NULL);
- }
- while (res == SOCKET_ERROR
- && WSAGetLastError () == WSAEWOULDBLOCK
- && !has_been_closed
- && !(res = wsock_evt.wait (get_socket (),
- has_been_closed)));
- wsock_evt.release (get_socket ());
- }
+ res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *) &flags,
+ from, fromlen,
+ wsock_evt.prepare (), NULL);
+
+ if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
+ ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
}
}
struct sockaddr *from = (struct sockaddr *) msg->msg_name;
int *fromlen = from ? &msg->msg_namelen : NULL;
- int res = SOCKET_ERROR;
+ int res;
if (!winsock2_active)
{
DWORD ret;
- if (is_nonblocking () || has_been_closed)
+ if (is_nonblocking ())
res = WSARecvFrom (get_socket (),
- wsabuf, iovcnt, (ret = 0, &ret), (DWORD *) &flags,
- from, fromlen, NULL, NULL);
+ wsabuf, iovcnt, &ret, (DWORD *) &flags,
+ from, fromlen,
+ NULL, NULL);
else
{
wsock_event wsock_evt;
- long evt = (FD_CLOSE | ((flags & MSG_OOB) ? FD_OOB : FD_READ));
- if (wsock_evt.prepare (get_socket (), evt))
- {
- do
- {
- res = WSARecvFrom (get_socket (), wsabuf, iovcnt,
- (ret = 0, &ret), (DWORD *) &flags,
- from, fromlen, NULL, NULL);
- }
- while (res == SOCKET_ERROR
- && WSAGetLastError () == WSAEWOULDBLOCK
- && !has_been_closed
- && !(res = wsock_evt.wait (get_socket (),
- has_been_closed)));
- wsock_evt.release (get_socket ());
- }
+ res = WSARecvFrom (get_socket (),
+ wsabuf, iovcnt, &ret, (DWORD *) &flags,
+ from, fromlen,
+ wsock_evt.prepare (), NULL);
+
+ if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
+ ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
}
if (res == SOCKET_ERROR)
sockaddr_in sin;
if (to && !get_inet_addr (to, tolen, &sin, &tolen))
- return -1;
+ return SOCKET_ERROR;
- int res = SOCKET_ERROR;
+ int res;
DWORD ret;
if (!winsock2_active)
{
WSABUF wsabuf = { len, (char *) ptr };
- if (is_nonblocking () || has_been_closed)
- res = WSASendTo (get_socket (), &wsabuf, 1, (ret = 0, &ret),
+ if (is_nonblocking ())
+ res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
flags & MSG_WINMASK,
(to ? (const struct sockaddr *) &sin : NULL), tolen,
NULL, NULL);
else
{
wsock_event wsock_evt;
- if (wsock_evt.prepare (get_socket (), FD_CLOSE | FD_WRITE))
- {
- do
- {
- res = WSASendTo (get_socket (), &wsabuf, 1, (ret = 0, &ret),
- flags & MSG_WINMASK,
- (to ? (const struct sockaddr *) &sin : NULL),
- tolen, NULL, NULL);
- if (res != SOCKET_ERROR
- || WSAGetLastError () != WSAEWOULDBLOCK)
- break;
- if (ret > 0)
- {
- res = 0;
- break;
- }
- }
- while (!(res = wsock_evt.wait (get_socket (), has_been_closed))
- && !has_been_closed);
- wsock_evt.release (get_socket ());
- }
+ res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
+ flags & MSG_WINMASK,
+ (to ? (const struct sockaddr *) &sin : NULL), tolen,
+ wsock_evt.prepare (), NULL);
+
+ if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
+ ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
}
}
struct iovec *const iov = msg->msg_iov;
const int iovcnt = msg->msg_iovlen;
- int res = SOCKET_ERROR;
+ int res;
if (!winsock2_active)
{
DWORD ret;
- if (is_nonblocking () || has_been_closed)
- res = WSASendTo (get_socket (), wsabuf, iovcnt, (ret = 0, &ret),
- flags, (struct sockaddr *) msg->msg_name,
- msg->msg_namelen, NULL, NULL);
+ if (is_nonblocking ())
+ res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret, flags,
+ (struct sockaddr *) msg->msg_name,
+ msg->msg_namelen,
+ NULL, NULL);
else
{
wsock_event wsock_evt;
- if (wsock_evt.prepare (get_socket (), FD_CLOSE | FD_WRITE))
- {
- do
- {
- res = WSASendTo (get_socket (), wsabuf, iovcnt,
- (ret = 0, &ret), flags,
- (struct sockaddr *) msg->msg_name,
- msg->msg_namelen, NULL, NULL);
- if (res != SOCKET_ERROR
- || WSAGetLastError () != WSAEWOULDBLOCK)
- break;
- if (ret > 0)
- {
- res = 0;
- break;
- }
- }
- while (!(res = wsock_evt.wait (get_socket (), has_been_closed))
- && !has_been_closed);
- wsock_evt.release (get_socket ());
- }
+ res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret, flags,
+ (struct sockaddr *) msg->msg_name,
+ msg->msg_namelen,
+ wsock_evt.prepare (), NULL);
+
+ if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
+ ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
}
if (res == SOCKET_ERROR)
int sscanf (const char *, const char *, ...);
} /* End of "C" section */
-bool
-wsock_event::prepare (int sock, long event_mask)
+LPWSAOVERLAPPED
+wsock_event::prepare ()
{
- WSASetLastError (0);
- if ((event = WSACreateEvent ()) == WSA_INVALID_EVENT)
- debug_printf ("WSACreateEvent: %E");
- else if (WSAEventSelect (sock, event, event_mask) == SOCKET_ERROR)
+ LPWSAOVERLAPPED ret = NULL;
+
+ SetLastError (0);
+ if ((event = WSACreateEvent ()) != WSA_INVALID_EVENT)
{
- debug_printf ("WSAEventSelect: %E");
- WSACloseEvent (event);
- event = WSA_INVALID_EVENT;
+ memset (&ovr, 0, sizeof ovr);
+ ovr.hEvent = event;
+ ret = &ovr;
}
- return event != WSA_INVALID_EVENT;
+ else if (GetLastError () == ERROR_PROC_NOT_FOUND) /* winsock2 not available */
+ WSASetLastError (0);
+
+ debug_printf ("%d = wsock_event::prepare ()", ret);
+ return ret;
}
int
-wsock_event::wait (int sock, int &closed)
+wsock_event::wait (int socket, LPDWORD flags)
{
int ret = SOCKET_ERROR;
- int wsa_err = 0;
WSAEVENT ev[2] = { event, signal_arrived };
+ DWORD len;
+
switch (WSAWaitForMultipleEvents (2, ev, FALSE, WSA_INFINITE, FALSE))
{
case WSA_WAIT_EVENT_0:
- WSANETWORKEVENTS evts;
- if (!WSAEnumNetworkEvents (sock, event, &evts))
+ if (WSAGetOverlappedResult (socket, &ovr, &len, FALSE, flags))
+ ret = (int) len;
+ break;
+ case WSA_WAIT_EVENT_0 + 1:
+ if (!CancelIo ((HANDLE) socket))
{
- if (evts.lNetworkEvents & FD_READ)
- {
- if (evts.iErrorCode[FD_READ_BIT])
- wsa_err = evts.iErrorCode[FD_READ_BIT];
- else
- ret = 0;
- }
- else if (evts.lNetworkEvents & FD_WRITE)
- {
- if (evts.iErrorCode[FD_WRITE_BIT])
- wsa_err = evts.iErrorCode[FD_WRITE_BIT];
- else
- ret = 0;
- }
- if (evts.lNetworkEvents & FD_CLOSE)
- {
- closed = 1;
- if (!wsa_err)
- {
- if (evts.iErrorCode[FD_CLOSE_BIT])
- wsa_err = evts.iErrorCode[FD_CLOSE_BIT];
- else
- ret = 0;
- }
- }
- if (wsa_err)
- WSASetLastError (wsa_err);
+ debug_printf ("CancelIo() %E, fallback to blocking io");
+ WSAGetOverlappedResult (socket, &ovr, &len, TRUE, flags);
}
+ else if (WSAGetOverlappedResult (socket, &ovr, &len, FALSE, flags)
+ && len > 0)
+ ret = (int) len;
+ else
+ WSASetLastError (WSAEINTR);
break;
- case WSA_WAIT_EVENT_0 + 1:
- WSASetLastError (WSAEINTR);
+ case WSA_WAIT_FAILED:
break;
- default:
+ default: /* Should be impossible. *LOL* */
WSASetLastError (WSAEFAULT);
+ break;
}
- return ret;
-}
-
-void
-wsock_event::release (int sock)
-{
- int last_err = WSAGetLastError ();
- /* KB 168349: NT4 fails if the event parameter is not NULL. */
- WSAEventSelect (sock, NULL, 0);
WSACloseEvent (event);
- unsigned long non_block = 0;
- if (ioctlsocket (sock, FIONBIO, &non_block))
- debug_printf ("return to blocking failed: %d", WSAGetLastError ());
- else
- WSASetLastError (last_err);
+ event = NULL;
+ return ret;
}
WSADATA wsadata;