Allow to limit the number of of client connections.
authorFabian Keil <fk@fabiankeil.de>
Fri, 24 Apr 2009 15:29:43 +0000 (15:29 +0000)
committerFabian Keil <fk@fabiankeil.de>
Fri, 24 Apr 2009 15:29:43 +0000 (15:29 +0000)
doc/source/p-config.sgml
jcc.c
loadcfg.c
loaders.c
loaders.h
project.h

index 2457d39..fff23cd 100644 (file)
@@ -3,7 +3,7 @@
 
  Purpose     :  Used with other docs and files only.
 
 
  Purpose     :  Used with other docs and files only.
 
- $Id: p-config.sgml,v 2.48 2009/04/17 11:42:07 fabiankeil Exp $
+ $Id: p-config.sgml,v 2.49 2009/04/19 17:39:55 fabiankeil Exp $
 
  Copyright (C) 2001-2009 Privoxy Developers http://www.privoxy.org/
  See LICENSE.
 
  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>
  Sample Configuration File for Privoxy v&p-version;
 </title>
 <para>
- $Id: p-config.sgml,v 2.48 2009/04/17 11:42:07 fabiankeil Exp $
+ $Id: p-config.sgml,v 2.49 2009/04/19 17:39:55 fabiankeil Exp $
 </para>
 <para>
 Copyright (C) 2001-2009 Privoxy Developers http://www.privoxy.org/
 </para>
 <para>
 Copyright (C) 2001-2009 Privoxy Developers http://www.privoxy.org/
@@ -2612,6 +2612,87 @@ forward-socks4, forward-socks4a and forward-socks5</title>
 </sect3>
 
 
 </sect3>
 
 
+<sect3 renderas="sect4" id="max-client-connections"><title>max-client-connections</title>
+<variablelist>
+ <varlistentry>
+  <term>Specifies:</term>
+  <listitem>
+   <para>
+    Maximum number of client connections that will be served.
+   </para>
+  </listitem>
+ </varlistentry>
+ <varlistentry>
+  <term>Type of value:</term>
+  <listitem>
+   <para>
+    <replaceable>Positive number.</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 served until a resource limit is reached.
+   </para>
+  </listitem>
+ </varlistentry>
+ <varlistentry>
+  <term>Notes:</term>
+  <listitem>
+   <para>
+    &my-app; creates one thread (or process) for every incoming client
+    connection that isn't rejected based on the access control settings.
+   </para>
+   <para>
+    If the system is powerful enough, &my-app; can theoretically deal with
+    several hundred (or thousand) connections at the same time, but some
+    operating systems enforce resource limits by shutting down offending
+    processes and their default limits may be below the ones &my-app; would
+    require under heavy load.
+   </para>
+   <para>
+    Configuring &my-app; to enforce a connection limit below the thread
+    or process limit used by the operating system makes sure this doesn't
+    happen. Simply increasing the operating system's limit would work too,
+    but if &my-app; isn't the only application running on the system,
+    you may actually want to limit the resources used by &my-app;.
+   </para>
+   <para>
+    If &my-app; is only used by a single trusted user, limiting the
+    number of client connections is probably unnecessary. If there
+    are multiple possibly untrusted users you probably still want to
+    additionally use a packet filter to limit the maximal number of
+    incoming connections per client. Otherwise a malicious user could
+    intentionally create a high number of connections to prevent other
+    users from using &my-app;.
+   </para>
+   <para>
+    Obviously using this option only makes sense if you choose a limit
+    below the one enforced by the operating system.
+   </para>
+  </listitem>
+ </varlistentry>
+ <varlistentry>
+  <term>Examples:</term>
+  <listitem>
+   <para>
+    max-client-connections 256
+   </para>
+  </listitem>
+ </varlistentry>
+</variablelist>
+<![%config-file;[<literallayout>@@max-client-connections 256</literallayout>]]>
+</sect3>
+
+
 </sect2>
 
 <!--  ~  End section  ~  -->
 </sect2>
 
 <!--  ~  End section  ~  -->
diff --git a/jcc.c b/jcc.c
index 83e3b3a..7ca0f46 100644 (file)
--- a/jcc.c
+++ b/jcc.c
@@ -1,4 +1,4 @@
-const char jcc_rcs[] = "$Id: jcc.c,v 1.243 2009/04/17 11:27:49 fabiankeil Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.244 2009/04/17 11:34:34 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/jcc.c,v $
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/jcc.c,v $
@@ -33,6 +33,9 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.243 2009/04/17 11:27:49 fabiankeil Exp $"
  *
  * Revisions   :
  *    $Log: jcc.c,v $
  *
  * Revisions   :
  *    $Log: jcc.c,v $
