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>
49 /* Convenience local macros */
51 #define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
53 int Curl_ack_eintr = 0;
54 #define error_not_EINTR (Curl_ack_eintr || error != EINTR)
57 * Internal function used for waiting a specific amount of ms
58 * in Curl_socket_ready() and Curl_poll() when no file descriptor
59 * is provided to wait on, just being used to delay execution.
60 * WinSock select() and poll() timeout mechanisms need a valid
61 * socket descriptor in a not null file descriptor set to work.
62 * Waiting indefinitely with this function is not allowed, a
63 * zero or negative timeout value will return immediately.
64 * Timeout resolution, accuracy, as well as maximum supported
65 * value is system dependent, neither factor is a citical issue
66 * for the intended use of this function in the library.
69 * -1 = system call error, invalid timeout value, or interrupted
70 * 0 = specified timeout has elapsed
72 int Curl_wait_ms(int timeout_ms)
74 #if !defined(MSDOS) && !defined(USE_WINSOCK)
75 #ifndef HAVE_POLL_FINE
76 struct timeval pending_tv;
78 struct timeval initial_tv;
87 SET_SOCKERRNO(EINVAL);
92 #elif defined(USE_WINSOCK)
95 pending_ms = timeout_ms;
96 initial_tv = curlx_tvnow();
98 #if defined(HAVE_POLL_FINE)
99 r = poll(NULL, 0, pending_ms);
101 pending_tv.tv_sec = pending_ms / 1000;
102 pending_tv.tv_usec = (pending_ms % 1000) * 1000;
103 r = select(0, NULL, NULL, NULL, &pending_tv);
104 #endif /* HAVE_POLL_FINE */
108 if(error && error_not_EINTR)
110 pending_ms = timeout_ms - elapsed_ms;
114 #endif /* USE_WINSOCK */
121 * Wait for read or write events on a set of file descriptors. It uses poll()
122 * when a fine poll() is available, in order to avoid limits with FD_SETSIZE,
123 * otherwise select() is used. An error is returned if select() is being used
124 * and a file descriptor is too large for FD_SETSIZE.
126 * A negative timeout value makes this function wait indefinitely,
127 * unles no valid file descriptor is given, when this happens the
128 * negative timeout is ignored and the function times out immediately.
131 * -1 = system call error or fd >= FD_SETSIZE
133 * [bitmask] = action as described below
135 * CURL_CSELECT_IN - first socket is readable
136 * CURL_CSELECT_IN2 - second socket is readable
137 * CURL_CSELECT_OUT - write socket is writable
138 * CURL_CSELECT_ERR - an error condition occurred
140 int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
141 curl_socket_t readfd1,
142 curl_socket_t writefd, /* socket to write to */
143 long timeout_ms) /* milliseconds to wait */
145 #ifdef HAVE_POLL_FINE
146 struct pollfd pfd[3];
149 struct timeval pending_tv;
150 struct timeval *ptimeout;
156 struct timeval initial_tv = {0,0};
162 if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
163 (writefd == CURL_SOCKET_BAD)) {
164 /* no sockets, just wait */
165 r = Curl_wait_ms((int)timeout_ms);
169 /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
170 time in this function does not need to be measured. This happens
171 when function is called with a zero timeout or a negative timeout
172 value indicating a blocking call should be performed. */
175 pending_ms = (int)timeout_ms;
176 initial_tv = curlx_tvnow();
179 #ifdef HAVE_POLL_FINE
182 if(readfd0 != CURL_SOCKET_BAD) {
183 pfd[num].fd = readfd0;
184 pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
185 pfd[num].revents = 0;
188 if(readfd1 != CURL_SOCKET_BAD) {
189 pfd[num].fd = readfd1;
190 pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
191 pfd[num].revents = 0;
194 if(writefd != CURL_SOCKET_BAD) {
195 pfd[num].fd = writefd;
196 pfd[num].events = POLLWRNORM|POLLOUT;
197 pfd[num].revents = 0;
206 r = poll(pfd, num, pending_ms);
210 if(error && error_not_EINTR)
213 pending_ms = (int)(timeout_ms - elapsed_ms);
214 if(pending_ms <= 0) {
215 r = 0; /* Simulate a "call timed out" case */
228 if(readfd0 != CURL_SOCKET_BAD) {
229 if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
230 ret |= CURL_CSELECT_IN;
231 if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
232 ret |= CURL_CSELECT_ERR;
235 if(readfd1 != CURL_SOCKET_BAD) {
236 if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
237 ret |= CURL_CSELECT_IN2;
238 if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
239 ret |= CURL_CSELECT_ERR;
242 if(writefd != CURL_SOCKET_BAD) {
243 if(pfd[num].revents & (POLLWRNORM|POLLOUT))
244 ret |= CURL_CSELECT_OUT;
245 if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
246 ret |= CURL_CSELECT_ERR;
251 #else /* HAVE_POLL_FINE */
254 maxfd = (curl_socket_t)-1;
257 if(readfd0 != CURL_SOCKET_BAD) {
258 VERIFY_SOCK(readfd0);
259 FD_SET(readfd0, &fds_read);
260 FD_SET(readfd0, &fds_err);
263 if(readfd1 != CURL_SOCKET_BAD) {
264 VERIFY_SOCK(readfd1);
265 FD_SET(readfd1, &fds_read);
266 FD_SET(readfd1, &fds_err);
272 if(writefd != CURL_SOCKET_BAD) {
273 VERIFY_SOCK(writefd);
274 FD_SET(writefd, &fds_write);
275 FD_SET(writefd, &fds_err);
280 ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
284 pending_tv.tv_sec = pending_ms / 1000;
285 pending_tv.tv_usec = (pending_ms % 1000) * 1000;
287 else if(!timeout_ms) {
288 pending_tv.tv_sec = 0;
289 pending_tv.tv_usec = 0;
291 r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
295 if(error && error_not_EINTR)
298 pending_ms = timeout_ms - elapsed_ms;
299 if(pending_ms <= 0) {
300 r = 0; /* Simulate a "call timed out" case */
312 if(readfd0 != CURL_SOCKET_BAD) {
313 if(FD_ISSET(readfd0, &fds_read))
314 ret |= CURL_CSELECT_IN;
315 if(FD_ISSET(readfd0, &fds_err))
316 ret |= CURL_CSELECT_ERR;
318 if(readfd1 != CURL_SOCKET_BAD) {
319 if(FD_ISSET(readfd1, &fds_read))
320 ret |= CURL_CSELECT_IN2;
321 if(FD_ISSET(readfd1, &fds_err))
322 ret |= CURL_CSELECT_ERR;
324 if(writefd != CURL_SOCKET_BAD) {
325 if(FD_ISSET(writefd, &fds_write))
326 ret |= CURL_CSELECT_OUT;
327 if(FD_ISSET(writefd, &fds_err))
328 ret |= CURL_CSELECT_ERR;
333 #endif /* HAVE_POLL_FINE */
338 * This is a wrapper around poll(). If poll() does not exist, then
339 * select() is used instead. An error is returned if select() is
340 * being used and a file descriptor is too large for FD_SETSIZE.
341 * A negative timeout value makes this function wait indefinitely,
342 * unles no valid file descriptor is given, when this happens the
343 * negative timeout is ignored and the function times out immediately.
346 * -1 = system call error or fd >= FD_SETSIZE
348 * N = number of structures with non zero revent fields
350 int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
352 #ifndef HAVE_POLL_FINE
353 struct timeval pending_tv;
354 struct timeval *ptimeout;
360 struct timeval initial_tv = {0,0};
361 bool fds_none = TRUE;
368 for(i = 0; i < nfds; i++) {
369 if(ufds[i].fd != CURL_SOCKET_BAD) {
376 r = Curl_wait_ms(timeout_ms);
380 /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
381 time in this function does not need to be measured. This happens
382 when function is called with a zero timeout or a negative timeout
383 value indicating a blocking call should be performed. */
386 pending_ms = timeout_ms;
387 initial_tv = curlx_tvnow();
390 #ifdef HAVE_POLL_FINE
397 r = poll(ufds, nfds, pending_ms);
401 if(error && error_not_EINTR)
404 pending_ms = timeout_ms - elapsed_ms;
415 for(i = 0; i < nfds; i++) {
416 if(ufds[i].fd == CURL_SOCKET_BAD)
418 if(ufds[i].revents & POLLHUP)
419 ufds[i].revents |= POLLIN;
420 if(ufds[i].revents & POLLERR)
421 ufds[i].revents |= (POLLIN|POLLOUT);
424 #else /* HAVE_POLL_FINE */
429 maxfd = (curl_socket_t)-1;
431 for(i = 0; i < nfds; i++) {
433 if(ufds[i].fd == CURL_SOCKET_BAD)
435 VERIFY_SOCK(ufds[i].fd);
436 if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
437 POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
438 if(ufds[i].fd > maxfd)
440 if(ufds[i].events & (POLLRDNORM|POLLIN))
441 FD_SET(ufds[i].fd, &fds_read);
442 if(ufds[i].events & (POLLWRNORM|POLLOUT))
443 FD_SET(ufds[i].fd, &fds_write);
444 if(ufds[i].events & (POLLRDBAND|POLLPRI))
445 FD_SET(ufds[i].fd, &fds_err);
449 ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
453 pending_tv.tv_sec = pending_ms / 1000;
454 pending_tv.tv_usec = (pending_ms % 1000) * 1000;
456 else if(!timeout_ms) {
457 pending_tv.tv_sec = 0;
458 pending_tv.tv_usec = 0;
460 r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
464 if(error && error_not_EINTR)
467 pending_ms = timeout_ms - elapsed_ms;
479 for(i = 0; i < nfds; i++) {
481 if(ufds[i].fd == CURL_SOCKET_BAD)
483 if(FD_ISSET(ufds[i].fd, &fds_read))
484 ufds[i].revents |= POLLIN;
485 if(FD_ISSET(ufds[i].fd, &fds_write))
486 ufds[i].revents |= POLLOUT;
487 if(FD_ISSET(ufds[i].fd, &fds_err))
488 ufds[i].revents |= POLLPRI;
489 if(ufds[i].revents != 0)
493 #endif /* HAVE_POLL_FINE */
500 * This is a replacement for select() on the TPF platform.
501 * It is used whenever libcurl calls select().
502 * The call below to tpf_process_signals() is required because
503 * TPF's select calls are not signal interruptible.
505 * Return values are the same as select's.
507 int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
508 fd_set* excepts, struct timeval* tv)
512 rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
513 tpf_process_signals();