Reenable server-side-only keep-alive support, but only share
authorFabian Keil <fk@fabiankeil.de>
Sun, 10 May 2009 10:19:23 +0000 (10:19 +0000)
committerFabian Keil <fk@fabiankeil.de>
Sun, 10 May 2009 10:19:23 +0000 (10:19 +0000)
outgoing connections if the connection-sharing option is set.

doc/source/p-config.sgml
gateway.c
jcc.c
loadcfg.c
project.h

index fff23cd..c622cf2 100644 (file)
@@ -3,7 +3,7 @@
 
  Purpose     :  Used with other docs and files only.
 
- $Id: p-config.sgml,v 2.49 2009/04/19 17:39:55 fabiankeil Exp $
+ $Id: p-config.sgml,v 2.50 2009/04/24 15:29:43 fabiankeil Exp $
 
  Copyright (C) 2001-2009 Privoxy Developers http://www.privoxy.org/
  See LICENSE.
@@ -95,7 +95,7 @@
  Sample Configuration File for Privoxy v&p-version;
 </title>
 <para>
- $Id: p-config.sgml,v 2.49 2009/04/19 17:39:55 fabiankeil Exp $
+ $Id: p-config.sgml,v 2.50 2009/04/24 15:29:43 fabiankeil Exp $
 </para>
 <para>
 Copyright (C) 2001-2009 Privoxy Developers http://www.privoxy.org/
@@ -2512,19 +2512,87 @@ forward-socks4, forward-socks4a and forward-socks5</title>
   <term>Effect if unset:</term>
   <listitem>
    <para>
-    Connections are not reused.
+    Connections are not kept alive.
    </para>
   </listitem>
  </varlistentry>
  <varlistentry>
   <term>Notes:</term>
   <listitem>
+   <para>
+    This option allows clients to keep the connection to &my-app;
+    alive. If the server supports it, &my-app; will keep
+    the connection to the server alive as well. Under certain
+    circumstances this may result in speed-ups.
+   </para>
+   <para>
+    By default, &my-app; will close the connection to the server if
+    the client connection gets closed, or if the specified timeout
+    has been reached without a new request coming in. This behaviour
+    can be changed with the <ulink
+     url="#CONNECTION-SHARING">connection-sharing</ulink> option.
+   </para>
    <para>
     This option has no effect if <application>Privoxy</application>
     has been compiled without keep-alive support.
    </para>
   </listitem>
  </varlistentry>
+ <varlistentry>
+  <term>Examples:</term>
+  <listitem>
+   <para>
+    keep-alive-timeout 300
+   </para>
+  </listitem>
+ </varlistentry>
+</variablelist>
+<![%config-file;[<literallayout>@@keep-alive-timeout 300</literallayout>]]>
+</sect3>
+
+
+<sect3 renderas="sect4" id="connection-sharing"><title>connection-sharing</title>
+<variablelist>
+ <varlistentry>
+  <term>Specifies:</term>
+  <listitem>
+   <para>
+    Whether or not outgoing connections that have been kept alive
+    should be shared between different incoming connections.
+   </para>
+  </listitem>
+ </varlistentry>
+ <varlistentry>
+  <term>Type of value:</term>
+  <listitem>
+   <para>
+    <replaceable>0 or 1</replaceable>
+   </para>
+  </listitem>
+ </varlistentry>
+ <varlistentry>
+  <term>Default value:</term>
+  <listitem>
+   <para>None</para>
+  </listitem>
+ </varlistentry>
+ <varlistentry>
+  <term>Effect if unset:</term>
+  <listitem>
+   <para>
+    Connections are not shared.
+   </para>
+  </listitem>
+ </varlistentry>
+ <varlistentry>
+  <term>Notes:</term>
+  <listitem>
+   <para>
+    This option has no effect if <application>Privoxy</application>
+    has been compiled without keep-alive support, or if it's disabled.
+   </para>
+  </listitem>
+ </varlistentry>
  <varlistentry>
   <term>Notes:</term>
   <listitem>
@@ -2533,13 +2601,34 @@ forward-socks4, forward-socks4a and forward-socks5</title>
     There are also a few privacy implications you should be aware of.
    </para>
    <para>
