1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2012, 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.
21 ***************************************************************************/
23 #include "curl_setup.h"
25 #ifdef HAVE_SYS_SELECT_H
26 #include <sys/select.h>
29 #if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE)
30 #error "We can't compile without select() or poll() support."
33 #if defined(__BEOS__) && !defined(__HAIKU__)
34 /* BeOS has FD_SET defined in socket.h */
39 #include <dos.h> /* delay() */
42 #include <curl/curl.h>
44 #include "curl_urldata.h"
45 #include "curl_connect.h"
46 #include "curl_select.h"
47 #include "curl_warnless.h"
49 /* Convenience local macros */
51 #define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
53 #ifdef CURL_ACKNOWLEDGE_EINTR
54 #define error_not_EINTR (1)
56 #define error_not_EINTR (error != EINTR)
60 * Internal function used for waiting a specific amount of ms
61 * in Curl_socket_ready() and Curl_poll() when no file descriptor
62 * is provided to wait on, just being used to delay execution.
63 * WinSock select() and poll() timeout mechanisms need a valid
64 * socket descriptor in a not null file descriptor set to work.
65 * Waiting indefinitely with this function is not allowed, a
66 * zero or negative timeout value will return immediately.
67 * Timeout resolution, accuracy, as well as maximum supported
68 * value is system dependent, neither factor is a citical issue
69 * for the intended use of this function in the library.
70 * On non-DOS and non-Winsock platforms, when compiled with
71 * CURL_ACKNOWLEDGE_EINTR defined, EINTR condition is honored
72 * and function might exit early without awaiting full timeout,
73 * otherwise EINTR will be ignored and full timeout will elapse.
76 * -1 = system call error, invalid timeout value, or interrupted
77 * 0 = specified timeout has elapsed
79 int Curl_wait_ms(int timeout_ms)
81 #if !defined(MSDOS) && !defined(USE_WINSOCK)
82 #ifndef HAVE_POLL_FINE
83 struct timeval pending_tv;
85 struct timeval initial_tv;
94 SET_SOCKERRNO(EINVAL);
99 #elif defined(USE_WINSOCK)
102 pending_ms = timeout_ms;
103 initial_tv = curlx_tvnow();
105 #if defined(HAVE_POLL_FINE)
106 r = poll(NULL, 0, pending_ms);
108 pending_tv.tv_sec = pending_ms / 1000;
109 pending_tv.tv_usec = (pending_ms % 1000) * 1000;
110 r = select(0, NULL, NULL, NULL, &pending_tv);
111 #endif /* HAVE_POLL_FINE */
115 if(error && error_not_EINTR)
117 pending_ms = timeout_ms - elapsed_ms;
121 #endif /* USE_WINSOCK */
128 * Wait for read or write events on a set of file descriptors. It uses poll()
129 * when a fine poll() is available, in order to avoid limits with FD_SETSIZE,
130 * otherwise select() is used. An error is returned if select() is being used
131 * and a file descriptor is too large for FD_SETSIZE.
133 * A negative timeout value makes this function wait indefinitely,
134 * unles no valid file descriptor is given, when this happens the
135 * negative timeout is ignored and the function times out immediately.
136 * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition
137 * is honored and function might exit early without awaiting timeout,
138 * otherwise EINTR will be ignored.
141 * -1 = system call error or fd >= FD_SETSIZE
143 * [bitmask] = action as described below
145 * CURL_CSELECT_IN - first socket is readable
146 * CURL_CSELECT_IN2 - second socket is readable
147 * CURL_CSELECT_OUT - write socket is writable
148 * CURL_CSELECT_ERR - an error condition occurred
150 int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
151 curl_socket_t readfd1,
152 curl_socket_t writefd, /* socket to write to */
153 long timeout_ms) /* milliseconds to wait */
155 #ifdef HAVE_POLL_FINE
156 struct pollfd pfd[3];
159 struct timeval pending_tv;
160 struct timeval *ptimeout;
166 struct timeval initial_tv = {0,0};
172 if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
173 (writefd == CURL_SOCKET_BAD)) {
174 /* no sockets, just wait */
175 r = Curl_wait_ms((int)timeout_ms);
179 /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
180 time in this function does not need to be measured. This happens
181 when function is called with a zero timeout or a negative timeout
182 value indicating a blocking call should be performed. */
185 pending_ms = (int)timeout_ms;
186 initial_tv = curlx_tvnow();
189 #ifdef HAVE_POLL_FINE
192 if(readfd0 != CURL_SOCKET_BAD) {
193 pfd[num].fd = readfd0;
194 pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
195 pfd[num].revents = 0;
198 if(readfd1 != CURL_SOCKET_BAD) {
199 pfd[num].fd = readfd1;
200 pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
201 pfd[num].revents = 0;
204 if(writefd != CURL_SOCKET_BAD) {
205 pfd[num].fd = writefd;
206 pfd[num].events = POLLWRNORM|POLLOUT;
207 pfd[num].revents = 0;
216 r = poll(pfd, num, pending_ms);
220 if(error && error_not_EINTR)
223 pending_ms = (int)(timeout_ms - elapsed_ms);
224 if(pending_ms <= 0) {
225 r = 0; /* Simulate a "call timed out" case */
238 if(readfd0 != CURL_SOCKET_BAD) {
239 if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
240 ret |= CURL_CSELECT_IN;
241 if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
242 ret |= CURL_CSELECT_ERR;
245 if(readfd1 != CURL_SOCKET_BAD) {
246 if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
247 ret |= CURL_CSELECT_IN2;
248 if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
249 ret |= CURL_CSELECT_ERR;
252 if(writefd != CURL_SOCKET_BAD) {
253 if(pfd[num].revents & (POLLWRNORM|POLLOUT))
254 ret |= CURL_CSELECT_OUT;
255 if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
256 ret |= CURL_CSELECT_ERR;
261 #else /* HAVE_POLL_FINE */
264 maxfd = (curl_socket_t)-1;
267 if(readfd0 != CURL_SOCKET_BAD) {
268 VERIFY_SOCK(readfd0);
269 FD_SET(readfd0, &fds_read);
270 FD_SET(readfd0, &fds_err);
273 if(readfd1 != CURL_SOCKET_BAD) {
274 VERIFY_SOCK(readfd1);
275 FD_SET(readfd1, &fds_read);
276 FD_SET(readfd1, &fds_err);
282 if(writefd != CURL_SOCKET_BAD) {
283 VERIFY_SOCK(writefd);
284 FD_SET(writefd, &fds_write);
285 FD_SET(writefd, &fds_err);
290 ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
294 pending_tv.tv_sec = pending_ms / 1000;
295 pending_tv.tv_usec = (pending_ms % 1000) * 1000;
297 else if(!timeout_ms) {
298 pending_tv.tv_sec = 0;
299 pending_tv.tv_usec = 0;
301 r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
305 if(error && error_not_EINTR)
308 pending_ms = timeout_ms - elapsed_ms;
309 if(pending_ms <= 0) {
310 r = 0; /* Simulate a "call timed out" case */
322 if(readfd0 != CURL_SOCKET_BAD) {
323 if(FD_ISSET(readfd0, &fds_read))
324 ret |= CURL_CSELECT_IN;
325 if(FD_ISSET(readfd0, &fds_err))
326 ret |= CURL_CSELECT_ERR;
328 if(readfd1 != CURL_SOCKET_BAD) {
329 if(FD_ISSET(readfd1, &fds_read))
330 ret |= CURL_CSELECT_IN2;
331 if(FD_ISSET(readfd1, &fds_err))
332 ret |= CURL_CSELECT_ERR;
334 if(writefd != CURL_SOCKET_BAD) {
335 if(FD_ISSET(writefd, &fds_write))
336 ret |= CURL_CSELECT_OUT;
337 if(FD_ISSET(writefd, &fds_err))
338 ret |= CURL_CSELECT_ERR;
343 #endif /* HAVE_POLL_FINE */
348 * This is a wrapper around poll(). If poll() does not exist, then
349 * select() is used instead. An error is returned if select() is
350 * being used and a file descriptor is too large for FD_SETSIZE.
351 * A negative timeout value makes this function wait indefinitely,
352 * unles no valid file descriptor is given, when this happens the
353 * negative timeout is ignored and the function times out immediately.
354 * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition
355 * is honored and function might exit early without awaiting timeout,
356 * otherwise EINTR will be ignored.
359 * -1 = system call error or fd >= FD_SETSIZE
361 * N = number of structures with non zero revent fields
363 int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
365 #ifndef HAVE_POLL_FINE
366 struct timeval pending_tv;
367 struct timeval *ptimeout;
373 struct timeval initial_tv = {0,0};
374 bool fds_none = TRUE;
381 for(i = 0; i < nfds; i++) {
382 if(ufds[i].fd != CURL_SOCKET_BAD) {
389 r = Curl_wait_ms(timeout_ms);
393 /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
394 time in this function does not need to be measured. This happens
395 when function is called with a zero timeout or a negative timeout
396 value indicating a blocking call should be performed. */
399 pending_ms = timeout_ms;
400 initial_tv = curlx_tvnow();
403 #ifdef HAVE_POLL_FINE
410 r = poll(ufds, nfds, pending_ms);
414 if(error && error_not_EINTR)
417 pending_ms = timeout_ms - elapsed_ms;
428 for(i = 0; i < nfds; i++) {
429 if(ufds[i].fd == CURL_SOCKET_BAD)
431 if(ufds[i].revents & POLLHUP)
432 ufds[i].revents |= POLLIN;
433 if(ufds[i].revents & POLLERR)
434 ufds[i].revents |= (POLLIN|POLLOUT);
437 #else /* HAVE_POLL_FINE */
442 maxfd = (curl_socket_t)-1;
444 for(i = 0; i < nfds; i++) {
446 if(ufds[i].fd == CURL_SOCKET_BAD)
448 VERIFY_SOCK(ufds[i].fd);
449 if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
450 POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
451 if(ufds[i].fd > maxfd)
453 if(ufds[i].events & (POLLRDNORM|POLLIN))
454 FD_SET(ufds[i].fd, &fds_read);
455 if(ufds[i].events & (POLLWRNORM|POLLOUT))
456 FD_SET(ufds[i].fd, &fds_write);
457 if(ufds[i].events & (POLLRDBAND|POLLPRI))
458 FD_SET(ufds[i].fd, &fds_err);
462 ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
466 pending_tv.tv_sec = pending_ms / 1000;
467 pending_tv.tv_usec = (pending_ms % 1000) * 1000;
469 else if(!timeout_ms) {
470 pending_tv.tv_sec = 0;
471 pending_tv.tv_usec = 0;
473 r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
477 if(error && error_not_EINTR)
480 pending_ms = timeout_ms - elapsed_ms;
492 for(i = 0; i < nfds; i++) {
494 if(ufds[i].fd == CURL_SOCKET_BAD)
496 if(FD_ISSET(ufds[i].fd, &fds_read))
497 ufds[i].revents |= POLLIN;
498 if(FD_ISSET(ufds[i].fd, &fds_write))
499 ufds[i].revents |= POLLOUT;
500 if(FD_ISSET(ufds[i].fd, &fds_err))
501 ufds[i].revents |= POLLPRI;
502 if(ufds[i].revents != 0)
506 #endif /* HAVE_POLL_FINE */
513 * This is a replacement for select() on the TPF platform.
514 * It is used whenever libcurl calls select().
515 * The call below to tpf_process_signals() is required because
516 * TPF's select calls are not signal interruptible.
518 * Return values are the same as select's.
520 int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
521 fd_set* excepts, struct timeval* tv)
525 rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
526 tpf_process_signals();