Update comments that still mentioned 'show-proxy-args' instead of 'show-status'
[privoxy.git] / jbsockets.c
index 182382b..7214979 100644 (file)
@@ -1,14 +1,14 @@
-const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.137 2016/08/22 14:50:18 fabiankeil Exp $";
+const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.144 2017/06/08 13:04:34 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/jbsockets.c,v $
  *
  * Purpose     :  Contains wrappers for system-specific sockets code,
- *                so that the rest of Junkbuster can be more
+ *                so that the rest of Privoxy can be more
  *                OS-independent.  Contains #ifdefs to make this work
  *                on many platforms.
  *
- * Copyright   :  Written by and Copyright (C) 2001-2016 the
+ * Copyright   :  Written by and Copyright (C) 2001-2017 the
  *                Privoxy team. http://www.privoxy.org/
  *
  *                Based on the Internet Junkbuster originally written
@@ -211,8 +211,12 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client
    char service[6];
    int retval;
    jb_socket fd;
+#ifdef HAVE_POLL
+   struct pollfd poll_fd[1];
+#else
    fd_set wfds;
    struct timeval timeout;
+#endif
 #if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
    int   flags;
 #endif
@@ -300,6 +304,7 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client
          continue;
       }
 
+#ifndef HAVE_POLL
 #ifndef _WIN32
       if (fd >= FD_SETSIZE)
       {
@@ -311,6 +316,7 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client
          return JB_INVALID_SOCKET;
       }
 #endif
+#endif
 
 #ifdef FEATURE_EXTERNAL_FILTERS
       mark_socket_for_close_on_execute(fd);
@@ -363,6 +369,31 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client
       }
 #endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */
 
+#ifdef HAVE_POLL
+      poll_fd[0].fd = fd;
+      poll_fd[0].events = POLLOUT;
+
+      retval = poll(poll_fd, 1, 30000);
+      if (retval == 0)
+      {
+         if (rp->ai_next != NULL)
+         {
+            /* Log this now as we'll try another address next */
+            log_error(LOG_LEVEL_CONNECT,
+               "Could not connect to [%s]:%s: Operation timed out.",
+               csp->http->host_ip_addr_str, service);
+         }
+         else
+         {
+            /*
+             * This is the last address, don't log this now
+             * as it would result in a duplicated log message.
+             */
+            socket_error = ETIMEDOUT;
+         }
+      }
+      else if (retval > 0)
+#else
       /* wait for connection to complete */
       FD_ZERO(&wfds);
       FD_SET(fd, &wfds);
@@ -373,6 +404,7 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client
       /* MS Windows uses int, not SOCKET, for the 1st arg of select(). Weird! */
       if ((select((int)fd + 1, NULL, &wfds, NULL, &timeout) > 0)
          && FD_ISSET(fd, &wfds))
+#endif
       {
          socklen_t optlen = sizeof(socket_error);
          if (!getsockopt(fd, SOL_SOCKET, SO_ERROR, &socket_error, &optlen))
@@ -430,8 +462,12 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli
    struct sockaddr_in inaddr;
    jb_socket fd;
    unsigned int addr;
+#ifdef HAVE_POLL
+   struct pollfd poll_fd[1];
+#else
    fd_set wfds;
    struct timeval tv[1];
+#endif
 #if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
    int   flags;
 #endif
@@ -493,6 +529,7 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli
       return(JB_INVALID_SOCKET);
    }
 
+#ifndef HAVE_POLL
 #ifndef _WIN32
    if (fd >= FD_SETSIZE)
    {
@@ -502,6 +539,7 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli
       close_socket(fd);
       return JB_INVALID_SOCKET;
    }
+#endif
 #endif
 
    set_no_delay_flag(fd);
@@ -549,6 +587,12 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli
    }
 #endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */
 
+#ifdef HAVE_POLL
+   poll_fd[0].fd = fd;
+   poll_fd[0].events = POLLOUT;
+
+   if (poll(poll_fd, 1, 30000) <= 0)
+#else
    /* wait for connection to complete */
    FD_ZERO(&wfds);
    FD_SET(fd, &wfds);
@@ -558,6 +602,7 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli
 
    /* MS Windows uses int, not SOCKET, for the 1st arg of select(). Weird! */
    if (select((int)fd + 1, NULL, &wfds, NULL, tv) <= 0)
+#endif
    {
       close_socket(fd);
       return(JB_INVALID_SOCKET);
@@ -594,6 +639,14 @@ int write_socket(jb_socket fd, const char *buf, size_t len)
       return 0;
    }
 
