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