Skip to content

Commit 3ddb01d

Browse files
committed
socket-win32.cxx (acceptSocket): Change implementation to use select() to allow timeouts.
1 parent 59b3662 commit 3ddb01d

File tree

1 file changed

+33
-48
lines changed

1 file changed

+33
-48
lines changed

src/socket-win32.cxx

Lines changed: 33 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -264,78 +264,63 @@ acceptSocket(SOCKET_TYPE sock, SocketState & state)
264264

265265
SOCKET osSocket = to_os_socket (sock);
266266

267-
// Prepare event objects.
268-
269-
WSAEVENT close_ev = WSACreateEvent ();
270-
if (close_ev == WSA_INVALID_EVENT)
271-
goto error;
272-
273-
WSAEVENT accept_ev = WSACreateEvent ();
274-
if (accept_ev == WSA_INVALID_EVENT)
275-
goto error;
276-
277-
// Prime the socket to report FD_CLOSE.
278-
279-
int ret = WSAEventSelect (osSocket, close_ev, FD_CLOSE);
280-
if (ret == SOCKET_ERROR)
281-
goto error;
282-
283-
// Prime the socket to report FD_ACCEPT.
267+
// Check that the socket is ok.
284268

285-
ret = WSAEventSelect (osSocket, accept_ev, FD_ACCEPT);
269+
int val = 0;
270+
int optlen = sizeof (val);
271+
int ret = getsockopt (osSocket, SOL_SOCKET, SO_TYPE,
272+
reinterpret_cast<char *>(&val), &optlen);
286273
if (ret == SOCKET_ERROR)
287274
goto error;
288275

289-
WSAEVENT events[2] = { close_ev, accept_ev };
276+
// Now that we know the socket is working ok we can wait for
277+
// either a new connection or for a transition to bad state.
290278

291279
while (1)
292280
{
293-
DWORD wfme = WSAWaitForMultipleEvents (2, events, FALSE, WSA_INFINITE,
294-
TRUE);
295-
switch (wfme)
296-
{
297-
case WSA_WAIT_TIMEOUT:
298-
// This should not happen for WSA_INFINITE timeout.
299-
// Fall through.
281+
fd_set readSet;
282+
timeval timeout;
300283

301-
case WSA_WAIT_IO_COMPLETION:
302-
continue;
303-
304-
case WSA_WAIT_EVENT_0:
305-
WSASetLastError (ERROR_NO_DATA);
306-
goto error;
284+
FD_ZERO (&readSet);
285+
FD_SET (osSocket, &readSet);
286+
timeout.tv_sec = 0;
287+
timeout.tv_usec = 200 * 1000;
307288

308-
case WSA_WAIT_EVENT_0 + 1:
289+
int selectResponse = ::select (1, &readSet, NULL, NULL, &timeout);
290+
if (selectResponse < 0)
309291
{
310-
WSACloseEvent (close_ev);
311-
WSACloseEvent (accept_ev);
292+
DWORD const eno = WSAGetLastError ();
293+
if (eno == WSAENOTSOCK || eno == WSAEINVAL)
294+
WSASetLastError (ERROR_NO_DATA);
312295

296+
goto error;
297+
}
298+
else if (selectResponse == 0)
299+
// Timeout.
300+
continue;
301+
else if (selectResponse == 1)
302+
{
313303
SOCKET connected_socket = ::accept (osSocket, NULL, NULL);
314304

315305
if (connected_socket != INVALID_OS_SOCKET_VALUE)
316306
state = ok;
307+
else
308+
goto error;
317309

318310
return to_log4cplus_socket (connected_socket);
319311
}
320-
321-
default:
312+
else
313+
{
322314
helpers::getLogLog ().error (
323-
LOG4CPLUS_TEXT ("unexpected WSAWaitForMultipleEvents return value: ")
324-
+ helpers::convertIntegerToString (wfme));
325-
315+
LOG4CPLUS_TEXT ("unexpected select() return value: ")
316+
+ helpers::convertIntegerToString (selectResponse));
317+
WSASetLastError (ERROR_UNSUPPORTED_TYPE);
326318
goto error;
327319
}
328320
}
329321

330322
error:
331-
DWORD const eno = WSAGetLastError ();
332-
333-
if (close_ev != WSA_INVALID_EVENT)
334-
WSACloseEvent (close_ev);
335-
336-
if (accept_ev != WSA_INVALID_EVENT)
337-
WSACloseEvent (accept_ev);
338-
323+
DWORD eno = WSAGetLastError ();
339324
set_last_socket_error (eno);
340325

341326
return to_log4cplus_socket (INVALID_SOCKET);

0 commit comments

Comments
 (0)