Commit 5527417a authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

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.
parent bedfafe3
Loading
Loading
Loading
Loading
+55 −20
Original line number Original line Diff line number Diff line
@@ -125,11 +125,11 @@ int Curl_wait_ms(int timeout_ms)
}
}


/*
/*
 * This is an internal function used for waiting for read or write
 * Wait for read or write events on a set of file descriptors. It uses poll()
 * events on a pair of file descriptors.  It uses poll() when a fine
 * when a fine poll() is available, in order to avoid limits with FD_SETSIZE,
 * poll() is available, in order to avoid limits with FD_SETSIZE,
 * otherwise select() is used.  An error is returned if select() is being used
 * otherwise select() is used.  An error is returned if select() is
 * and a file descriptor is too large for FD_SETSIZE.
 * being used and a file descriptor is too large for FD_SETSIZE.
 *
 * A negative timeout value makes this function wait indefinitely,
 * A negative timeout value makes this function wait indefinitely,
 * unles no valid file descriptor is given, when this happens the
 * unles no valid file descriptor is given, when this happens the
 * negative timeout is ignored and the function times out immediately.
 * negative timeout is ignored and the function times out immediately.
@@ -140,10 +140,17 @@ int Curl_wait_ms(int timeout_ms)
 * Return values:
 * Return values:
 *   -1 = system call error or fd >= FD_SETSIZE
 *   -1 = system call error or fd >= FD_SETSIZE
 *    0 = timeout
 *    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,
int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
                      long timeout_ms)
                      curl_socket_t readfd1,
                      curl_socket_t writefd, /* socket to write to */
                      long timeout_ms)       /* milliseconds to wait */
{
{
#ifdef HAVE_POLL_FINE
#ifdef HAVE_POLL_FINE
  struct pollfd pfd[2];
  struct pollfd pfd[2];
@@ -162,7 +169,9 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd,
  int r;
  int r;
  int ret;
  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);
    r = Curl_wait_ms((int)timeout_ms);
    return r;
    return r;
  }
  }
@@ -180,8 +189,14 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd,
#ifdef HAVE_POLL_FINE
#ifdef HAVE_POLL_FINE


  num = 0;
  num = 0;
  if(readfd != CURL_SOCKET_BAD) {
  if(readfd0 != CURL_SOCKET_BAD) {
    pfd[num].fd = readfd;
    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].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
    pfd[num].revents = 0;
    pfd[num].revents = 0;
    num++;
    num++;
@@ -218,13 +233,20 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd,


  ret = 0;
  ret = 0;
  num = 0;
  num = 0;
  if(readfd != CURL_SOCKET_BAD) {
  if(readfd0 != CURL_SOCKET_BAD) {
    if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
    if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
      ret |= CURL_CSELECT_IN;
      ret |= CURL_CSELECT_IN;
    if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
    if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
      ret |= CURL_CSELECT_ERR;
      ret |= CURL_CSELECT_ERR;
    num++;
    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(writefd != CURL_SOCKET_BAD) {
    if(pfd[num].revents & (POLLWRNORM|POLLOUT))
    if(pfd[num].revents & (POLLWRNORM|POLLOUT))
      ret |= CURL_CSELECT_OUT;
      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;
  maxfd = (curl_socket_t)-1;


  FD_ZERO(&fds_read);
  FD_ZERO(&fds_read);
  if(readfd != CURL_SOCKET_BAD) {
  if(readfd0 != CURL_SOCKET_BAD) {
    VERIFY_SOCK(readfd);
    VERIFY_SOCK(readfd0);
    FD_SET(readfd, &fds_read);
    FD_SET(readfd0, &fds_read);
    FD_SET(readfd, &fds_err);
    FD_SET(readfd0, &fds_err);
    maxfd = readfd;
    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);
  FD_ZERO(&fds_write);
@@ -286,10 +315,16 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd,
    return 0;
    return 0;


  ret = 0;
  ret = 0;
  if(readfd != CURL_SOCKET_BAD) {
  if(readfd0 != CURL_SOCKET_BAD) {
    if(FD_ISSET(readfd, &fds_read))
    if(FD_ISSET(readfd0, &fds_read))
      ret |= CURL_CSELECT_IN;
      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;
      ret |= CURL_CSELECT_ERR;
  }
  }
  if(writefd != CURL_SOCKET_BAD) {
  if(writefd != CURL_SOCKET_BAD) {
+11 −1
Original line number Original line Diff line number Diff line
@@ -84,9 +84,19 @@ struct pollfd
#define POLLRDBAND POLLPRI
#define POLLRDBAND POLLPRI
#endif
#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);
                      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_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms);


int Curl_wait_ms(int timeout_ms);
int Curl_wait_ms(int timeout_ms);