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