1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2020, 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 https://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 #include <limits.h>
26
27 #ifdef HAVE_SYS_SELECT_H
28 #include <sys/select.h>
29 #elif defined(HAVE_UNISTD_H)
30 #include <unistd.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 #if defined(__BEOS__) && !defined(__HAIKU__)
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 #ifdef __VXWORKS__
47 #include <strings.h> /* bzero() in FD_SET */
48 #endif
49
50 #include <curl/curl.h>
51
52 #include "urldata.h"
53 #include "connect.h"
54 #include "select.h"
55 #include "timeval.h"
56 #include "warnless.h"
57
58 /*
59 * Internal function used for waiting a specific amount of ms
60 * in Curl_socket_check() and Curl_poll() when no file descriptor
61 * is provided to wait on, just being used to delay execution.
62 * WinSock select() and poll() timeout mechanisms need a valid
63 * socket descriptor in a not null file descriptor set to work.
64 * Waiting indefinitely with this function is not allowed, a
65 * zero or negative timeout value will return immediately.
66 * Timeout resolution, accuracy, as well as maximum supported
67 * value is system dependent, neither factor is a citical issue
68 * for the intended use of this function in the library.
69 *
70 * Return values:
71 * -1 = system call error, invalid timeout value, or interrupted
72 * 0 = specified timeout has elapsed
73 */
Curl_wait_ms(timediff_t timeout_ms)74 int Curl_wait_ms(timediff_t timeout_ms)
75 {
76 int r = 0;
77
78 if(!timeout_ms)
79 return 0;
80 if(timeout_ms < 0) {
81 SET_SOCKERRNO(EINVAL);
82 return -1;
83 }
84 #if defined(MSDOS)
85 delay(timeout_ms);
86 #elif defined(WIN32)
87 /* prevent overflow, timeout_ms is typecast to ULONG/DWORD. */
88 #if TIMEDIFF_T_MAX >= ULONG_MAX
89 if(timeout_ms >= ULONG_MAX)
90 timeout_ms = ULONG_MAX-1;
91 /* don't use ULONG_MAX, because that is equal to INFINITE */
92 #endif
93 Sleep((ULONG)timeout_ms);
94 #else
95 #if defined(HAVE_POLL_FINE)
96 /* prevent overflow, timeout_ms is typecast to int. */
97 #if TIMEDIFF_T_MAX > INT_MAX
98 if(timeout_ms > INT_MAX)
99 timeout_ms = INT_MAX;
100 #endif
101 r = poll(NULL, 0, (int)timeout_ms);
102 #else
103 {
104 struct timeval pending_tv;
105 timediff_t tv_sec = timeout_ms / 1000;
106 timediff_t tv_usec = (timeout_ms % 1000) * 1000; /* max=999999 */
107 #ifdef HAVE_SUSECONDS_T
108 #if TIMEDIFF_T_MAX > TIME_T_MAX
109 /* tv_sec overflow check in case time_t is signed */
110 if(tv_sec > TIME_T_MAX)
111 tv_sec = TIME_T_MAX;
112 #endif
113 pending_tv.tv_sec = (time_t)tv_sec;
114 pending_tv.tv_usec = (suseconds_t)tv_usec;
115 #else
116 #if TIMEDIFF_T_MAX > INT_MAX
117 /* tv_sec overflow check in case time_t is signed */
118 if(tv_sec > INT_MAX)
119 tv_sec = INT_MAX;
120 #endif
121 pending_tv.tv_sec = (int)tv_sec;
122 pending_tv.tv_usec = (int)tv_usec;
123 #endif
124 r = select(0, NULL, NULL, NULL, &pending_tv);
125 }
126 #endif /* HAVE_POLL_FINE */
127 #endif /* USE_WINSOCK */
128 if(r)
129 r = -1;
130 return r;
131 }
132
133 /*
134 * This is a wrapper around select() to aid in Windows compatibility.
135 * A negative timeout value makes this function wait indefinitely,
136 * unless no valid file descriptor is given, when this happens the
137 * negative timeout is ignored and the function times out immediately.
138 *
139 * Return values:
140 * -1 = system call error or fd >= FD_SETSIZE
141 * 0 = timeout
142 * N = number of signalled file descriptors
143 */
Curl_select(curl_socket_t maxfd,fd_set * fds_read,fd_set * fds_write,fd_set * fds_err,timediff_t timeout_ms)144 int Curl_select(curl_socket_t maxfd, /* highest socket number */
145 fd_set *fds_read, /* sockets ready for reading */
146 fd_set *fds_write, /* sockets ready for writing */
147 fd_set *fds_err, /* sockets with errors */
148 timediff_t timeout_ms) /* milliseconds to wait */
149 {
150 struct timeval pending_tv;
151 struct timeval *ptimeout;
152
153 #ifdef USE_WINSOCK
154 /* WinSock select() can't handle zero events. See the comment below. */
155 if((!fds_read || fds_read->fd_count == 0) &&
156 (!fds_write || fds_write->fd_count == 0) &&
157 (!fds_err || fds_err->fd_count == 0)) {
158 /* no sockets, just wait */
159 return Curl_wait_ms(timeout_ms);
160 }
161 #endif
162
163 ptimeout = &pending_tv;
164 if(timeout_ms < 0) {
165 ptimeout = NULL;
166 }
167 else if(timeout_ms > 0) {
168 timediff_t tv_sec = timeout_ms / 1000;
169 timediff_t tv_usec = (timeout_ms % 1000) * 1000; /* max=999999 */
170 #ifdef HAVE_SUSECONDS_T
171 #if TIMEDIFF_T_MAX > TIME_T_MAX
172 /* tv_sec overflow check in case time_t is signed */
173 if(tv_sec > TIME_T_MAX)
174 tv_sec = TIME_T_MAX;
175 #endif
176 pending_tv.tv_sec = (time_t)tv_sec;
177 pending_tv.tv_usec = (suseconds_t)tv_usec;
178 #elif defined(WIN32) /* maybe also others in the future */
179 #if TIMEDIFF_T_MAX > LONG_MAX
180 /* tv_sec overflow check on Windows there we know it is long */
181 if(tv_sec > LONG_MAX)
182 tv_sec = LONG_MAX;
183 #endif
184 pending_tv.tv_sec = (long)tv_sec;
185 pending_tv.tv_usec = (long)tv_usec;
186 #else
187 #if TIMEDIFF_T_MAX > INT_MAX
188 /* tv_sec overflow check in case time_t is signed */
189 if(tv_sec > INT_MAX)
190 tv_sec = INT_MAX;
191 #endif
192 pending_tv.tv_sec = (int)tv_sec;
193 pending_tv.tv_usec = (int)tv_usec;
194 #endif
195 }
196 else {
197 pending_tv.tv_sec = 0;
198 pending_tv.tv_usec = 0;
199 }
200
201 #ifdef USE_WINSOCK
202 /* WinSock select() must not be called with an fd_set that contains zero
203 fd flags, or it will return WSAEINVAL. But, it also can't be called
204 with no fd_sets at all! From the documentation:
205
206 Any two of the parameters, readfds, writefds, or exceptfds, can be
207 given as null. At least one must be non-null, and any non-null
208 descriptor set must contain at least one handle to a socket.
209
210 It is unclear why WinSock doesn't just handle this for us instead of
211 calling this an error. Luckily, with WinSock, we can _also_ ask how
212 many bits are set on an fd_set. So, let's just check it beforehand.
213 */
214 return select((int)maxfd + 1,
215 fds_read && fds_read->fd_count ? fds_read : NULL,
216 fds_write && fds_write->fd_count ? fds_write : NULL,
217 fds_err && fds_err->fd_count ? fds_err : NULL, ptimeout);
218 #else
219 return select((int)maxfd + 1, fds_read, fds_write, fds_err, ptimeout);
220 #endif
221 }
222
223 /*
224 * Wait for read or write events on a set of file descriptors. It uses poll()
225 * when a fine poll() is available, in order to avoid limits with FD_SETSIZE,
226 * otherwise select() is used. An error is returned if select() is being used
227 * and a file descriptor is too large for FD_SETSIZE.
228 *
229 * A negative timeout value makes this function wait indefinitely,
230 * unless no valid file descriptor is given, when this happens the
231 * negative timeout is ignored and the function times out immediately.
232 *
233 * Return values:
234 * -1 = system call error or fd >= FD_SETSIZE
235 * 0 = timeout
236 * [bitmask] = action as described below
237 *
238 * CURL_CSELECT_IN - first socket is readable
239 * CURL_CSELECT_IN2 - second socket is readable
240 * CURL_CSELECT_OUT - write socket is writable
241 * CURL_CSELECT_ERR - an error condition occurred
242 */
Curl_socket_check(curl_socket_t readfd0,curl_socket_t readfd1,curl_socket_t writefd,timediff_t timeout_ms)243 int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
244 curl_socket_t readfd1,
245 curl_socket_t writefd, /* socket to write to */
246 timediff_t timeout_ms) /* milliseconds to wait */
247 {
248 struct pollfd pfd[3];
249 int num;
250 int r;
251
252 if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
253 (writefd == CURL_SOCKET_BAD)) {
254 /* no sockets, just wait */
255 return Curl_wait_ms(timeout_ms);
256 }
257
258 /* Avoid initial timestamp, avoid Curl_now() call, when elapsed
259 time in this function does not need to be measured. This happens
260 when function is called with a zero timeout or a negative timeout
261 value indicating a blocking call should be performed. */
262
263 num = 0;
264 if(readfd0 != CURL_SOCKET_BAD) {
265 pfd[num].fd = readfd0;
266 pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
267 pfd[num].revents = 0;
268 num++;
269 }
270 if(readfd1 != CURL_SOCKET_BAD) {
271 pfd[num].fd = readfd1;
272 pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
273 pfd[num].revents = 0;
274 num++;
275 }
276 if(writefd != CURL_SOCKET_BAD) {
277 pfd[num].fd = writefd;
278 pfd[num].events = POLLWRNORM|POLLOUT|POLLPRI;
279 pfd[num].revents = 0;
280 num++;
281 }
282
283 r = Curl_poll(pfd, num, timeout_ms);
284 if(r <= 0)
285 return r;
286
287 r = 0;
288 num = 0;
289 if(readfd0 != CURL_SOCKET_BAD) {
290 if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
291 r |= CURL_CSELECT_IN;
292 if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
293 r |= CURL_CSELECT_ERR;
294 num++;
295 }
296 if(readfd1 != CURL_SOCKET_BAD) {
297 if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
298 r |= CURL_CSELECT_IN2;
299 if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
300 r |= CURL_CSELECT_ERR;
301 num++;
302 }
303 if(writefd != CURL_SOCKET_BAD) {
304 if(pfd[num].revents & (POLLWRNORM|POLLOUT))
305 r |= CURL_CSELECT_OUT;
306 if(pfd[num].revents & (POLLERR|POLLHUP|POLLPRI|POLLNVAL))
307 r |= CURL_CSELECT_ERR;
308 }
309
310 return r;
311 }
312
313 /*
314 * This is a wrapper around poll(). If poll() does not exist, then
315 * select() is used instead. An error is returned if select() is
316 * being used and a file descriptor is too large for FD_SETSIZE.
317 * A negative timeout value makes this function wait indefinitely,
318 * unless no valid file descriptor is given, when this happens the
319 * negative timeout is ignored and the function times out immediately.
320 *
321 * Return values:
322 * -1 = system call error or fd >= FD_SETSIZE
323 * 0 = timeout
324 * N = number of structures with non zero revent fields
325 */
Curl_poll(struct pollfd ufds[],unsigned int nfds,timediff_t timeout_ms)326 int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
327 {
328 #ifdef HAVE_POLL_FINE
329 int pending_ms;
330 #else
331 fd_set fds_read;
332 fd_set fds_write;
333 fd_set fds_err;
334 curl_socket_t maxfd;
335 #endif
336 bool fds_none = TRUE;
337 unsigned int i;
338 int r;
339
340 if(ufds) {
341 for(i = 0; i < nfds; i++) {
342 if(ufds[i].fd != CURL_SOCKET_BAD) {
343 fds_none = FALSE;
344 break;
345 }
346 }
347 }
348 if(fds_none) {
349 /* no sockets, just wait */
350 return Curl_wait_ms(timeout_ms);
351 }
352
353 /* Avoid initial timestamp, avoid Curl_now() call, when elapsed
354 time in this function does not need to be measured. This happens
355 when function is called with a zero timeout or a negative timeout
356 value indicating a blocking call should be performed. */
357
358 #ifdef HAVE_POLL_FINE
359
360 /* prevent overflow, timeout_ms is typecast to int. */
361 #if TIMEDIFF_T_MAX > INT_MAX
362 if(timeout_ms > INT_MAX)
363 timeout_ms = INT_MAX;
364 #endif
365 if(timeout_ms > 0)
366 pending_ms = (int)timeout_ms;
367 else if(timeout_ms < 0)
368 pending_ms = -1;
369 else
370 pending_ms = 0;
371 r = poll(ufds, nfds, pending_ms);
372 if(r <= 0)
373 return r;
374
375 for(i = 0; i < nfds; i++) {
376 if(ufds[i].fd == CURL_SOCKET_BAD)
377 continue;
378 if(ufds[i].revents & POLLHUP)
379 ufds[i].revents |= POLLIN;
380 if(ufds[i].revents & POLLERR)
381 ufds[i].revents |= POLLIN|POLLOUT;
382 }
383
384 #else /* HAVE_POLL_FINE */
385
386 FD_ZERO(&fds_read);
387 FD_ZERO(&fds_write);
388 FD_ZERO(&fds_err);
389 maxfd = (curl_socket_t)-1;
390
391 for(i = 0; i < nfds; i++) {
392 ufds[i].revents = 0;
393 if(ufds[i].fd == CURL_SOCKET_BAD)
394 continue;
395 VERIFY_SOCK(ufds[i].fd);
396 if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
397 POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
398 if(ufds[i].fd > maxfd)
399 maxfd = ufds[i].fd;
400 if(ufds[i].events & (POLLRDNORM|POLLIN))
401 FD_SET(ufds[i].fd, &fds_read);
402 if(ufds[i].events & (POLLWRNORM|POLLOUT))
403 FD_SET(ufds[i].fd, &fds_write);
404 if(ufds[i].events & (POLLRDBAND|POLLPRI))
405 FD_SET(ufds[i].fd, &fds_err);
406 }
407 }
408
409 /*
410 Note also that WinSock ignores the first argument, so we don't worry
411 about the fact that maxfd is computed incorrectly with WinSock (since
412 curl_socket_t is unsigned in such cases and thus -1 is the largest
413 value).
414 */
415 r = Curl_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms);
416 if(r <= 0)
417 return r;
418
419 r = 0;
420 for(i = 0; i < nfds; i++) {
421 ufds[i].revents = 0;
422 if(ufds[i].fd == CURL_SOCKET_BAD)
423 continue;
424 if(FD_ISSET(ufds[i].fd, &fds_read)) {
425 if(ufds[i].events & POLLRDNORM)
426 ufds[i].revents |= POLLRDNORM;
427 if(ufds[i].events & POLLIN)
428 ufds[i].revents |= POLLIN;
429 }
430 if(FD_ISSET(ufds[i].fd, &fds_write)) {
431 if(ufds[i].events & POLLWRNORM)
432 ufds[i].revents |= POLLWRNORM;
433 if(ufds[i].events & POLLOUT)
434 ufds[i].revents |= POLLOUT;
435 }
436 if(FD_ISSET(ufds[i].fd, &fds_err)) {
437 if(ufds[i].events & POLLRDBAND)
438 ufds[i].revents |= POLLRDBAND;
439 if(ufds[i].events & POLLPRI)
440 ufds[i].revents |= POLLPRI;
441 }
442 if(ufds[i].revents != 0)
443 r++;
444 }
445
446 #endif /* HAVE_POLL_FINE */
447
448 return r;
449 }
450
451 #ifdef TPF
452 /*
453 * This is a replacement for select() on the TPF platform.
454 * It is used whenever libcurl calls select().
455 * The call below to tpf_process_signals() is required because
456 * TPF's select calls are not signal interruptible.
457 *
458 * Return values are the same as select's.
459 */
tpf_select_libcurl(int maxfds,fd_set * reads,fd_set * writes,fd_set * excepts,struct timeval * tv)460 int tpf_select_libcurl(int maxfds, fd_set *reads, fd_set *writes,
461 fd_set *excepts, struct timeval *tv)
462 {
463 int rc;
464
465 rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
466 tpf_process_signals();
467 return rc;
468 }
469 #endif /* TPF */
470