+ *    Revision 1.244  2009/04/17 11:34:34  fabiankeil
+ *    Style cosmetics for the IPv6 code.
+ *
  *    Revision 1.243  2009/04/17 11:27:49  fabiankeil
  *    Petr Pisar's privoxy-3.0.12-ipv6-3.diff.
  *
  *    Revision 1.243  2009/04/17 11:27:49  fabiankeil
  *    Petr Pisar's privoxy-3.0.12-ipv6-3.diff.
  *
@@ -4180,7 +4183,8 @@ static void listen_loop(void)
 {
    struct client_state *csp = NULL;
    jb_socket bfd;
 {
    struct client_state *csp = NULL;
    jb_socket bfd;
-   struct configuration_spec * config;
+   struct configuration_spec *config;
+   unsigned int active_threads = 0;
 
    config = load_config();
 
 
    config = load_config();
 
@@ -4210,7 +4214,7 @@ static void listen_loop(void)
       /*
        * Free data that was used by died threads
        */
       /*
        * Free data that was used by died threads
        */
-      sweep();
+      active_threads = sweep();
 
 #if defined(unix)
       /*
 
 #if defined(unix)
       /*
@@ -4301,6 +4305,20 @@ static void listen_loop(void)
       }
 #endif /* def FEATURE_ACL */
 
       }
 #endif /* def FEATURE_ACL */
 
+      if ((0 != config->max_client_connections)
+         && (active_threads >= config->max_client_connections))
+      {
+         log_error(LOG_LEVEL_CONNECT,
+            "Rejecting connection from %s. Maximum number of connections reached.",
+            csp->ip_addr_str);
+         write_socket(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
+            strlen(TOO_MANY_CONNECTIONS_RESPONSE));
+         close_socket(csp->cfd);
+         freez(csp->ip_addr_str);
+         freez(csp);
+         continue;
+      }
+
       /* add it to the list of clients */
       csp->next = clients->next;
       clients->next = csp;
       /* add it to the list of clients */
       csp->next = clients->next;
       clients->next = csp;
index d1fb7c1..fb804f8 100644 (file)
--- a/loadcfg.c
+++ b/loadcfg.c
@@ -1,4 +1,4 @@
-const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.96 2009/04/17 11:38:28 fabiankeil Exp $";
+const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.97 2009/04/17 11:45:19 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/loadcfg.c,v $
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/loadcfg.c,v $
@@ -35,6 +35,10 @@ const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.96 2009/04/17 11:38:28 fabiankeil
  *
  * Revisions   :
  *    $Log: loadcfg.c,v $
  *
  * Revisions   :
  *    $Log: loadcfg.c,v $
+ *    Revision 1.97  2009/04/17 11:45:19  fabiankeil
+ *    Replace HAVE_GETADDRINFO and HAVE_GETNAMEINFO macros
+ *    with HAVE_RFC2553 macro. Original patch by Petr Pisar.
+ *
  *    Revision 1.96  2009/04/17 11:38:28  fabiankeil
  *    Add and use parse_forwarder_address() to reduce code duplication.
  *
  *    Revision 1.96  2009/04/17 11:38:28  fabiankeil
  *    Add and use parse_forwarder_address() to reduce code duplication.
  *
@@ -643,6 +647,7 @@ static struct file_list *current_configfile = NULL;
 #define hash_listen_address              1255650842ul /* "listen-address" */
 #define hash_logdir                          422889ul /* "logdir" */
 #define hash_logfile                        2114766ul /* "logfile" */
 #define hash_listen_address              1255650842ul /* "listen-address" */
 #define hash_logdir                          422889ul /* "logdir" */
 #define hash_logfile                        2114766ul /* "logfile" */
+#define hash_max_client_connections      3595884446ul /* "max-client-connections" */
 #define hash_permit_access               3587953268ul /* "permit-access" */
 #define hash_proxy_info_url              3903079059ul /* "proxy-info-url" */
 #define hash_single_threaded             4250084780ul /* "single-threaded" */
 #define hash_permit_access               3587953268ul /* "permit-access" */
 #define hash_proxy_info_url              3903079059ul /* "proxy-info-url" */
 #define hash_single_threaded             4250084780ul /* "single-threaded" */
@@ -848,6 +853,7 @@ struct configuration_spec * load_config(void)
    config->usermanual                = strdup(USER_MANUAL_URL);
    config->proxy_args                = strdup("");
    config->forwarded_connect_retries = 0;
    config->usermanual                = strdup(USER_MANUAL_URL);
    config->proxy_args                = strdup("");
    config->forwarded_connect_retries = 0;
+   config->max_client_connections    = 0;
    config->socket_timeout            = 300; /* XXX: Should be a macro. */
    config->feature_flags            &= ~RUNTIME_FEATURE_CGI_TOGGLE;
    config->feature_flags            &= ~RUNTIME_FEATURE_SPLIT_LARGE_FORMS;
    config->socket_timeout            = 300; /* XXX: Should be a macro. */
    config->feature_flags            &= ~RUNTIME_FEATURE_CGI_TOGGLE;
    config->feature_flags            &= ~RUNTIME_FEATURE_SPLIT_LARGE_FORMS;
@@ -1423,6 +1429,20 @@ struct configuration_spec * load_config(void)
             }
             break;
 
             }
             break;
 
