00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "curl_setup.h"
00024
00025 #ifdef HAVE_SYS_SELECT_H
00026 #include <sys/select.h>
00027 #endif
00028
00029 #if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE)
00030 #error "We can't compile without select() or poll() support."
00031 #endif
00032
00033 #if defined(__BEOS__) && !defined(__HAIKU__)
00034
00035 #include <socket.h>
00036 #endif
00037
00038 #ifdef MSDOS
00039 #include <dos.h>
00040 #endif
00041
00042 #ifdef __VXWORKS__
00043 #include <strings.h>
00044 #endif
00045
00046 #include <curl/curl.h>
00047
00048 #include "urldata.h"
00049 #include "connect.h"
00050 #include "select.h"
00051 #include "warnless.h"
00052
00053
00054 #define ELAPSED_MS() (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
00055
00056 int Curl_ack_eintr = 0;
00057 #define ERROR_NOT_EINTR(error) (Curl_ack_eintr || error != EINTR)
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 int Curl_wait_ms(int timeout_ms)
00076 {
00077 #if !defined(MSDOS) && !defined(USE_WINSOCK)
00078 #ifndef HAVE_POLL_FINE
00079 struct timeval pending_tv;
00080 #endif
00081 struct timeval initial_tv;
00082 int pending_ms;
00083 int error;
00084 #endif
00085 int r = 0;
00086
00087 if(!timeout_ms)
00088 return 0;
00089 if(timeout_ms < 0) {
00090 SET_SOCKERRNO(EINVAL);
00091 return -1;
00092 }
00093 #if defined(MSDOS)
00094 delay(timeout_ms);
00095 #elif defined(USE_WINSOCK)
00096 Sleep(timeout_ms);
00097 #else
00098 pending_ms = timeout_ms;
00099 initial_tv = curlx_tvnow();
00100 do {
00101 #if defined(HAVE_POLL_FINE)
00102 r = poll(NULL, 0, pending_ms);
00103 #else
00104 pending_tv.tv_sec = pending_ms / 1000;
00105 pending_tv.tv_usec = (pending_ms % 1000) * 1000;
00106 r = select(0, NULL, NULL, NULL, &pending_tv);
00107 #endif
00108 if(r != -1)
00109 break;
00110 error = SOCKERRNO;
00111 if(error && ERROR_NOT_EINTR(error))
00112 break;
00113 pending_ms = timeout_ms - ELAPSED_MS();
00114 if(pending_ms <= 0) {
00115 r = 0;
00116 break;
00117 }
00118 } while(r == -1);
00119 #endif
00120 if(r)
00121 r = -1;
00122 return r;
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 int Curl_socket_check(curl_socket_t readfd0,
00146 curl_socket_t readfd1,
00147 curl_socket_t writefd,
00148 time_t timeout_ms)
00149 {
00150 #ifdef HAVE_POLL_FINE
00151 struct pollfd pfd[3];
00152 int num;
00153 #else
00154 struct timeval pending_tv;
00155 struct timeval *ptimeout;
00156 fd_set fds_read;
00157 fd_set fds_write;
00158 fd_set fds_err;
00159 curl_socket_t maxfd;
00160 #endif
00161 struct timeval initial_tv = {0, 0};
00162 int pending_ms = 0;
00163 int error;
00164 int r;
00165 int ret;
00166
00167 #if SIZEOF_LONG != SIZEOF_INT
00168
00169 if(timeout_ms >= INT_MAX)
00170 timeout_ms = INT_MAX;
00171 #endif
00172
00173 if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
00174 (writefd == CURL_SOCKET_BAD)) {
00175
00176 r = Curl_wait_ms((int)timeout_ms);
00177 return r;
00178 }
00179
00180
00181
00182
00183
00184
00185 if(timeout_ms > 0) {
00186 pending_ms = (int)timeout_ms;
00187 initial_tv = curlx_tvnow();
00188 }
00189
00190 #ifdef HAVE_POLL_FINE
00191
00192 num = 0;
00193 if(readfd0 != CURL_SOCKET_BAD) {
00194 pfd[num].fd = readfd0;
00195 pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
00196 pfd[num].revents = 0;
00197 num++;
00198 }
00199 if(readfd1 != CURL_SOCKET_BAD) {
00200 pfd[num].fd = readfd1;
00201 pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
00202 pfd[num].revents = 0;
00203 num++;
00204 }
00205 if(writefd != CURL_SOCKET_BAD) {
00206 pfd[num].fd = writefd;
00207 pfd[num].events = POLLWRNORM|POLLOUT;
00208 pfd[num].revents = 0;
00209 num++;
00210 }
00211
00212 do {
00213 if(timeout_ms < 0)
00214 pending_ms = -1;
00215 else if(!timeout_ms)
00216 pending_ms = 0;
00217 r = poll(pfd, num, pending_ms);
00218 if(r != -1)
00219 break;
00220 error = SOCKERRNO;
00221 if(error && ERROR_NOT_EINTR(error))
00222 break;
00223 if(timeout_ms > 0) {
00224 pending_ms = (int)(timeout_ms - ELAPSED_MS());
00225 if(pending_ms <= 0) {
00226 r = 0;
00227 break;
00228 }
00229 }
00230 } while(r == -1);
00231
00232 if(r < 0)
00233 return -1;
00234 if(r == 0)
00235 return 0;
00236
00237 ret = 0;
00238 num = 0;
00239 if(readfd0 != CURL_SOCKET_BAD) {
00240 if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
00241 ret |= CURL_CSELECT_IN;
00242 if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
00243 ret |= CURL_CSELECT_ERR;
00244 num++;
00245 }
00246 if(readfd1 != CURL_SOCKET_BAD) {
00247 if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
00248 ret |= CURL_CSELECT_IN2;
00249 if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
00250 ret |= CURL_CSELECT_ERR;
00251 num++;
00252 }
00253 if(writefd != CURL_SOCKET_BAD) {
00254 if(pfd[num].revents & (POLLWRNORM|POLLOUT))
00255 ret |= CURL_CSELECT_OUT;
00256 if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
00257 ret |= CURL_CSELECT_ERR;
00258 }
00259
00260 return ret;
00261
00262 #else
00263
00264 FD_ZERO(&fds_err);
00265 maxfd = (curl_socket_t)-1;
00266
00267 FD_ZERO(&fds_read);
00268 if(readfd0 != CURL_SOCKET_BAD) {
00269 VERIFY_SOCK(readfd0);
00270 FD_SET(readfd0, &fds_read);
00271 FD_SET(readfd0, &fds_err);
00272 maxfd = readfd0;
00273 }
00274 if(readfd1 != CURL_SOCKET_BAD) {
00275 VERIFY_SOCK(readfd1);
00276 FD_SET(readfd1, &fds_read);
00277 FD_SET(readfd1, &fds_err);
00278 if(readfd1 > maxfd)
00279 maxfd = readfd1;
00280 }
00281
00282 FD_ZERO(&fds_write);
00283 if(writefd != CURL_SOCKET_BAD) {
00284 VERIFY_SOCK(writefd);
00285 FD_SET(writefd, &fds_write);
00286 FD_SET(writefd, &fds_err);
00287 if(writefd > maxfd)
00288 maxfd = writefd;
00289 }
00290
00291 ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
00292
00293 do {
00294 if(timeout_ms > 0) {
00295 pending_tv.tv_sec = pending_ms / 1000;
00296 pending_tv.tv_usec = (pending_ms % 1000) * 1000;
00297 }
00298 else if(!timeout_ms) {
00299 pending_tv.tv_sec = 0;
00300 pending_tv.tv_usec = 0;
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 #ifdef USE_WINSOCK
00325 r = select((int)maxfd + 1,
00326 fds_read.fd_count ? &fds_read : NULL,
00327 fds_write.fd_count ? &fds_write : NULL,
00328 &fds_err, ptimeout);
00329 #else
00330 r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
00331 #endif
00332
00333 if(r != -1)
00334 break;
00335 error = SOCKERRNO;
00336 if(error && ERROR_NOT_EINTR(error))
00337 break;
00338 if(timeout_ms > 0) {
00339 pending_ms = (int)(timeout_ms - ELAPSED_MS());
00340 if(pending_ms <= 0) {
00341 r = 0;
00342 break;
00343 }
00344 }
00345 } while(r == -1);
00346
00347 if(r < 0)
00348 return -1;
00349 if(r == 0)
00350 return 0;
00351
00352 ret = 0;
00353 if(readfd0 != CURL_SOCKET_BAD) {
00354 if(FD_ISSET(readfd0, &fds_read))
00355 ret |= CURL_CSELECT_IN;
00356 if(FD_ISSET(readfd0, &fds_err))
00357 ret |= CURL_CSELECT_ERR;
00358 }
00359 if(readfd1 != CURL_SOCKET_BAD) {
00360 if(FD_ISSET(readfd1, &fds_read))
00361 ret |= CURL_CSELECT_IN2;
00362 if(FD_ISSET(readfd1, &fds_err))
00363 ret |= CURL_CSELECT_ERR;
00364 }
00365 if(writefd != CURL_SOCKET_BAD) {
00366 if(FD_ISSET(writefd, &fds_write))
00367 ret |= CURL_CSELECT_OUT;
00368 if(FD_ISSET(writefd, &fds_err))
00369 ret |= CURL_CSELECT_ERR;
00370 }
00371
00372 return ret;
00373
00374 #endif
00375
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
00392 {
00393 #ifndef HAVE_POLL_FINE
00394 struct timeval pending_tv;
00395 struct timeval *ptimeout;
00396 fd_set fds_read;
00397 fd_set fds_write;
00398 fd_set fds_err;
00399 curl_socket_t maxfd;
00400 #endif
00401 struct timeval initial_tv = {0, 0};
00402 bool fds_none = TRUE;
00403 unsigned int i;
00404 int pending_ms = 0;
00405 int error;
00406 int r;
00407
00408 if(ufds) {
00409 for(i = 0; i < nfds; i++) {
00410 if(ufds[i].fd != CURL_SOCKET_BAD) {
00411 fds_none = FALSE;
00412 break;
00413 }
00414 }
00415 }
00416 if(fds_none) {
00417 r = Curl_wait_ms(timeout_ms);
00418 return r;
00419 }
00420
00421
00422
00423
00424
00425
00426 if(timeout_ms > 0) {
00427 pending_ms = timeout_ms;
00428 initial_tv = curlx_tvnow();
00429 }
00430
00431 #ifdef HAVE_POLL_FINE
00432
00433 do {
00434 if(timeout_ms < 0)
00435 pending_ms = -1;
00436 else if(!timeout_ms)
00437 pending_ms = 0;
00438 r = poll(ufds, nfds, pending_ms);
00439 if(r != -1)
00440 break;
00441 error = SOCKERRNO;
00442 if(error && ERROR_NOT_EINTR(error))
00443 break;
00444 if(timeout_ms > 0) {
00445 pending_ms = (int)(timeout_ms - ELAPSED_MS());
00446 if(pending_ms <= 0) {
00447 r = 0;
00448 break;
00449 }
00450 }
00451 } while(r == -1);
00452
00453 if(r < 0)
00454 return -1;
00455 if(r == 0)
00456 return 0;
00457
00458 for(i = 0; i < nfds; i++) {
00459 if(ufds[i].fd == CURL_SOCKET_BAD)
00460 continue;
00461 if(ufds[i].revents & POLLHUP)
00462 ufds[i].revents |= POLLIN;
00463 if(ufds[i].revents & POLLERR)
00464 ufds[i].revents |= (POLLIN|POLLOUT);
00465 }
00466
00467 #else
00468
00469 FD_ZERO(&fds_read);
00470 FD_ZERO(&fds_write);
00471 FD_ZERO(&fds_err);
00472 maxfd = (curl_socket_t)-1;
00473
00474 for(i = 0; i < nfds; i++) {
00475 ufds[i].revents = 0;
00476 if(ufds[i].fd == CURL_SOCKET_BAD)
00477 continue;
00478 VERIFY_SOCK(ufds[i].fd);
00479 if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
00480 POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
00481 if(ufds[i].fd > maxfd)
00482 maxfd = ufds[i].fd;
00483 if(ufds[i].events & (POLLRDNORM|POLLIN))
00484 FD_SET(ufds[i].fd, &fds_read);
00485 if(ufds[i].events & (POLLWRNORM|POLLOUT))
00486 FD_SET(ufds[i].fd, &fds_write);
00487 if(ufds[i].events & (POLLRDBAND|POLLPRI))
00488 FD_SET(ufds[i].fd, &fds_err);
00489 }
00490 }
00491
00492 #ifdef USE_WINSOCK
00493
00494
00495 if(fds_read.fd_count == 0 && fds_write.fd_count == 0
00496 && fds_err.fd_count == 0) {
00497 r = Curl_wait_ms(timeout_ms);
00498 return r;
00499 }
00500 #endif
00501
00502 ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
00503
00504 do {
00505 if(timeout_ms > 0) {
00506 pending_tv.tv_sec = pending_ms / 1000;
00507 pending_tv.tv_usec = (pending_ms % 1000) * 1000;
00508 }
00509 else if(!timeout_ms) {
00510 pending_tv.tv_sec = 0;
00511 pending_tv.tv_usec = 0;
00512 }
00513
00514 #ifdef USE_WINSOCK
00515 r = select((int)maxfd + 1,
00516
00517
00518
00519
00520 fds_read.fd_count ? &fds_read : NULL,
00521 fds_write.fd_count ? &fds_write : NULL,
00522 fds_err.fd_count ? &fds_err : NULL, ptimeout);
00523 #else
00524 r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
00525 #endif
00526 if(r != -1)
00527 break;
00528 error = SOCKERRNO;
00529 if(error && ERROR_NOT_EINTR(error))
00530 break;
00531 if(timeout_ms > 0) {
00532 pending_ms = timeout_ms - ELAPSED_MS();
00533 if(pending_ms <= 0) {
00534 r = 0;
00535 break;
00536 }
00537 }
00538 } while(r == -1);
00539
00540 if(r < 0)
00541 return -1;
00542 if(r == 0)
00543 return 0;
00544
00545 r = 0;
00546 for(i = 0; i < nfds; i++) {
00547 ufds[i].revents = 0;
00548 if(ufds[i].fd == CURL_SOCKET_BAD)
00549 continue;
00550 if(FD_ISSET(ufds[i].fd, &fds_read))
00551 ufds[i].revents |= POLLIN;
00552 if(FD_ISSET(ufds[i].fd, &fds_write))
00553 ufds[i].revents |= POLLOUT;
00554 if(FD_ISSET(ufds[i].fd, &fds_err))
00555 ufds[i].revents |= POLLPRI;
00556 if(ufds[i].revents != 0)
00557 r++;
00558 }
00559
00560 #endif
00561
00562 return r;
00563 }
00564
00565 #ifdef TPF
00566
00567
00568
00569
00570
00571
00572
00573
00574 int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
00575 fd_set* excepts, struct timeval* tv)
00576 {
00577 int rc;
00578
00579 rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
00580 tpf_process_signals();
00581 return rc;
00582 }
00583 #endif