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