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