mod_choke.c
Nathan Shafer <nate-mod_choke@seekio.com>

Limit resource usage by greedy clients.

Requirements:
  Apache 1.3.x
  Concurrent connection limiting requires that Apache is compiled with shared
  memory support (SHMGET).

--------------------------------------------------------------------------
Synopsis
--------------------------------------------------------------------------
<IfModule mod_choke.c>
  Choke         On
  ChokeRate     10k
  ChokeRateEnv  CHOKE_RATE
  ChokeBurst    50k
  ChokeBurstEnv CHOKE_BURST
  ChokeSummary  On

  <Directory /usr/local/apache/htdocs/big_files>
    ChokeRate  50k
    ChokeBurst 500k
  </Directory>

  <Location /images>
    Choke Off
  </Location>

  <Files *.mp3>
    ChokeRate  20k
    ChokeBurst 30k
  </Files>

  GlobalMaxConnectionsPerIP   20
  GlobalMaxConnectionsPerUser 10

  <Location /choke-status>
    SetHandler choke-status
  </Location>
</IfModule>

NameVirtualHost *

<VirtualHost *>
  ServerName www.example.com

  <IfModule mod_choke.c>
    MaxConnectionsPerIP   10
    MaxConnectionsPerUser 3
  </IfModule>
</VirtualHost>

 <VirtualHost *>
   ServerName www.someothersite.com

  <IfModule mod_choke.c>
    MaxConnectionsPerIP   10
    MaxConnectionsPerUser 3
  </IfModule>
</VirtualHost>

--------------------------------------------------------------------------
Directives
--------------------------------------------------------------------------
Choke
    Syntax:   Choke On|Off
    Default:  Off
    Context:  server config, virtual host, directory, .htaccess
    Override: Options
    Module:   mod_choke

    Set this to On to limit the outbound rate for each apache child.  This only
    affects the rate, burst and summary settings.  This does not affect the max
    concurrent directives.

ChokeRate
    Syntax:   ChokeRate BYTES
    Default:  
    Context:  server config, virtual host, directory, .htaccess
    Override: Options
    Module:   mod_choke

    Number of BYTES per second to limit the connection to.  You may use the
    suffixes 'K' and 'M' to specify Kilobytes and Megabytes.  Set to 0 to
    disable rate limiting.

ChokeRateEnv
    Syntax:   ChokeRateEnv VARIABLE
    Default:  
    Context:  server config, virtual host, directory, .htaccess
    Override: Options
    Module:   mod_choke

    Name of environment variable to get the ChokeRate setting from.  See the
    ChokeRate directive for format options.

ChokeBurst
    Syntax:   ChokeBurst BYTES
    Default:  
    Context:  server config, virtual host, directory, .htaccess
    Override: Options
    Module:   mod_choke

    Send the first BYTES of the file to the client at full speed. This is
    useful for streaming type protocols, such as video and audio, because
    faster clients will start playing the media sooner.  You may use the
    suffixes 'K' and 'M' to specify Kilobytes and Megabytes.

ChokeBurstEnv
    Syntax:   ChokeBurstEnv BYTES
    Default:  
    Context:  server config, virtual host, directory, .htaccess
    Override: Options
    Module:   mod_choke

    Name of environment variable to get the ChokeBusrt setting from.  See the
    ChokeBurst directive for format options.

ChokeSummary
    Syntax:   ChokeSummary On|Off
    Default:  Off
    Context:  server config, virtual host, directory, .htaccess
    Override: Options
    Module:   mod_choke

    Turns on a summary that is printed to the error log after every send with
    information on the file it sent, who it sent it to and the rate that it
    sent it at.  Useful for debugging complicated configs with multiple levels
    of directives.

MaxConnectionsPerIP
    Syntax:   MaxConnectionsPerIP number
    Default:  
    Context:  server config, virtual host
    Override: 
    Module:   mod_choke

    Maximum umber of concurrent connections that this IP is allowed to make to
    each VirtualHost.  If you have two virtual hosts with this set to 5 for
    both, then a single IP can have 5 connections open to each virtual host for
    a total of 10.
    
MaxConnectionsPerUser
    Syntax:   MaxConnectionsPerUser number
    Default:  
    Context:  server config, virtual host
    Override: 
    Module:   mod_choke

    Maximum number of concurrent connections that the authenticated user is
    able to make to each VirtualHost. If you have two virtual hosts with this
    set to 5 for both, then a single username can have 5 connections open to
    each virtual host for a total of 10.

GlobalMaxConnectionsPerIP
    Syntax:   GlobalMaxConnectionsPerIP number
    Default:  
    Context:  server config
    Override: 
    Module:   mod_choke

    The maximum number of concurrent connections that a single IP is allowed to
    make to the entire apache server.
    
GlobalMaxConnectionsPerUser
    Syntax:   GlobalMaxConnectionsPerUser number
    Default:  
    Context:  server config
    Override: 
    Module:   mod_choke

    The maximum number of concurrent connections that a single user is allowed
    to make to the entire apache server.

--------------------------------------------------------------------------
Notes
--------------------------------------------------------------------------
    
This module only limits the rate that a single child sends at.  So if a person
from a single IP opens up 10 connections to the server, each of those 10
connections will be limited to ChokeRate bytes/second.  Thus, the total rate
that someone can fetch at is ChokeRate * MaxConnectionsPerIP or ChokeRate *
MaxConnectionsPerUser.  Example, if ChokeRate is set to 10k and
MaxConnectionsPerIP is set to 5, then a person from one IP can open 5
connections and fetch data at 10k * 5 or 50k/sec.

This module can be split into two major modes.  Limiting the number of
concurrent connections per user or IP, and limiting the rate for sending files.
The connection limiting code works in the Fixup stage of the apache cycle.
This means that it checks concurrency after URI translation, authorization,
authentication and just before the main response phase.  It will limit
connections no matter what the content handler is, whether it be a plain file,
PHP, perl, CGI, or whatever.  The rate limiting code, however, replaces the
default response handler when no other response handlers are defined.
Therefore, it will limit the rate of regular file sends, but will not limit the
rate of output from PHP scripts, CGI scripts, etc.  A future version written
for Apache2 should support rate limiting for all content types because Apache2
adds the ability to have modules act as filters.

The module will count the following child states when it does concurrency checks:
  For IP concurrency:   WKDLG
  For User concurrency: WKLG

Apache chilren in the R (Reading Request) phase will not be counted because apache
doesn't allow modules to hook in until after the read request phase is done.

Due to the low resolution of time from gettimeofday(), the accuracy of this
module degrades when dealing with rates > ~5 MB/sec.  We try to account for
this by increasing the send size, but that can only do so much.