-    Outgoing connections are shared between clients (if there are more
-    than one) and closing the client that initiated the outgoing connection
-    does not affect the connection between &my-app; and the server unless
-    the client's request hasn't been completed yet. If the outgoing connection
-    is idle, it will not be closed until either <application>Privoxy's</application>
-    or the server's timeout is reached. While it's open, the server knows
-    that the system running &my-app; is still there.
+    If this option is effective, outgoing connections are shared between
+    clients (if there are more than one) and closing the client that initiated
+    the outgoing connection does no longer affect the connection between &my-app;
+    and the server unless the client's request hasn't been completed yet.
+   </para>
+   <para>
+    If the outgoing connection  is idle, it will not be closed until either
+    <application>Privoxy's</application> or the server's timeout is reached.
+    While it's open, the server knows that the system running &my-app; is still
+    there.
+   </para>
+   <para>
+    If there are more than one client (maybe even belonging to multiple users),
+    they will be able to reuse each others connections. This is potentially
+    dangerous in case of authentication schemes like NTLM where only the
+    connection is authenticated, instead of requiring authentication for
+    each request.
+   </para>
+   <para>
+    If there is only a single client, and if said client can keep connections
+    alive on its own, enabling this option has next to no effect. If the client
+    doesn't support connection keep-alive, enabling this option may make sense
+    as it allows &my-app; to keep outgoing connections alive even if the client
+    itself doesn't support it.
+   </para>
+   <para>
+    This option should only be used by experienced users who
+    understand the risks and can weight them against the benefits.
    </para>
   </listitem>
  </varlistentry>
@@ -2547,12 +2636,12 @@ forward-socks4, forward-socks4a and forward-socks5</title>
   <term>Examples:</term>
   <listitem>
    <para>
-    keep-alive-timeout 300
+    connection-sharing 1
    </para>
   </listitem>
  </varlistentry>
 </variablelist>
