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