Add new config option: keep-alive-timeout.
[privoxy.git] / gateway.c
index 7e79831..77ff47a 100644 (file)
--- a/gateway.c
+++ b/gateway.c
@@ -1,4 +1,4 @@
-const char gateway_rcs[] = "$Id: gateway.c,v 1.35 2008/10/17 17:12:01 fabiankeil Exp $";
+const char gateway_rcs[] = "$Id: gateway.c,v 1.41 2008/11/08 15:29:58 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/gateway.c,v $
@@ -34,6 +34,34 @@ const char gateway_rcs[] = "$Id: gateway.c,v 1.35 2008/10/17 17:12:01 fabiankeil
  *
  * Revisions   :
  *    $Log: gateway.c,v $
+ *    Revision 1.41  2008/11/08 15:29:58  fabiankeil
+ *    Unify two debug messages.
+ *
+ *    Revision 1.40  2008/11/08 15:14:05  fabiankeil
+ *    Fix duplicated debugging check.
+ *
+ *    Revision 1.39  2008/10/25 11:33:01  fabiankeil
+ *    Remove already out-commented line left over from debugging.
+ *
+ *    Revision 1.38  2008/10/24 17:33:00  fabiankeil
+ *    - Tone the "keep-alive support is experimental" warning
+ *      down a bit as hackish 0-chunk detection has been
+ *      implemented recently.
+ *    - Only show the "ndef HAVE_POLL" warning once on start-up.
+ *
+ *    Revision 1.37  2008/10/23 17:40:53  fabiankeil
+ *    Fix forget_connection() and mark_connection_unused(),
+ *    which would both under certain circumstances access
+ *    reusable_connection[MAX_REUSABLE_CONNECTIONS]. Oops.
+ *
+ *    Revision 1.36  2008/10/18 19:49:15  fabiankeil
+ *    - Factor close_unusable_connections() out of
+ *      get_reusable_connection() to make sure we really check
+ *      all the remembered connections, not just the ones before
+ *      the next reusable one.
+ *    - Plug two file descriptor leaks. Internally marking
+ *      connections as closed doesn't cut it.
+ *
  *    Revision 1.35  2008/10/17 17:12:01  fabiankeil
  *    In socket_is_still_usable(), use select()
  *    and FD_ISSET() if poll() isn't available.
@@ -285,8 +313,7 @@ static const char socks_userid[] = "anonymous";
 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 
 #define MAX_REUSABLE_CONNECTIONS 100
-/* XXX: should be a config option. */
-#define CONNECTION_KEEP_ALIVE_TIMEOUT 3 * 60
+int keep_alive_timeout = DEFAULT_KEEP_ALIVE_TIMEOUT;
 
 struct reusable_connection
 {
@@ -327,8 +354,12 @@ extern void initialize_reusable_connections(void)
    unsigned int slot = 0;
 
    log_error(LOG_LEVEL_INFO,
-      "Support for 'Connection: keep-alive' is experimental, "
-      "incomplete and known not to work properly in some situations.");
+      "Support for 'Connection: keep-alive' is experimental."
+#ifndef HAVE_POLL
+      " Detecting already dead connections might not work"
+      " correctly on your platform."
+#endif /* ndef HAVE_POLL */
+   );
 
    for (slot = 0; slot < SZ(reusable_connection); slot++)
    {
@@ -497,23 +528,20 @@ void forget_connection(jb_socket sfd)
       if (reusable_connection[slot].sfd == sfd)
       {
          assert(reusable_connection[slot].in_use);
-         break;
-      }
-   }
 
-   if (reusable_connection[slot].sfd != sfd)
-   {
-      log_error(LOG_LEVEL_CONNECT,
-        "Socket %d already forgotten or never remembered.", sfd);
-      privoxy_mutex_unlock(&connection_reuse_mutex);
-      return;
+         log_error(LOG_LEVEL_CONNECT,
+            "Forgetting socket %d for %s:%d in slot %d.",
+            sfd, reusable_connection[slot].host,
+            reusable_connection[slot].port, slot);
+         mark_connection_closed(&reusable_connection[slot]);
+         privoxy_mutex_unlock(&connection_reuse_mutex);
+
+         return;
+      }
    }
 
    log_error(LOG_LEVEL_CONNECT,
-      "Forgetting socket %d for %s:%d in slot %d.",
-      sfd, reusable_connection[slot].host, reusable_connection[slot].port, slot);
-
-   mark_connection_closed(&reusable_connection[slot]);
+      "Socket %d already forgotten or never remembered.", sfd);
 
    privoxy_mutex_unlock(&connection_reuse_mutex);
 }
