keep lines < 80 columns
[platform/upstream/curl.git] / lib / select.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2007, 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  * $Id$
22  ***************************************************************************/
23
24 #include "setup.h"
25
26 #ifdef HAVE_SYS_SELECT_H
27 #include <sys/select.h>
28 #endif
29 #ifdef HAVE_SYS_TIME_H
30 #include <sys/time.h>
31 #endif
32
33 #if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE)
34 #error "We can't compile without select() or poll() support."
35 #endif
36
37 #ifdef __BEOS__
38 /* BeOS has FD_SET defined in socket.h */
39 #include <socket.h>
40 #endif
41
42 #ifdef MSDOS
43 #include <dos.h>  /* delay() */
44 #endif
45
46 #include <curl/curl.h>
47
48 #include "urldata.h"
49 #include "connect.h"
50 #include "select.h"
51
52 /* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1] */
53
54 #if defined(USE_WINSOCK) || defined(TPF)
55 #define VERIFY_SOCK(x) do { } while (0)
56 #define VERIFY_NFDS(x) do { } while (0)
57 #else
58 #define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
59 #define VERIFY_SOCK(x) do { \
60   if(!VALID_SOCK(x)) { \
61     SET_SOCKERRNO(EINVAL); \
62     return -1; \
63   } \
64 } while(0)
65 #define VALID_NFDS(n) (((n) >= 0) && ((n) <= FD_SETSIZE))
66 #define VERIFY_NFDS(x) do { \
67   if(!VALID_NFDS(x)) { \
68     SET_SOCKERRNO(EINVAL); \
69     return -1; \
70   } \
71 } while(0)
72 #endif
73
74 /* Convenience local macros */
75
76 #define elapsed_ms  (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
77
78 #ifdef CURL_ACKNOWLEDGE_EINTR
79 #define error_not_EINTR  (error != EINTR)
80 #else
81 #define error_not_EINTR  (1)
82 #endif
83
84 #define SMALL_POLLNFDS  0X20
85
86 /*
87  * Internal function used for waiting a specific amount of ms
88  * in Curl_socket_ready() and Curl_poll() when no file descriptor
89  * is provided to wait on, just being used to delay execution.
90  * WinSock select() and poll() timeout mechanisms need a valid
91  * socket descriptor in a not null file descriptor set to work.
92  * Waiting indefinitely with this function is not allowed, a
93  * zero or negative timeout value will return immediately.
94  * Timeout resolution, accuracy, as well as maximum supported
95  * value is system dependant, neither factor is a citical issue
96  * for the intended use of this function in the library.
97  * On non-DOS and non-Winsock platforms, when compiled with
98  * CURL_ACKNOWLEDGE_EINTR defined, EINTR condition is honored
99  * and function might exit early without awaiting full timeout,
100  * otherwise EINTR will be ignored and full timeout will elapse.
101  *
102  * Return values:
103  *   -1 = system call error, invalid timeout value, or interrupted
104  *    0 = specified timeout has elapsed
105  */
106 static int wait_ms(int timeout_ms)
107 {
108 #if !defined(MSDOS) && !defined(USE_WINSOCK)
109 #ifndef HAVE_POLL_FINE
110   struct timeval pending_tv;
111 #endif
112   struct timeval initial_tv;
113   int pending_ms;
114   int error;
115 #endif
116   int r = 0;
117
118   if (!timeout_ms)
119     return 0;
120   if (timeout_ms < 0) {
121     SET_SOCKERRNO(EINVAL);
122     return -1;
123   }
124 #if defined(MSDOS)
125   delay(timeout_ms);
126 #elif defined(USE_WINSOCK)
127   Sleep(timeout_ms);
128 #else
129   pending_ms = timeout_ms;
130   initial_tv = curlx_tvnow();
131   do {
132 #if defined(HAVE_POLL_FINE)
133     r = poll(NULL, 0, pending_ms);
134 #else
135     pending_tv.tv_sec = pending_ms / 1000;
136     pending_tv.tv_usec = (pending_ms % 1000) * 1000;
137     r = select(0, NULL, NULL, NULL, &pending_tv);
138 #endif /* HAVE_POLL_FINE */
139   } while ((r == -1) && (error = SOCKERRNO) &&
140            (error != EINVAL) && error_not_EINTR &&
141            ((pending_ms = timeout_ms - elapsed_ms) > 0));
142 #endif /* USE_WINSOCK */
143   if (r)
144     r = -1;
145   return r;
146 }
147
148 /*
149  * This is an internal function used for waiting for read or write
150  * events on a pair of file descriptors.  It uses poll() when a fine
151  * poll() is available, in order to avoid limits with FD_SETSIZE,
152  * otherwise select() is used.  An error is returned if select() is
153  * being used and a file descriptor is too large for FD_SETSIZE.
154  * A negative timeout value makes this function wait indefinitely,
155  * unles no valid file descriptor is given, when this happens the
156  * negative timeout is ignored and the function times out immediately.
157  * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition
158  * is honored and function might exit early without awaiting timeout,
159  * otherwise EINTR will be ignored.
160  *
161  * Return values:
162  *   -1 = system call error or fd >= FD_SETSIZE
163  *    0 = timeout
164  *    CURL_CSELECT_IN | CURL_CSELECT_OUT | CURL_CSELECT_ERR
165  */
166 int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd,
167                       int timeout_ms)
168 {
169 #ifdef HAVE_POLL_FINE
170   struct pollfd pfd[2];
171   int num;
172 #else
173   struct timeval pending_tv;
174   struct timeval *ptimeout;
175   fd_set fds_read;
176   fd_set fds_write;
177   fd_set fds_err;
178   curl_socket_t maxfd;
179 #endif
180   struct timeval initial_tv;
181   int pending_ms;
182   int error;
183   int r;
184   int ret;
185
186   if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) {
187     r = wait_ms(timeout_ms);
188     return r;
189   }
190
191   pending_ms = timeout_ms;
192   initial_tv = curlx_tvnow();
193
194 #ifdef HAVE_POLL_FINE
195
196   num = 0;
197   if (readfd != CURL_SOCKET_BAD) {
198     pfd[num].fd = readfd;
199     pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
200     pfd[num].revents = 0;
201     num++;
202   }
203   if (writefd != CURL_SOCKET_BAD) {
204     pfd[num].fd = writefd;
205     pfd[num].events = POLLWRNORM|POLLOUT;
206     pfd[num].revents = 0;
207     num++;
208   }
209
210   do {
211     if (timeout_ms < 0)
212       pending_ms = -1;
213     r = poll(pfd, num, pending_ms);
214   } while ((r == -1) && (error = SOCKERRNO) &&
215            (error != EINVAL) && error_not_EINTR &&
216            ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
217
218   if (r < 0)
219     return -1;
220   if (r == 0)
221     return 0;
222
223   ret = 0;
224   num = 0;
225   if (readfd != CURL_SOCKET_BAD) {
226     if (pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
227       ret |= CURL_CSELECT_IN;
228     if (pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
229       ret |= CURL_CSELECT_ERR;
230     num++;
231   }
232   if (writefd != CURL_SOCKET_BAD) {
233     if (pfd[num].revents & (POLLWRNORM|POLLOUT))
234       ret |= CURL_CSELECT_OUT;
235     if (pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
236       ret |= CURL_CSELECT_ERR;
237   }
238
239   return ret;
240
241 #else  /* HAVE_POLL_FINE */
242
243   FD_ZERO(&fds_err);
244   maxfd = (curl_socket_t)-1;
245
246   FD_ZERO(&fds_read);
247   if (readfd != CURL_SOCKET_BAD) {
248     VERIFY_SOCK(readfd);
249     FD_SET(readfd, &fds_read);
250     FD_SET(readfd, &fds_err);
251     maxfd = readfd;
252   }
253
254   FD_ZERO(&fds_write);
255   if (writefd != CURL_SOCKET_BAD) {
256     VERIFY_SOCK(writefd);
257     FD_SET(writefd, &fds_write);
258     FD_SET(writefd, &fds_err);
259     if (writefd > maxfd)
260       maxfd = writefd;
261   }
262
263   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
264
265   do {
266     if (ptimeout) {
267       pending_tv.tv_sec = pending_ms / 1000;
268       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
269     }
270     r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
271   } while ((r == -1) && (error = SOCKERRNO) &&
272            (error != EINVAL) && (error != EBADF) && error_not_EINTR &&
273            ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
274
275   if (r < 0)
276     return -1;
277   if (r == 0)
278     return 0;
279
280   ret = 0;
281   if (readfd != CURL_SOCKET_BAD) {
282     if (FD_ISSET(readfd, &fds_read))
283       ret |= CURL_CSELECT_IN;
284     if (FD_ISSET(readfd, &fds_err))
285       ret |= CURL_CSELECT_ERR;
286   }
287   if (writefd != CURL_SOCKET_BAD) {
288     if (FD_ISSET(writefd, &fds_write))
289       ret |= CURL_CSELECT_OUT;
290     if (FD_ISSET(writefd, &fds_err))
291       ret |= CURL_CSELECT_ERR;
292   }
293
294   return ret;
295
296 #endif  /* HAVE_POLL_FINE */
297
298 }
299
300 /*
301  * This is a wrapper around poll().  If poll() does not exist, then
302  * select() is used instead.  An error is returned if select() is
303  * being used and a file descriptor is too large for FD_SETSIZE.
304  * A negative timeout value makes this function wait indefinitely,
305  * unles no valid file descriptor is given, when this happens the
306  * negative timeout is ignored and the function times out immediately.
307  * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition
308  * is honored and function might exit early without awaiting timeout,
309  * otherwise EINTR will be ignored.
310  *
311  * Return values:
312  *   -1 = system call error or fd >= FD_SETSIZE
313  *    0 = timeout
314  *    N = number of structures with non zero revent fields
315  */
316 int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
317 {
318 #ifndef HAVE_POLL_FINE
319   struct timeval pending_tv;
320   struct timeval *ptimeout;
321   fd_set fds_read;
322   fd_set fds_write;
323   fd_set fds_err;
324   curl_socket_t maxfd;
325 #endif
326   struct timeval initial_tv;
327   bool fds_none = TRUE;
328   unsigned int i;
329   int pending_ms;
330   int error;
331   int r;
332
333   if (ufds) {
334     for (i = 0; i < nfds; i++) {
335       if (ufds[i].fd != CURL_SOCKET_BAD) {
336         fds_none = FALSE;
337         break;
338       }
339     }
340   }
341   if (fds_none) {
342     r = wait_ms(timeout_ms);
343     return r;
344   }
345
346   pending_ms = timeout_ms;
347   initial_tv = curlx_tvnow();
348
349 #ifdef HAVE_POLL_FINE
350
351   do {
352     if (timeout_ms < 0)
353       pending_ms = -1;
354     r = poll(ufds, nfds, pending_ms);
355   } while ((r == -1) && (error = SOCKERRNO) &&
356            (error != EINVAL) && error_not_EINTR &&
357            ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
358
359 #else  /* HAVE_POLL_FINE */
360
361   FD_ZERO(&fds_read);
362   FD_ZERO(&fds_write);
363   FD_ZERO(&fds_err);
364   maxfd = (curl_socket_t)-1;
365
366   for (i = 0; i < nfds; i++) {
367     ufds[i].revents = 0;
368     if (ufds[i].fd == CURL_SOCKET_BAD)
369       continue;
370     VERIFY_SOCK(ufds[i].fd);
371     if (ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
372                           POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
373       if (ufds[i].fd > maxfd)
374         maxfd = ufds[i].fd;
375       if (ufds[i].events & (POLLRDNORM|POLLIN))
376         FD_SET(ufds[i].fd, &fds_read);
377       if (ufds[i].events & (POLLWRNORM|POLLOUT))
378         FD_SET(ufds[i].fd, &fds_write);
379       if (ufds[i].events & (POLLRDBAND|POLLPRI))
380         FD_SET(ufds[i].fd, &fds_err);
381     }
382   }
383
384   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
385
386   do {
387     if (ptimeout) {
388       pending_tv.tv_sec = pending_ms / 1000;
389       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
390     }
391     r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
392   } while ((r == -1) && (error = SOCKERRNO) &&
393            (error != EINVAL) && (error != EBADF) && error_not_EINTR &&
394            ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
395
396   if (r < 0)
397     return -1;
398   if (r == 0)
399     return 0;
400
401   r = 0;
402   for (i = 0; i < nfds; i++) {
403     ufds[i].revents = 0;
404     if (ufds[i].fd == CURL_SOCKET_BAD)
405       continue;
406     if (FD_ISSET(ufds[i].fd, &fds_read))
407       ufds[i].revents |= POLLIN;
408     if (FD_ISSET(ufds[i].fd, &fds_write))
409       ufds[i].revents |= POLLOUT;
410     if (FD_ISSET(ufds[i].fd, &fds_err))
411       ufds[i].revents |= POLLPRI;
412     if (ufds[i].revents != 0)
413       r++;
414   }
415
416 #endif  /* HAVE_POLL_FINE */
417
418   return r;
419 }
420
421 /*
422  * This is a wrapper around select().  It uses poll() when a fine
423  * poll() is available, in order to avoid limits with FD_SETSIZE,
424  * otherwise select() is used.  An error is returned if select() is
425  * being used and a the number of file descriptors is larger than
426  * FD_SETSIZE.  A NULL timeout pointer makes this function wait
427  * indefinitely, unles no valid file descriptor is given, when this
428  * happens the NULL timeout is ignored and the function times out
429  * immediately.  When compiled with CURL_ACKNOWLEDGE_EINTR defined,
430  * EINTR condition is honored and function might exit early without
431  * awaiting timeout, otherwise EINTR will be ignored.
432  *
433  * Return values:
434  *   -1 = system call error or nfds > FD_SETSIZE
435  *    0 = timeout
436  *    N = number of file descriptors kept in file descriptor sets.
437  */
438 int Curl_select(int nfds,
439                 fd_set *fds_read, fd_set *fds_write, fd_set *fds_excep,
440                 struct timeval *timeout)
441 {
442   struct timeval initial_tv;
443   int timeout_ms;
444   int pending_ms;
445   int error;
446   int r;
447 #ifdef HAVE_POLL_FINE
448   struct pollfd small_fds[SMALL_POLLNFDS];
449   struct pollfd *poll_fds;
450   int ix;
451   int fd;
452   int poll_nfds = 0;
453 #else
454   struct timeval pending_tv;
455   struct timeval *ptimeout;
456 #endif
457   int ret = 0;
458
459   if ((nfds < 0) ||
460      ((nfds > 0) && (!fds_read && !fds_write && !fds_excep))) {
461     SET_SOCKERRNO(EINVAL);
462     return -1;
463   }
464
465   if (timeout) {
466     if ((timeout->tv_sec < 0) ||
467         (timeout->tv_usec < 0) ||
468         (timeout->tv_usec >= 1000000)) {
469       SET_SOCKERRNO(EINVAL);
470       return -1;
471     }
472     timeout_ms = (int)(timeout->tv_sec * 1000) +
473       (int)(timeout->tv_usec / 1000);
474   }
475   else {
476     timeout_ms = -1;
477   }
478
479   if ((!nfds) || (!fds_read && !fds_write && !fds_excep)) {
480     r = wait_ms(timeout_ms);
481     return r;
482   }
483
484   pending_ms = timeout_ms;
485   initial_tv = curlx_tvnow();
486
487 #ifdef HAVE_POLL_FINE
488
489   if (fds_read || fds_write || fds_excep) {
490     fd = nfds;
491     while (fd--) {
492       if ((fds_read && (0 != FD_ISSET(fd, fds_read))) ||
493           (fds_write && (0 != FD_ISSET(fd, fds_write))) ||
494           (fds_excep && (0 != FD_ISSET(fd, fds_excep))))
495         poll_nfds++;
496     }
497   }
498
499   if (!poll_nfds)
500     poll_fds = NULL;
501   else if (poll_nfds <= SMALL_POLLNFDS)
502     poll_fds = small_fds;
503   else {
504     poll_fds = calloc((size_t)poll_nfds, sizeof(struct pollfd));
505     if (!poll_fds) {
506       SET_SOCKERRNO(ENOBUFS);
507       return -1;
508     }
509   }
510
511   if (poll_fds) {
512     ix = 0;
513     fd = nfds;
514     while (fd--) {
515       poll_fds[ix].events = 0;
516       if (fds_read && (0 != FD_ISSET(fd, fds_read)))
517         poll_fds[ix].events |= (POLLRDNORM|POLLIN);
518       if (fds_write && (0 != FD_ISSET(fd, fds_write)))
519         poll_fds[ix].events |= (POLLWRNORM|POLLOUT);
520       if (fds_excep && (0 != FD_ISSET(fd, fds_excep)))
521         poll_fds[ix].events |= (POLLRDBAND|POLLPRI);
522       if (poll_fds[ix].events) {
523         poll_fds[ix].fd = fd;
524         poll_fds[ix].revents = 0;
525         ix++;
526       }
527     }
528   }
529
530   do {
531     if (timeout_ms < 0)
532       pending_ms = -1;
533     r = poll(poll_fds, poll_nfds, pending_ms);
534   } while ((r == -1) && (error = SOCKERRNO) &&
535            (error != EINVAL) && error_not_EINTR &&
536            ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
537
538   if (r < 0)
539     ret = -1;
540
541   if (r > 0) {
542     ix = poll_nfds;
543     while (ix--) {
544       if (poll_fds[ix].revents & POLLNVAL) {
545         SET_SOCKERRNO(EBADF);
546         ret = -1;
547         break;
548       }
549     }
550   }
551
552   if (!ret) {
553     ix = poll_nfds;
554     while (ix--) {
555       if (fds_read && (0 != FD_ISSET(poll_fds[ix].fd, fds_read))) {
556         if (0 == (poll_fds[ix].revents & (POLLRDNORM|POLLERR|POLLHUP|POLLIN)))
557           FD_CLR(poll_fds[ix].fd, fds_read);
558         else
559           ret++;
560       }
561       if (fds_write && (0 != FD_ISSET(poll_fds[ix].fd, fds_write))) {
562         if (0 == (poll_fds[ix].revents & (POLLWRNORM|POLLERR|POLLHUP|POLLOUT)))
563           FD_CLR(poll_fds[ix].fd, fds_write);
564         else
565           ret++;
566       }
567       if (fds_excep && (0 != FD_ISSET(poll_fds[ix].fd, fds_excep))) {
568         if (0 == (poll_fds[ix].revents & (POLLRDBAND|POLLERR|POLLHUP|POLLPRI)))
569           FD_CLR(poll_fds[ix].fd, fds_excep);
570         else
571           ret++;
572       }
573     }
574   }
575
576   if (poll_fds && (poll_nfds > SMALL_POLLNFDS))
577     free(poll_fds);
578
579 #else  /* HAVE_POLL_FINE */
580
581   VERIFY_NFDS(nfds);
582
583   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
584
585   do {
586     if (ptimeout) {
587       pending_tv.tv_sec = pending_ms / 1000;
588       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
589     }
590     r = select(nfds, fds_read, fds_write, fds_excep, ptimeout);
591   } while ((r == -1) && (error = SOCKERRNO) &&
592            (error != EINVAL) && (error != EBADF) && error_not_EINTR &&
593            ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
594
595   if (r < 0)
596     ret = -1;
597   else
598     ret = r;
599
600 #endif  /* HAVE_POLL_FINE */
601
602   return ret;
603 }
604
605 #ifdef TPF
606 /*
607  * This is a replacement for select() on the TPF platform.
608  * It is used whenever libcurl calls select().
609  * The call below to tpf_process_signals() is required because
610  * TPF's select calls are not signal interruptible.
611  *
612  * Return values are the same as select's.
613  */
614 int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
615                        fd_set* excepts, struct timeval* tv)
616 {
617    int rc;
618
619    rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
620    tpf_process_signals();
621    return(rc);
622 }
623 #endif /* TPF */