+/* *************************************************************************
+ * max-client-connections number
+ * *************************************************************************/
+         case hash_max_client_connections :
+            if (*arg != '\0')
+            {
+               int max_client_connections = atoi(arg);
+               if (0 <= max_client_connections)
+               {
+                  config->max_client_connections = max_client_connections;
+               }
+            }
+            break;
+
 /* *************************************************************************
  * permit-access source-ip[/significant-bits] [dest-ip[/significant-bits]]
  * *************************************************************************/
 /* *************************************************************************
  * permit-access source-ip[/significant-bits] [dest-ip[/significant-bits]]
  * *************************************************************************/
index f33e2c2..e7dbbe4 100644 (file)
--- a/loaders.c
+++ b/loaders.c
@@ -1,4 +1,4 @@
-const char loaders_rcs[] = "$Id: loaders.c,v 1.70 2009/03/01 18:34:24 fabiankeil Exp $";
+const char loaders_rcs[] = "$Id: loaders.c,v 1.71 2009/03/04 18:24:47 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/loaders.c,v $
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/loaders.c,v $
@@ -35,6 +35,9 @@ const char loaders_rcs[] = "$Id: loaders.c,v 1.70 2009/03/01 18:34:24 fabiankeil
  *
  * Revisions   :
  *    $Log: loaders.c,v $
  *
  * Revisions   :
  *    $Log: loaders.c,v $
+ *    Revision 1.71  2009/03/04 18:24:47  fabiankeil
+ *    No need to create empty strings manually, strdup("") FTW.
+ *
  *    Revision 1.70  2009/03/01 18:34:24  fabiankeil
  *    Help clang understand that we aren't dereferencing
  *    NULL pointers here.
  *    Revision 1.70  2009/03/01 18:34:24  fabiankeil
  *    Help clang understand that we aren't dereferencing
  *    NULL pointers here.
@@ -450,14 +453,15 @@ static struct file_list *current_re_filterfile[MAX_AF_FILES]  = {
  *
  * Parameters  :  None
  *
  *
  * Parameters  :  None
  *
- * Returns     :  N/A
+ * Returns     :  The number of threads that are still active.
  *
  *********************************************************************/
  *
  *********************************************************************/
-void sweep(void)
+unsigned int sweep(void)
 {
    struct file_list *fl, *nfl;
    struct client_state *csp, *last_active;
    int i;
 {
    struct file_list *fl, *nfl;
    struct client_state *csp, *last_active;
    int i;
+   unsigned int active_threads = 0;
 
    /* clear all of the file's active flags */
    for ( fl = files->next; NULL != fl; fl = fl->next )
 
    /* clear all of the file's active flags */
    for ( fl = files->next; NULL != fl; fl = fl->next )
@@ -512,10 +516,11 @@ void sweep(void)
             csp->tlist->active = 1;
          }
 #endif /* def FEATURE_TRUST */
             csp->tlist->active = 1;
          }
 #endif /* def FEATURE_TRUST */
-         
+
+         active_threads++;
+
          last_active = csp;
          csp = csp->next;
          last_active = csp;
          csp = csp->next;
-
       }
       else 
       /*
       }
       else 
       /*
@@ -577,6 +582,8 @@ void sweep(void)
       }
    }
 
       }
    }
 
+   return active_threads;
+
 }
 
 
 }
 
 
index 30be639..9d544c4 100644 (file)
--- a/loaders.h
+++ b/loaders.h
@@ -1,6 +1,6 @@
 #ifndef LOADERS_H_INCLUDED
 #define LOADERS_H_INCLUDED
 #ifndef LOADERS_H_INCLUDED
 #define LOADERS_H_INCLUDED
-#define LOADERS_H_VERSION "$Id: loaders.h,v 1.22 2007/06/01 14:12:38 fabiankeil Exp $"
+#define LOADERS_H_VERSION "$Id: loaders.h,v 1.23 2008/03/30 14:52:10 fabiankeil Exp $"
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/loaders.h,v $
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/loaders.h,v $
@@ -10,7 +10,7 @@
  *                the list of active loaders, and to automatically 
  *                unload files that are no longer in use.
  *
  *                the list of active loaders, and to automatically 
  *                unload files that are no longer in use.
  *
- * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
+ * Copyright   :  Written by and Copyright (C) 2001-2009 the
  *                Privoxy team. http://www.privoxy.org/
  *
  *                Based on the Internet Junkbuster originally written
  *                Privoxy team. http://www.privoxy.org/
  *
  *                Based on the Internet Junkbuster originally written
  *
  * Revisions   :
  *    $Log: loaders.h,v $
  *
  * Revisions   :
  *    $Log: loaders.h,v $
+ *    Revision 1.23  2008/03/30 14:52:10  fabiankeil
+ *    Rename load_actions_file() and load_re_filterfile()
+ *    as they load multiple files "now".
+ *
  *    Revision 1.22  2007/06/01 14:12:38  fabiankeil
  *    Add unload_forward_spec() in preparation for forward-override{}.
  *
  *    Revision 1.22  2007/06/01 14:12:38  fabiankeil
  *    Add unload_forward_spec() in preparation for forward-override{}.
  *
@@ -175,7 +179,7 @@ struct file_list;
 struct configuration_spec;
 struct url_spec;
 
 struct configuration_spec;
 struct url_spec;
 
-extern void sweep(void);
+extern unsigned int sweep(void);
 extern char *read_config_line(char *buf, size_t buflen, FILE *fp, unsigned long *linenum);
 extern int check_file_changed(const struct file_list * current,
                               const char * filename,
 extern char *read_config_line(char *buf, size_t buflen, FILE *fp, unsigned long *linenum);
 extern int check_file_changed(const struct file_list * current,
                               const char * filename,
index d242266..ccd29f3 100644 (file)
--- a/project.h
+++ b/project.h
@@ -1,7 +1,7 @@
 #ifndef PROJECT_H_INCLUDED
 #define PROJECT_H_INCLUDED
 /** Version string. */
 #ifndef PROJECT_H_INCLUDED
 #define PROJECT_H_INCLUDED
 /** Version string. */
-#define PROJECT_H_VERSION "$Id: project.h,v 1.131 2009/04/17 11:34:35 fabiankeil Exp $"
+#define PROJECT_H_VERSION "$Id: project.h,v 1.132 2009/04/17 11:45:19 fabiankeil Exp $"
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/project.h,v $
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/project.h,v $
  *
  * Revisions   :
  *    $Log: project.h,v $
  *
  * Revisions   :
  *    $Log: project.h,v $
+ *    Revision 1.132  2009/04/17 11:45:19  fabiankeil
+ *    Replace HAVE_GETADDRINFO and HAVE_GETNAMEINFO macros
+ *    with HAVE_RFC2553 macro. Original patch by Petr Pisar.
+ *
  *    Revision 1.131  2009/04/17 11:34:35  fabiankeil
  *    Style cosmetics for the IPv6 code.
  *
  *    Revision 1.131  2009/04/17 11:34:35  fabiankeil
  *    Style cosmetics for the IPv6 code.
  *
@@ -1823,7 +1827,10 @@ struct configuration_spec
    struct forward_spec *forward;
 
    /** Number of retries in case a forwarded connection attempt fails */
    struct forward_spec *forward;
 
    /** Number of retries in case a forwarded connection attempt fails */
-   int         forwarded_connect_retries;
+   int forwarded_connect_retries;
+
+   /** Maximum number of client connections. */
+   int max_client_connections;
 
    /* Timeout when waiting on sockets for data to become available. */
    int socket_timeout;
 
    /* Timeout when waiting on sockets for data to become available. */
    int socket_timeout;