db7fb6d43c57d5311b3f98fff48c65f22a321b87
[platform/upstream/curl.git] / lib / select.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
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.
13  *
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.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22
23 #include "curl_setup.h"
24
25 #ifdef HAVE_SYS_SELECT_H
26 #include <sys/select.h>
27 #endif
28
29 #if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE)
30 #error "We can't compile without select() or poll() support."
31 #endif
32
33 #if defined(__BEOS__) && !defined(__HAIKU__)
34 /* BeOS has FD_SET defined in socket.h */
35 #include <socket.h>
36 #endif
37
38 #ifdef MSDOS
39 #include <dos.h>  /* delay() */
40 #endif
41
42 #include <curl/curl.h>
43
44 #include "urldata.h"
45 #include "connect.h"
46 #include "select.h"
47 #include "warnless.h"
48
49 /* Convenience local macros */
50
51 #define elapsed_ms  (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
52
53 int Curl_ack_eintr = 0;
54 #define error_not_EINTR (Curl_ack_eintr || error != EINTR)
55
56 /*
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.
67  *
68  * Return values:
69  *   -1 = system call error, invalid timeout value, or interrupted
70  *    0 = specified timeout has elapsed
71  */
72 int Curl_wait_ms(int timeout_ms)
73 {
74 #if !defined(MSDOS) && !defined(USE_WINSOCK)
75 #ifndef HAVE_POLL_FINE
76   struct timeval pending_tv;
77 #endif
78   struct timeval initial_tv;
79   int pending_ms;
80   int error;
81 #endif
82   int r = 0;
83
84   if(!timeout_ms)
85     return 0;
86   if(timeout_ms < 0) {
87     SET_SOCKERRNO(EINVAL);
88     return -1;
89   }
90 #if defined(MSDOS)
91   delay(timeout_ms);
92 #elif defined(USE_WINSOCK)
93   Sleep(timeout_ms);
94 #else
95   pending_ms = timeout_ms;
96   initial_tv = curlx_tvnow();
97   do {
98 #if defined(HAVE_POLL_FINE)
99     r = poll(NULL, 0, pending_ms);
100 #else
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 */
105     if(r != -1)
106       break;
107     error = SOCKERRNO;
108     if(error && error_not_EINTR)
109       break;
110     pending_ms = timeout_ms - elapsed_ms;
111     if(pending_ms <= 0)
112       break;
113   } while(r == -1);
114 #endif /* USE_WINSOCK */
115   if(r)
116     r = -1;
117   return r;
118 }
119
120 /*
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.
125  *
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.
129  *
130  * Return values:
131  *   -1 = system call error or fd >= FD_SETSIZE
132  *    0 = timeout
133  *    [bitmask] = action as described below
134  *
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
139  */
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 */
144 {
145 #ifdef HAVE_POLL_FINE
146   struct pollfd pfd[3];
147   int num;
148 #else
149   struct timeval pending_tv;
150   struct timeval *ptimeout;
151   fd_set fds_read;
152   fd_set fds_write;
153   fd_set fds_err;
154   curl_socket_t maxfd;
155 #endif
156   struct timeval initial_tv = {0,0};
157   int pending_ms = 0;
158   int error;
159   int r;
160   int ret;
161
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);
166     return r;
167   }
168
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. */
173
174   if(timeout_ms > 0) {
175     pending_ms = (int)timeout_ms;
176     initial_tv = curlx_tvnow();
177   }
178
179 #ifdef HAVE_POLL_FINE
180
181   num = 0;
182   if(readfd0 != CURL_SOCKET_BAD) {
183     pfd[num].fd = readfd0;
184     pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
185     pfd[num].revents = 0;
186     num++;
187   }
188   if(readfd1 != CURL_SOCKET_BAD) {
189     pfd[num].fd = readfd1;
190     pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
191     pfd[num].revents = 0;
192     num++;
193   }
194   if(writefd != CURL_SOCKET_BAD) {
195     pfd[num].fd = writefd;
196     pfd[num].events = POLLWRNORM|POLLOUT;
197     pfd[num].revents = 0;
198     num++;
199   }
200
201   do {
202     if(timeout_ms < 0)
203       pending_ms = -1;
204     else if(!timeout_ms)
205       pending_ms = 0;
206     r = poll(pfd, num, pending_ms);
207     if(r != -1)
208       break;
209     error = SOCKERRNO;
210     if(error && error_not_EINTR)
211       break;
212     if(timeout_ms > 0) {
213       pending_ms = (int)(timeout_ms - elapsed_ms);
214       if(pending_ms <= 0) {
215         r = 0;  /* Simulate a "call timed out" case */
216         break;
217       }
218     }
219   } while(r == -1);
220
221   if(r < 0)
222     return -1;
223   if(r == 0)
224     return 0;
225
226   ret = 0;
227   num = 0;
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;
233     num++;
234   }
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;
240     num++;
241   }
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;
247   }
248
249   return ret;
250
251 #else  /* HAVE_POLL_FINE */
252
253   FD_ZERO(&fds_err);
254   maxfd = (curl_socket_t)-1;
255
256   FD_ZERO(&fds_read);
257   if(readfd0 != CURL_SOCKET_BAD) {
258     VERIFY_SOCK(readfd0);
259     FD_SET(readfd0, &fds_read);
260     FD_SET(readfd0, &fds_err);
261     maxfd = readfd0;
262   }
263   if(readfd1 != CURL_SOCKET_BAD) {
264     VERIFY_SOCK(readfd1);
265     FD_SET(readfd1, &fds_read);
266     FD_SET(readfd1, &fds_err);
267     if(readfd1 > maxfd)
268       maxfd = readfd1;
269   }
270
271   FD_ZERO(&fds_write);
272   if(writefd != CURL_SOCKET_BAD) {
273     VERIFY_SOCK(writefd);
274     FD_SET(writefd, &fds_write);
275     FD_SET(writefd, &fds_err);
276     if(writefd > maxfd)
277       maxfd = writefd;
278   }
279
280   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
281
282   do {
283     if(timeout_ms > 0) {
284       pending_tv.tv_sec = pending_ms / 1000;
285       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
286     }
287     else if(!timeout_ms) {
288       pending_tv.tv_sec = 0;
289       pending_tv.tv_usec = 0;
290     }
291     r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
292     if(r != -1)
293       break;
294     error = SOCKERRNO;
295     if(error && error_not_EINTR)
296       break;
297     if(timeout_ms > 0) {
298       pending_ms = timeout_ms - elapsed_ms;
299       if(pending_ms <= 0) {
300         r = 0;  /* Simulate a "call timed out" case */
301         break;
302       }
303     }
304   } while(r == -1);
305
306   if(r < 0)
307     return -1;
308   if(r == 0)
309     return 0;
310
311   ret = 0;
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;
317   }
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;
323   }
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;
329   }
330
331   return ret;
332
333 #endif  /* HAVE_POLL_FINE */
334
335 }
336
337 /*
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.
344  *
345  * Return values:
346  *   -1 = system call error or fd >= FD_SETSIZE
347  *    0 = timeout
348  *    N = number of structures with non zero revent fields
349  */
350 int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
351 {
352 #ifndef HAVE_POLL_FINE
353   struct timeval pending_tv;
354   struct timeval *ptimeout;
355   fd_set fds_read;
356   fd_set fds_write;
357   fd_set fds_err;
358   curl_socket_t maxfd;
359 #endif
360   struct timeval initial_tv = {0,0};
361   bool fds_none = TRUE;
362   unsigned int i;
363   int pending_ms = 0;
364   int error;
365   int r;
366
367   if(ufds) {
368     for(i = 0; i < nfds; i++) {
369       if(ufds[i].fd != CURL_SOCKET_BAD) {
370         fds_none = FALSE;
371         break;
372       }
373     }
374   }
375   if(fds_none) {
376     r = Curl_wait_ms(timeout_ms);
377     return r;
378   }
379
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. */
384
385   if(timeout_ms > 0) {
386     pending_ms = timeout_ms;
387     initial_tv = curlx_tvnow();
388   }
389
390 #ifdef HAVE_POLL_FINE
391
392   do {
393     if(timeout_ms < 0)
394       pending_ms = -1;
395     else if(!timeout_ms)
396       pending_ms = 0;
397     r = poll(ufds, nfds, pending_ms);
398     if(r != -1)
399       break;
400     error = SOCKERRNO;
401     if(error && error_not_EINTR)
402       break;
403     if(timeout_ms > 0) {
404       pending_ms = timeout_ms - elapsed_ms;
405       if(pending_ms <= 0)
406         break;
407     }
408   } while(r == -1);
409
410   if(r < 0)
411     return -1;
412   if(r == 0)
413     return 0;
414
415   for(i = 0; i < nfds; i++) {
416     if(ufds[i].fd == CURL_SOCKET_BAD)
417       continue;
418     if(ufds[i].revents & POLLHUP)
419       ufds[i].revents |= POLLIN;
420     if(ufds[i].revents & POLLERR)
421       ufds[i].revents |= (POLLIN|POLLOUT);
422   }
423
424 #else  /* HAVE_POLL_FINE */
425
426   FD_ZERO(&fds_read);
427   FD_ZERO(&fds_write);
428   FD_ZERO(&fds_err);
429   maxfd = (curl_socket_t)-1;
430
431   for(i = 0; i < nfds; i++) {
432     ufds[i].revents = 0;
433     if(ufds[i].fd == CURL_SOCKET_BAD)
434       continue;
435     VERIFY_SOCK(ufds[i].fd);
436     if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
437                           POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
438       if(ufds[i].fd > maxfd)
439         maxfd = ufds[i].fd;
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);
446     }
447   }
448
449   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
450
451   do {
452     if(timeout_ms > 0) {
453       pending_tv.tv_sec = pending_ms / 1000;
454       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
455     }
456     else if(!timeout_ms) {
457       pending_tv.tv_sec = 0;
458       pending_tv.tv_usec = 0;
459     }
460     r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
461     if(r != -1)
462       break;
463     error = SOCKERRNO;
464     if(error && error_not_EINTR)
465       break;
466     if(timeout_ms > 0) {
467       pending_ms = timeout_ms - elapsed_ms;
468       if(pending_ms <= 0)
469         break;
470     }
471   } while(r == -1);
472
473   if(r < 0)
474     return -1;
475   if(r == 0)
476     return 0;
477
478   r = 0;
479   for(i = 0; i < nfds; i++) {
480     ufds[i].revents = 0;
481     if(ufds[i].fd == CURL_SOCKET_BAD)
482       continue;
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)
490       r++;
491   }
492
493 #endif  /* HAVE_POLL_FINE */
494
495   return r;
496 }
497
498 #ifdef TPF
499 /*
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.
504  *
505  * Return values are the same as select's.
506  */
507 int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
508                        fd_set* excepts, struct timeval* tv)
509 {
510    int rc;
511
512    rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
513    tpf_process_signals();
514    return(rc);
515 }
516 #endif /* TPF */