1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel (at) 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 #ifdef HAVE_SYS_SELECT_H 26 #include <sys/select.h> 27 #endif 28 29 #if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE) 30 #error "We can't compile without select() or poll() support." 31 #endif 32 33 #if defined(__BEOS__) && !defined(__HAIKU__) 34 /* BeOS has FD_SET defined in socket.h */ 35 #include <socket.h> 36 #endif 37 38 #ifdef MSDOS 39 #include <dos.h> /* delay() */ 40 #endif 41 42 #ifdef __VXWORKS__ 43 #include <strings.h> /* bzero() in FD_SET */ 44 #endif 45 46 #include <curl/curl.h> 47 48 #include "urldata.h" 49 #include "connect.h" 50 #include "select.h" 51 #include "warnless.h" 52 53 /* Convenience local macros */ 54 #define ELAPSED_MS() (int)curlx_tvdiff(curlx_tvnow(), initial_tv) 55 56 int Curl_ack_eintr = 0; 57 #define ERROR_NOT_EINTR(error) (Curl_ack_eintr || error != EINTR) 58 59 /* 60 * Internal function used for waiting a specific amount of ms 61 * in Curl_socket_check() and Curl_poll() when no file descriptor 62 * is provided to wait on, just being used to delay execution. 63 * WinSock select() and poll() timeout mechanisms need a valid 64 * socket descriptor in a not null file descriptor set to work. 65 * Waiting indefinitely with this function is not allowed, a 66 * zero or negative timeout value will return immediately. 67 * Timeout resolution, accuracy, as well as maximum supported 68 * value is system dependent, neither factor is a citical issue 69 * for the intended use of this function in the library. 70 * 71 * Return values: 72 * -1 = system call error, invalid timeout value, or interrupted 73 * 0 = specified timeout has elapsed 74 */ 75 int Curl_wait_ms(int timeout_ms) 76 { 77 #if !defined(MSDOS) && !defined(USE_WINSOCK) 78 #ifndef HAVE_POLL_FINE 79 struct timeval pending_tv; 80 #endif 81 struct timeval initial_tv; 82 int pending_ms; 83 int error; 84 #endif 85 int r = 0; 86 87 if(!timeout_ms) 88 return 0; 89 if(timeout_ms < 0) { 90 SET_SOCKERRNO(EINVAL); 91 return -1; 92 } 93 #if defined(MSDOS) 94 delay(timeout_ms); 95 #elif defined(USE_WINSOCK) 96 Sleep(timeout_ms); 97 #else 98 pending_ms = timeout_ms; 99 initial_tv = curlx_tvnow(); 100 do { 101 #if defined(HAVE_POLL_FINE) 102 r = poll(NULL, 0, pending_ms); 103 #else 104 pending_tv.tv_sec = pending_ms / 1000; 105 pending_tv.tv_usec = (pending_ms % 1000) * 1000; 106 r = select(0, NULL, NULL, NULL, &pending_tv); 107 #endif /* HAVE_POLL_FINE */ 108 if(r != -1) 109 break; 110 error = SOCKERRNO; 111 if(error && ERROR_NOT_EINTR(error)) 112 break; 113 pending_ms = timeout_ms - ELAPSED_MS(); 114 if(pending_ms <= 0) { 115 r = 0; /* Simulate a "call timed out" case */ 116 break; 117 } 118 } while(r == -1); 119 #endif /* USE_WINSOCK */ 120 if(r) 121 r = -1; 122 return r; 123 } 124 125 /* 126 * Wait for read or write events on a set of file descriptors. It uses poll() 127 * when a fine poll() is available, in order to avoid limits with FD_SETSIZE, 128 * otherwise select() is used. An error is returned if select() is being used 129 * and a file descriptor is too large for FD_SETSIZE. 130 * 131 * A negative timeout value makes this function wait indefinitely, 132 * unles no valid file descriptor is given, when this happens the 133 * negative timeout is ignored and the function times out immediately. 134 * 135 * Return values: 136 * -1 = system call error or fd >= FD_SETSIZE 137 * 0 = timeout 138 * [bitmask] = action as described below 139 * 140 * CURL_CSELECT_IN - first socket is readable 141 * CURL_CSELECT_IN2 - second socket is readable 142 * CURL_CSELECT_OUT - write socket is writable 143 * CURL_CSELECT_ERR - an error condition occurred 144 */ 145 int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ 146 curl_socket_t readfd1, 147 curl_socket_t writefd, /* socket to write to */ 148 time_t timeout_ms) /* milliseconds to wait */ 149 { 150 #ifdef HAVE_POLL_FINE 151 struct pollfd pfd[3]; 152 int num; 153 #else 154 struct timeval pending_tv; 155 struct timeval *ptimeout; 156 fd_set fds_read; 157 fd_set fds_write; 158 fd_set fds_err; 159 curl_socket_t maxfd; 160 #endif 161 struct timeval initial_tv = {0, 0}; 162 int pending_ms = 0; 163 int error; 164 int r; 165 int ret; 166 167 #if SIZEOF_LONG != SIZEOF_INT 168 /* wrap-around precaution */ 169 if(timeout_ms >= INT_MAX) 170 timeout_ms = INT_MAX; 171 #endif 172 173 if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) && 174 (writefd == CURL_SOCKET_BAD)) { 175 /* no sockets, just wait */ 176 r = Curl_wait_ms((int)timeout_ms); 177 return r; 178 } 179 180 /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed 181 time in this function does not need to be measured. This happens 182 when function is called with a zero timeout or a negative timeout 183 value indicating a blocking call should be performed. */ 184 185 if(timeout_ms > 0) { 186 pending_ms = (int)timeout_ms; 187 initial_tv = curlx_tvnow(); 188 } 189 190 #ifdef HAVE_POLL_FINE 191 192 num = 0; 193 if(readfd0 != CURL_SOCKET_BAD) { 194 pfd[num].fd = readfd0; 195 pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; 196 pfd[num].revents = 0; 197 num++; 198 } 199 if(readfd1 != CURL_SOCKET_BAD) { 200 pfd[num].fd = readfd1; 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(error)) 222 break; 223 if(timeout_ms > 0) { 224 pending_ms = (int)(timeout_ms - ELAPSED_MS()); 225 if(pending_ms <= 0) { 226 r = 0; /* Simulate a "call timed out" case */ 227 break; 228 } 229 } 230 } while(r == -1); 231 232 if(r < 0) 233 return -1; 234 if(r == 0) 235 return 0; 236 237 ret = 0; 238 num = 0; 239 if(readfd0 != CURL_SOCKET_BAD) { 240 if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) 241 ret |= CURL_CSELECT_IN; 242 if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) 243 ret |= CURL_CSELECT_ERR; 244 num++; 245 } 246 if(readfd1 != CURL_SOCKET_BAD) { 247 if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) 248 ret |= CURL_CSELECT_IN2; 249 if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) 250 ret |= CURL_CSELECT_ERR; 251 num++; 252 } 253 if(writefd != CURL_SOCKET_BAD) { 254 if(pfd[num].revents & (POLLWRNORM|POLLOUT)) 255 ret |= CURL_CSELECT_OUT; 256 if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL)) 257 ret |= CURL_CSELECT_ERR; 258 } 259 260 return ret; 261 262 #else /* HAVE_POLL_FINE */ 263 264 FD_ZERO(&fds_err); 265 maxfd = (curl_socket_t)-1; 266 267 FD_ZERO(&fds_read); 268 if(readfd0 != CURL_SOCKET_BAD) { 269 VERIFY_SOCK(readfd0); 270 FD_SET(readfd0, &fds_read); 271 FD_SET(readfd0, &fds_err); 272 maxfd = readfd0; 273 } 274 if(readfd1 != CURL_SOCKET_BAD) { 275 VERIFY_SOCK(readfd1); 276 FD_SET(readfd1, &fds_read); 277 FD_SET(readfd1, &fds_err); 278 if(readfd1 > maxfd) 279 maxfd = readfd1; 280 } 281 282 FD_ZERO(&fds_write); 283 if(writefd != CURL_SOCKET_BAD) { 284 VERIFY_SOCK(writefd); 285 FD_SET(writefd, &fds_write); 286 FD_SET(writefd, &fds_err); 287 if(writefd > maxfd) 288 maxfd = writefd; 289 } 290 291 ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; 292 293 do { 294 if(timeout_ms > 0) { 295 pending_tv.tv_sec = pending_ms / 1000; 296 pending_tv.tv_usec = (pending_ms % 1000) * 1000; 297 } 298 else if(!timeout_ms) { 299 pending_tv.tv_sec = 0; 300 pending_tv.tv_usec = 0; 301 } 302 303 /* WinSock select() must not be called with an fd_set that contains zero 304 fd flags, or it will return WSAEINVAL. But, it also can't be called 305 with no fd_sets at all! From the documentation: 306 307 Any two of the parameters, readfds, writefds, or exceptfds, can be 308 given as null. At least one must be non-null, and any non-null 309 descriptor set must contain at least one handle to a socket. 310 311 We know that we have at least one bit set in at least two fd_sets in 312 this case, but we may have no bits set in either fds_read or fd_write, 313 so check for that and handle it. Luckily, with WinSock, we can _also_ 314 ask how many bits are set on an fd_set. 315 316 It is unclear why WinSock doesn't just handle this for us instead of 317 calling this an error. 318 319 Note also that WinSock ignores the first argument, so we don't worry 320 about the fact that maxfd is computed incorrectly with WinSock (since 321 curl_socket_t is unsigned in such cases and thus -1 is the largest 322 value). 323 */ 324 #ifdef USE_WINSOCK 325 r = select((int)maxfd + 1, 326 fds_read.fd_count ? &fds_read : NULL, 327 fds_write.fd_count ? &fds_write : NULL, 328 &fds_err, ptimeout); 329 #else 330 r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); 331 #endif 332 333 if(r != -1) 334 break; 335 error = SOCKERRNO; 336 if(error && ERROR_NOT_EINTR(error)) 337 break; 338 if(timeout_ms > 0) { 339 pending_ms = (int)(timeout_ms - ELAPSED_MS()); 340 if(pending_ms <= 0) { 341 r = 0; /* Simulate a "call timed out" case */ 342 break; 343 } 344 } 345 } while(r == -1); 346 347 if(r < 0) 348 return -1; 349 if(r == 0) 350 return 0; 351 352 ret = 0; 353 if(readfd0 != CURL_SOCKET_BAD) { 354 if(FD_ISSET(readfd0, &fds_read)) 355 ret |= CURL_CSELECT_IN; 356 if(FD_ISSET(readfd0, &fds_err)) 357 ret |= CURL_CSELECT_ERR; 358 } 359 if(readfd1 != CURL_SOCKET_BAD) { 360 if(FD_ISSET(readfd1, &fds_read)) 361 ret |= CURL_CSELECT_IN2; 362 if(FD_ISSET(readfd1, &fds_err)) 363 ret |= CURL_CSELECT_ERR; 364 } 365 if(writefd != CURL_SOCKET_BAD) { 366 if(FD_ISSET(writefd, &fds_write)) 367 ret |= CURL_CSELECT_OUT; 368 if(FD_ISSET(writefd, &fds_err)) 369 ret |= CURL_CSELECT_ERR; 370 } 371 372 return ret; 373 374 #endif /* HAVE_POLL_FINE */ 375 376 } 377 378 /* 379 * This is a wrapper around poll(). If poll() does not exist, then 380 * select() is used instead. An error is returned if select() is 381 * being used and a file descriptor is too large for FD_SETSIZE. 382 * A negative timeout value makes this function wait indefinitely, 383 * unles no valid file descriptor is given, when this happens the 384 * negative timeout is ignored and the function times out immediately. 385 * 386 * Return values: 387 * -1 = system call error or fd >= FD_SETSIZE 388 * 0 = timeout 389 * N = number of structures with non zero revent fields 390 */ 391 int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) 392 { 393 #ifndef HAVE_POLL_FINE 394 struct timeval pending_tv; 395 struct timeval *ptimeout; 396 fd_set fds_read; 397 fd_set fds_write; 398 fd_set fds_err; 399 curl_socket_t maxfd; 400 #endif 401 struct timeval initial_tv = {0, 0}; 402 bool fds_none = TRUE; 403 unsigned int i; 404 int pending_ms = 0; 405 int error; 406 int r; 407 408 if(ufds) { 409 for(i = 0; i < nfds; i++) { 410 if(ufds[i].fd != CURL_SOCKET_BAD) { 411 fds_none = FALSE; 412 break; 413 } 414 } 415 } 416 if(fds_none) { 417 r = Curl_wait_ms(timeout_ms); 418 return r; 419 } 420 421 /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed 422 time in this function does not need to be measured. This happens 423 when function is called with a zero timeout or a negative timeout 424 value indicating a blocking call should be performed. */ 425 426 if(timeout_ms > 0) { 427 pending_ms = timeout_ms; 428 initial_tv = curlx_tvnow(); 429 } 430 431 #ifdef HAVE_POLL_FINE 432 433 do { 434 if(timeout_ms < 0) 435 pending_ms = -1; 436 else if(!timeout_ms) 437 pending_ms = 0; 438 r = poll(ufds, nfds, pending_ms); 439 if(r != -1) 440 break; 441 error = SOCKERRNO; 442 if(error && ERROR_NOT_EINTR(error)) 443 break; 444 if(timeout_ms > 0) { 445 pending_ms = (int)(timeout_ms - ELAPSED_MS()); 446 if(pending_ms <= 0) { 447 r = 0; /* Simulate a "call timed out" case */ 448 break; 449 } 450 } 451 } while(r == -1); 452 453 if(r < 0) 454 return -1; 455 if(r == 0) 456 return 0; 457 458 for(i = 0; i < nfds; i++) { 459 if(ufds[i].fd == CURL_SOCKET_BAD) 460 continue; 461 if(ufds[i].revents & POLLHUP) 462 ufds[i].revents |= POLLIN; 463 if(ufds[i].revents & POLLERR) 464 ufds[i].revents |= (POLLIN|POLLOUT); 465 } 466 467 #else /* HAVE_POLL_FINE */ 468 469 FD_ZERO(&fds_read); 470 FD_ZERO(&fds_write); 471 FD_ZERO(&fds_err); 472 maxfd = (curl_socket_t)-1; 473 474 for(i = 0; i < nfds; i++) { 475 ufds[i].revents = 0; 476 if(ufds[i].fd == CURL_SOCKET_BAD) 477 continue; 478 VERIFY_SOCK(ufds[i].fd); 479 if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI| 480 POLLRDNORM|POLLWRNORM|POLLRDBAND)) { 481 if(ufds[i].fd > maxfd) 482 maxfd = ufds[i].fd; 483 if(ufds[i].events & (POLLRDNORM|POLLIN)) 484 FD_SET(ufds[i].fd, &fds_read); 485 if(ufds[i].events & (POLLWRNORM|POLLOUT)) 486 FD_SET(ufds[i].fd, &fds_write); 487 if(ufds[i].events & (POLLRDBAND|POLLPRI)) 488 FD_SET(ufds[i].fd, &fds_err); 489 } 490 } 491 492 #ifdef USE_WINSOCK 493 /* WinSock select() can't handle zero events. See the comment about this in 494 Curl_check_socket(). */ 495 if(fds_read.fd_count == 0 && fds_write.fd_count == 0 496 && fds_err.fd_count == 0) { 497 r = Curl_wait_ms(timeout_ms); 498 return r; 499 } 500 #endif 501 502 ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; 503 504 do { 505 if(timeout_ms > 0) { 506 pending_tv.tv_sec = pending_ms / 1000; 507 pending_tv.tv_usec = (pending_ms % 1000) * 1000; 508 } 509 else if(!timeout_ms) { 510 pending_tv.tv_sec = 0; 511 pending_tv.tv_usec = 0; 512 } 513 514 #ifdef USE_WINSOCK 515 r = select((int)maxfd + 1, 516 /* WinSock select() can't handle fd_sets with zero bits set, so 517 don't give it such arguments. See the comment about this in 518 Curl_check_socket(). 519 */ 520 fds_read.fd_count ? &fds_read : NULL, 521 fds_write.fd_count ? &fds_write : NULL, 522 fds_err.fd_count ? &fds_err : NULL, ptimeout); 523 #else 524 r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); 525 #endif 526 if(r != -1) 527 break; 528 error = SOCKERRNO; 529 if(error && ERROR_NOT_EINTR(error)) 530 break; 531 if(timeout_ms > 0) { 532 pending_ms = timeout_ms - ELAPSED_MS(); 533 if(pending_ms <= 0) { 534 r = 0; /* Simulate a "call timed out" case */ 535 break; 536 } 537 } 538 } while(r == -1); 539 540 if(r < 0) 541 return -1; 542 if(r == 0) 543 return 0; 544 545 r = 0; 546 for(i = 0; i < nfds; i++) { 547 ufds[i].revents = 0; 548 if(ufds[i].fd == CURL_SOCKET_BAD) 549 continue; 550 if(FD_ISSET(ufds[i].fd, &fds_read)) 551 ufds[i].revents |= POLLIN; 552 if(FD_ISSET(ufds[i].fd, &fds_write)) 553 ufds[i].revents |= POLLOUT; 554 if(FD_ISSET(ufds[i].fd, &fds_err)) 555 ufds[i].revents |= POLLPRI; 556 if(ufds[i].revents != 0) 557 r++; 558 } 559 560 #endif /* HAVE_POLL_FINE */ 561 562 return r; 563 } 564 565 #ifdef TPF 566 /* 567 * This is a replacement for select() on the TPF platform. 568 * It is used whenever libcurl calls select(). 569 * The call below to tpf_process_signals() is required because 570 * TPF's select calls are not signal interruptible. 571 * 572 * Return values are the same as select's. 573 */ 574 int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, 575 fd_set* excepts, struct timeval* tv) 576 { 577 int rc; 578 579 rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv); 580 tpf_process_signals(); 581 return rc; 582 } 583 #endif /* TPF */ 584