socklift.c: Added select_ws function to support Windows
WinSock select() does not support standard file descriptors, it can only check SOCKETs. The following function is an attempt to create a select() function with support for other handles.
This commit is contained in:
parent
d335aa2cdc
commit
a662f86f6f
@ -399,6 +399,146 @@ static void lograw(unsigned char *buffer, ssize_t len)
|
|||||||
logmsg("'%s'", data);
|
logmsg("'%s'", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WinSock select() does not support standard file descriptors,
|
||||||
|
* it can only check SOCKETs. The following function is an attempt
|
||||||
|
* to re-create a select() function with support for other handle types.
|
||||||
|
*/
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
/*
|
||||||
|
* select() function with support for WINSOCK2 sockets and all
|
||||||
|
* other handle types supported by WaitForMultipleObjectsEx().
|
||||||
|
*
|
||||||
|
* TODO: Differentiate between read/write/except for non-SOCKET handles.
|
||||||
|
*
|
||||||
|
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms687028.aspx
|
||||||
|
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms741572.aspx
|
||||||
|
*/
|
||||||
|
static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
|
||||||
|
fd_set *exceptfds, struct timeval *timeout)
|
||||||
|
{
|
||||||
|
int ret = 0, fds = 0, nfd = 0, idx = 0, wsa = 0, error = 0;
|
||||||
|
long networkevents;
|
||||||
|
DWORD milliseconds, wait;
|
||||||
|
WSAEVENT wsaevent, *wsaevents;
|
||||||
|
WSANETWORKEVENTS wsanetevents;
|
||||||
|
HANDLE *handles;
|
||||||
|
int *fdarr;
|
||||||
|
|
||||||
|
/* allocate internal array for the original input handles */
|
||||||
|
fdarr = malloc(sizeof(int)*nfds);
|
||||||
|
if(fdarr == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate internal array for the internal event handles */
|
||||||
|
handles = malloc(sizeof(HANDLE)*nfds);
|
||||||
|
if(handles == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate internal array for the internal WINSOCK2 events */
|
||||||
|
wsaevents = malloc(sizeof(WSAEVENT)*nfds);
|
||||||
|
if(wsaevents == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* loop over the handles in the input descriptor sets */
|
||||||
|
for(fds = 0; fds < nfds; fds++) {
|
||||||
|
networkevents = 0;
|
||||||
|
handles[nfd] = 0;
|
||||||
|
|
||||||
|
if(FD_ISSET(fds, readfds))
|
||||||
|
networkevents |= FD_READ;
|
||||||
|
|
||||||
|
if(FD_ISSET(fds, writefds))
|
||||||
|
networkevents |= FD_WRITE;
|
||||||
|
|
||||||
|
if(FD_ISSET(fds, exceptfds))
|
||||||
|
networkevents |= FD_CLOSE;
|
||||||
|
|
||||||
|
if(networkevents) {
|
||||||
|
fdarr[nfd] = fds;
|
||||||
|
if(fds == fileno(stdin)) {
|
||||||
|
handles[nfd] = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
}
|
||||||
|
else if(fds == fileno(stdout)) {
|
||||||
|
handles[nfd] = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
}
|
||||||
|
else if(fds == fileno(stderr)) {
|
||||||
|
handles[nfd] = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wsaevent = WSACreateEvent();
|
||||||
|
if(wsaevent != WSA_INVALID_EVENT) {
|
||||||
|
error = WSAEventSelect(fds, wsaevent, networkevents);
|
||||||
|
if(error != SOCKET_ERROR) {
|
||||||
|
handles[nfd] = wsaevent;
|
||||||
|
wsaevents[wsa++] = wsaevent;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handles[nfd] = (HANDLE) fds;
|
||||||
|
WSACloseEvent(wsaevent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nfd++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert struct timeval to milliseconds */
|
||||||
|
if(timeout) {
|
||||||
|
milliseconds = ((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
milliseconds = INFINITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait for one of the internal handles to trigger */
|
||||||
|
wait = WaitForMultipleObjectsEx(nfd, handles, FALSE, milliseconds, FALSE);
|
||||||
|
|
||||||
|
/* loop over the internal handles returned in the descriptors */
|
||||||
|
for(idx = 0; idx < nfd; idx++) {
|
||||||
|
if(wait != WAIT_OBJECT_0 + idx) {
|
||||||
|
/* remove from all descriptor sets since this handle did not trigger */
|
||||||
|
FD_CLR(fdarr[idx], readfds);
|
||||||
|
FD_CLR(fdarr[idx], writefds);
|
||||||
|
FD_CLR(fdarr[idx], exceptfds);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* first try to handle the event with the WINSOCK2 functions */
|
||||||
|
error = WSAEnumNetworkEvents(fdarr[idx], NULL, &wsanetevents);
|
||||||
|
if(error != SOCKET_ERROR) {
|
||||||
|
/* remove from descriptor set if not ready for read */
|
||||||
|
if(!(wsanetevents.lNetworkEvents & FD_READ))
|
||||||
|
FD_CLR(fdarr[idx], readfds);
|
||||||
|
|
||||||
|
/* remove from descriptor set if not ready for write */
|
||||||
|
if(!(wsanetevents.lNetworkEvents & FD_WRITE))
|
||||||
|
FD_CLR(fdarr[idx], writefds);
|
||||||
|
|
||||||
|
/* remove from descriptor set if not exceptional */
|
||||||
|
if(!(wsanetevents.lNetworkEvents & FD_CLOSE))
|
||||||
|
FD_CLR(fdarr[idx], exceptfds);
|
||||||
|
}
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(idx = 0; idx < wsa; idx++)
|
||||||
|
WSACloseEvent(wsaevents[idx]);
|
||||||
|
|
||||||
|
free(wsaevents);
|
||||||
|
free(handles);
|
||||||
|
free(fdarr);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
sockfdp is a pointer to an established stream or CURL_SOCKET_BAD
|
sockfdp is a pointer to an established stream or CURL_SOCKET_BAD
|
||||||
|
|
||||||
@ -447,18 +587,6 @@ static bool juggle(curl_socket_t *sockfdp,
|
|||||||
FD_ZERO(&fds_write);
|
FD_ZERO(&fds_write);
|
||||||
FD_ZERO(&fds_err);
|
FD_ZERO(&fds_err);
|
||||||
|
|
||||||
#ifdef USE_WINSOCK
|
|
||||||
/*
|
|
||||||
** WinSock select() does not support standard file descriptors,
|
|
||||||
** it can only check SOCKETs. Since this program in its current
|
|
||||||
** state will not work on WinSock based systems, next line is
|
|
||||||
** commented out to allow warning-free compilation awaiting the
|
|
||||||
** day it will be fixed to also run on WinSock systems.
|
|
||||||
*/
|
|
||||||
#else
|
|
||||||
FD_SET(fileno(stdin), &fds_read);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch(*mode) {
|
switch(*mode) {
|
||||||
|
|
||||||
case PASSIVE_LISTEN:
|
case PASSIVE_LISTEN:
|
||||||
@ -511,7 +639,11 @@ static bool juggle(curl_socket_t *sockfdp,
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
#ifdef USE_WINSOCK
|
||||||
|
rc = select_ws((int)maxfd + 1, &fds_read, &fds_write, &fds_err, &timeout);
|
||||||
|
#else
|
||||||
rc = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, &timeout);
|
rc = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, &timeout);
|
||||||
|
#endif
|
||||||
|
|
||||||
if(got_exit_signal) {
|
if(got_exit_signal) {
|
||||||
logmsg("signalled to die, exiting...");
|
logmsg("signalled to die, exiting...");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user