Home | History | Annotate | Download | only in lib
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel (at) 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)Curl_timediff(Curl_now(), 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 curltime 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 = Curl_now();
    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  * unless 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 curltime initial_tv = {0, 0};
    162   int pending_ms = 0;
    163   int error;
    164   int r;
    165   int ret;
    166 
    167 #if SIZEOF_TIME_T != 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 Curl_now() 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 = Curl_now();
    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  * unless 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 curltime 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 Curl_now() 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 = Curl_now();
    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 */
    584