You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
4.6 KiB

  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 4 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2003 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.0 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_0.txt. |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Wez Furlong <wez@thebrainroom.com> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #include "php.h"
  19. #include "php_network.h"
  20. /* $Id$ */
  21. /* Win32 select() will only work with sockets, so we roll our own implementation that will
  22. * get the OS file handle from regular fd's and sockets and then use WaitForMultipleObjects().
  23. * This implementation is not as feature-full as posix select, but it works for our purposes
  24. */
  25. PHPAPI int php_select(php_socket_t max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)
  26. {
  27. HANDLE *handles;
  28. DWORD waitret;
  29. DWORD ms_total;
  30. int f, s, fd_count = 0, sock_count = 0;
  31. int retval;
  32. php_socket_t i;
  33. fd_set ard, awr, aex; /* active fd sets */
  34. for (i = 0; i < max_fd; i++) {
  35. if (FD_ISSET(i, rfds) || FD_ISSET(i, wfds) || FD_ISSET(i, efds)) {
  36. if (_get_osfhandle(i) == 0xffffffff) {
  37. /* it is a socket */
  38. sock_count++;
  39. } else {
  40. fd_count++;
  41. }
  42. }
  43. }
  44. if (fd_count + sock_count == 0) {
  45. return 0;
  46. }
  47. handles = (HANDLE*)emalloc((fd_count + sock_count) * sizeof(HANDLE));
  48. /* populate the events and handles arrays */
  49. f = 0;
  50. s = 0;
  51. for (i = 0; i < max_fd; i++) {
  52. if (FD_ISSET(i, rfds) || FD_ISSET(i, wfds) || FD_ISSET(i, efds)) {
  53. long h = _get_osfhandle(i);
  54. if (h == 0xFFFFFFFF) {
  55. HANDLE evt;
  56. long evt_flags = 0;
  57. if (FD_ISSET(i, rfds)) {
  58. evt_flags |= FD_READ|FD_CONNECT|FD_ACCEPT|FD_CLOSE;
  59. }
  60. if (FD_ISSET(i, wfds)) {
  61. evt_flags |= FD_WRITE;
  62. }
  63. if (FD_ISSET(i, efds)) {
  64. evt_flags |= FD_OOB;
  65. }
  66. evt = WSACreateEvent();
  67. WSAEventSelect(i, evt, evt_flags);
  68. handles[fd_count + s] = evt;
  69. s++;
  70. } else {
  71. handles[f++] = (HANDLE)h;
  72. }
  73. }
  74. }
  75. /* calculate how long we need to wait in milliseconds */
  76. if (tv == NULL) {
  77. ms_total = INFINITE;
  78. } else {
  79. ms_total = tv->tv_sec * 1000;
  80. ms_total += tv->tv_usec / 1000;
  81. }
  82. waitret = MsgWaitForMultipleObjects(fd_count + sock_count, handles, FALSE, ms_total, QS_ALLEVENTS);
  83. if (waitret == WAIT_TIMEOUT) {
  84. retval = 0;
  85. } else if (waitret == 0xFFFFFFFF) {
  86. retval = -1;
  87. } else {
  88. FD_ZERO(&ard);
  89. FD_ZERO(&awr);
  90. FD_ZERO(&aex);
  91. f = 0;
  92. retval = 0;
  93. for (i = 0; i < max_fd; i++) {
  94. if (FD_ISSET(i, rfds) || FD_ISSET(i, wfds) || FD_ISSET(i, efds)) {
  95. if (f >= fd_count) {
  96. /* socket event */
  97. HANDLE evt = handles[f];
  98. if (WAIT_OBJECT_0 == WaitForSingleObject(evt, 0)) {
  99. /* check for various signal states */
  100. if (FD_ISSET(i, rfds)) {
  101. WSAEventSelect(i, evt, FD_READ|FD_CONNECT|FD_ACCEPT|FD_CLOSE);
  102. if (WAIT_OBJECT_0 == WaitForSingleObject(evt, 0)) {
  103. FD_SET(i, &ard);
  104. }
  105. }
  106. if (FD_ISSET(i, wfds)) {
  107. WSAEventSelect(i, evt, FD_WRITE);
  108. if (WAIT_OBJECT_0 == WaitForSingleObject(evt, 0)) {
  109. FD_SET(i, &awr);
  110. }
  111. }
  112. if (FD_ISSET(i, efds)) {
  113. WSAEventSelect(i, evt, FD_OOB);
  114. if (WAIT_OBJECT_0 == WaitForSingleObject(evt, 0)) {
  115. FD_SET(i, &aex);
  116. }
  117. }
  118. retval++;
  119. }
  120. WSACloseEvent(evt);
  121. } else {
  122. if (WAIT_OBJECT_0 == WaitForSingleObject(handles[f], 0)) {
  123. if (FD_ISSET(i, rfds)) {
  124. FD_SET(i, &ard);
  125. }
  126. if (FD_ISSET(i, wfds)) {
  127. FD_SET(i, &awr);
  128. }
  129. if (FD_ISSET(i, efds)) {
  130. FD_SET(i, &aex);
  131. }
  132. retval++;
  133. }
  134. }
  135. f++;
  136. }
  137. }
  138. if (rfds) {
  139. *rfds = ard;
  140. }
  141. if (wfds) {
  142. *wfds = awr;
  143. }
  144. if (efds) {
  145. *efds = aex;
  146. }
  147. }
  148. efree(handles);
  149. return retval;
  150. }
  151. /*
  152. * Local variables:
  153. * tab-width: 4
  154. * c-basic-offset: 4
  155. * End:
  156. * vim600: noet sw=4 ts=4 fdm=marker
  157. * vim<600: noet sw=4 ts=4
  158. */