• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
Curl_wait_ms(int timeout_ms)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  */
Curl_socket_check(curl_socket_t readfd0,curl_socket_t readfd1,curl_socket_t writefd,time_t timeout_ms)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  */
Curl_poll(struct pollfd ufds[],unsigned int nfds,int timeout_ms)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  */
tpf_select_libcurl(int maxfds,fd_set * reads,fd_set * writes,fd_set * excepts,struct timeval * tv)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