xref: /aosp_15_r20/external/curl/lib/select.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker  *                                  _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker  *  Project                     ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker  *                             / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker  *                            | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker  *                             \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker  *
8*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker  *
10*6236dae4SAndroid Build Coastguard Worker  * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker  * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker  * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker  *
14*6236dae4SAndroid Build Coastguard Worker  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker  * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker  * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker  *
18*6236dae4SAndroid Build Coastguard Worker  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker  * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker  *
21*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker  *
23*6236dae4SAndroid Build Coastguard Worker  ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker 
25*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
26*6236dae4SAndroid Build Coastguard Worker 
27*6236dae4SAndroid Build Coastguard Worker #if !defined(HAVE_SELECT) && !defined(HAVE_POLL)
28*6236dae4SAndroid Build Coastguard Worker #error "We cannot compile without select() or poll() support."
29*6236dae4SAndroid Build Coastguard Worker #endif
30*6236dae4SAndroid Build Coastguard Worker 
31*6236dae4SAndroid Build Coastguard Worker #include <limits.h>
32*6236dae4SAndroid Build Coastguard Worker 
33*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SYS_SELECT_H
34*6236dae4SAndroid Build Coastguard Worker #include <sys/select.h>
35*6236dae4SAndroid Build Coastguard Worker #elif defined(HAVE_UNISTD_H)
36*6236dae4SAndroid Build Coastguard Worker #include <unistd.h>
37*6236dae4SAndroid Build Coastguard Worker #endif
38*6236dae4SAndroid Build Coastguard Worker 
39*6236dae4SAndroid Build Coastguard Worker #ifdef MSDOS
40*6236dae4SAndroid Build Coastguard Worker #include <dos.h>  /* delay() */
41*6236dae4SAndroid Build Coastguard Worker #endif
42*6236dae4SAndroid Build Coastguard Worker 
43*6236dae4SAndroid Build Coastguard Worker #include <curl/curl.h>
44*6236dae4SAndroid Build Coastguard Worker 
45*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
46*6236dae4SAndroid Build Coastguard Worker #include "connect.h"
47*6236dae4SAndroid Build Coastguard Worker #include "select.h"
48*6236dae4SAndroid Build Coastguard Worker #include "timediff.h"
49*6236dae4SAndroid Build Coastguard Worker #include "warnless.h"
50*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
51*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
52*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
53*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
54*6236dae4SAndroid Build Coastguard Worker 
55*6236dae4SAndroid Build Coastguard Worker /*
56*6236dae4SAndroid Build Coastguard Worker  * Internal function used for waiting a specific amount of ms in
57*6236dae4SAndroid Build Coastguard Worker  * Curl_socket_check() and Curl_poll() when no file descriptor is provided to
58*6236dae4SAndroid Build Coastguard Worker  * wait on, just being used to delay execution. Winsock select() and poll()
59*6236dae4SAndroid Build Coastguard Worker  * timeout mechanisms need a valid socket descriptor in a not null file
60*6236dae4SAndroid Build Coastguard Worker  * descriptor set to work. Waiting indefinitely with this function is not
61*6236dae4SAndroid Build Coastguard Worker  * allowed, a zero or negative timeout value will return immediately. Timeout
62*6236dae4SAndroid Build Coastguard Worker  * resolution, accuracy, as well as maximum supported value is system
63*6236dae4SAndroid Build Coastguard Worker  * dependent, neither factor is a critical issue for the intended use of this
64*6236dae4SAndroid Build Coastguard Worker  * function in the library.
65*6236dae4SAndroid Build Coastguard Worker  *
66*6236dae4SAndroid Build Coastguard Worker  * Return values:
67*6236dae4SAndroid Build Coastguard Worker  *   -1 = system call error, or invalid timeout value
68*6236dae4SAndroid Build Coastguard Worker  *    0 = specified timeout has elapsed, or interrupted
69*6236dae4SAndroid Build Coastguard Worker  */
Curl_wait_ms(timediff_t timeout_ms)70*6236dae4SAndroid Build Coastguard Worker int Curl_wait_ms(timediff_t timeout_ms)
71*6236dae4SAndroid Build Coastguard Worker {
72*6236dae4SAndroid Build Coastguard Worker   int r = 0;
73*6236dae4SAndroid Build Coastguard Worker 
74*6236dae4SAndroid Build Coastguard Worker   if(!timeout_ms)
75*6236dae4SAndroid Build Coastguard Worker     return 0;
76*6236dae4SAndroid Build Coastguard Worker   if(timeout_ms < 0) {
77*6236dae4SAndroid Build Coastguard Worker     SET_SOCKERRNO(EINVAL);
78*6236dae4SAndroid Build Coastguard Worker     return -1;
79*6236dae4SAndroid Build Coastguard Worker   }
80*6236dae4SAndroid Build Coastguard Worker #if defined(MSDOS)
81*6236dae4SAndroid Build Coastguard Worker   delay(timeout_ms);
82*6236dae4SAndroid Build Coastguard Worker #elif defined(_WIN32)
83*6236dae4SAndroid Build Coastguard Worker   /* prevent overflow, timeout_ms is typecast to ULONG/DWORD. */
84*6236dae4SAndroid Build Coastguard Worker #if TIMEDIFF_T_MAX >= ULONG_MAX
85*6236dae4SAndroid Build Coastguard Worker   if(timeout_ms >= ULONG_MAX)
86*6236dae4SAndroid Build Coastguard Worker     timeout_ms = ULONG_MAX-1;
87*6236dae4SAndroid Build Coastguard Worker     /* do not use ULONG_MAX, because that is equal to INFINITE */
88*6236dae4SAndroid Build Coastguard Worker #endif
89*6236dae4SAndroid Build Coastguard Worker   Sleep((ULONG)timeout_ms);
90*6236dae4SAndroid Build Coastguard Worker #else
91*6236dae4SAndroid Build Coastguard Worker   /* avoid using poll() for this since it behaves incorrectly with no sockets
92*6236dae4SAndroid Build Coastguard Worker      on Apple operating systems */
93*6236dae4SAndroid Build Coastguard Worker   {
94*6236dae4SAndroid Build Coastguard Worker     struct timeval pending_tv;
95*6236dae4SAndroid Build Coastguard Worker     r = select(0, NULL, NULL, NULL, curlx_mstotv(&pending_tv, timeout_ms));
96*6236dae4SAndroid Build Coastguard Worker   }
97*6236dae4SAndroid Build Coastguard Worker #endif /* _WIN32 */
98*6236dae4SAndroid Build Coastguard Worker   if(r) {
99*6236dae4SAndroid Build Coastguard Worker     if((r == -1) && (SOCKERRNO == EINTR))
100*6236dae4SAndroid Build Coastguard Worker       /* make EINTR from select or poll not a "lethal" error */
101*6236dae4SAndroid Build Coastguard Worker       r = 0;
102*6236dae4SAndroid Build Coastguard Worker     else
103*6236dae4SAndroid Build Coastguard Worker       r = -1;
104*6236dae4SAndroid Build Coastguard Worker   }
105*6236dae4SAndroid Build Coastguard Worker   return r;
106*6236dae4SAndroid Build Coastguard Worker }
107*6236dae4SAndroid Build Coastguard Worker 
108*6236dae4SAndroid Build Coastguard Worker #ifndef HAVE_POLL
109*6236dae4SAndroid Build Coastguard Worker /*
110*6236dae4SAndroid Build Coastguard Worker  * This is a wrapper around select() to aid in Windows compatibility. A
111*6236dae4SAndroid Build Coastguard Worker  * negative timeout value makes this function wait indefinitely, unless no
112*6236dae4SAndroid Build Coastguard Worker  * valid file descriptor is given, when this happens the negative timeout is
113*6236dae4SAndroid Build Coastguard Worker  * ignored and the function times out immediately.
114*6236dae4SAndroid Build Coastguard Worker  *
115*6236dae4SAndroid Build Coastguard Worker  * Return values:
116*6236dae4SAndroid Build Coastguard Worker  *   -1 = system call error or fd >= FD_SETSIZE
117*6236dae4SAndroid Build Coastguard Worker  *    0 = timeout
118*6236dae4SAndroid Build Coastguard Worker  *    N = number of signalled file descriptors
119*6236dae4SAndroid Build Coastguard Worker  */
our_select(curl_socket_t maxfd,fd_set * fds_read,fd_set * fds_write,fd_set * fds_err,timediff_t timeout_ms)120*6236dae4SAndroid Build Coastguard Worker static int our_select(curl_socket_t maxfd,   /* highest socket number */
121*6236dae4SAndroid Build Coastguard Worker                       fd_set *fds_read,      /* sockets ready for reading */
122*6236dae4SAndroid Build Coastguard Worker                       fd_set *fds_write,     /* sockets ready for writing */
123*6236dae4SAndroid Build Coastguard Worker                       fd_set *fds_err,       /* sockets with errors */
124*6236dae4SAndroid Build Coastguard Worker                       timediff_t timeout_ms) /* milliseconds to wait */
125*6236dae4SAndroid Build Coastguard Worker {
126*6236dae4SAndroid Build Coastguard Worker   struct timeval pending_tv;
127*6236dae4SAndroid Build Coastguard Worker   struct timeval *ptimeout;
128*6236dae4SAndroid Build Coastguard Worker 
129*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
130*6236dae4SAndroid Build Coastguard Worker   /* Winsock select() cannot handle zero events. See the comment below. */
131*6236dae4SAndroid Build Coastguard Worker   if((!fds_read || fds_read->fd_count == 0) &&
132*6236dae4SAndroid Build Coastguard Worker      (!fds_write || fds_write->fd_count == 0) &&
133*6236dae4SAndroid Build Coastguard Worker      (!fds_err || fds_err->fd_count == 0)) {
134*6236dae4SAndroid Build Coastguard Worker     /* no sockets, just wait */
135*6236dae4SAndroid Build Coastguard Worker     return Curl_wait_ms(timeout_ms);
136*6236dae4SAndroid Build Coastguard Worker   }
137*6236dae4SAndroid Build Coastguard Worker #endif
138*6236dae4SAndroid Build Coastguard Worker 
139*6236dae4SAndroid Build Coastguard Worker   ptimeout = curlx_mstotv(&pending_tv, timeout_ms);
140*6236dae4SAndroid Build Coastguard Worker 
141*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
142*6236dae4SAndroid Build Coastguard Worker   /* Winsock select() must not be called with an fd_set that contains zero
143*6236dae4SAndroid Build Coastguard Worker     fd flags, or it will return WSAEINVAL. But, it also cannot be called
144*6236dae4SAndroid Build Coastguard Worker     with no fd_sets at all!  From the documentation:
145*6236dae4SAndroid Build Coastguard Worker 
146*6236dae4SAndroid Build Coastguard Worker     Any two of the parameters, readfds, writefds, or exceptfds, can be
147*6236dae4SAndroid Build Coastguard Worker     given as null. At least one must be non-null, and any non-null
148*6236dae4SAndroid Build Coastguard Worker     descriptor set must contain at least one handle to a socket.
149*6236dae4SAndroid Build Coastguard Worker 
150*6236dae4SAndroid Build Coastguard Worker     It is unclear why Winsock does not just handle this for us instead of
151*6236dae4SAndroid Build Coastguard Worker     calling this an error. Luckily, with Winsock, we can _also_ ask how
152*6236dae4SAndroid Build Coastguard Worker     many bits are set on an fd_set. So, let's just check it beforehand.
153*6236dae4SAndroid Build Coastguard Worker   */
154*6236dae4SAndroid Build Coastguard Worker   return select((int)maxfd + 1,
155*6236dae4SAndroid Build Coastguard Worker                 fds_read && fds_read->fd_count ? fds_read : NULL,
156*6236dae4SAndroid Build Coastguard Worker                 fds_write && fds_write->fd_count ? fds_write : NULL,
157*6236dae4SAndroid Build Coastguard Worker                 fds_err && fds_err->fd_count ? fds_err : NULL, ptimeout);
158*6236dae4SAndroid Build Coastguard Worker #else
159*6236dae4SAndroid Build Coastguard Worker   return select((int)maxfd + 1, fds_read, fds_write, fds_err, ptimeout);
160*6236dae4SAndroid Build Coastguard Worker #endif
161*6236dae4SAndroid Build Coastguard Worker }
162*6236dae4SAndroid Build Coastguard Worker 
163*6236dae4SAndroid Build Coastguard Worker #endif
164*6236dae4SAndroid Build Coastguard Worker 
165*6236dae4SAndroid Build Coastguard Worker /*
166*6236dae4SAndroid Build Coastguard Worker  * Wait for read or write events on a set of file descriptors. It uses poll()
167*6236dae4SAndroid Build Coastguard Worker  * when poll() is available, in order to avoid limits with FD_SETSIZE,
168*6236dae4SAndroid Build Coastguard Worker  * otherwise select() is used. An error is returned if select() is being used
169*6236dae4SAndroid Build Coastguard Worker  * and a file descriptor is too large for FD_SETSIZE.
170*6236dae4SAndroid Build Coastguard Worker  *
171*6236dae4SAndroid Build Coastguard Worker  * A negative timeout value makes this function wait indefinitely, unless no
172*6236dae4SAndroid Build Coastguard Worker  * valid file descriptor is given, when this happens the negative timeout is
173*6236dae4SAndroid Build Coastguard Worker  * ignored and the function times out immediately.
174*6236dae4SAndroid Build Coastguard Worker  *
175*6236dae4SAndroid Build Coastguard Worker  * Return values:
176*6236dae4SAndroid Build Coastguard Worker  *   -1 = system call error or fd >= FD_SETSIZE
177*6236dae4SAndroid Build Coastguard Worker  *    0 = timeout
178*6236dae4SAndroid Build Coastguard Worker  *    [bitmask] = action as described below
179*6236dae4SAndroid Build Coastguard Worker  *
180*6236dae4SAndroid Build Coastguard Worker  * CURL_CSELECT_IN - first socket is readable
181*6236dae4SAndroid Build Coastguard Worker  * CURL_CSELECT_IN2 - second socket is readable
182*6236dae4SAndroid Build Coastguard Worker  * CURL_CSELECT_OUT - write socket is writable
183*6236dae4SAndroid Build Coastguard Worker  * CURL_CSELECT_ERR - an error condition occurred
184*6236dae4SAndroid Build Coastguard Worker  */
Curl_socket_check(curl_socket_t readfd0,curl_socket_t readfd1,curl_socket_t writefd,timediff_t timeout_ms)185*6236dae4SAndroid Build Coastguard Worker int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
186*6236dae4SAndroid Build Coastguard Worker                       curl_socket_t readfd1,
187*6236dae4SAndroid Build Coastguard Worker                       curl_socket_t writefd, /* socket to write to */
188*6236dae4SAndroid Build Coastguard Worker                       timediff_t timeout_ms) /* milliseconds to wait */
189*6236dae4SAndroid Build Coastguard Worker {
190*6236dae4SAndroid Build Coastguard Worker   struct pollfd pfd[3];
191*6236dae4SAndroid Build Coastguard Worker   int num;
192*6236dae4SAndroid Build Coastguard Worker   int r;
193*6236dae4SAndroid Build Coastguard Worker 
194*6236dae4SAndroid Build Coastguard Worker   if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
195*6236dae4SAndroid Build Coastguard Worker      (writefd == CURL_SOCKET_BAD)) {
196*6236dae4SAndroid Build Coastguard Worker     /* no sockets, just wait */
197*6236dae4SAndroid Build Coastguard Worker     return Curl_wait_ms(timeout_ms);
198*6236dae4SAndroid Build Coastguard Worker   }
199*6236dae4SAndroid Build Coastguard Worker 
200*6236dae4SAndroid Build Coastguard Worker   /* Avoid initial timestamp, avoid Curl_now() call, when elapsed
201*6236dae4SAndroid Build Coastguard Worker      time in this function does not need to be measured. This happens
202*6236dae4SAndroid Build Coastguard Worker      when function is called with a zero timeout or a negative timeout
203*6236dae4SAndroid Build Coastguard Worker      value indicating a blocking call should be performed. */
204*6236dae4SAndroid Build Coastguard Worker 
205*6236dae4SAndroid Build Coastguard Worker   num = 0;
206*6236dae4SAndroid Build Coastguard Worker   if(readfd0 != CURL_SOCKET_BAD) {
207*6236dae4SAndroid Build Coastguard Worker     pfd[num].fd = readfd0;
208*6236dae4SAndroid Build Coastguard Worker     pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
209*6236dae4SAndroid Build Coastguard Worker     pfd[num].revents = 0;
210*6236dae4SAndroid Build Coastguard Worker     num++;
211*6236dae4SAndroid Build Coastguard Worker   }
212*6236dae4SAndroid Build Coastguard Worker   if(readfd1 != CURL_SOCKET_BAD) {
213*6236dae4SAndroid Build Coastguard Worker     pfd[num].fd = readfd1;
214*6236dae4SAndroid Build Coastguard Worker     pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
215*6236dae4SAndroid Build Coastguard Worker     pfd[num].revents = 0;
216*6236dae4SAndroid Build Coastguard Worker     num++;
217*6236dae4SAndroid Build Coastguard Worker   }
218*6236dae4SAndroid Build Coastguard Worker   if(writefd != CURL_SOCKET_BAD) {
219*6236dae4SAndroid Build Coastguard Worker     pfd[num].fd = writefd;
220*6236dae4SAndroid Build Coastguard Worker     pfd[num].events = POLLWRNORM|POLLOUT|POLLPRI;
221*6236dae4SAndroid Build Coastguard Worker     pfd[num].revents = 0;
222*6236dae4SAndroid Build Coastguard Worker     num++;
223*6236dae4SAndroid Build Coastguard Worker   }
224*6236dae4SAndroid Build Coastguard Worker 
225*6236dae4SAndroid Build Coastguard Worker   r = Curl_poll(pfd, (unsigned int)num, timeout_ms);
226*6236dae4SAndroid Build Coastguard Worker   if(r <= 0)
227*6236dae4SAndroid Build Coastguard Worker     return r;
228*6236dae4SAndroid Build Coastguard Worker 
229*6236dae4SAndroid Build Coastguard Worker   r = 0;
230*6236dae4SAndroid Build Coastguard Worker   num = 0;
231*6236dae4SAndroid Build Coastguard Worker   if(readfd0 != CURL_SOCKET_BAD) {
232*6236dae4SAndroid Build Coastguard Worker     if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
233*6236dae4SAndroid Build Coastguard Worker       r |= CURL_CSELECT_IN;
234*6236dae4SAndroid Build Coastguard Worker     if(pfd[num].revents & (POLLPRI|POLLNVAL))
235*6236dae4SAndroid Build Coastguard Worker       r |= CURL_CSELECT_ERR;
236*6236dae4SAndroid Build Coastguard Worker     num++;
237*6236dae4SAndroid Build Coastguard Worker   }
238*6236dae4SAndroid Build Coastguard Worker   if(readfd1 != CURL_SOCKET_BAD) {
239*6236dae4SAndroid Build Coastguard Worker     if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
240*6236dae4SAndroid Build Coastguard Worker       r |= CURL_CSELECT_IN2;
241*6236dae4SAndroid Build Coastguard Worker     if(pfd[num].revents & (POLLPRI|POLLNVAL))
242*6236dae4SAndroid Build Coastguard Worker       r |= CURL_CSELECT_ERR;
243*6236dae4SAndroid Build Coastguard Worker     num++;
244*6236dae4SAndroid Build Coastguard Worker   }
245*6236dae4SAndroid Build Coastguard Worker   if(writefd != CURL_SOCKET_BAD) {
246*6236dae4SAndroid Build Coastguard Worker     if(pfd[num].revents & (POLLWRNORM|POLLOUT))
247*6236dae4SAndroid Build Coastguard Worker       r |= CURL_CSELECT_OUT;
248*6236dae4SAndroid Build Coastguard Worker     if(pfd[num].revents & (POLLERR|POLLHUP|POLLPRI|POLLNVAL))
249*6236dae4SAndroid Build Coastguard Worker       r |= CURL_CSELECT_ERR;
250*6236dae4SAndroid Build Coastguard Worker   }
251*6236dae4SAndroid Build Coastguard Worker 
252*6236dae4SAndroid Build Coastguard Worker   return r;
253*6236dae4SAndroid Build Coastguard Worker }
254*6236dae4SAndroid Build Coastguard Worker 
255*6236dae4SAndroid Build Coastguard Worker /*
256*6236dae4SAndroid Build Coastguard Worker  * This is a wrapper around poll(). If poll() does not exist, then
257*6236dae4SAndroid Build Coastguard Worker  * select() is used instead. An error is returned if select() is
258*6236dae4SAndroid Build Coastguard Worker  * being used and a file descriptor is too large for FD_SETSIZE.
259*6236dae4SAndroid Build Coastguard Worker  * A negative timeout value makes this function wait indefinitely,
260*6236dae4SAndroid Build Coastguard Worker  * unless no valid file descriptor is given, when this happens the
261*6236dae4SAndroid Build Coastguard Worker  * negative timeout is ignored and the function times out immediately.
262*6236dae4SAndroid Build Coastguard Worker  *
263*6236dae4SAndroid Build Coastguard Worker  * Return values:
264*6236dae4SAndroid Build Coastguard Worker  *   -1 = system call error or fd >= FD_SETSIZE
265*6236dae4SAndroid Build Coastguard Worker  *    0 = timeout
266*6236dae4SAndroid Build Coastguard Worker  *    N = number of structures with non zero revent fields
267*6236dae4SAndroid Build Coastguard Worker  */
Curl_poll(struct pollfd ufds[],unsigned int nfds,timediff_t timeout_ms)268*6236dae4SAndroid Build Coastguard Worker int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
269*6236dae4SAndroid Build Coastguard Worker {
270*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_POLL
271*6236dae4SAndroid Build Coastguard Worker   int pending_ms;
272*6236dae4SAndroid Build Coastguard Worker #else
273*6236dae4SAndroid Build Coastguard Worker   fd_set fds_read;
274*6236dae4SAndroid Build Coastguard Worker   fd_set fds_write;
275*6236dae4SAndroid Build Coastguard Worker   fd_set fds_err;
276*6236dae4SAndroid Build Coastguard Worker   curl_socket_t maxfd;
277*6236dae4SAndroid Build Coastguard Worker #endif
278*6236dae4SAndroid Build Coastguard Worker   bool fds_none = TRUE;
279*6236dae4SAndroid Build Coastguard Worker   unsigned int i;
280*6236dae4SAndroid Build Coastguard Worker   int r;
281*6236dae4SAndroid Build Coastguard Worker 
282*6236dae4SAndroid Build Coastguard Worker   if(ufds) {
283*6236dae4SAndroid Build Coastguard Worker     for(i = 0; i < nfds; i++) {
284*6236dae4SAndroid Build Coastguard Worker       if(ufds[i].fd != CURL_SOCKET_BAD) {
285*6236dae4SAndroid Build Coastguard Worker         fds_none = FALSE;
286*6236dae4SAndroid Build Coastguard Worker         break;
287*6236dae4SAndroid Build Coastguard Worker       }
288*6236dae4SAndroid Build Coastguard Worker     }
289*6236dae4SAndroid Build Coastguard Worker   }
290*6236dae4SAndroid Build Coastguard Worker   if(fds_none) {
291*6236dae4SAndroid Build Coastguard Worker     /* no sockets, just wait */
292*6236dae4SAndroid Build Coastguard Worker     return Curl_wait_ms(timeout_ms);
293*6236dae4SAndroid Build Coastguard Worker   }
294*6236dae4SAndroid Build Coastguard Worker 
295*6236dae4SAndroid Build Coastguard Worker   /* Avoid initial timestamp, avoid Curl_now() call, when elapsed
296*6236dae4SAndroid Build Coastguard Worker      time in this function does not need to be measured. This happens
297*6236dae4SAndroid Build Coastguard Worker      when function is called with a zero timeout or a negative timeout
298*6236dae4SAndroid Build Coastguard Worker      value indicating a blocking call should be performed. */
299*6236dae4SAndroid Build Coastguard Worker 
300*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_POLL
301*6236dae4SAndroid Build Coastguard Worker 
302*6236dae4SAndroid Build Coastguard Worker   /* prevent overflow, timeout_ms is typecast to int. */
303*6236dae4SAndroid Build Coastguard Worker #if TIMEDIFF_T_MAX > INT_MAX
304*6236dae4SAndroid Build Coastguard Worker   if(timeout_ms > INT_MAX)
305*6236dae4SAndroid Build Coastguard Worker     timeout_ms = INT_MAX;
306*6236dae4SAndroid Build Coastguard Worker #endif
307*6236dae4SAndroid Build Coastguard Worker   if(timeout_ms > 0)
308*6236dae4SAndroid Build Coastguard Worker     pending_ms = (int)timeout_ms;
309*6236dae4SAndroid Build Coastguard Worker   else if(timeout_ms < 0)
310*6236dae4SAndroid Build Coastguard Worker     pending_ms = -1;
311*6236dae4SAndroid Build Coastguard Worker   else
312*6236dae4SAndroid Build Coastguard Worker     pending_ms = 0;
313*6236dae4SAndroid Build Coastguard Worker   r = poll(ufds, nfds, pending_ms);
314*6236dae4SAndroid Build Coastguard Worker   if(r <= 0) {
315*6236dae4SAndroid Build Coastguard Worker     if((r == -1) && (SOCKERRNO == EINTR))
316*6236dae4SAndroid Build Coastguard Worker       /* make EINTR from select or poll not a "lethal" error */
317*6236dae4SAndroid Build Coastguard Worker       r = 0;
318*6236dae4SAndroid Build Coastguard Worker     return r;
319*6236dae4SAndroid Build Coastguard Worker   }
320*6236dae4SAndroid Build Coastguard Worker 
321*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < nfds; i++) {
322*6236dae4SAndroid Build Coastguard Worker     if(ufds[i].fd == CURL_SOCKET_BAD)
323*6236dae4SAndroid Build Coastguard Worker       continue;
324*6236dae4SAndroid Build Coastguard Worker     if(ufds[i].revents & POLLHUP)
325*6236dae4SAndroid Build Coastguard Worker       ufds[i].revents |= POLLIN;
326*6236dae4SAndroid Build Coastguard Worker     if(ufds[i].revents & POLLERR)
327*6236dae4SAndroid Build Coastguard Worker       ufds[i].revents |= POLLIN|POLLOUT;
328*6236dae4SAndroid Build Coastguard Worker   }
329*6236dae4SAndroid Build Coastguard Worker 
330*6236dae4SAndroid Build Coastguard Worker #else  /* HAVE_POLL */
331*6236dae4SAndroid Build Coastguard Worker 
332*6236dae4SAndroid Build Coastguard Worker   FD_ZERO(&fds_read);
333*6236dae4SAndroid Build Coastguard Worker   FD_ZERO(&fds_write);
334*6236dae4SAndroid Build Coastguard Worker   FD_ZERO(&fds_err);
335*6236dae4SAndroid Build Coastguard Worker   maxfd = (curl_socket_t)-1;
336*6236dae4SAndroid Build Coastguard Worker 
337*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < nfds; i++) {
338*6236dae4SAndroid Build Coastguard Worker     ufds[i].revents = 0;
339*6236dae4SAndroid Build Coastguard Worker     if(ufds[i].fd == CURL_SOCKET_BAD)
340*6236dae4SAndroid Build Coastguard Worker       continue;
341*6236dae4SAndroid Build Coastguard Worker     VERIFY_SOCK(ufds[i].fd);
342*6236dae4SAndroid Build Coastguard Worker     if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
343*6236dae4SAndroid Build Coastguard Worker                          POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
344*6236dae4SAndroid Build Coastguard Worker       if(ufds[i].fd > maxfd)
345*6236dae4SAndroid Build Coastguard Worker         maxfd = ufds[i].fd;
346*6236dae4SAndroid Build Coastguard Worker       if(ufds[i].events & (POLLRDNORM|POLLIN))
347*6236dae4SAndroid Build Coastguard Worker         FD_SET(ufds[i].fd, &fds_read);
348*6236dae4SAndroid Build Coastguard Worker       if(ufds[i].events & (POLLWRNORM|POLLOUT))
349*6236dae4SAndroid Build Coastguard Worker         FD_SET(ufds[i].fd, &fds_write);
350*6236dae4SAndroid Build Coastguard Worker       if(ufds[i].events & (POLLRDBAND|POLLPRI))
351*6236dae4SAndroid Build Coastguard Worker         FD_SET(ufds[i].fd, &fds_err);
352*6236dae4SAndroid Build Coastguard Worker     }
353*6236dae4SAndroid Build Coastguard Worker   }
354*6236dae4SAndroid Build Coastguard Worker 
355*6236dae4SAndroid Build Coastguard Worker   /*
356*6236dae4SAndroid Build Coastguard Worker      Note also that Winsock ignores the first argument, so we do not worry
357*6236dae4SAndroid Build Coastguard Worker      about the fact that maxfd is computed incorrectly with Winsock (since
358*6236dae4SAndroid Build Coastguard Worker      curl_socket_t is unsigned in such cases and thus -1 is the largest
359*6236dae4SAndroid Build Coastguard Worker      value).
360*6236dae4SAndroid Build Coastguard Worker   */
361*6236dae4SAndroid Build Coastguard Worker   r = our_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms);
362*6236dae4SAndroid Build Coastguard Worker   if(r <= 0) {
363*6236dae4SAndroid Build Coastguard Worker     if((r == -1) && (SOCKERRNO == EINTR))
364*6236dae4SAndroid Build Coastguard Worker       /* make EINTR from select or poll not a "lethal" error */
365*6236dae4SAndroid Build Coastguard Worker       r = 0;
366*6236dae4SAndroid Build Coastguard Worker     return r;
367*6236dae4SAndroid Build Coastguard Worker   }
368*6236dae4SAndroid Build Coastguard Worker 
369*6236dae4SAndroid Build Coastguard Worker   r = 0;
370*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < nfds; i++) {
371*6236dae4SAndroid Build Coastguard Worker     ufds[i].revents = 0;
372*6236dae4SAndroid Build Coastguard Worker     if(ufds[i].fd == CURL_SOCKET_BAD)
373*6236dae4SAndroid Build Coastguard Worker       continue;
374*6236dae4SAndroid Build Coastguard Worker     if(FD_ISSET(ufds[i].fd, &fds_read)) {
375*6236dae4SAndroid Build Coastguard Worker       if(ufds[i].events & POLLRDNORM)
376*6236dae4SAndroid Build Coastguard Worker         ufds[i].revents |= POLLRDNORM;
377*6236dae4SAndroid Build Coastguard Worker       if(ufds[i].events & POLLIN)
378*6236dae4SAndroid Build Coastguard Worker         ufds[i].revents |= POLLIN;
379*6236dae4SAndroid Build Coastguard Worker     }
380*6236dae4SAndroid Build Coastguard Worker     if(FD_ISSET(ufds[i].fd, &fds_write)) {
381*6236dae4SAndroid Build Coastguard Worker       if(ufds[i].events & POLLWRNORM)
382*6236dae4SAndroid Build Coastguard Worker         ufds[i].revents |= POLLWRNORM;
383*6236dae4SAndroid Build Coastguard Worker       if(ufds[i].events & POLLOUT)
384*6236dae4SAndroid Build Coastguard Worker         ufds[i].revents |= POLLOUT;
385*6236dae4SAndroid Build Coastguard Worker     }
386*6236dae4SAndroid Build Coastguard Worker     if(FD_ISSET(ufds[i].fd, &fds_err)) {
387*6236dae4SAndroid Build Coastguard Worker       if(ufds[i].events & POLLRDBAND)
388*6236dae4SAndroid Build Coastguard Worker         ufds[i].revents |= POLLRDBAND;
389*6236dae4SAndroid Build Coastguard Worker       if(ufds[i].events & POLLPRI)
390*6236dae4SAndroid Build Coastguard Worker         ufds[i].revents |= POLLPRI;
391*6236dae4SAndroid Build Coastguard Worker     }
392*6236dae4SAndroid Build Coastguard Worker     if(ufds[i].revents)
393*6236dae4SAndroid Build Coastguard Worker       r++;
394*6236dae4SAndroid Build Coastguard Worker   }
395*6236dae4SAndroid Build Coastguard Worker 
396*6236dae4SAndroid Build Coastguard Worker #endif  /* HAVE_POLL */
397*6236dae4SAndroid Build Coastguard Worker 
398*6236dae4SAndroid Build Coastguard Worker   return r;
399*6236dae4SAndroid Build Coastguard Worker }
400*6236dae4SAndroid Build Coastguard Worker 
Curl_pollfds_init(struct curl_pollfds * cpfds,struct pollfd * static_pfds,unsigned int static_count)401*6236dae4SAndroid Build Coastguard Worker void Curl_pollfds_init(struct curl_pollfds *cpfds,
402*6236dae4SAndroid Build Coastguard Worker                        struct pollfd *static_pfds,
403*6236dae4SAndroid Build Coastguard Worker                        unsigned int static_count)
404*6236dae4SAndroid Build Coastguard Worker {
405*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(cpfds);
406*6236dae4SAndroid Build Coastguard Worker   memset(cpfds, 0, sizeof(*cpfds));
407*6236dae4SAndroid Build Coastguard Worker   if(static_pfds && static_count) {
408*6236dae4SAndroid Build Coastguard Worker     cpfds->pfds = static_pfds;
409*6236dae4SAndroid Build Coastguard Worker     cpfds->count = static_count;
410*6236dae4SAndroid Build Coastguard Worker   }
411*6236dae4SAndroid Build Coastguard Worker }
412*6236dae4SAndroid Build Coastguard Worker 
Curl_pollfds_cleanup(struct curl_pollfds * cpfds)413*6236dae4SAndroid Build Coastguard Worker void Curl_pollfds_cleanup(struct curl_pollfds *cpfds)
414*6236dae4SAndroid Build Coastguard Worker {
415*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(cpfds);
416*6236dae4SAndroid Build Coastguard Worker   if(cpfds->allocated_pfds) {
417*6236dae4SAndroid Build Coastguard Worker     free(cpfds->pfds);
418*6236dae4SAndroid Build Coastguard Worker   }
419*6236dae4SAndroid Build Coastguard Worker   memset(cpfds, 0, sizeof(*cpfds));
420*6236dae4SAndroid Build Coastguard Worker }
421*6236dae4SAndroid Build Coastguard Worker 
cpfds_increase(struct curl_pollfds * cpfds,unsigned int inc)422*6236dae4SAndroid Build Coastguard Worker static CURLcode cpfds_increase(struct curl_pollfds *cpfds, unsigned int inc)
423*6236dae4SAndroid Build Coastguard Worker {
424*6236dae4SAndroid Build Coastguard Worker   struct pollfd *new_fds;
425*6236dae4SAndroid Build Coastguard Worker   unsigned int new_count = cpfds->count + inc;
426*6236dae4SAndroid Build Coastguard Worker 
427*6236dae4SAndroid Build Coastguard Worker   new_fds = calloc(new_count, sizeof(struct pollfd));
428*6236dae4SAndroid Build Coastguard Worker   if(!new_fds)
429*6236dae4SAndroid Build Coastguard Worker     return CURLE_OUT_OF_MEMORY;
430*6236dae4SAndroid Build Coastguard Worker 
431*6236dae4SAndroid Build Coastguard Worker   memcpy(new_fds, cpfds->pfds, cpfds->count * sizeof(struct pollfd));
432*6236dae4SAndroid Build Coastguard Worker   if(cpfds->allocated_pfds)
433*6236dae4SAndroid Build Coastguard Worker     free(cpfds->pfds);
434*6236dae4SAndroid Build Coastguard Worker   cpfds->pfds = new_fds;
435*6236dae4SAndroid Build Coastguard Worker   cpfds->count = new_count;
436*6236dae4SAndroid Build Coastguard Worker   cpfds->allocated_pfds = TRUE;
437*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
438*6236dae4SAndroid Build Coastguard Worker }
439*6236dae4SAndroid Build Coastguard Worker 
cpfds_add_sock(struct curl_pollfds * cpfds,curl_socket_t sock,short events,bool fold)440*6236dae4SAndroid Build Coastguard Worker static CURLcode cpfds_add_sock(struct curl_pollfds *cpfds,
441*6236dae4SAndroid Build Coastguard Worker                                curl_socket_t sock, short events, bool fold)
442*6236dae4SAndroid Build Coastguard Worker {
443*6236dae4SAndroid Build Coastguard Worker   int i;
444*6236dae4SAndroid Build Coastguard Worker 
445*6236dae4SAndroid Build Coastguard Worker   if(fold && cpfds->n <= INT_MAX) {
446*6236dae4SAndroid Build Coastguard Worker     for(i = (int)cpfds->n - 1; i >= 0; --i) {
447*6236dae4SAndroid Build Coastguard Worker       if(sock == cpfds->pfds[i].fd) {
448*6236dae4SAndroid Build Coastguard Worker         cpfds->pfds[i].events |= events;
449*6236dae4SAndroid Build Coastguard Worker         return CURLE_OK;
450*6236dae4SAndroid Build Coastguard Worker       }
451*6236dae4SAndroid Build Coastguard Worker     }
452*6236dae4SAndroid Build Coastguard Worker   }
453*6236dae4SAndroid Build Coastguard Worker   /* not folded, add new entry */
454*6236dae4SAndroid Build Coastguard Worker   if(cpfds->n >= cpfds->count) {
455*6236dae4SAndroid Build Coastguard Worker     if(cpfds_increase(cpfds, 100))
456*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
457*6236dae4SAndroid Build Coastguard Worker   }
458*6236dae4SAndroid Build Coastguard Worker   cpfds->pfds[cpfds->n].fd = sock;
459*6236dae4SAndroid Build Coastguard Worker   cpfds->pfds[cpfds->n].events = events;
460*6236dae4SAndroid Build Coastguard Worker   ++cpfds->n;
461*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
462*6236dae4SAndroid Build Coastguard Worker }
463*6236dae4SAndroid Build Coastguard Worker 
Curl_pollfds_add_sock(struct curl_pollfds * cpfds,curl_socket_t sock,short events)464*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_pollfds_add_sock(struct curl_pollfds *cpfds,
465*6236dae4SAndroid Build Coastguard Worker                                curl_socket_t sock, short events)
466*6236dae4SAndroid Build Coastguard Worker {
467*6236dae4SAndroid Build Coastguard Worker   return cpfds_add_sock(cpfds, sock, events, FALSE);
468*6236dae4SAndroid Build Coastguard Worker }
469*6236dae4SAndroid Build Coastguard Worker 
Curl_pollfds_add_ps(struct curl_pollfds * cpfds,struct easy_pollset * ps)470*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_pollfds_add_ps(struct curl_pollfds *cpfds,
471*6236dae4SAndroid Build Coastguard Worker                              struct easy_pollset *ps)
472*6236dae4SAndroid Build Coastguard Worker {
473*6236dae4SAndroid Build Coastguard Worker   size_t i;
474*6236dae4SAndroid Build Coastguard Worker 
475*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(cpfds);
476*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(ps);
477*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < ps->num; i++) {
478*6236dae4SAndroid Build Coastguard Worker     short events = 0;
479*6236dae4SAndroid Build Coastguard Worker     if(ps->actions[i] & CURL_POLL_IN)
480*6236dae4SAndroid Build Coastguard Worker       events |= POLLIN;
481*6236dae4SAndroid Build Coastguard Worker     if(ps->actions[i] & CURL_POLL_OUT)
482*6236dae4SAndroid Build Coastguard Worker       events |= POLLOUT;
483*6236dae4SAndroid Build Coastguard Worker     if(events) {
484*6236dae4SAndroid Build Coastguard Worker       if(cpfds_add_sock(cpfds, ps->sockets[i], events, TRUE))
485*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
486*6236dae4SAndroid Build Coastguard Worker     }
487*6236dae4SAndroid Build Coastguard Worker   }
488*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
489*6236dae4SAndroid Build Coastguard Worker }
490*6236dae4SAndroid Build Coastguard Worker 
Curl_waitfds_init(struct curl_waitfds * cwfds,struct curl_waitfd * static_wfds,unsigned int static_count)491*6236dae4SAndroid Build Coastguard Worker void Curl_waitfds_init(struct curl_waitfds *cwfds,
492*6236dae4SAndroid Build Coastguard Worker                        struct curl_waitfd *static_wfds,
493*6236dae4SAndroid Build Coastguard Worker                        unsigned int static_count)
494*6236dae4SAndroid Build Coastguard Worker {
495*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(cwfds);
496*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(static_wfds);
497*6236dae4SAndroid Build Coastguard Worker   memset(cwfds, 0, sizeof(*cwfds));
498*6236dae4SAndroid Build Coastguard Worker   cwfds->wfds = static_wfds;
499*6236dae4SAndroid Build Coastguard Worker   cwfds->count = static_count;
500*6236dae4SAndroid Build Coastguard Worker }
501*6236dae4SAndroid Build Coastguard Worker 
cwfds_add_sock(struct curl_waitfds * cwfds,curl_socket_t sock,short events)502*6236dae4SAndroid Build Coastguard Worker static CURLcode cwfds_add_sock(struct curl_waitfds *cwfds,
503*6236dae4SAndroid Build Coastguard Worker                                curl_socket_t sock, short events)
504*6236dae4SAndroid Build Coastguard Worker {
505*6236dae4SAndroid Build Coastguard Worker   int i;
506*6236dae4SAndroid Build Coastguard Worker 
507*6236dae4SAndroid Build Coastguard Worker   if(cwfds->n <= INT_MAX) {
508*6236dae4SAndroid Build Coastguard Worker     for(i = (int)cwfds->n - 1; i >= 0; --i) {
509*6236dae4SAndroid Build Coastguard Worker       if(sock == cwfds->wfds[i].fd) {
510*6236dae4SAndroid Build Coastguard Worker         cwfds->wfds[i].events |= events;
511*6236dae4SAndroid Build Coastguard Worker         return CURLE_OK;
512*6236dae4SAndroid Build Coastguard Worker       }
513*6236dae4SAndroid Build Coastguard Worker     }
514*6236dae4SAndroid Build Coastguard Worker   }
515*6236dae4SAndroid Build Coastguard Worker   /* not folded, add new entry */
516*6236dae4SAndroid Build Coastguard Worker   if(cwfds->n >= cwfds->count)
517*6236dae4SAndroid Build Coastguard Worker     return CURLE_OUT_OF_MEMORY;
518*6236dae4SAndroid Build Coastguard Worker   cwfds->wfds[cwfds->n].fd = sock;
519*6236dae4SAndroid Build Coastguard Worker   cwfds->wfds[cwfds->n].events = events;
520*6236dae4SAndroid Build Coastguard Worker   ++cwfds->n;
521*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
522*6236dae4SAndroid Build Coastguard Worker }
523*6236dae4SAndroid Build Coastguard Worker 
Curl_waitfds_add_ps(struct curl_waitfds * cwfds,struct easy_pollset * ps)524*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_waitfds_add_ps(struct curl_waitfds *cwfds,
525*6236dae4SAndroid Build Coastguard Worker                              struct easy_pollset *ps)
526*6236dae4SAndroid Build Coastguard Worker {
527*6236dae4SAndroid Build Coastguard Worker   size_t i;
528*6236dae4SAndroid Build Coastguard Worker 
529*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(cwfds);
530*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(ps);
531*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < ps->num; i++) {
532*6236dae4SAndroid Build Coastguard Worker     short events = 0;
533*6236dae4SAndroid Build Coastguard Worker     if(ps->actions[i] & CURL_POLL_IN)
534*6236dae4SAndroid Build Coastguard Worker       events |= CURL_WAIT_POLLIN;
535*6236dae4SAndroid Build Coastguard Worker     if(ps->actions[i] & CURL_POLL_OUT)
536*6236dae4SAndroid Build Coastguard Worker       events |= CURL_WAIT_POLLOUT;
537*6236dae4SAndroid Build Coastguard Worker     if(events) {
538*6236dae4SAndroid Build Coastguard Worker       if(cwfds_add_sock(cwfds, ps->sockets[i], events))
539*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
540*6236dae4SAndroid Build Coastguard Worker     }
541*6236dae4SAndroid Build Coastguard Worker   }
542*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
543*6236dae4SAndroid Build Coastguard Worker }
544