03af645eef713938c7a376318b1c5558621ead28
[platform/upstream/curl.git] / lib / select.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2016, 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 https://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 #ifdef __VXWORKS__
43 #include <strings.h>  /* bzero() in FD_SET */
44 #endif
45
46 #include <curl/curl.h>
47
48 #include "urldata.h"
49 #include "connect.h"
50 #include "select.h"
51 #include "warnless.h"
52
53 /* Convenience local macros */
54 #define ELAPSED_MS()  (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
55
56 int Curl_ack_eintr = 0;
57 #define ERROR_NOT_EINTR(error) (Curl_ack_eintr || error != EINTR)
58
59 /*
60  * Internal function used for waiting a specific amount of ms
61  * in Curl_socket_check() 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  *
71  * Return values:
72  *   -1 = system call error, invalid timeout value, or interrupted
73  *    0 = specified timeout has elapsed
74  */
75 int Curl_wait_ms(int timeout_ms)
76 {
77 #if !defined(MSDOS) && !defined(USE_WINSOCK)
78 #ifndef HAVE_POLL_FINE
79   struct timeval pending_tv;
80 #endif
81   struct timeval initial_tv;
82   int pending_ms;
83   int error;
84 #endif
85   int r = 0;
86
87   if(!timeout_ms)
88     return 0;
89   if(timeout_ms < 0) {
90     SET_SOCKERRNO(EINVAL);
91     return -1;
92   }
93 #if defined(MSDOS)
94   delay(timeout_ms);
95 #elif defined(USE_WINSOCK)
96   Sleep(timeout_ms);
97 #else
98   pending_ms = timeout_ms;
99   initial_tv = curlx_tvnow();
100   do {
101 #if defined(HAVE_POLL_FINE)
102     r = poll(NULL, 0, pending_ms);
103 #else
104     pending_tv.tv_sec = pending_ms / 1000;
105     pending_tv.tv_usec = (pending_ms % 1000) * 1000;
106     r = select(0, NULL, NULL, NULL, &pending_tv);
107 #endif /* HAVE_POLL_FINE */
108     if(r != -1)
109       break;
110     error = SOCKERRNO;
111     if(error && ERROR_NOT_EINTR(error))
112       break;
113     pending_ms = timeout_ms - ELAPSED_MS();
114     if(pending_ms <= 0) {
115       r = 0;  /* Simulate a "call timed out" case */
116       break;
117     }
118   } while(r == -1);
119 #endif /* USE_WINSOCK */
120   if(r)
121     r = -1;
122   return r;
123 }
124
125 /*
126  * Wait for read or write events on a set of file descriptors. It uses poll()
127  * when a fine poll() is available, in order to avoid limits with FD_SETSIZE,
128  * otherwise select() is used.  An error is returned if select() is being used
129  * and a file descriptor is too large for FD_SETSIZE.
130  *
131  * A negative timeout value makes this function wait indefinitely,
132  * unles no valid file descriptor is given, when this happens the
133  * negative timeout is ignored and the function times out immediately.
134  *
135  * Return values:
136  *   -1 = system call error or fd >= FD_SETSIZE
137  *    0 = timeout
138  *    [bitmask] = action as described below
139  *
140  * CURL_CSELECT_IN - first socket is readable
141  * CURL_CSELECT_IN2 - second socket is readable
142  * CURL_CSELECT_OUT - write socket is writable
143  * CURL_CSELECT_ERR - an error condition occurred
144  */
145 int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
146                       curl_socket_t readfd1,
147                       curl_socket_t writefd, /* socket to write to */
148                       time_t timeout_ms)     /* milliseconds to wait */
149 {
150 #ifdef HAVE_POLL_FINE
151   struct pollfd pfd[3];
152   int num;
153 #else
154   struct timeval pending_tv;
155   struct timeval *ptimeout;
156   fd_set fds_read;
157   fd_set fds_write;
158   fd_set fds_err;
159   curl_socket_t maxfd;
160 #endif
161   struct timeval initial_tv = {0, 0};
162   int pending_ms = 0;
163   int error;
164   int r;
165   int ret;
166
167 #if SIZEOF_LONG != SIZEOF_INT
168   /* wrap-around precaution */
169   if(timeout_ms >= INT_MAX)
170     timeout_ms = INT_MAX;
171 #endif
172
173   if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
174      (writefd == CURL_SOCKET_BAD)) {
175     /* no sockets, just wait */
176     r = Curl_wait_ms((int)timeout_ms);
177     return r;
178   }
179
180   /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
181      time in this function does not need to be measured. This happens
182      when function is called with a zero timeout or a negative timeout
183      value indicating a blocking call should be performed. */
184
185   if(timeout_ms > 0) {
186     pending_ms = (int)timeout_ms;
187     initial_tv = curlx_tvnow();
188   }
189
190 #ifdef HAVE_POLL_FINE
191
192   num = 0;
193   if(readfd0 != CURL_SOCKET_BAD) {
194     pfd[num].fd = readfd0;
195     pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
196     pfd[num].revents = 0;
197     num++;
198   }
199   if(readfd1 != CURL_SOCKET_BAD) {
200     pfd[num].fd = readfd1;
201     pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
202     pfd[num].revents = 0;
203     num++;
204   }
205   if(writefd != CURL_SOCKET_BAD) {
206     pfd[num].fd = writefd;
207     pfd[num].events = POLLWRNORM|POLLOUT;
208     pfd[num].revents = 0;
209     num++;
210   }
211
212   do {
213     if(timeout_ms < 0)
214       pending_ms = -1;
215     else if(!timeout_ms)
216       pending_ms = 0;
217     r = poll(pfd, num, pending_ms);
218     if(r != -1)
219       break;
220     error = SOCKERRNO;
221     if(error && ERROR_NOT_EINTR(error))
222       break;
223     if(timeout_ms > 0) {
224       pending_ms = (int)(timeout_ms - ELAPSED_MS());
225       if(pending_ms <= 0) {
226         r = 0;  /* Simulate a "call timed out" case */
227         break;
228       }
229     }
230   } while(r == -1);
231
232   if(r < 0)
233     return -1;
234   if(r == 0)
235     return 0;
236
237   ret = 0;
238   num = 0;
239   if(readfd0 != CURL_SOCKET_BAD) {
240     if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
241       ret |= CURL_CSELECT_IN;
242     if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
243       ret |= CURL_CSELECT_ERR;
244     num++;
245   }
246   if(readfd1 != CURL_SOCKET_BAD) {
247     if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
248       ret |= CURL_CSELECT_IN2;
249     if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
250       ret |= CURL_CSELECT_ERR;
251     num++;
252   }
253   if(writefd != CURL_SOCKET_BAD) {
254     if(pfd[num].revents & (POLLWRNORM|POLLOUT))
255       ret |= CURL_CSELECT_OUT;
256     if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
257       ret |= CURL_CSELECT_ERR;
258   }
259
260   return ret;
261
262 #else  /* HAVE_POLL_FINE */
263
264   FD_ZERO(&fds_err);
265   maxfd = (curl_socket_t)-1;
266
267   FD_ZERO(&fds_read);
268   if(readfd0 != CURL_SOCKET_BAD) {
269     VERIFY_SOCK(readfd0);
270     FD_SET(readfd0, &fds_read);
271     FD_SET(readfd0, &fds_err);
272     maxfd = readfd0;
273   }
274   if(readfd1 != CURL_SOCKET_BAD) {
275     VERIFY_SOCK(readfd1);
276     FD_SET(readfd1, &fds_read);
277     FD_SET(readfd1, &fds_err);
278     if(readfd1 > maxfd)
279       maxfd = readfd1;
280   }
281
282   FD_ZERO(&fds_write);
283   if(writefd != CURL_SOCKET_BAD) {
284     VERIFY_SOCK(writefd);
285     FD_SET(writefd, &fds_write);
286     FD_SET(writefd, &fds_err);
287     if(writefd > maxfd)
288       maxfd = writefd;
289   }
290
291   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
292
293   do {
294     if(timeout_ms > 0) {
295       pending_tv.tv_sec = pending_ms / 1000;
296       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
297     }
298     else if(!timeout_ms) {
299       pending_tv.tv_sec = 0;
300       pending_tv.tv_usec = 0;
301     }
302
303     /* WinSock select() must not be called with an fd_set that contains zero
304        fd flags, or it will return WSAEINVAL.  But, it also can't be called
305        with no fd_sets at all!  From the documentation:
306
307          Any two of the parameters, readfds, writefds, or exceptfds, can be
308          given as null. At least one must be non-null, and any non-null
309          descriptor set must contain at least one handle to a socket.
310
311        We know that we have at least one bit set in at least two fd_sets in
312        this case, but we may have no bits set in either fds_read or fd_write,
313        so check for that and handle it.  Luckily, with WinSock, we can _also_
314        ask how many bits are set on an fd_set.
315
316        It is unclear why WinSock doesn't just handle this for us instead of
317        calling this an error.
318
319        Note also that WinSock ignores the first argument, so we don't worry
320        about the fact that maxfd is computed incorrectly with WinSock (since
321        curl_socket_t is unsigned in such cases and thus -1 is the largest
322        value).
323     */
324 #ifdef USE_WINSOCK
325     r = select((int)maxfd + 1,
326                fds_read.fd_count ? &fds_read : NULL,
327                fds_write.fd_count ? &fds_write : NULL,
328                &fds_err, ptimeout);
329 #else
330     r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
331 #endif
332
333     if(r != -1)
334       break;
335     error = SOCKERRNO;
336     if(error && ERROR_NOT_EINTR(error))
337       break;
338     if(timeout_ms > 0) {
339       pending_ms = (int)(timeout_ms - ELAPSED_MS());
340       if(pending_ms <= 0) {
341         r = 0;  /* Simulate a "call timed out" case */
342         break;
343       }
344     }
345   } while(r == -1);
346
347   if(r < 0)
348     return -1;
349   if(r == 0)
350     return 0;
351
352   ret = 0;
353   if(readfd0 != CURL_SOCKET_BAD) {
354     if(FD_ISSET(readfd0, &fds_read))
355       ret |= CURL_CSELECT_IN;
356     if(FD_ISSET(readfd0, &fds_err))
357       ret |= CURL_CSELECT_ERR;
358   }
359   if(readfd1 != CURL_SOCKET_BAD) {
360     if(FD_ISSET(readfd1, &fds_read))
361       ret |= CURL_CSELECT_IN2;
362     if(FD_ISSET(readfd1, &fds_err))
363       ret |= CURL_CSELECT_ERR;
364   }
365   if(writefd != CURL_SOCKET_BAD) {
366     if(FD_ISSET(writefd, &fds_write))
367       ret |= CURL_CSELECT_OUT;
368     if(FD_ISSET(writefd, &fds_err))
369       ret |= CURL_CSELECT_ERR;
370   }
371
372   return ret;
373
374 #endif  /* HAVE_POLL_FINE */
375
376 }
377
378 /*
379  * This is a wrapper around poll().  If poll() does not exist, then
380  * select() is used instead.  An error is returned if select() is
381  * being used and a file descriptor is too large for FD_SETSIZE.
382  * A negative timeout value makes this function wait indefinitely,
383  * unles no valid file descriptor is given, when this happens the
384  * negative timeout is ignored and the function times out immediately.
385  *
386  * Return values:
387  *   -1 = system call error or fd >= FD_SETSIZE
388  *    0 = timeout
389  *    N = number of structures with non zero revent fields
390  */
391 int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
392 {
393 #ifndef HAVE_POLL_FINE
394   struct timeval pending_tv;
395   struct timeval *ptimeout;
396   fd_set fds_read;
397   fd_set fds_write;
398   fd_set fds_err;
399   curl_socket_t maxfd;
400 #endif
401   struct timeval initial_tv = {0, 0};
402   bool fds_none = TRUE;
403   unsigned int i;
404   int pending_ms = 0;
405   int error;
406   int r;
407
408   if(ufds) {
409     for(i = 0; i < nfds; i++) {
410       if(ufds[i].fd != CURL_SOCKET_BAD) {
411         fds_none = FALSE;
412         break;
413       }
414     }
415   }
416   if(fds_none) {
417     r = Curl_wait_ms(timeout_ms);
418     return r;
419   }
420
421   /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
422      time in this function does not need to be measured. This happens
423      when function is called with a zero timeout or a negative timeout
424      value indicating a blocking call should be performed. */
425
426   if(timeout_ms > 0) {
427     pending_ms = timeout_ms;
428     initial_tv = curlx_tvnow();
429   }
430
431 #ifdef HAVE_POLL_FINE
432
433   do {
434     if(timeout_ms < 0)
435       pending_ms = -1;
436     else if(!timeout_ms)
437       pending_ms = 0;
438     r = poll(ufds, nfds, pending_ms);
439     if(r != -1)
440       break;
441     error = SOCKERRNO;
442     if(error && ERROR_NOT_EINTR(error))
443       break;
444     if(timeout_ms > 0) {
445       pending_ms = (int)(timeout_ms - ELAPSED_MS());
446       if(pending_ms <= 0) {
447         r = 0;  /* Simulate a "call timed out" case */
448         break;
449       }
450     }
451   } while(r == -1);
452
453   if(r < 0)
454     return -1;
455   if(r == 0)
456     return 0;
457
458   for(i = 0; i < nfds; i++) {
459     if(ufds[i].fd == CURL_SOCKET_BAD)
460       continue;
461     if(ufds[i].revents & POLLHUP)
462       ufds[i].revents |= POLLIN;
463     if(ufds[i].revents & POLLERR)
464       ufds[i].revents |= (POLLIN|POLLOUT);
465   }
466
467 #else  /* HAVE_POLL_FINE */
468
469   FD_ZERO(&fds_read);
470   FD_ZERO(&fds_write);
471   FD_ZERO(&fds_err);
472   maxfd = (curl_socket_t)-1;
473
474   for(i = 0; i < nfds; i++) {
475     ufds[i].revents = 0;
476     if(ufds[i].fd == CURL_SOCKET_BAD)
477       continue;
478     VERIFY_SOCK(ufds[i].fd);
479     if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
480                           POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
481       if(ufds[i].fd > maxfd)
482         maxfd = ufds[i].fd;
483       if(ufds[i].events & (POLLRDNORM|POLLIN))
484         FD_SET(ufds[i].fd, &fds_read);
485       if(ufds[i].events & (POLLWRNORM|POLLOUT))
486         FD_SET(ufds[i].fd, &fds_write);
487       if(ufds[i].events & (POLLRDBAND|POLLPRI))
488         FD_SET(ufds[i].fd, &fds_err);
489     }
490   }
491
492 #ifdef USE_WINSOCK
493   /* WinSock select() can't handle zero events.  See the comment about this in
494      Curl_check_socket(). */
495   if(fds_read.fd_count == 0 && fds_write.fd_count == 0
496      && fds_err.fd_count == 0) {
497     r = Curl_wait_ms(timeout_ms);
498     return r;
499   }
500 #endif
501
502   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
503
504   do {
505     if(timeout_ms > 0) {
506       pending_tv.tv_sec = pending_ms / 1000;
507       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
508     }
509     else if(!timeout_ms) {
510       pending_tv.tv_sec = 0;
511       pending_tv.tv_usec = 0;
512     }
513
514 #ifdef USE_WINSOCK
515     r = select((int)maxfd + 1,
516                /* WinSock select() can't handle fd_sets with zero bits set, so
517                   don't give it such arguments.  See the comment about this in
518                   Curl_check_socket().
519                */
520                fds_read.fd_count ? &fds_read : NULL,
521                fds_write.fd_count ? &fds_write : NULL,
522                fds_err.fd_count ? &fds_err : NULL, ptimeout);
523 #else
524     r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
525 #endif
526     if(r != -1)
527       break;
528     error = SOCKERRNO;
529     if(error && ERROR_NOT_EINTR(error))
530       break;
531     if(timeout_ms > 0) {
532       pending_ms = timeout_ms - ELAPSED_MS();
533       if(pending_ms <= 0) {
534         r = 0;  /* Simulate a "call timed out" case */
535         break;
536       }
537     }
538   } while(r == -1);
539
540   if(r < 0)
541     return -1;
542   if(r == 0)
543     return 0;
544
545   r = 0;
546   for(i = 0; i < nfds; i++) {
547     ufds[i].revents = 0;
548     if(ufds[i].fd == CURL_SOCKET_BAD)
549       continue;
550     if(FD_ISSET(ufds[i].fd, &fds_read))
551       ufds[i].revents |= POLLIN;
552     if(FD_ISSET(ufds[i].fd, &fds_write))
553       ufds[i].revents |= POLLOUT;
554     if(FD_ISSET(ufds[i].fd, &fds_err))
555       ufds[i].revents |= POLLPRI;
556     if(ufds[i].revents != 0)
557       r++;
558   }
559
560 #endif  /* HAVE_POLL_FINE */
561
562   return r;
563 }
564
565 #ifdef TPF
566 /*
567  * This is a replacement for select() on the TPF platform.
568  * It is used whenever libcurl calls select().
569  * The call below to tpf_process_signals() is required because
570  * TPF's select calls are not signal interruptible.
571  *
572  * Return values are the same as select's.
573  */
574 int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
575                        fd_set* excepts, struct timeval* tv)
576 {
577    int rc;
578
579    rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
580    tpf_process_signals();
581    return rc;
582 }
583 #endif /* TPF */