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