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