1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
22 ***************************************************************************/
26 #ifdef HAVE_SYS_TYPES_H
27 #include <sys/types.h>
29 #ifdef HAVE_SYS_SELECT_H
30 #include <sys/select.h>
32 #ifdef HAVE_SYS_TIME_H
37 #error "We can't compile without select() support!"
43 /* BeOS has FD_SET defined in socket.h */
48 #define VALID_SOCK(s) (1) /* Win-sockets are not in range [0..FD_SETSIZE> */
50 #define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
54 * This is an internal function used for waiting for read or write
55 * events on single file descriptors. It attempts to replace select()
56 * in order to avoid limits with FD_SETSIZE.
59 * -1 = system call error
61 * CSELECT_IN | CSELECT_OUT | CSELECT_ERR
63 int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
72 if (readfd != CURL_SOCKET_BAD) {
74 pfd[num].events = POLLIN;
77 if (writefd != CURL_SOCKET_BAD) {
78 pfd[num].fd = writefd;
79 pfd[num].events = POLLOUT;
83 r = poll(pfd, num, timeout_ms);
92 if (readfd != CURL_SOCKET_BAD) {
93 if (pfd[num].revents & POLLIN)
95 if (pfd[num].revents & POLLERR)
99 if (writefd != CURL_SOCKET_BAD) {
100 if (pfd[num].revents & POLLOUT)
102 if (pfd[num].revents & POLLERR)
108 struct timeval timeout;
116 timeout.tv_sec = timeout_ms / 1000;
117 timeout.tv_usec = (timeout_ms % 1000) * 1000;
123 if (readfd != CURL_SOCKET_BAD) {
124 if (!VALID_SOCK(readfd)) {
128 FD_SET(readfd, &fds_read);
129 FD_SET(readfd, &fds_err);
134 if (writefd != CURL_SOCKET_BAD) {
135 if (!VALID_SOCK(writefd)) {
139 FD_SET(writefd, &fds_write);
140 FD_SET(writefd, &fds_err);
145 r = select(maxfd + 1, &fds_read, &fds_write, &fds_err, &timeout);
153 if (readfd != CURL_SOCKET_BAD) {
154 if (FD_ISSET(readfd, &fds_read))
156 if (FD_ISSET(readfd, &fds_err))
159 if (writefd != CURL_SOCKET_BAD) {
160 if (FD_ISSET(writefd, &fds_write))
162 if (FD_ISSET(writefd, &fds_err))
171 * This is a wrapper around poll(). If poll() does not exist, then
172 * select() is used instead. An error is returned if select() is
173 * being used and a file descriptor too large for FD_SETSIZE.
176 * -1 = system call error or fd >= FD_SETSIZE
178 * 1 = number of structures with non zero revent fields
180 int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
182 #ifdef HAVE_POLL_FINE
183 return poll(ufds, nfds, timeout_ms);
185 struct timeval timeout;
186 struct timeval *ptimeout;
199 for (i = 0; i < nfds; i++) {
200 if (ufds[i].fd == CURL_SOCKET_BAD)
202 #ifndef WIN32 /* This is harmless and wrong on Win32 */
203 if (ufds[i].fd >= FD_SETSIZE) {
208 if (ufds[i].fd > maxfd)
210 if (ufds[i].events & POLLIN)
211 FD_SET(ufds[i].fd, &fds_read);
212 if (ufds[i].events & POLLOUT)
213 FD_SET(ufds[i].fd, &fds_write);
214 if (ufds[i].events & POLLERR)
215 FD_SET(ufds[i].fd, &fds_err);
218 if (timeout_ms < 0) {
219 ptimeout = NULL; /* wait forever */
221 timeout.tv_sec = timeout_ms / 1000;
222 timeout.tv_usec = (timeout_ms % 1000) * 1000;
226 r = select(maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
234 for (i = 0; i < nfds; i++) {
236 if (ufds[i].fd == CURL_SOCKET_BAD)
238 if (FD_ISSET(ufds[i].fd, &fds_read))
239 ufds[i].revents |= POLLIN;
240 if (FD_ISSET(ufds[i].fd, &fds_write))
241 ufds[i].revents |= POLLOUT;
242 if (FD_ISSET(ufds[i].fd, &fds_err))
243 ufds[i].revents |= POLLERR;
244 if (ufds[i].revents != 0)