+#ifdef FUZZ
+   if (!daemon_mode && fd <= 3)
+   {
+      log_error(LOG_LEVEL_WRITING, "Pretending to write to socket %d: %N", fd, len, buf);
+      return 0;
+   }
+#endif
+
    log_error(LOG_LEVEL_WRITING, "to socket %d: %N", fd, len, buf);
 
 #if defined(_WIN32)
@@ -695,10 +748,18 @@ int read_socket(jb_socket fd, char *buf, int len)
  *********************************************************************/
 int data_is_available(jb_socket fd, int seconds_to_wait)
 {
+   int n;
    char buf[10];
+#ifdef HAVE_POLL
+   struct pollfd poll_fd[1];
+
+   poll_fd[0].fd = fd;
+   poll_fd[0].events = POLLIN;
+
+   n = poll(poll_fd, 1, seconds_to_wait * 1000);
+#else
    fd_set rfds;
    struct timeval timeout;
-   int n;
 
    memset(&timeout, 0, sizeof(timeout));
    timeout.tv_sec = seconds_to_wait;
@@ -712,6 +773,7 @@ int data_is_available(jb_socket fd, int seconds_to_wait)
    FD_SET(fd, &rfds);
 
    n = select(fd+1, &rfds, NULL, NULL, &timeout);
+#endif
 
    /*
     * XXX: Do we care about the different error conditions?
@@ -1220,25 +1282,41 @@ int accept_connection(struct client_state * csp, jb_socket fds[])
    int retval;
    int i;
    int max_selected_socket;
+#ifdef HAVE_POLL
+   struct pollfd poll_fds[MAX_LISTENING_SOCKETS];
+   nfds_t polled_sockets;
+#else
    fd_set selected_fds;
+#endif
    jb_socket fd;
    const char *host_addr;
    size_t listen_addr_size;
 
    c_length = sizeof(client);
 
+#ifdef HAVE_POLL
+   memset(poll_fds, 0, sizeof(poll_fds));
+   polled_sockets = 0;
+#else
    /*
     * Wait for a connection on any socket.
     * Return immediately if no socket is listening.
     * XXX: Why not treat this as fatal error?
     */
    FD_ZERO(&selected_fds);
+#endif
    max_selected_socket = 0;
    for (i = 0; i < MAX_LISTENING_SOCKETS; i++)
    {
       if (JB_INVALID_SOCKET != fds[i])
       {
+#ifdef HAVE_POLL
+         poll_fds[i].fd = fds[i];
+         poll_fds[i].events = POLLIN;
+         polled_sockets++;
+#else
          FD_SET(fds[i], &selected_fds);
+#endif
          if (max_selected_socket < fds[i] + 1)
          {
             max_selected_socket = fds[i] + 1;
@@ -1251,7 +1329,11 @@ int accept_connection(struct client_state * csp, jb_socket fds[])
    }
    do
    {
+#ifdef HAVE_POLL
+      retval = poll(poll_fds, polled_sockets, -1);
+#else
       retval = select(max_selected_socket, &selected_fds, NULL, NULL, NULL);
+#endif
    } while (retval < 0 && errno == EINTR);
    if (retval <= 0)
    {
@@ -1269,8 +1351,12 @@ int accept_connection(struct client_state * csp, jb_socket fds[])
       }
       return 0;
    }
+#ifdef HAVE_POLL
+   for (i = 0; i < MAX_LISTENING_SOCKETS && (poll_fds[i].revents == 0); i++);
+#else
    for (i = 0; i < MAX_LISTENING_SOCKETS && !FD_ISSET(fds[i], &selected_fds);
          i++);
+#endif
    if (i >= MAX_LISTENING_SOCKETS)
    {
       log_error(LOG_LEVEL_ERROR,
@@ -1317,6 +1403,7 @@ int accept_connection(struct client_state * csp, jb_socket fds[])
    }
 #endif
 
+#ifndef HAVE_POLL
 #ifndef _WIN32
    if (afd >= FD_SETSIZE)
    {
@@ -1327,6 +1414,7 @@ int accept_connection(struct client_state * csp, jb_socket fds[])
       return 0;
    }
 #endif
+#endif
 
 #ifdef FEATURE_EXTERNAL_FILTERS
    mark_socket_for_close_on_execute(afd);
@@ -1508,7 +1596,6 @@ int socket_is_still_alive(jb_socket sfd)
 {
    char buf[10];
    int no_data_waiting;
-
 #ifdef HAVE_POLL
    int poll_result;
    struct pollfd poll_fd[1];