-<![%config-file;[<literallayout>@@keep-alive-timeout 300</literallayout>]]>
+<![%config-file;[<literallayout>@@#connection-sharing 1</literallayout>]]>
 </sect3>
 
 
@@ -2689,7 +2778,7 @@ forward-socks4, forward-socks4a and forward-socks5</title>
   </listitem>
  </varlistentry>
 </variablelist>
-<![%config-file;[<literallayout>@@max-client-connections 256</literallayout>]]>
+<![%config-file;[<literallayout>@@#max-client-connections 256</literallayout>]]>
 </sect3>
 
 
index 3181609..3c251fe 100644 (file)
--- a/gateway.c
+++ b/gateway.c
@@ -1,4 +1,4 @@
-const char gateway_rcs[] = "$Id: gateway.c,v 1.48 2009/02/13 17:20:36 fabiankeil Exp $";
+const char gateway_rcs[] = "$Id: gateway.c,v 1.49 2009/05/10 10:12:30 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/gateway.c,v $
@@ -34,6 +34,10 @@ const char gateway_rcs[] = "$Id: gateway.c,v 1.48 2009/02/13 17:20:36 fabiankeil
  *
  * Revisions   :
  *    $Log: gateway.c,v $
+ *    Revision 1.49  2009/05/10 10:12:30  fabiankeil
+ *    Initial keep-alive support for the client socket.
+ *    Temporarily disable the server-side-only keep-alive code.
+ *
  *    Revision 1.48  2009/02/13 17:20:36  fabiankeil
  *    Reword keep-alive support warning and only show
  *    it #if !defined(HAVE_POLL) && !defined(_WIN32).
@@ -800,10 +804,13 @@ jb_socket forwarded_connect(const struct forward_spec * fwd,
    jb_socket sfd = JB_INVALID_SOCKET;
 
 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
-   sfd = get_reusable_connection(http, fwd);
-   if (JB_INVALID_SOCKET != sfd)
+   if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING))
    {
-      return sfd;
+      sfd = get_reusable_connection(http, fwd);
+      if (JB_INVALID_SOCKET != sfd)
+      {
+         return sfd;
+      }
    }
 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 
diff --git a/jcc.c b/jcc.c
index 5991a72..7ab3f32 100644 (file)
--- a/jcc.c
+++ b/jcc.c
@@ -1,4 +1,4 @@
-const char jcc_rcs[] = "$Id: jcc.c,v 1.245 2009/04/24 15:29:43 fabiankeil Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.246 2009/05/10 10:12:30 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/jcc.c,v $
@@ -33,6 +33,10 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.245 2009/04/24 15:29:43 fabiankeil Exp $"
  *
  * Revisions   :
  *    $Log: jcc.c,v $
+ *    Revision 1.246  2009/05/10 10:12:30  fabiankeil
+ *    Initial keep-alive support for the client socket.
+ *    Temporarily disable the server-side-only keep-alive code.
+ *
  *    Revision 1.245  2009/04/24 15:29:43  fabiankeil
  *    Allow to limit the number of of client connections.
  *
@@ -3507,6 +3511,7 @@ static void serve(struct client_state *csp)
 #endif /* def AMIGA */
 {
 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
+   static int monitor_thread_running = 0;
    int continue_chatting = 0;
    do
    {
@@ -3519,30 +3524,6 @@ static void serve(struct client_state *csp)
          && (csp->sfd != JB_INVALID_SOCKET)
          && socket_is_still_usable(csp->sfd);
 
-      /*
-       * Get the csp in a mostly vergin state again.
-       * XXX: Should be done elsewhere.
-       */
-      csp->content_type = 0;
-      csp->content_length = 0;
-      csp->expected_content_length = 0;
-      list_remove_all(csp->headers);
-      freez(csp->iob->buf);
-      memset(csp->iob, 0, sizeof(csp->iob));
-      freez(csp->error_message);
-      free_http_request(csp->http);
-      destroy_list(csp->headers);
-      destroy_list(csp->tags);
-      free_current_action(csp->action);
-      if (NULL != csp->fwd)
-      {
-         unload_forward_spec(csp->fwd);
-         csp->fwd = NULL;
-      }
-
-      /* XXX: Store per-connection flags someplace else. */
-      csp->flags = CSP_FLAG_ACTIVE | (csp->flags & CSP_FLAG_TOGGLED_ON);
-
       if (continue_chatting)
       {
          log_error(LOG_LEVEL_CONNECT,
@@ -3556,13 +3537,52 @@ static void serve(struct client_state *csp)
          {
             log_error(LOG_LEVEL_CONNECT, "Client request arrived in "
                "time or the client closed the connection.");
+            /*
+             * Get the csp in a mostly vergin state again.
+             * XXX: Should be done elsewhere.
+             */
+            csp->content_type = 0;
+            csp->content_length = 0;
+            csp->expected_content_length = 0;
+            list_remove_all(csp->headers);
+            freez(csp->iob->buf);
+            memset(csp->iob, 0, sizeof(csp->iob));
+            freez(csp->error_message);
+            free_http_request(csp->http);
+            destroy_list(csp->headers);
+            destroy_list(csp->tags);
+            free_current_action(csp->action);
+            if (NULL != csp->fwd)
+            {
+               unload_forward_spec(csp->fwd);
+               csp->fwd = NULL;
+            }
+
+            /* XXX: Store per-connection flags someplace else. */
+            csp->flags = CSP_FLAG_ACTIVE | (csp->flags & CSP_FLAG_TOGGLED_ON);
          }
          else
          {
             log_error(LOG_LEVEL_CONNECT,
-               "No additional client request received in time. "
-               "Closing server socket %d, initially opened for %s.",
-               csp->sfd, csp->server_connection.host);
+               "No additional client request received in time.");
+            if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING))
+            {
+               remember_connection(csp->sfd, csp->http,
+                  forward_url(csp, csp->http));
+               csp->sfd = JB_INVALID_SOCKET;
+               close_socket(csp->cfd);
+               csp->cfd = JB_INVALID_SOCKET;
+               privoxy_mutex_lock(&connection_reuse_mutex);
+               if (!monitor_thread_running)
+               {
+                  monitor_thread_running = 1;
+                  privoxy_mutex_unlock(&connection_reuse_mutex);
+                  wait_for_alive_connections();
+                  privoxy_mutex_lock(&connection_reuse_mutex);
+                  monitor_thread_running = 0;
+               }
+               privoxy_mutex_unlock(&connection_reuse_mutex);
+            }
             break;
          }
       }
@@ -3573,12 +3593,17 @@ static void serve(struct client_state *csp)
             "Closing.", csp->sfd, csp->server_connection.host);
       }
    } while (continue_chatting);
