• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2015, 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 http://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  */
Curl_wait_ms(int timeout_ms)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  */
Curl_socket_check(curl_socket_t readfd0,curl_socket_t readfd1,curl_socket_t writefd,long timeout_ms)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     r = select((int)maxfd + 1,
320 #ifndef USE_WINSOCK
321                &fds_read,
322                &fds_write,
323 #else
324                fds_read.fd_count ? &fds_read : NULL,
325                fds_write.fd_count ? &fds_write : NULL,
326 #endif
327                &fds_err, ptimeout);
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  */
Curl_poll(struct pollfd ufds[],unsigned int nfds,int timeout_ms)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     r = select((int)maxfd + 1,
509 #ifndef USE_WINSOCK
510                &fds_read, &fds_write, &fds_err,
511 #else
512                /* WinSock select() can't handle fd_sets with zero bits set, so
513                   don't give it such arguments.  See the comment about this in
514                   Curl_check_socket().
515                */
516                fds_read.fd_count ? &fds_read : NULL,
517                fds_write.fd_count ? &fds_write : NULL,
518                fds_err.fd_count ? &fds_err : NULL,
519 #endif
520                ptimeout);
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  */
tpf_select_libcurl(int maxfds,fd_set * reads,fd_set * writes,fd_set * excepts,struct timeval * tv)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