mirror of
https://github.com/php/php-src.git
synced 2024-11-30 21:35:36 +08:00
182 lines
4.6 KiB
C
182 lines
4.6 KiB
C
/*
|
|
+----------------------------------------------------------------------+
|
|
| PHP Version 4 |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 1997-2003 The PHP Group |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 3.0 of the PHP license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.php.net/license/3_0.txt. |
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
| Author: Wez Furlong <wez@thebrainroom.com> |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
#include "php.h"
|
|
#include "php_network.h"
|
|
|
|
/* $Id$ */
|
|
|
|
/* Win32 select() will only work with sockets, so we roll our own implementation that will
|
|
* get the OS file handle from regular fd's and sockets and then use WaitForMultipleObjects().
|
|
* This implementation is not as feature-full as posix select, but it works for our purposes
|
|
*/
|
|
PHPAPI int php_select(php_socket_t max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)
|
|
{
|
|
HANDLE *handles;
|
|
DWORD waitret;
|
|
DWORD ms_total;
|
|
int f, s, fd_count = 0, sock_count = 0;
|
|
int retval;
|
|
php_socket_t i;
|
|
fd_set ard, awr, aex; /* active fd sets */
|
|
|
|
for (i = 0; i < max_fd; i++) {
|
|
if (FD_ISSET(i, rfds) || FD_ISSET(i, wfds) || FD_ISSET(i, efds)) {
|
|
if (_get_osfhandle(i) == 0xffffffff) {
|
|
/* it is a socket */
|
|
sock_count++;
|
|
} else {
|
|
fd_count++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fd_count + sock_count == 0) {
|
|
return 0;
|
|
}
|
|
|
|
handles = (HANDLE*)safe_emalloc((fd_count + sock_count), sizeof(HANDLE), 0);
|
|
|
|
/* populate the events and handles arrays */
|
|
f = 0;
|
|
s = 0;
|
|
for (i = 0; i < max_fd; i++) {
|
|
if (FD_ISSET(i, rfds) || FD_ISSET(i, wfds) || FD_ISSET(i, efds)) {
|
|
long h = _get_osfhandle(i);
|
|
if (h == 0xFFFFFFFF) {
|
|
HANDLE evt;
|
|
long evt_flags = 0;
|
|
|
|
if (FD_ISSET(i, rfds)) {
|
|
evt_flags |= FD_READ|FD_CONNECT|FD_ACCEPT|FD_CLOSE;
|
|
}
|
|
if (FD_ISSET(i, wfds)) {
|
|
evt_flags |= FD_WRITE;
|
|
}
|
|
if (FD_ISSET(i, efds)) {
|
|
evt_flags |= FD_OOB;
|
|
}
|
|
|
|
evt = WSACreateEvent();
|
|
WSAEventSelect(i, evt, evt_flags);
|
|
|
|
handles[fd_count + s] = evt;
|
|
s++;
|
|
} else {
|
|
handles[f++] = (HANDLE)h;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* calculate how long we need to wait in milliseconds */
|
|
if (tv == NULL) {
|
|
ms_total = INFINITE;
|
|
} else {
|
|
ms_total = tv->tv_sec * 1000;
|
|
ms_total += tv->tv_usec / 1000;
|
|
}
|
|
|
|
waitret = MsgWaitForMultipleObjects(fd_count + sock_count, handles, FALSE, ms_total, QS_ALLEVENTS);
|
|
|
|
if (waitret == WAIT_TIMEOUT) {
|
|
retval = 0;
|
|
} else if (waitret == 0xFFFFFFFF) {
|
|
retval = -1;
|
|
} else {
|
|
|
|
FD_ZERO(&ard);
|
|
FD_ZERO(&awr);
|
|
FD_ZERO(&aex);
|
|
|
|
f = 0;
|
|
retval = 0;
|
|
for (i = 0; i < max_fd; i++) {
|
|
if (FD_ISSET(i, rfds) || FD_ISSET(i, wfds) || FD_ISSET(i, efds)) {
|
|
if (f >= fd_count) {
|
|
/* socket event */
|
|
HANDLE evt = handles[f];
|
|
|
|
if (WAIT_OBJECT_0 == WaitForSingleObject(evt, 0)) {
|
|
/* check for various signal states */
|
|
if (FD_ISSET(i, rfds)) {
|
|
WSAEventSelect(i, evt, FD_READ|FD_CONNECT|FD_ACCEPT|FD_CLOSE);
|
|
if (WAIT_OBJECT_0 == WaitForSingleObject(evt, 0)) {
|
|
FD_SET(i, &ard);
|
|
}
|
|
}
|
|
if (FD_ISSET(i, wfds)) {
|
|
WSAEventSelect(i, evt, FD_WRITE);
|
|
if (WAIT_OBJECT_0 == WaitForSingleObject(evt, 0)) {
|
|
FD_SET(i, &awr);
|
|
}
|
|
}
|
|
if (FD_ISSET(i, efds)) {
|
|
WSAEventSelect(i, evt, FD_OOB);
|
|
if (WAIT_OBJECT_0 == WaitForSingleObject(evt, 0)) {
|
|
FD_SET(i, &aex);
|
|
}
|
|
}
|
|
retval++;
|
|
}
|
|
|
|
WSACloseEvent(evt);
|
|
|
|
} else {
|
|
if (WAIT_OBJECT_0 == WaitForSingleObject(handles[f], 0)) {
|
|
if (FD_ISSET(i, rfds)) {
|
|
FD_SET(i, &ard);
|
|
}
|
|
if (FD_ISSET(i, wfds)) {
|
|
FD_SET(i, &awr);
|
|
}
|
|
if (FD_ISSET(i, efds)) {
|
|
FD_SET(i, &aex);
|
|
}
|
|
retval++;
|
|
}
|
|
|
|
}
|
|
f++;
|
|
}
|
|
}
|
|
|
|
if (rfds) {
|
|
*rfds = ard;
|
|
}
|
|
if (wfds) {
|
|
*wfds = awr;
|
|
}
|
|
if (efds) {
|
|
*efds = aex;
|
|
}
|
|
}
|
|
|
|
efree(handles);
|
|
|
|
return retval;
|
|
}
|
|
|
|
/*
|
|
* Local variables:
|
|
* tab-width: 4
|
|
* c-basic-offset: 4
|
|
* End:
|
|
* vim600: noet sw=4 ts=4 fdm=marker
|
|
* vim<600: noet sw=4 ts=4
|
|
*/
|