Browse Source

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.
Daniel Stenberg 12 years ago
parent
commit
5527417afa
2 changed files with 66 additions and 21 deletions
  1. 55 20
      lib/select.c
  2. 11 1
      lib/select.h

+ 55 - 20
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) {

+ 11 - 1
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);