From 5527417afae062d7a2b12ee80730a0ab22b86eab Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 8 Dec 2011 16:14:30 +0100 Subject: sockets: new Curl_socket_check() can wait for 3 sockets This offers an alternative to the existing Curl_socket_ready() API which only checks one socket for read and one for write. --- lib/select.c | 75 ++++++++++++++++++++++++++++++++++++++++++++---------------- lib/select.h | 12 +++++++++- 2 files changed, 66 insertions(+), 21 deletions(-) diff --git a/lib/select.c b/lib/select.c index 6cecbf701..549da077c 100644 --- a/lib/select.c +++ b/lib/select.c @@ -125,11 +125,11 @@ int Curl_wait_ms(int timeout_ms) } /* - * This is an internal function used for waiting for read or write - * events on a pair of file descriptors. It uses poll() when a fine - * poll() is available, in order to avoid limits with FD_SETSIZE, - * otherwise select() is used. An error is returned if select() is - * being used and a file descriptor is too large for FD_SETSIZE. + * Wait for read or write events on a set of file descriptors. It uses poll() + * when a fine poll() is available, in order to avoid limits with FD_SETSIZE, + * otherwise select() is used. An error is returned if select() is being used + * and a file descriptor is too large for FD_SETSIZE. + * * A negative timeout value makes this function wait indefinitely, * unles no valid file descriptor is given, when this happens the * negative timeout is ignored and the function times out immediately. @@ -140,10 +140,17 @@ int Curl_wait_ms(int timeout_ms) * Return values: * -1 = system call error or fd >= FD_SETSIZE * 0 = timeout - * CURL_CSELECT_IN | CURL_CSELECT_OUT | CURL_CSELECT_ERR + * [bitmask] = action as described below + * + * CURL_CSELECT_IN - first socket is readable + * CURL_CSELECT_IN2 - second socket is readable + * CURL_CSELECT_OUT - write socket is writable + * CURL_CSELECT_ERR - an error condition occurred */ -int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, - long timeout_ms) +int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ + curl_socket_t readfd1, + curl_socket_t writefd, /* socket to write to */ + long timeout_ms) /* milliseconds to wait */ { #ifdef HAVE_POLL_FINE struct pollfd pfd[2]; @@ -162,7 +169,9 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, int r; int ret; - if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) { + if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) && + (writefd == CURL_SOCKET_BAD)) { + /* no sockets, just wait */ r = Curl_wait_ms((int)timeout_ms); return r; } @@ -180,8 +189,14 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, #ifdef HAVE_POLL_FINE num = 0; - if(readfd != CURL_SOCKET_BAD) { - pfd[num].fd = readfd; + if(readfd0 != CURL_SOCKET_BAD) { + pfd[num].fd = readfd0; + pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; + pfd[num].revents = 0; + num++; + } + if(readfd1 != CURL_SOCKET_BAD) { + pfd[num].fd = readfd1; pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; pfd[num].revents = 0; num++; @@ -218,13 +233,20 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, ret = 0; num = 0; - if(readfd != CURL_SOCKET_BAD) { + if(readfd0 != CURL_SOCKET_BAD) { if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) ret |= CURL_CSELECT_IN; if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) ret |= CURL_CSELECT_ERR; num++; } + if(readfd1 != CURL_SOCKET_BAD) { + if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) + ret |= CURL_CSELECT_IN2; + if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) + ret |= CURL_CSELECT_ERR; + num++; + } if(writefd != CURL_SOCKET_BAD) { if(pfd[num].revents & (POLLWRNORM|POLLOUT)) ret |= CURL_CSELECT_OUT; @@ -240,11 +262,18 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, maxfd = (curl_socket_t)-1; FD_ZERO(&fds_read); - if(readfd != CURL_SOCKET_BAD) { - VERIFY_SOCK(readfd); - FD_SET(readfd, &fds_read); - FD_SET(readfd, &fds_err); - maxfd = readfd; + if(readfd0 != CURL_SOCKET_BAD) { + VERIFY_SOCK(readfd0); + FD_SET(readfd0, &fds_read); + FD_SET(readfd0, &fds_err); + maxfd = readfd0; + } + if(readfd1 != CURL_SOCKET_BAD) { + VERIFY_SOCK(readfd1); + FD_SET(readfd1, &fds_read); + FD_SET(readfd1, &fds_err); + if(readfd1 > maxfd) + maxfd = readfd1; } FD_ZERO(&fds_write); @@ -286,10 +315,16 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, return 0; ret = 0; - if(readfd != CURL_SOCKET_BAD) { - if(FD_ISSET(readfd, &fds_read)) + if(readfd0 != CURL_SOCKET_BAD) { + if(FD_ISSET(readfd0, &fds_read)) ret |= CURL_CSELECT_IN; - if(FD_ISSET(readfd, &fds_err)) + if(FD_ISSET(readfd0, &fds_err)) + ret |= CURL_CSELECT_ERR; + } + if(readfd1 != CURL_SOCKET_BAD) { + if(FD_ISSET(readfd1, &fds_read)) + ret |= CURL_CSELECT_IN2; + if(FD_ISSET(readfd1, &fds_err)) ret |= CURL_CSELECT_ERR; } if(writefd != CURL_SOCKET_BAD) { diff --git a/lib/select.h b/lib/select.h index 56729a3b2..b50604b0a 100644 --- a/lib/select.h +++ b/lib/select.h @@ -84,9 +84,19 @@ struct pollfd #define POLLRDBAND POLLPRI #endif -int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, +/* there are three CSELECT defines that are defined in the public header that + are exposed to users, but this *IN2 bit is only ever used internally and + therefore defined here */ +#define CURL_CSELECT_IN2 (CURL_CSELECT_ERR << 1) + +int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2, + curl_socket_t writefd, long timeout_ms); +/* provide the former API internally */ +#define Curl_socket_ready(x,y,z) \ + Curl_socket_check(x, CURL_SOCKET_BAD, y, z) + int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms); int Curl_wait_ms(int timeout_ms); -- cgit v1.2.3