@@ -563,10 +591,10 @@ static int connection_destination_matches(const struct reusable_connection *conn
          connection->forward_port, fwd->forward_port, http->host);
       return FALSE;
    }
-   if (connection->forward_port   != fwd->forward_port)
+   if (connection->port != http->port)
    {
       log_error(LOG_LEVEL_CONNECT, "Server port mismatch: %d %d (%s)",
-         connection->forward_port, fwd->forward_port, http->host);
+         connection->port, http->port, http->host);
       return FALSE;
    }
 
@@ -626,12 +654,14 @@ static void close_unusable_connections(void)
       {
          time_t time_open = time(NULL) - reusable_connection[slot].timestamp;
 
-         if (CONNECTION_KEEP_ALIVE_TIMEOUT < time_open)
+         if (keep_alive_timeout < time_open)
          {
             log_error(LOG_LEVEL_CONNECT,
-               "The connection to %s:%d in slot %d timed out. Closing.",
-               reusable_connection[slot].host, reusable_connection[slot].port,
-               slot);
+               "The connection to %s:%d in slot %d timed out. "
+               "Closing socket %d. Timeout is: %d.",
+               reusable_connection[slot].host,
+               reusable_connection[slot].port, slot,
+               reusable_connection[slot].sfd, keep_alive_timeout);
             close_socket(reusable_connection[slot].sfd);
             mark_connection_closed(&reusable_connection[slot]);
             continue;
@@ -640,9 +670,10 @@ static void close_unusable_connections(void)
          if (!socket_is_still_usable(reusable_connection[slot].sfd))
          {
             log_error(LOG_LEVEL_CONNECT,
-               "Socket %d for %s:%d in slot %d is no longer usable. Closing.",
-               reusable_connection[slot].sfd, reusable_connection[slot].host,
-               reusable_connection[slot].port, slot);
+               "The connection to %s:%d in slot %d is no longer usable. "
+               "Closing socket %d.", reusable_connection[slot].host,
+               reusable_connection[slot].port, slot,
+               reusable_connection[slot].sfd);
             close_socket(reusable_connection[slot].sfd);
             mark_connection_closed(&reusable_connection[slot]);
             continue;
@@ -692,7 +723,6 @@ static int socket_is_still_usable(jb_socket sfd)
    int socket_is_alive = 0;
 
    memset(&timeout, '\0', sizeof(timeout));
-   /*   timeout.tv_usec = 150;*/
    FD_ZERO(&readable_fds);
    FD_SET(sfd, &readable_fds);
 
@@ -708,11 +738,6 @@ static int socket_is_still_usable(jb_socket sfd)
     */
    socket_is_alive = !FD_ISSET(sfd, &readable_fds);
 
-   log_error(LOG_LEVEL_INFO,
-      "Detecting already dead sockets might not work correctly "
-      "on your platform. Anyway, socket %d appears to be %s.",
-      sfd, (socket_is_alive ? "still alive" : "already dead"));
-
    return socket_is_alive;
 #endif /* def HAVE_POLL */
 }
@@ -794,25 +819,41 @@ static int mark_connection_unused(jb_socket sfd)
       if (reusable_connection[slot].sfd == sfd)
       {
          assert(reusable_connection[slot].in_use);
+         socket_found = TRUE;
+         log_error(LOG_LEVEL_CONNECT,
+            "Marking open socket %d for %s:%d in slot %d as unused.",
+            sfd, reusable_connection[slot].host,
+            reusable_connection[slot].port, slot);
+         reusable_connection[slot].in_use = 0;
+         reusable_connection[slot].timestamp = time(NULL);
          break;
       }
    }
 
-   if (reusable_connection[slot].sfd == sfd)
-   {
-      socket_found = TRUE;
-      log_error(LOG_LEVEL_CONNECT,
-         "Marking open socket %d for %s:%d in slot %d as unused.",
-         sfd, reusable_connection[slot].host, reusable_connection[slot].port, slot);
-      reusable_connection[slot].in_use = 0;
-      reusable_connection[slot].timestamp = time(NULL);
-   }
-
    privoxy_mutex_unlock(&connection_reuse_mutex);
 
    return socket_found;
 
 }
+
+
+/*********************************************************************
+ *
+ * Function    :  set_keep_alive_timeout
+ *
+ * Description :  Sets the timeout after which open
+ *                connections will no longer be reused.
+ *
+ * Parameters  :
+ *          1  :  timeout = The timeout in seconds.
+ *
+ * Returns     :  void
+ *
+ *********************************************************************/
+void set_keep_alive_timeout(int timeout)
+{
+   keep_alive_timeout = timeout;
+}
 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */