aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/select.c75
-rw-r--r--lib/select.h12
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);