Commit 0e2d3b7b authored by Yang Tse's avatar Yang Tse
Browse files

Code refactoring, extracting a new function wait_ms() from Curl_select and

Curl_poll() which is called whenever not a single valid file descriptor is
passed to these functions.

Improve readibility using a poll() macro to replace WSApoll().
parent 46a50aa0
Loading
Loading
Loading
Loading
+75 −46
Original line number Diff line number Diff line
@@ -65,6 +65,33 @@
} while(0)
#endif

/*
 * Internal function used for waiting a specific amount of ms
 * in Curl_select() and Curl_poll() when no file descriptor is
 * provided to wait on, just being used to delay execution.
 * WinSock select() and poll() timeout mechanisms need a valid
 * socket descriptor in a not null file descriptor set to work.
 * Waiting indefinitely with this function is not allowed, a
 * zero or negative timeout value will return immediately.
 */
static void wait_ms(int timeout_ms)
{
  if (timeout_ms <= 0)
    return;
#if defined(__MSDOS__)
  delay(timeout_ms);
#elif defined(USE_WINSOCK)
  Sleep(timeout_ms);
#elif defined(HAVE_POLL_FINE)
  poll(NULL, 0, timeout_ms);
#else
  struct timeval timeout;
  timeout.tv_sec = timeout_ms / 1000;
  timeout.tv_usec = (timeout_ms % 1000) * 1000;
  select(0, NULL, NULL, NULL, &timeout);
#endif
}

/*
 * This is an internal function used for waiting for read or write
 * events on single file descriptors.  It attempts to replace select()
@@ -77,12 +104,26 @@
 */
int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
{
#if defined(HAVE_POLL_FINE) || defined(CURL_HAVE_WSAPOLL)
#ifdef HAVE_POLL_FINE
  struct pollfd pfd[2];
  int num;
#else
  struct timeval timeout;
  fd_set fds_read;
  fd_set fds_write;
  fd_set fds_err;
  curl_socket_t maxfd;
#endif
  int r;
  int ret;

  if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) {
    wait_ms(timeout_ms);
    return 0;
  }

#ifdef HAVE_POLL_FINE

  num = 0;
  if (readfd != CURL_SOCKET_BAD) {
    pfd[num].fd = readfd;
@@ -96,11 +137,7 @@ int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
  }

  do {
#ifdef CURL_HAVE_WSAPOLL
    r = WSAPoll(pfd, num, timeout_ms);
#else
    r = poll(pfd, num, timeout_ms);
#endif
  } while((r == -1) && (SOCKERRNO == EINTR));

  if (r < 0)
@@ -132,33 +169,12 @@ int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
  }

  return ret;
#else
  struct timeval timeout;
  fd_set fds_read;
  fd_set fds_write;
  fd_set fds_err;
  curl_socket_t maxfd;
  int r;
  int ret;

#else  /* HAVE_POLL_FINE */

  timeout.tv_sec = timeout_ms / 1000;
  timeout.tv_usec = (timeout_ms % 1000) * 1000;

  if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) {
    /* According to POSIX we should pass in NULL pointers if we don't want to
       wait for anything in particular but just use the timeout function.
       Windows however returns immediately if done so. I copied the MSDOS
       delay() use from src/main.c that already had this work-around. */
#ifdef WIN32
    Sleep(timeout_ms);
#elif defined(__MSDOS__)
    delay(timeout_ms);
#else
    select(0, NULL, NULL, NULL, &timeout);
#endif
    return 0;
  }

  FD_ZERO(&fds_err);
  maxfd = (curl_socket_t)-1;

@@ -203,7 +219,9 @@ int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
  }

  return ret;
#endif

#endif  /* HAVE_POLL_FINE */

}

/*
@@ -218,23 +236,38 @@ int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
 */
int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
{
  int r;
#ifdef HAVE_POLL_FINE
  do {
#ifdef CURL_HAVE_WSAPOLL
    r = WSAPoll(ufds, nfds, timeout_ms);
#else
    r = poll(ufds, nfds, timeout_ms);
#endif
  } while((r == -1) && (SOCKERRNO == EINTR));
#else  /* HAVE_POLL_FINE */
#ifndef HAVE_POLL_FINE
  struct timeval timeout;
  struct timeval *ptimeout;
  fd_set fds_read;
  fd_set fds_write;
  fd_set fds_err;
  curl_socket_t maxfd;
#endif
  bool fds_none = TRUE;
  unsigned int i;
  int r;

  if (ufds) {
    for (i = 0; i < nfds; i++) {
      if (ufds[i].fd != CURL_SOCKET_BAD) {
        fds_none = FALSE;
        break;
      }
    }
  }
  if (fds_none) {
    wait_ms(timeout_ms);
    return 0;
  }

#ifdef HAVE_POLL_FINE

  do {
    r = poll(ufds, nfds, timeout_ms);
  } while((r == -1) && (SOCKERRNO == EINTR));

#else  /* HAVE_POLL_FINE */

  FD_ZERO(&fds_read);
  FD_ZERO(&fds_write);
@@ -244,13 +277,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
  for (i = 0; i < nfds; i++) {
    if (ufds[i].fd == CURL_SOCKET_BAD)
      continue;
#if !defined(USE_WINSOCK) && !defined(TPF)
    /* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1] */
    if (ufds[i].fd >= FD_SETSIZE) {
      SET_SOCKERRNO(EINVAL);
      return -1;
    }
#endif
    VERIFY_SOCK(ufds[i].fd);
    if (ufds[i].fd > maxfd)
      maxfd = ufds[i].fd;
    if (ufds[i].events & POLLIN)
@@ -292,7 +319,9 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
    if (ufds[i].revents != 0)
      r++;
  }

#endif  /* HAVE_POLL_FINE */

  return r;
}

+24 −7
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
@@ -23,13 +23,30 @@
 * $Id$
 ***************************************************************************/

#include "setup.h"

#ifdef HAVE_SYS_POLL_H
#include <sys/poll.h>
#elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
/* for Vista, use WSAPoll(). */
#include <winsock2.h>
#define CURL_HAVE_WSAPOLL
#else
#endif

/*
 * poll() function on Windows Vista and later is called WSAPoll()
 */

#if defined(USE_WINSOCK) && (USE_WINSOCK > 1) && \
    defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
#undef  HAVE_POLL
#define HAVE_POLL 1
#undef  HAVE_POLL_FINE
#define HAVE_POLL_FINE 1
#define poll(x,y,z) WSAPoll((x),(y),(z))
#endif

/*
 * Definition of pollfd struct and constants for platforms lacking them.
 */

#ifndef HAVE_POLL

#define POLLIN      0x01
#define POLLPRI     0x02
@@ -60,4 +77,4 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
                       fd_set* excepts, struct timeval* tv);
#endif

#endif
#endif /* __SELECT_H */