+
+   mark_connection_closed(&csp->server_connection);
 #else
    chat(csp);
 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 
    if (csp->sfd != JB_INVALID_SOCKET)
    {
+#ifdef FEATURE_CONNECTION_KEEP_ALIVE
+      forget_connection(csp->sfd);
+#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
       close_socket(csp->sfd);
    }
 
index 4942ca4..0d026e4 100644 (file)
--- a/loadcfg.c
+++ b/loadcfg.c
@@ -1,4 +1,4 @@
-const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.98 2009/04/24 15:29:43 fabiankeil Exp $";
+const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.99 2009/05/10 10:12:30 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/loadcfg.c,v $
@@ -35,6 +35,10 @@ const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.98 2009/04/24 15:29:43 fabiankeil
  *
  * Revisions   :
  *    $Log: loadcfg.c,v $
+ *    Revision 1.99  2009/05/10 10:12:30  fabiankeil
+ *    Initial keep-alive support for the client socket.
+ *    Temporarily disable the server-side-only keep-alive code.
+ *
  *    Revision 1.98  2009/04/24 15:29:43  fabiankeil
  *    Allow to limit the number of of client connections.
  *
@@ -633,6 +637,7 @@ static struct file_list *current_configfile = NULL;
 #define hash_allow_cgi_request_crunching  258915987ul /* "allow-cgi-request-crunching" */
 #define hash_buffer_limit                1881726070ul /* "buffer-limit */
 #define hash_confdir                        1978389ul /* "confdir" */
+#define hash_connection_sharing          1348841265ul /* "connection-sharing" */
 #define hash_debug                            78263ul /* "debug" */
 #define hash_deny_access                 1227333715ul /* "deny-access" */
 #define hash_enable_edit_actions         2517097536ul /* "enable-edit-actions" */
@@ -858,6 +863,7 @@ struct configuration_spec * load_config(void)
 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    config->keep_alive_timeout        = DEFAULT_KEEP_ALIVE_TIMEOUT;
    config->feature_flags            &= ~RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE;
+   config->feature_flags            &= ~RUNTIME_FEATURE_CONNECTION_SHARING;
 #endif
    config->feature_flags            &= ~RUNTIME_FEATURE_CGI_TOGGLE;
    config->feature_flags            &= ~RUNTIME_FEATURE_SPLIT_LARGE_FORMS;
@@ -994,6 +1000,22 @@ struct configuration_spec * load_config(void)
             config->confdir = make_path( NULL, arg);
             break;
 
+/* *************************************************************************
+ * connection-sharing (0|1)
+ * *************************************************************************/
+#ifdef FEATURE_CONNECTION_KEEP_ALIVE
+         case hash_connection_sharing :
+            if ((*arg != '\0') && (0 != atoi(arg)))
+            {
+               config->feature_flags |= RUNTIME_FEATURE_CONNECTION_SHARING;
+            }
+            else
+            {
+               config->feature_flags &= ~RUNTIME_FEATURE_CONNECTION_SHARING;
+            }
+            break;
+#endif
+
 /* *************************************************************************
  * debug n
  * Specifies debug level, multiple values are ORed together.
index 0fab7ff..8b83f65 100644 (file)
--- a/project.h
+++ b/project.h
@@ -1,7 +1,7 @@
 #ifndef PROJECT_H_INCLUDED
 #define PROJECT_H_INCLUDED
 /** Version string. */
-#define PROJECT_H_VERSION "$Id: project.h,v 1.133 2009/04/24 15:29:43 fabiankeil Exp $"
+#define PROJECT_H_VERSION "$Id: project.h,v 1.134 2009/05/10 10:12:30 fabiankeil Exp $"
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/project.h,v $
  *
  * Revisions   :
  *    $Log: project.h,v $
+ *    Revision 1.134  2009/05/10 10:12:30  fabiankeil
+ *    Initial keep-alive support for the client socket.
+ *    Temporarily disable the server-side-only keep-alive code.
+ *
  *    Revision 1.133  2009/04/24 15:29:43  fabiankeil
  *    Allow to limit the number of of client connections.
  *
@@ -1766,6 +1770,9 @@ struct access_control_list
 /** configuration_spec::feature_flags: Try to keep the connection to the server alive. */
 #define RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE      128U
 
+/** configuration_spec::feature_flags: Share outgoing connections between different client connections. */
+#define RUNTIME_FEATURE_CONNECTION_SHARING         256U
+
 /**
  * Data loaded from the configuration file.
  *