Skip to content

Commit

Permalink
sockfilt.c: fixed and simplified Windows select function
Browse files Browse the repository at this point in the history
Since the previous complex select function with initial support for
non-socket file descriptors, did not actually work correctly for
Console handles, this change simplifies the whole procedure by using
an internal waiting thread for the stdin console handle.

The previous implementation made it continuously trigger for the stdin
handle if it was being redirected to a parent process instead of
an actual Console input window.

This approach supports actual Console input handles as well as
anonymous Pipe handles which are used during input redirection.

It depends on the fact that ReadFile supports trying to read zero bytes
which makes it wait for the handle to become ready for reading.
  • Loading branch information
mback2k committed Jan 25, 2014
1 parent f55f8d4 commit 49b63cf
Showing 1 changed file with 21 additions and 46 deletions.
67 changes: 21 additions & 46 deletions tests/server/sockfilt.c
Expand Up @@ -92,9 +92,6 @@
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef USE_WINSOCK
#include <conio.h> /* for _kbhit() used in select_ws() */
#endif

#define ENABLE_CURLX_PRINTF
/* make the curlx header define all printf() functions to use the curlx_*
Expand Down Expand Up @@ -514,16 +511,29 @@ static void lograw(unsigned char *buffer, ssize_t len)
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms687028.aspx
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms741572.aspx
*/
DWORD WINAPI select_ws_stdin_wait_thread(LPVOID lpParameter)
{
HANDLE handle;
DWORD mode;

handle = (HANDLE) lpParameter;

if(GetConsoleMode(handle, &mode))
WaitForSingleObjectEx(handle, INFINITE, FALSE);
else
ReadFile(handle, NULL, 0, &mode, NULL);

return 0;
}
static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout)
{
long networkevents;
DWORD milliseconds, wait, idx, mode, avail, events, inputs;
DWORD milliseconds, wait, idx, mode;
WSAEVENT wsaevent, *wsaevents;
WSANETWORKEVENTS wsanetevents;
INPUT_RECORD *inputrecords;
HANDLE handle, *handles;
curl_socket_t sock, *fdarr, *wsasocks;
long networkevents;
int error, fds;
DWORD nfd = 0, wsa = 0;
int ret = 0;
Expand Down Expand Up @@ -586,7 +596,10 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
if(networkevents) {
fdarr[nfd] = curlx_sitosk(fds);
if(fds == fileno(stdin)) {
handles[nfd] = GetStdHandle(STD_INPUT_HANDLE);
handles[nfd] = CreateThread(NULL, 0,
&select_ws_stdin_wait_thread,
GetStdHandle(STD_INPUT_HANDLE),
0, NULL);
}
else if(fds == fileno(stdout)) {
handles[nfd] = GetStdHandle(STD_OUTPUT_HANDLE);
Expand Down Expand Up @@ -634,46 +647,8 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
/* check if the current internal handle was triggered */
if(wait != WAIT_FAILED && (wait - WAIT_OBJECT_0) <= idx &&
WaitForSingleObjectEx(handle, 0, FALSE) == WAIT_OBJECT_0) {
/* try to handle the event with STD* handle functions */
/* first handle stdin, stdout and stderr */
if(fds == fileno(stdin)) {
/* check if there is no data in the input buffer */
if(!stdin->_cnt) {
/* check if we are getting data from a PIPE */
if(!GetConsoleMode(handle, &mode)) {
/* check if there is no data from PIPE input */
if(!PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL))
avail = 0;
if(!avail) {
FD_CLR(sock, readfds);
/* reduce CPU load */
Sleep(10);
}
} /* check if there is no data from keyboard input */
else if (!_kbhit()) {
/* check if there are INPUT_RECORDs in the input buffer */
if(GetNumberOfConsoleInputEvents(handle, &events)) {
if(events > 0) {
/* remove INPUT_RECORDs from the input buffer */
inputrecords = (INPUT_RECORD*)malloc(events *
sizeof(INPUT_RECORD));
if(inputrecords) {
if(!ReadConsoleInput(handle, inputrecords,
events, &inputs))
inputs = 0;
free(inputrecords);
}

/* check if we got all inputs, otherwise clear buffer */
if(events != inputs)
FlushConsoleInputBuffer(handle);
}
}

/* remove from descriptor set since there is no real data */
FD_CLR(sock, readfds);
}
}

/* stdin is never ready for write or exceptional */
FD_CLR(sock, writefds);
FD_CLR(sock, exceptfds);
Expand Down

0 comments on commit 49b63cf

Please sign in to comment.