1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2005, 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 ***************************************************************************/
28 #ifdef HAVE_SYS_TYPES_H
29 #include <sys/types.h>
31 #ifdef HAVE_SYS_SELECT_H
32 #include <sys/select.h>
34 #ifdef HAVE_SYS_TIME_H
39 #error "We can't compile without select() support!"
43 /* BeOS has FD_SET defined in socket.h */
47 #include <curl/curl.h>
53 #if defined(WIN32) || defined(TPF)
54 #define VERIFY_SOCK(x) /* sockets are not in range [0..FD_SETSIZE] */
56 #define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
57 #define VERIFY_SOCK(x) do { \
58 if(!VALID_SOCK(x)) { \
66 * This is an internal function used for waiting for read or write
67 * events on single file descriptors. It attempts to replace select()
68 * in order to avoid limits with FD_SETSIZE.
71 * -1 = system call error
73 * CSELECT_IN | CSELECT_OUT | CSELECT_ERR
75 int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
84 if (readfd != CURL_SOCKET_BAD) {
86 pfd[num].events = POLLIN;
89 if (writefd != CURL_SOCKET_BAD) {
90 pfd[num].fd = writefd;
91 pfd[num].events = POLLOUT;
96 r = poll(pfd, num, timeout_ms);
97 } while((r == -1) && (errno == EINTR));
106 if (readfd != CURL_SOCKET_BAD) {
107 if (pfd[num].revents & (POLLIN|POLLHUP))
109 if (pfd[num].revents & POLLERR)
113 if (writefd != CURL_SOCKET_BAD) {
114 if (pfd[num].revents & POLLOUT)
116 if (pfd[num].revents & POLLERR)
122 struct timeval timeout;
130 timeout.tv_sec = timeout_ms / 1000;
131 timeout.tv_usec = (timeout_ms % 1000) * 1000;
134 maxfd = (curl_socket_t)-1;
137 if (readfd != CURL_SOCKET_BAD) {
139 FD_SET(readfd, &fds_read);
140 FD_SET(readfd, &fds_err);
145 if (writefd != CURL_SOCKET_BAD) {
146 VERIFY_SOCK(writefd);
147 FD_SET(writefd, &fds_write);
148 FD_SET(writefd, &fds_err);
154 r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, &timeout);
155 } while((r == -1) && (Curl_ourerrno() == EINTR));
163 if (readfd != CURL_SOCKET_BAD) {
164 if (FD_ISSET(readfd, &fds_read))
166 if (FD_ISSET(readfd, &fds_err))
169 if (writefd != CURL_SOCKET_BAD) {
170 if (FD_ISSET(writefd, &fds_write))
172 if (FD_ISSET(writefd, &fds_err))
181 * This is a wrapper around poll(). If poll() does not exist, then
182 * select() is used instead. An error is returned if select() is
183 * being used and a file descriptor too large for FD_SETSIZE.
186 * -1 = system call error or fd >= FD_SETSIZE
188 * 1 = number of structures with non zero revent fields
190 int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
193 #ifdef HAVE_POLL_FINE
195 r = poll(ufds, nfds, timeout_ms);
196 } while((r == -1) && (errno == EINTR));
198 struct timeval timeout;
199 struct timeval *ptimeout;
209 maxfd = (curl_socket_t)-1;
211 for (i = 0; i < nfds; i++) {
212 if (ufds[i].fd == CURL_SOCKET_BAD)
214 #ifndef WIN32 /* This is harmless and wrong on Win32 */
215 if (ufds[i].fd >= FD_SETSIZE) {
220 if (ufds[i].fd > maxfd)
222 if (ufds[i].events & POLLIN)
223 FD_SET(ufds[i].fd, &fds_read);
224 if (ufds[i].events & POLLOUT)
225 FD_SET(ufds[i].fd, &fds_write);
226 if (ufds[i].events & POLLERR)
227 FD_SET(ufds[i].fd, &fds_err);
230 if (timeout_ms < 0) {
231 ptimeout = NULL; /* wait forever */
233 timeout.tv_sec = timeout_ms / 1000;
234 timeout.tv_usec = (timeout_ms % 1000) * 1000;
239 r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
240 } while((r == -1) && (Curl_ourerrno() == EINTR));
248 for (i = 0; i < nfds; i++) {
250 if (ufds[i].fd == CURL_SOCKET_BAD)
252 if (FD_ISSET(ufds[i].fd, &fds_read))
253 ufds[i].revents |= POLLIN;
254 if (FD_ISSET(ufds[i].fd, &fds_write))
255 ufds[i].revents |= POLLOUT;
256 if (FD_ISSET(ufds[i].fd, &fds_err))
257 ufds[i].revents |= POLLERR;
258 if (ufds[i].revents != 0)
267 * This is a replacement for select() on the TPF platform.
268 * It is used whenever libcurl calls select().
269 * The call below to tpf_process_signals() is required because
270 * TPF's select calls are not signal interruptible.
272 * Return values are the same as select's.
274 int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
275 fd_set* excepts, struct timeval* tv)
279 rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
280 tpf_process_signals();