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