• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, 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)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  */
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 curltime initial_tv;
82   int pending_ms;
83 #endif
84   int r = 0;
85 
86   if(!timeout_ms)
87     return 0;
88   if(timeout_ms < 0) {
89     SET_SOCKERRNO(EINVAL);
90     return -1;
91   }
92 #if defined(MSDOS)
93   delay(timeout_ms);
94 #elif defined(USE_WINSOCK)
95   Sleep(timeout_ms);
96 #else
97   pending_ms = timeout_ms;
98   initial_tv = Curl_now();
99   do {
100     int error;
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  */
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 curltime initial_tv = {0, 0};
162   int pending_ms = 0;
163   int r;
164   int ret;
165 
166 #if SIZEOF_TIME_T != SIZEOF_INT
167   /* wrap-around precaution */
168   if(timeout_ms >= INT_MAX)
169     timeout_ms = INT_MAX;
170 #endif
171 
172   if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
173      (writefd == CURL_SOCKET_BAD)) {
174     /* no sockets, just wait */
175     r = Curl_wait_ms((int)timeout_ms);
176     return r;
177   }
178 
179   /* Avoid initial timestamp, avoid Curl_now() call, when elapsed
180      time in this function does not need to be measured. This happens
181      when function is called with a zero timeout or a negative timeout
182      value indicating a blocking call should be performed. */
183 
184   if(timeout_ms > 0) {
185     pending_ms = (int)timeout_ms;
186     initial_tv = Curl_now();
187   }
188 
189 #ifdef HAVE_POLL_FINE
190 
191   num = 0;
192   if(readfd0 != CURL_SOCKET_BAD) {
193     pfd[num].fd = readfd0;
194     pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
195     pfd[num].revents = 0;
196     num++;
197   }
198   if(readfd1 != CURL_SOCKET_BAD) {
199     pfd[num].fd = readfd1;
200     pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
201     pfd[num].revents = 0;
202     num++;
203   }
204   if(writefd != CURL_SOCKET_BAD) {
205     pfd[num].fd = writefd;
206     pfd[num].events = POLLWRNORM|POLLOUT;
207     pfd[num].revents = 0;
208     num++;
209   }
210 
211   do {
212     int error;
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     int error;
295     if(timeout_ms > 0) {
296       pending_tv.tv_sec = pending_ms / 1000;
297       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
298     }
299     else if(!timeout_ms) {
300       pending_tv.tv_sec = 0;
301       pending_tv.tv_usec = 0;
302     }
303 
304     /* WinSock select() must not be called with an fd_set that contains zero
305        fd flags, or it will return WSAEINVAL.  But, it also can't be called
306        with no fd_sets at all!  From the documentation:
307 
308          Any two of the parameters, readfds, writefds, or exceptfds, can be
309          given as null. At least one must be non-null, and any non-null
310          descriptor set must contain at least one handle to a socket.
311 
312        We know that we have at least one bit set in at least two fd_sets in
313        this case, but we may have no bits set in either fds_read or fd_write,
314        so check for that and handle it.  Luckily, with WinSock, we can _also_
315        ask how many bits are set on an fd_set.
316 
317        It is unclear why WinSock doesn't just handle this for us instead of
318        calling this an error.
319 
320        Note also that WinSock ignores the first argument, so we don't worry
321        about the fact that maxfd is computed incorrectly with WinSock (since
322        curl_socket_t is unsigned in such cases and thus -1 is the largest
323        value).
324     */
325 #ifdef USE_WINSOCK
326     r = select((int)maxfd + 1,
327                fds_read.fd_count ? &fds_read : NULL,
328                fds_write.fd_count ? &fds_write : NULL,
329                &fds_err, ptimeout);
330 #else
331     r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
332 #endif
333 
334     if(r != -1)
335       break;
336     error = SOCKERRNO;
337     if(error && ERROR_NOT_EINTR(error))
338       break;
339     if(timeout_ms > 0) {
340       pending_ms = (int)(timeout_ms - ELAPSED_MS());
341       if(pending_ms <= 0) {
342         r = 0;  /* Simulate a "call timed out" case */
343         break;
344       }
345     }
346   } while(r == -1);
347 
348   if(r < 0)
349     return -1;
350   if(r == 0)
351     return 0;
352 
353   ret = 0;
354   if(readfd0 != CURL_SOCKET_BAD) {
355     if(FD_ISSET(readfd0, &fds_read))
356       ret |= CURL_CSELECT_IN;
357     if(FD_ISSET(readfd0, &fds_err))
358       ret |= CURL_CSELECT_ERR;
359   }
360   if(readfd1 != CURL_SOCKET_BAD) {
361     if(FD_ISSET(readfd1, &fds_read))
362       ret |= CURL_CSELECT_IN2;
363     if(FD_ISSET(readfd1, &fds_err))
364       ret |= CURL_CSELECT_ERR;
365   }
366   if(writefd != CURL_SOCKET_BAD) {
367     if(FD_ISSET(writefd, &fds_write))
368       ret |= CURL_CSELECT_OUT;
369     if(FD_ISSET(writefd, &fds_err))
370       ret |= CURL_CSELECT_ERR;
371   }
372 
373   return ret;
374 
375 #endif  /* HAVE_POLL_FINE */
376 
377 }
378 
379 /*
380  * This is a wrapper around poll().  If poll() does not exist, then
381  * select() is used instead.  An error is returned if select() is
382  * being used and a file descriptor is too large for FD_SETSIZE.
383  * A negative timeout value makes this function wait indefinitely,
384  * unless no valid file descriptor is given, when this happens the
385  * negative timeout is ignored and the function times out immediately.
386  *
387  * Return values:
388  *   -1 = system call error or fd >= FD_SETSIZE
389  *    0 = timeout
390  *    N = number of structures with non zero revent fields
391  */
Curl_poll(struct pollfd ufds[],unsigned int nfds,int timeout_ms)392 int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
393 {
394 #ifndef HAVE_POLL_FINE
395   struct timeval pending_tv;
396   struct timeval *ptimeout;
397   fd_set fds_read;
398   fd_set fds_write;
399   fd_set fds_err;
400   curl_socket_t maxfd;
401 #endif
402   struct curltime initial_tv = {0, 0};
403   bool fds_none = TRUE;
404   unsigned int i;
405   int pending_ms = 0;
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     int error;
435     if(timeout_ms < 0)
436       pending_ms = -1;
437     else if(!timeout_ms)
438       pending_ms = 0;
439     r = poll(ufds, nfds, pending_ms);
440     if(r != -1)
441       break;
442     error = SOCKERRNO;
443     if(error && ERROR_NOT_EINTR(error))
444       break;
445     if(timeout_ms > 0) {
446       pending_ms = (int)(timeout_ms - ELAPSED_MS());
447       if(pending_ms <= 0) {
448         r = 0;  /* Simulate a "call timed out" case */
449         break;
450       }
451     }
452   } while(r == -1);
453 
454   if(r < 0)
455     return -1;
456   if(r == 0)
457     return 0;
458 
459   for(i = 0; i < nfds; i++) {
460     if(ufds[i].fd == CURL_SOCKET_BAD)
461       continue;
462     if(ufds[i].revents & POLLHUP)
463       ufds[i].revents |= POLLIN;
464     if(ufds[i].revents & POLLERR)
465       ufds[i].revents |= (POLLIN|POLLOUT);
466   }
467 
468 #else  /* HAVE_POLL_FINE */
469 
470   FD_ZERO(&fds_read);
471   FD_ZERO(&fds_write);
472   FD_ZERO(&fds_err);
473   maxfd = (curl_socket_t)-1;
474 
475   for(i = 0; i < nfds; i++) {
476     ufds[i].revents = 0;
477     if(ufds[i].fd == CURL_SOCKET_BAD)
478       continue;
479     VERIFY_SOCK(ufds[i].fd);
480     if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
481                           POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
482       if(ufds[i].fd > maxfd)
483         maxfd = ufds[i].fd;
484       if(ufds[i].events & (POLLRDNORM|POLLIN))
485         FD_SET(ufds[i].fd, &fds_read);
486       if(ufds[i].events & (POLLWRNORM|POLLOUT))
487         FD_SET(ufds[i].fd, &fds_write);
488       if(ufds[i].events & (POLLRDBAND|POLLPRI))
489         FD_SET(ufds[i].fd, &fds_err);
490     }
491   }
492 
493 #ifdef USE_WINSOCK
494   /* WinSock select() can't handle zero events.  See the comment about this in
495      Curl_check_socket(). */
496   if(fds_read.fd_count == 0 && fds_write.fd_count == 0
497      && fds_err.fd_count == 0) {
498     r = Curl_wait_ms(timeout_ms);
499     return r;
500   }
501 #endif
502 
503   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
504 
505   do {
506     int error;
507     if(timeout_ms > 0) {
508       pending_tv.tv_sec = pending_ms / 1000;
509       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
510     }
511     else if(!timeout_ms) {
512       pending_tv.tv_sec = 0;
513       pending_tv.tv_usec = 0;
514     }
515 
516 #ifdef USE_WINSOCK
517     r = select((int)maxfd + 1,
518                /* WinSock select() can't handle fd_sets with zero bits set, so
519                   don't give it such arguments.  See the comment about this in
520                   Curl_check_socket().
521                */
522                fds_read.fd_count ? &fds_read : NULL,
523                fds_write.fd_count ? &fds_write : NULL,
524                fds_err.fd_count ? &fds_err : NULL, ptimeout);
525 #else
526     r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
527 #endif
528     if(r != -1)
529       break;
530     error = SOCKERRNO;
531     if(error && ERROR_NOT_EINTR(error))
532       break;
533     if(timeout_ms > 0) {
534       pending_ms = timeout_ms - ELAPSED_MS();
535       if(pending_ms <= 0) {
536         r = 0;  /* Simulate a "call timed out" case */
537         break;
538       }
539     }
540   } while(r == -1);
541 
542   if(r < 0)
543     return -1;
544   if(r == 0)
545     return 0;
546 
547   r = 0;
548   for(i = 0; i < nfds; i++) {
549     ufds[i].revents = 0;
550     if(ufds[i].fd == CURL_SOCKET_BAD)
551       continue;
552     if(FD_ISSET(ufds[i].fd, &fds_read))
553       ufds[i].revents |= POLLIN;
554     if(FD_ISSET(ufds[i].fd, &fds_write))
555       ufds[i].revents |= POLLOUT;
556     if(FD_ISSET(ufds[i].fd, &fds_err))
557       ufds[i].revents |= POLLPRI;
558     if(ufds[i].revents != 0)
559       r++;
560   }
561 
562 #endif  /* HAVE_POLL_FINE */
563 
564   return r;
565 }
566 
567 #ifdef TPF
568 /*
569  * This is a replacement for select() on the TPF platform.
570  * It is used whenever libcurl calls select().
571  * The call below to tpf_process_signals() is required because
572  * TPF's select calls are not signal interruptible.
573  *
574  * Return values are the same as select's.
575  */
tpf_select_libcurl(int maxfds,fd_set * reads,fd_set * writes,fd_set * excepts,struct timeval * tv)576 int tpf_select_libcurl(int maxfds, fd_set *reads, fd_set *writes,
577                        fd_set *excepts, struct timeval *tv)
578 {
579    int rc;
580 
581    rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
582    tpf_process_signals();
583    return rc;
584 }
585 #endif /* TPF */
586