12 May 2000. The Sre2000 manual: an Internet Server for OS/2

Sre2000: An Internet Server for OS/2


Abstract     Sre2000 is an Internet server for OS/2. More precisely, Sre2000 provides a set of functions and capabilties that allow you to implement a web server through a "filter" program that is written in REXX. Several filter programs are publically available, such as SREhttp/2 - or you can write your own.

Table of Contents

  1. Introduction
  2. Installation
  3. Starting Sre2000
  4. Configuring Sre2000
       Description of Sre2000 configuation parameters.
       Detailed description of Sre2000 parameters
  5. Using Sre2000
       Arguments sent to the filter
       The Sre2000 functions
       The Sre2000 functions: full descriptions

1) Introduction

Sre2000 is an Internet server for OS/2. More precisely, Sre2000 provides a set of functions and capabilties that allow you to implement a web server through a filter program that is written in REXX. Several filter programs are publically available, such as SREhttp/2 -- or you can write your own.

Sre2000 is designed for small to intermediate sized sites. It's primary strengths are flexibiity and ease of customization. Speed, resource use, security, and scalability are not the primary goals. That said, these are operational concerns; and quite a bit can be done to enhance performance along any of these dimensions.

In many ways, Sre2000 is an outgrowth of GoServe, which was designed and created by Mike Cowlishaw In fact, it is the end of support for GoServe that motivated the creation of Sre2000.

In comparison with GoServe, the primary immediate advantage of Sre2000 is increased support for http/1.1 functions, including a greatly improved cache. Just as important, Sre2000 can be readily modified (it's written in REXX) -- we are always interested in suggestions and ideas!

Are you are upgrading from GoServe/SRE-http? Then you'll find a number of hints and suggestions in UPGRADER.TXT!

Sre2000 comes with a very simple filter program, whose primary purpose is to illustrate basic functions. For a serious web site we recommend the SREhttp/2 filter, which you can find (along with a myriad of tools, scripts, and addons) at http://www.srehttp.org. Of course, there is a disclaimer .. Before choosing & using Sre2000, you must read the disclaimer (in appendix 2). Basically, Sre2000 is "gnu" style freeware; and is to be used at your own risk. We do try to create a fairly secure product, and we try to quickly fix any problems (or potential problems). However, we can NOT guarantee that Sre2000 has no security holes or is free from other potentials for failure.

2) Installation

The easiest way to install Sre2000 is to use the installation program.
  1. UnZIP SRE2000.zip to an empty temporary directory
  2. open up an OS/2 prompt, and CD to this directory
  3. run INSTALL.CMD
    For example, assuming you unzipped SRE2000.zip to E:\TEMP:
        E:\TEMP>install
  4. select a working directory, etc.

Notes


3) Starting Sre2000

To start Sre2000,
  1. open an OS/2 box
  2. CD to the working directory (selected in step d above)
  3. run Sre2000
    For example, assuming the working directory is D:\SERVER:
       D:\SERVER>Sre2000
  4. Sre2000 will start, and after some initializations a text-based status screen will be displayed.

Notes


4) Configuring Sre2000

Sre2000 uses a single configuration file: SRE2000.CFG.

SRE2000.CFG is a text file that you can modify using any text editor (such as EPM). You can also modify Sre2000 by entering, from an OS/2 prompt:
   Sre2000 -m
You will be presented, in a sequential fashion, with a list of the most important Sre2000 parameters, and their current values. You can change, or retain these values; you can also dislay some rudimentary on-line help.

Alternatively, if you enter
   Sre2000 -mall
you will be presented with a list of all the parameters contained in SRE2000.CFG, many of which you'll never need to change.


4a) Description of Sre2000 configuation parameters.

The variables set in SRE2000.CFG are:
AUDITFILE File containing audit and status information
AUDIT_ITEMS Specifies what is written to the AUDITFILE
DAEMON_MANAGER Name of a "daemon manager" program
DATADIR The default "data" directory (your site's root directory)
DEFAULT_SOCKET_TIMEOUT Time to wait on a socket, in seconds
FILTER Name of the filter program
FAST_FILTER Name of "fast-filter" program
INIT_PROC File containing an initialization procedure
LIMITHEADER Maximum size of request headers (in Kbytes)
LIMITBODY Maximum size of request body (in Kbytes)
LIMITCLIENTS Maximum simultaneous connections (on-the-fly changeable)
LIMITTIMETOTAL Maximum time allowed per request (in seconds)
LIMITTIMEWAIT Maximum time to wait on a maintained connection
LIMITTIMEINACTIVE Maximum intra-request idle time (in seconds)
MAXTHREADS Upper limit of LIMITCLIENTS
MAXHOSTS Maximum number of hosts allowed
MAXLOCALS Maximum number of "local" variables
MAXSYSVARS Maximum number of "system" variables
MAXCOUNTERS Maximum number of "counter" variables
MAXCLIENTNAMES Size (number of entries) in "client name" cache
MAXSTATVALS Size (number of entries) to use to compute statistics
MAXMD5S Size (number of entries) in MD5 cache
NO_MODIFY_ONTHEFLY Suppress on-the-fly modification of parameters
PORT Port the server is running on
REQ_CACHE_ENABLE Enable the request cache
REQ_CACHE_CALL_ANYWAYS Call the filter even if request cache is used
REQ_CACHE_HITFILE File containing record of cache hits
REQ_CACHE_RECORD Record cache hits to the cache_hitfile
REQ_CACHE_SIZE Size of "request cache"
REQ_CACHE_VERIFY Enable http/1.1 style verification prior to use of cache
SERVER_SOFTWARE Reported name of this server software
SERVER_SOFTWARE_SHORT Short reported name of this server software
STATUS_ITEMS Specify what to display on status screen
TRACKING_ON Enable Sre2000's "client tracking" facility
UNALLOWED_FILE File containing a list of "UnAllowed" IP addresses.
USER_STATS List of variables to set up as "statistics" variables

The most important of these variables are:
  AUDIT_ITEMS DAEMON_MANAGER DATADIR FILTER
  LIMITCLIENTS PORT REQ_CACHE_ENABLE
  REQ_CACHE_RECORD STATUS_ITEMS.
(these "most important" variables can be modified using by running "Sre2000 -m").

Notes


4b) Detailed description of Sre2000 parameters

The following provides a more detailed description of the SRE2000.CFG parameters.
AUDITFILE
Where to write audit items (as specified by AUDIT_ITEMS) to. Should be a relative filename; relative to the Sre2000 working directory.

AUDIT_ITEMS
Specifiy what additional events to write to audit file. Should contain a space delimited list of options, the options being: CLIENT, REQUEST, SENT, RESET, DIAG, and DIAG2.
Example: audit_items=CLIENT SENT
  These options yields the following information.

   CLIENT: 
      Client and server info. 
      For example:
          C : 1A 00:25:07: 131.10.51.21 80 1 15.12.112.3 1104
      where:
              C :    -- this is the "client audit item"
               1A    -- transaction and request number
         00:25:07    -- time of connection
      31.10.51.21    -- ip address of server
               80    -- port of server
      15.12.112.3    -- ip address of client
             1104    -- port of the client
   
   REQUEST: 
       The request string. For example:
            R : 1A 00:25:06: GET /samples/daemons.doc HTTP/1.1

   SENT:  
       Summary of bytes sent & recieved. For example:
              S : 1A 00:25:07: 158, 200 8992
        Where
            158 : Bytes recieved
            200 : response code
           8992 : Bytes sent

   DIAG: 
       Diagnostic messages. A variety of diagnostic messages. 
       For example:                
         D : 3A 00:33:50: REQFIELD = If-match If-Unmodified-Since If-None-Match 
         D : 3A 00:33:50: FILE = CHUNK NOWAIT ERASE type text/plain NOCACHE Name G:\SRENEW\TEMP\_17111__.TGZ

   DIAG2: 
       A superset of DIAG -- you should not use both DIAG and DIAG2.
       The following are examples of information produced by DIAG2, but not DIAG.
         D : 3A 00:33:50: Header = HEADER NOAUTO
         D : 3A 00:33:50: Header = Header Add Date: Sat, 25 Mar 2000 05:33:49 GMT
         D : 1A 00:25:06: ReqHdr = Referer:do_get@localhost
         D : 1A 00:25:06: ReqHdr = If-none-match: "dir.d","dir.doc"
DAEMON_MANAGER
Name of a "daemon manager" program. This should be a relative filename (relative to the Sre2000 working directory); it will be launched as a permanent thread under the Sre2000 process. Often, this "daemon manager" thread will launch several "daemons" that your filter can use to provide status and configuation information.

For example, the SREhttp/2 filter uses daemons to provide user authorization information, selector specific attributes, auditing, and several other functions. These daemons are launched by the DMN2000 "daemon manager" program.

Examples:
   DAEMON_MANAGER="DMN2000.RXX"
   DAEMON_MANAGER=0    (no daemon manager)

Notes:

  • Sre2000 provides the following arguments to the daemon manager program, which can be read using parse arg.
                 pid  -- process id (of the Sre2000 process)
                asem  -- a semaphore to use to signal "ready to continue"
             maindir  -- the Sre2000 main ("working") directory
                port  -- the http port
          servername  -- the canonical name of this site
  • Sre2000 will wait on the daemon manager to finish initialization. The daemon manager signals that it's done with initialization by setting the "asem" semaphore. For example: foo=eventsem_post(asem)
  • DATADIR
    The default "data" directory. This is the "root" directory of you web site -- it's where resources corresponding to selectors of the form "/afile.ext" are located.
    Note that the filter does NOT have to use this directory!

    Notes:


    DEFAULT_SOCKET_TIMEOUT
    Time to wait on a socket, in seconds. If a read or write action on a TCP/IP socket takes longer then DEFAULT_SOCKET_TIMEOUT to do anything, then a timeout will result (the connection will be closed).

    Notes:


    FILTER
    Name of the filter program. Should be a filename relative to the Sre2000 working directory.
    Example: FILTER = SREhttp/2.RXX

    FAST_FILTER
    Name of "fast-filter" program. If specified, the FAST_FILTER is called first. If the fast-filter does not return a response to the client, the "normal" filter is then called. For more details on use of a "fast filter", see Appendix 5.
    Examples:
       FAST_FILTER = FASTFILT.RXX
       FAST_FILTER = 0 -- do not use a fast filter.

    INIT_PROC
    File containing an initialization procedure. This should be a file located In the Sre2000 initialization directory.

    Examples:
       INIT_PROC= PSTART1.RXX
       INIT_PROC=0 -- no initialization procedure

    Notes:

    LIMITHEADER
    The maximum size of request headers, in Kbytes. If the request has headers greater then this size, a 413 response is returned.

    Note that there are no size restrictions on a single request header -- so long as all request headers (including the request line) are less then LIMITHEADER kbytes.

    Example: LIMITHEADER=10

    LIMITBODY
    The maximum size of a request body (as may be included in a POST or PUT request). If the request body is greater then this size, a 413 response is returned.

    Example: LIMITBODY=150

    LIMITCLIENTS
    Maximum simultaneous connections. Each connection handles a single request at a time (though a "maintained connection" can handle a sequence of requests").

    Example: LIMITCLIENTS=15

    Note: LIMITCLIENTS must be less then MAXTHREADS.

    LIMITTIMETOTAL
    Maximum time allowed per request (in seconds). If the total time required to resolve AND transmit a response exceeds LIMITTIMETOTAL, the connection will be closed. No error message is sent to the client -- the connection is just closed.

    Example: LIMITTIMETOTAL=160

    Notes:

    LIMITTIMEWAIT
    Maximum time to wait on a maintained connection (in seconds). This is the number of seconds that Sre2000 will wait for a new request to arrive. This wait occurs after a prior request has been resolved.

    Example: LIMITTIMEWAIT=10

    LIMITTIMEINACTIVE
    Maximum intra-request idle time (in seconds). If LIMITTIMEINACTIVE seconds have passed without any bytes being transmitted (or recieved), Sre2000 will close the connection.

    Example: LIMITTIMEINACTIVE=20

    Notes:

    MAXTHREADS
    Maximum number of "connection" threads. MAXTHREADS is used to set aside "connection specific" storage. Note that Note that LIMITCLIENTS must be less then MAXTHREADS.

    Example: MAXTHREADS=100 Note: each "connection thread" requires about 500 bytes of storage.

    MAXHOSTS
    Maximum number of hosts allowed. Hosts refer to alternative IP names that are aliases for your IP address. It may also refer to names (or addresses) on servers that are handling multiple IP numeric-addresses.

    Example: MAXHOSTS=50

    Notes:

    * each host requires about 50 bytes of storage * you can set & read host-information using the SRE_HOSTINFO function.

    MAXLOCALS
    Maximum number of "local" variables. Local variables are defined for a single connection -- when a connection is closed, the local variables are discarded.

    Local variables are provided as a service to filter writers; their use is strictly optional. However, a minimum of 5 is required.

    Example: MAXLOCALS=15

    Notes:

    MAXSYSVARS
    Maximum number of "system" variables. System variables are global variables that are used to store "system" like parameters. You should have at least 40.

    Example: MAXSYSVARS=60

    Notes:

    MAXCOUNTERS
    Maximum number of "counter" variables. Counter variables are used to maintain counts. Currently, Sre2000 maintains the following counts: BYTESREADTOTAL, BYTESSENTTOTAL, TRANSACTIONS, REQUESTS, LIMITS, and ERRORS

    Thus, MAXCOUNTERS should be at least 6.

    Examples: MAXCOUNTERS=10

    Notes:

    MAXCLIENTNAMES
    Size (number of entries) in "client name" cache. The client name cache is used to lookup an IP name given an IP numeric address (IP requests contain the IP address of the client, but not the IP name). Since this may require a DNS lookup, Sre2000 can maintain a cache of the most recently used names (thereby avoiding a potentially costly call to your DNS server). This is most useful when clients tend to revisit your site several times in a short time periods (say, to fetch embedded images).

    Example: MAXCLIENTNAMES=250

    Notes:

    MAXSTATVALS
    Size (number of entries) to use to compute statistics Sre2000 can compute several sets of statistics, including average, minimum, variance, and maximum. To do this, a set of the "most recent" values is required. MAXSTATVALS sets how large this set should be.

    Currently, Sre2000 maintains statistics on the following measures: TOTAL_TIME,START_TRANSMIT_TIME, and BYTES.

    In other words, MAXSTATVALS sets the number of "measures of the most recent responses" to retain.

    Example: MAXSTATVALS=100

    Notes:

    MAXMD5S
    Size (number of entries) of MD5 cache. Http/1.1 allows the server to attach a Content-MD5 response header, which contains the md5 hash of the response body. Clients can use this value to detect transmission problems, tampering, or other errors.

    Since computation of an MD5 is mildly CPU intensive (especially for long files), Sre2000 maintains an "MD5" cache. The MD5 cache is used for "permanent" files -- when Sre2000 is asked to compute an MD5 for such a file, Sre2000 can first check it's cache to see if such a value has already been computed.

    Examples:
    MAXMD5S= 200
    MAXMD5S=0
    -- do NOT maintain an MD5 cache.

    Notes:

    NO_MODIFY_ONTHEFLY
    Flag to suppress the Alt-M "modify a few parameters on-the-fly" feature (parameters in the SRE2000.CFG file)

    NO_MODIFY_ONTHEFLY=1 -- suppress on the fly modification
    NO_MODIFY_ONTHEFLY=0 -- allow on the fly modification

    Notes:

    PORT
    Port the server is running on. The standard http port is 80.

    Example: PORT=80

    REQ_CACHE_ENABLE
    Enable the request cache.

    REQ_CACHE_ENABLE=1 -- enable
    REQ_CACHE_ENABLE=0 -- do NOT attempt to resolve requests from the request cache

    REQ_CACHE_CALL_ANYWAYS
    For auditing and other purposes, Sre2000 can call the filter even when the request has been resolved through use of the request cache.

    REQ_CACHECALL_ANYWAYS can take the following values:
       REQ_CACHECALL_ANYWAYS 0 Do not call the filter after use of the request cache
       REQ_CACHECALL_ANYWAYS * Always call the filter
       REQ_CACHECALL_ANYWAYS A list Call the filter if any of the "abbrev iations" in the spaced delimited A_list matches the selector
    Example: REQ_CACHECALL_ANYWAYS=/DOCS/ /HTMLS/

    Notes:

    REQ_CACHE_HITFILE
    File containing record of cache hits. This file is used when REQ_CACHE_RECORD is enabled. It should be a relative filename (relative to the Sre2000 installation directory).

    Example: REQ_CACHE_HITFILE=DATA\CACHEHIT.LOG

    REQ_CACHE_RECORD
    Record cache hits to the REQ_CACHE hitfile, As an alternative to "calling the filter anyways", Sre2000 can maintain a simple log of all requests for which a "request cache" response was used. This log file (specified in REQ_CACHE_HITFILE) contains a running sum, by selector, of the 200 and 30x (unmodified) responses).

    REQ_CACHE_RECORD can take the following values:
       0     Do NOT use the cache-hit file
       mmm     Use the cache hit file, and save results very mmm minutes
    Example: REQ_CACHE_RECORD = 5

    Note: the cache hit file is not augmented when you "call the filter anyways"

    REQ_CACHE_SIZE
    The size of the request cache, in number of entries. Each entry requires about 300 bytes.

    Example: REQ_CACHE_SIZE=200

    REQ_CACHE_VERIFY
    Enable http/1.1 style verification prior to use of the request cache.

    REQ_CACHE_VERIFY can take the following values:
       0     never verify (always use cache entry if it exists)
       1     verify, check Pragma, Cache-Control, If-None-Match, and If-modified request headers. If these are active (i.e.; if Cache-control: no-cache is specified), then do NOT use the request cache.
       2     verify, but ignore Pragma and Cache-Control:no-cache request headers

    SERVER_SOFTWARE
    Reported name of this server software. This variable can be used when reporting the name of the server software; say, in a Server: response header.

    Example: SERVER_SOFTWARE = Sre2000 for OS/2, ver 1.01

    Notes:

    SERVER_SOFTWARE_SHORT
    Short reported name of this server software. This is an alternative to SERVER_SOFTWARE.

    Example: SERVER_SOFTWARE_SHORT= Sre2000

    Notes:

    STATUS_ITEMS
    Specify what to display on the status screen. Sre2000 can display several types of dynamic information on it's status screen (the status screen is displayed after running SRE2000.CMD from an OS/2 command prompt). STATUS_ITEMS should be a space delimited list containing one or more of the following tokens:
    ERRORS, CONNECTION, CLIENTS, LIMITS, PEAK, STATS, and/or VERBOSE.
    where:
       CONNECTION report each connection
       CLIENTS report number of currently active connections
       ERRORS report cumulative number of errors.
       LIMITS report cumulative number of timeouts
       PEAK report peak number of connections
       STATS report summary statistics
       SHOW_LAST display time of most recent connection
       VERBOSE report various other items

    TRACKING_ON
    Enable Sre2000's "client tracking" facility. TRACKING_ON = 0 -- suppress TRACKING_ON = 1 -- enable The tracking facility instructs SREhtttp/2 to write "status" and other "tracking" information to the audit daemon. You can the retrieve this tracking information, on a client specific basis, by using SRE_TRACKIT.

    For more details on tracking, see Appendix 6.

    UNALLOWED_FILE
    A file name (relative to the Sre2000 working directory). This file can contain a list of UnAllowed numeric IP addresses. All requests from clients with these IP addresses are immediately closed -- no response is given, the socket is shutdown.

    If you do NOT need this capability, set UNALLOWED_FILE=0

    Examples:
    UNALLOWED_FILE=BadIPS.IN
    UNALLOWED_FILE=0

    The UNALLOWED_FILE should contain one IP address per line. Lines that start with a semi-colon are comments (and are ignored), as are blank lines.

    IP addresses should be the dotted numeric address. Alternatively, a simple form of abbreviation matching is supported, where the last character is an '*' (with the preceding character implicitily a '.')

    Examples of UNALLOWED_FILE entries

            98.13.61.22
            98.13.61.23
            ;clients from 98.14.* are not granted access
            98.14*  

    Note that you can add and remove entries from the UNALLOWED_FILE at any time -- Sre2000 will check the UNALLOWED_FILE about once a minute.

    USER_STATS
    A space delimited list of variable names, each name can be up to 25 characters long. A "statistics buffer" will be created for each of these variables, which can be used to retain a window of MAXSTATVALS entries (per variable). See the description of SRE_SAVEVALS in Appendix 4 for more details.

    5) Using Sre2000

    This section is meant for those interested in writing custom filters for SRE2000. It may also be of interest to those interested in writing utilties (such as CGI-scripts, or addons) for use with SREhttp/2 or other Sre2000 filters.

    Before proceeding, consider this short introduction to how Sre2000 works. Abstracting from configuration and startup issues, and ignoring some fancy tricks one can use, the sequence of events leading to resolution of a request is:

    1. Sre2000 recieves a TCP/IP request from a client.
    2. Sre2000 launches a thread (the "transaction thread"), which reads the request line, request headers, and (possibly) the request body.
    3. Sre2000 launches another thread (the "request thread"). This thread calls the "filter", and provides several arguments that give information about the request -- in particular, the "selector" and the client IP address.
    4. The filter then uses these arguments, along with additional information, to fashion a response. Typically, the response consists of the contents of a file stored on the server's hard disk. However, if may be a 3xx (redirection) or a 4xx (access denied) response.
    5. In addition to the arguments sent from Sre2000, the filter can use function calls to request additional information (such as the value of specific request headers) from SRE2000. Operationally, these function calls commumicate with the "transaction thread".
      In some sense, one can think of Sre2000 as providing an API, an API that a REXX "filter" uses to recieve http requests and send http responses.
    6. When the filter is ready to send a response, it uses function calls to tell the transaction thread what to send. The transaction thread takes care of all the tcp/ip details, and upon completion of the response informs the filter.
    7. The filter may then do some auditing, informs the transaction thread that it is done, and exits (the request thread immediately dies).
    8. The transaction thread waits to see if another request has been sent (that is, the connection may be a "maintained connection"). If a new request is available, go back to step c. Otherwise, the connection records some transaction information, and exits.
    Thus, there are two important sets of information provided by Sre2000 -- the arguments, and the functions.


    5a) Arguments sent to the filter

    The following arguments are passed to the filter by SRE2000.
       source
       request
       selector
       hostInfo
       semaphore_info
       process_Id
       thread_id
       request_number
       authorization_header
       is_alive   
    where...
       source where, and to whom, the request is sent
       request the request line
       selector the "selector" portion of the request line
       hostinfo the host (and host-nickname) to whom the request is sent
      semaphore_info used to expedite processing of some Sre2000 functions
       process_id the Sre2000 process id
       thread_id the thread id of the "transaction thread"
      request_number the request number
      authorization_header the value of a Authorization: request header
       is_alive flag indicating whether the request is still alive

    In greater detail ...

    SOURCE:    
       Contains the following information in a space delimited list
        servaddr: ip address of destination server (may vary if your server
                  is handling multiple ip addresses)
        port: port that recieved the request
        transaction: the transaction number
        who: numeric IP address of the client
        whoport: port used by the client
    
      You can parse "source" using:
         parse var source myaddr port transaction who whoport . 
    
    REQUEST: 
      The request line. 
    
      For example:
        GET /samples/foo.bar HTTP/1.1
    
    SELECTOR:  
       The "selector" portion of the request line, with leading / removed.
    
       From the above example, the selector is samples/foo.bar
    
    HOSTINFO: 
       Information about the host this request was sent to.  This will
       be three words, seperated by commas: 
         host,host_nickname,datadir
       where:
           host_header : either the ip name of your site, or the value of a
                         HOST: request header.
         host_nickname : the "host-nickname" assigned to this host, or ' '.
               datadir : the "default data directory". If no host_nickname
                         is available, this will be the value specified by the
                         DATADIR parameter (in SRE2000.CFG). Otherwise, it's
                         a host-specific data directory (which may be the same as
                         the "default" data directory).        
    
       Examples:
    
            jones.gonzo.net,,f:\www
            bigtime.circus.org,circus1,g:\webs1\circwww
    
       The first example could be to a site for which no hosts have been defined.
    
       Notes:
          *   Specification of host-nicknames is done with the 
              SRE_HOSTINFO procedure (see Appendix 4).
    
    SEMQUEUE:
      Information on the queue and semaphore used by the "transaction" and
      "request" threads. This can be used by some filters to talk to
      it's own daemons. It is also used in advanced forms of Sre2000 function
      calls to slightly expedite processing.
    
      SEMQUEUE contains 4 items, seperated by spaces:
        transaction-semaphore transaction-queue request-semaphore request-queue
      For example:
            \SEM32\SRE_P278_10 SRE_P278_10 \SEM32\SRE\C278_11 SRE_C278_11
      (the P stands for "parent", the C for "child")
    
    
    PROCESS_ID
        The Sre2000 process id.
    
    
    THREAD_ID:
       Thread_id: the thread id of the "request thread".
    
       Note that the filter is running in the request thread -- the transaction
       thread is running in parallel (it awaits commands delivered 
       by the filter, through Sre2000 functions that use the queue
       and semaphores mentioned in SEMQUEUE to perform inter-process
       communication).
    
    REQUEST_NUMBER: 
       The request number.
       This has two components: a numeric "transaction number", followed
       by an alphabetic "request number". The request number, which
       starts from A, is the "request within this transaction", it is NOT
       the total number of requests recieved.
      
       Note that the sequence of request numbers is: A,B,..,J,AA,AB,..,AJ,BA,... 
    
       Example: 4A
    
    AUTHORIZATION_HEADER: 
       Since the Authorization: request header is often used, it is provided
       as an argument (it can also be read using the REQFIELD function).
    
      Example:  Basic ZGFuOmRhbg==
    
    IS_ALIVE:
       Flag indicating whether the request is still alive.  The 
       request may already have been satisfied (typically due to 
       a request-cache hit), and the filter may have been "called anyways" --
       say, so that the filter can audit the request.
       If IS_ALIVE=1, the request has NOT been satisfied.
       Otherwise, it has.
    
    Notes:

    5b) The Sre2000 functions

    The following lists the Sre2000 functions. Note that filters (such as SREhttp/2) may have their own set of functions -- in many cases these provide additional capabilities that addon/script creators may find useful.

       COMPLETED return whether current request has been completed
       DATADIR return the default data directory
       CLIENTNAME do a DNS lookup of an IP name
       EXTRACT returns settings of several Sre2000 variables.
       QUERY returns settings of several Sre2000 variables.
       REQFIELD return value of a request header.
       SRE_AUDIT write lines to the AUDIT.LOG file
       SRE_COMMAND recieve and send information to the client, etc.
       SRE_TRACKIT set and get client specific tracking info
       SERVERNAME return the servername


    5c) The Sre2000 functions: full descriptions


    COMPLETED: return whether current request has been completed

    COMPLETED will return a 0 if the current request is still open. Otherwise, it returns a 1.

    Syntax: iscompleted=completed() iscompleted=completed(a_thread_id)

    A_thread_id is optional -- it is used if you know the threadid (otherwise, the threadid of the current connection is looked up). It can also be used to determine the completion status of other requests. Note that this is the threadid of the "request" thread that called SRE_FILTER. It is NOT the threadid of the "connection" thread (that spawned a request thread), nor is it the "slot number" used to store connection-specific information. Hint: to find the "request thread id of a client", you can use SRE_LOCALVARS('CLIENT',CLIENT_ID).


    CLIENTNAME [ipaddress]) : Do a DNS lookup of an IP name Returns the ip name of the current client, or of the numeric ipaddress (if ipaddress is specified). cname=clientname() cname=clientname('151.22.51.76') Sre2000 uses a "IPname" cache to avoid unnecessary calls to a DNS -- the most recent several hundred IP name lookups (are retained) -- see the description of MAXCLIENTNAMES.
    DATADIR: return the default data directory DATADIR will return the default data directory. This may be a host specific directory. Syntax: sname=datadir() sname=datadir('default') If 'default' is specified, then the default data directory (as set in SRE2000.CFG) is returned. Notes: * SRE_COMMAND('SET DATADIR ',adir) can be used to modify the value returned by datadir().
    EXTRACT: returns settings of several Sre2000 variables. EXTRACT is used to obtain values of many of the Sre2000 variables, several of which are request (or connection) specific. The syntax of EXTRACT closely follows the GoServe EXTRACT function, with several additional fields supported (and a few not supported). Syntax: avalue=EXTRACT(varname) where: varname is one of the following variables. o BYTESREAD -- the number of bytes received from the network, so far during the current transaction. o BYTESREADTOTAL -- the total number of bytes received from the network. You may need to increase the Rexx NUMERIC DIGITS setting if you wish to do arithmetic on this count. 16 digits should be sufficient. o BYTESSENT -- the number of bytes sent to the network, so far during the current transaction. o BYTESSENTTOTAL -- the total number of bytes sent to the network. You may need to increase the Rexx NUMERIC DIGITS setting if you wish to do arithmetic on this count. 16 digits should be sufficient. o CLIENTADDR -- the client's address used for the connection, in numeric form (for example, 12.34.56.78). For a symbolic name for the address, see the CLIENTNAME function. o CLIENTMETHOD -- the method (verb) being invoked by the client (on the HTTP request, or "GET" if a Gopher request). For example, "GET" or "POST". o CLIENTPORT -- the client's port number used for the connection. o CLIENTPROTOCOL -- the protocol being used by the client (on the HTTP request, or "GOPHER" if a Gopher request). For example, "HTTP/1.0". o CLIENTS -- the number of clients currently connected. o DATADIR -- The connection specific default data directory. You can also use the datadir() function to return this value. In addition, the filter will called with datadir as one of the entries in the hostinfo argument. o DATADIR_DEFAULT -- The default value of datadir. o ELAPSED -- the elapsed time, in seconds, since the current transaction started (that is, when the network connection was accepted). o ERRORS -- the count of errors detected. o FILTER -- the name of the Rexx filter. o HOST_NICKNAME -- the "host nickname" assigned to this "host" If no host nicknames are assigned, returns a '' o GMTOFFSET -- the GMT offset (in seconds). o LASTACCEPT -- timestamp of the last accepted connection [format: yyyy.mm.dd hh:mm:ss]. o LASTIDLE -- timestamp of when Sre2000 last entered an idle state, with no connections [format: yyyy.mm.dd hh:mm:ss]. Note that this is only as accurate as the "update rate" (set in SRE2000.CMD). o LASTSECOND -- time now, in the same format [yyyy.mm.dd hh:mm:ss] as the other LASTxxxx items. o LASTSTART -- timestamp of when this instance of Sre2000 was started [format: yyyy.mm.dd hh:mm:ss]. o LASTRESET -- timestamp of last RESET ALL "CONTROL" command [format: yyyy.mm.dd hh:mm:ss]. o LIMITS -- the count of limits exceeded (that is, the count of transactions that were ended due to a limit being exceeded). The limits counted are the total connection timeout (LIMITTIMETOTAL), the incoming data measures (LIMITBODY and LIMITHEADER), and maximum clients exceeded (LIMITCLIENTS). The latter is only counted once for each non-idle burst of connections. o LIMITBODY -- Connection specific maximum size of request body (as sent by a POST or PUT request), in kB o LIMITBODY_DEFAULT -- Default value of LIMITBODY o LIMITCLIENTS -- maximum number of client connections allowed concurrently [1 through 200 -- to increase max size, set the MAXCLIENTS value in SRE2000.CFG). o LIMITHEADER -- Maximum size of headers (including the request line), in kB o LIMITTIMEINACTIVE -- Connection specific maximum time, in seconds, for which Sre2000 will allow a client to remain connected but inactive (that is, without sending or reading data) [0 through LIMITTIMETOTAL]. o LIMITTIMEINACTIVE_DEFAULT -- The default value of the above. o LIMITTIMETOTAL -- Connection specific maximum time, in seconds, for which Sre2000 will allow a client to remain connected, even if active [LIMITTIMEINACTIVE through 1E+9]. o LIMITTIMETOTAL_DEFAULT -- default value of the above o LIMITTIMEWAIT -- Connection specific maximum time, in seconds, for which Sre2000 will keep a client connection open waiting for a new request. This applies for all http/1.1 requests, and for all http/1.0 requests that contain a 'Connection: keep-alive' header with the previous request [0 through 1E+9]. o LIMITTIMEWAIT_CURRENT -- default value of the above o NUMSENDS -- number of VAR, FILE, CONTROL, STRING, and NODATA commands issued after a SEND command (0 if no SEND command was ever issued). Note that the initial SEND will set NUMSENDS=1. o PEAKCLIENTS -- the maximum number of clients that were connected simultaneously. o READWAITTIME -- average read wait time (seconds). o READBODY_STATUS -- The status of a read of the request body. If not POST or PUT, then returns 'none'. Otherwise, returns 'pending','completed', or 'error'. o REQUEST and REQUEST_NUMERIC -- the unique number for this HTTP request. This is incremented as each HTTP request is read. This can differ from the TRANSACTION (connection) number if a connection fails to send a request, or if there is more than one request in a transaction. REQUEST is structured as TRANSACTION_NUMBER || REQUEST_AS_LETTER REQUEST_NUMERIC is structured as TRANSACTION_NUMBER || REQUEST_AS_DIGITS Thus, for the tranaction # 115, request 1 would yield: REQUEST: 115A REQUEST_NUMERIC: 1151 Thus, for the tranaction # 4312, request 3 would yield: REQUEST: 4312C REQUEST_NUMERIC: 43123 o REQUESTS -- the number of HTTP requests read since Sre2000 was started. o REQUEST_ERROR -- most recent connection error (for this connection) or '', if no connection. o RESPONSE_CODE -- the response code (i.e.; 200, 404, 301). If response not yet send, returns '000'. o RESPONSETIME -- average response time (seconds). o RESPONSEOVER -- number of connections over which RESPONSETIME and READWAITTIME have been averaged. o SELECTOR -- the selector string: the Universal Resource Indicator, as recieved from the client (that is, the leading / is retained, and without url unpacking) o SERVERADDR -- the server's address used for the connection, in numeric form (for example, 11.22.33.44). For a symbolic name for the address, see the SERVERNAME function. o SERVERPORT -- the server's port number used for the connection (for example, 80 for default HTTP). o SERVERPROTOCOL -- always returns "http/1.1" o SERVERSOFTWARE -- the level of the server software (for example "Sre2000 ver 1.01"). This is the same as returned by the function calls SERVER() . o TRANSACTION -- the unique number for this transaction (connection). This is incremented as each client connects to the server. Note that each transaction may yields several requests (though not concurrently). o TRANSACTIONS -- the number of transactions since SRE-http was started. Note: The following "GoServe EXTRACTABLE" variables are not supported. o GMTSET -- GMT MUST be available o FASTFILE -- Instead, see the REQ_CACHE* parameters in SRE2000.CFG o FASTFILTER -- Instead, see the REQ_CACHE* parameters in SRE2000.CFG o NETBUFFER -- May be supported later o TRACE -- Instead, see the AUDIT_ITEMS parameter in SRE2000.CFG. There are a number of other variables (such as the various AUDIT and DIAG variables) for which no support is currently planned. However, the AUDIT_ITEMS parameter (in SRE2000.CFG) can be used to obtain much of this information.
    QUERY: returns settings of several Sre2000 variables. QUERY is the same as EXTRACT, except that you can provide several parameters. The values of these parameters will be returned in a CRLF ('0d0a'x) delimited list.
    REQFIELD: returns settings of several Sre2000 variables. Return the value of a request header. call as aheader=reqfield('HEADER_NAME:'[,nth]) where: HEADER_NAME: is a request header name. The trailing ':' is optional, and the search is case insensitive. Thus, the following are equivalent: aa=reqfield('User-Agent:') aa=reqfield('USER-AGENT') aa=reqfield('user-AgenT') nth an optional "occurrence". If nth is NOT specified, then all occurences of HEADER_NAME will be concatenated and returned. If nth is specified, then just the nth occurence will be retrurned. For example, if the request headers include: X-Foo: This is foo1 x-FOO: and this is foo2 then aa=reqfield('x-foo') will return This is foo1 and this is foo2 wheras. aa=reqfield('x-foo',2) will return and this is foo2 Note that aa=reqfield(x-foo',3) will return an empty string
    SRE_AUDIT: call as foo=sre_audit(source_name,message,whereto,brief) where: source_name: a short string identifying from where this message came message: the message whereto: where to write the message to whereto should be a 3 character (either 0 or 1) string: audit_file|pmprintf|screen (with 0=no, 1=yes) For example: '101' means "write to audit_file and to screen" Special values of whereto: ' '= write to audit_file and to pmprintf '0' = write to audit_file only '1' = write to audit_file and to screen brief: if 1, do not write the "process and thread" id, and time
    SRE_COMMAND: Recieve and send information to the client, etc. SRE_COMMAND is used to recieve and send information to the client and to set certain server variables. SRE_COMMAND follows the syntax used in several of GoServe's "completion codes" -- many of the GoServe "completion codes" are implemented via calls to SRE_COMMAND (upgraders may want to refer to GOSERVE.DOC for alternative descriptions). The syntax of SRE_COMMAND is status=SRE_COMMAND('ACOMMAND option') where:
    ACOMMAND can be one of:
    ALIVE AUDIT CONTROL FILE HEADER NODATA READ REPSONSE SEND SET VAR
    and
      option is an option list that depends on ACOMMAND.
    
    The following describes the "ACOMMAND" modes of SRE_COMMAND in 
    greater detail.
    
       Note that several of these modes (FILE, VAR, CONTROl, NODATA, and
       STRING) are "completion commands" --  by default, performing the action 
       entails finishing the request (and possibly closing the connection). 
       This default may be modified if you've enabled "SEND" mode.
       
    
    > ALIVE 
    
      Checks to see whether the socket (for this connection) is still alive.
    
       Syntax:
           conn_status=sre_command('ALIVE')
    
       Returns:
         -3 = SockSelect error 
         -2 = Could not determine current connections socket
         -1 = Socket has been closed
          0 = Socket is inactive
         >0 = Bytes pending on socket
    
       Note that if a client dies, or otherwise uncleanly breaks a connection,
       then a 0 may be returned.  Thus, 0 indicates, but does not guarantee,
       that the client is waiting.
    
       Notes:
         * The STILL_ALIVE function can also be used to check connection status.
    
    
    ''''''''''''''''
    > AUDIT 
    
      Write information to the audit log file.
    
      Syntax:
    
      vv=sre_command('AUDIT message')
    
      Will write the message to the Sre2000 audit log file.
    
      Example:
        foo=sre_command('AUDIT FOOBAR used on '||date('n'))
    
      Notes:
         * The SRE_AUDIT function can also be used to write to the audit log file.
    
    
    ''''''''''''''''
    >  CONTROL 
    
      Compute statistics, and reset counters.
    
      Syntax:
    
      vv=sre_command('CONTROL [NOWAIT] [VAR] option')
    
    
      The possible options are:
    
      o RESET [BYTES] [REQUESTS] [RESPONSE] [TRANSACTIONS] [LIMITS] [ERRORS] [ALL]
    
        The specified Sre2000 counters and statistics are reset (after
        auditing, if appropriate).  Any or all of the keywords may be given,
        in any order. RESPONSE refers to the response time record.
    
        If ALL is used, all of the items are reset, and the current time
        is noted as the "time of last reset" -- the last reset time
        is shown on the display window and in any  statistics requests.
    
    
      o STATISTICS
    
        Current statistics and settings are returned.  These include:
    
          1. Transaction, error, limits, byte, and client counts, with
             response time averages
    
          2. Certain settings and options (not including audit selections)
    
          3. The local time of certain events (if an event has not occurred,
             it is shown as the Sre2000 start time).
    
    
       examples:
          status=sre_command('CONTROL STATISTICS ')
            val1=sre_command('CONTROL RESET LIMITS VAR')
    
      The result of a CONTROL command is a single string, which may include
      multiple lines, separated by Carriage Return-Line Feed (CR-LF, ASCII
      '0d0a'x) sequences.  The exact format is not defined.  The result string
      is either placed in a variable or returned to the client:
    
      o If 'VAR' was specified, the result string is returned to
        the caller.
    
      o If 'VAR' was not specified, a document containing the string is
        returned to the client (just as though the STRING mode of
        SRE_COMMAND were used), so in this case, CONTROL is a 
        completion command.
        A  response_code' 'byte_sent (or an 'error error_message')
        is returned to the filter (or to whatever procedure called
        SRE_COMMAND).
    
    
      The NOWAIT keyword may be used to force the current connection to be
      closed after any response is sent, even if a persistent connection had
      been requested.
    
      Upgraders note:
        The following GoServe CONTROL are not supported:
          MOVEAUDIT
          RESET PEAK
          SAY 
    
    ''''''''''''''''
    > FILE 
    
      Send a file to the client.  
    
      This is similar to the GoServe FILE command, with a few new 
      options (CHUNK, ETAG, QUICKPOST) and without the BINARY and TEXT options.
    
      Syntax:
    
       FILE [ERASE] [NOWAIT] [TYPE content-type] [CHUNK]
            [QUICKPOST] [ETAG etag] [NOCACHE] NAME filespec
    
      The file named by 'filespec' will be sent to the client.  'filespec'
      should normally be a fully qualified name (if it is not, Sre2000 would
      look for it in the Sre2000 working directory).  
    
      The optional keywords may be specified, in any order, and have the
      following effects:
    
      o CHUNK -- send the file using a chunked format
    
      o ERASE -- the file is a temporary file, and should be erased after
        being sent. 
    
      o ETAG eee -- eee is the etag associated with this response.  
        If used, an Etag: "eee" response header will be added.
        For example:
            Etag gxyq1
        will cause a
            Etag: "gxyq1" 
        response header to be added.
    
      o NOWAIT -- forces the current connection to be closed after any
        response is sent, even if a persistent connection had been requested.
    
      o QUICKPOST --immediately return "anticipated status" information prior to
        responding to the client. This can speed up throughput, since
        the filter can exit (releasing memory) prior to completion of response.
        Though potentially wrong (say, if  a client kills a connection) this
        "anticipated" information is often sufficient for logging purposes.
    
      o TYPE  xxx -- xxx is the "mimetype" of this resource. 
        Sre2000 will include a Content-type response header that uses
        xxx. For example:
               type text/plain
        will cause Sre2000 to add a
            Content-type: text/plain
        response header.
    
      o NOCACHE -- prevents this FILE command being cached (that is, this
        command will not be associated with a request).  See Appendix 1
        for more details.
    
      Examples:
    
         * stat=sre_command('file type text/html etag fae94 name d:\sre\index.htm')
         * stat=sre_command('file erase type image/gif name d:\sre\temp\$7681.80')
         * stat=sre_command('file chunk type application/octet-stream e:\arc\fo.zip')
    
      Notes:
    
        * The FILE mode of SRE_COMMAND will always return two numbers, 
          seperated by a   space -- a status code and  the bytes sent. For  example:
            200 15161
            
        * The filespec may not include an 'upwards reference' sequence ("..\")
          as such a sequence could possibly allow clients access 
          to any file on the server machine.
    
       *  Sre2000 will generate a header automatically if the TYPE option 
          is specified. You can also use the HEADER option to specify
          a content-type.
    
       *  When using CHUNK, you should NOT include a content-length
          header, and you SHOULD include a "transfer-encoding: chunked" header.
    
       *  CHUNK can also be used with SRE_COMMAND('VAR ...
    
       *  FILE is a "completion code"
    
    ''''''''''''''''
    > HEADER 
      
       Add or remove a response header.
    
       Syntax:
         aa=sre_command('HEADER [ADD|DROP] [NOAUTO] [NOTIME] aheader')
       where:
           ADD|DROP : Either ADD or DROP. 
                     If ADD, then the header specified in aheader is added
                     If DROP, then the header specified in aheader is dropped
                     (assuming it was specified by an earlier ADD).
           NOAUTO   : Optional. If specified, then the automatically
                      generated headers (time, servername, etc.) will
                      NOT be added.
           NOTIME   : Optional. If specified, then Last-Modified and/or
                      Expires: headers will not be included
          aheader   : A response header, of the form:
                            header_name: header message
                      For example:
                            x-new-header: This is my new header
            
       Examples:
    
            foo=sre_command('Header add X1: This is x1 ')
            foo=sre_command('Header add X2: This is X2 ')
              ...
            foo=sre_command('Header drop x2:')
    
            
            foo=sre_command('Header NoAuto Add  Simple: this is the only header')
    
       Notes:
    
         *  NoAuto and NoTime can be included with ADD or DROP. But
            you should only use it once per response.
    
         *  HEADER DROP only examines the portion of aheader that precedes
            the first ":".
    
         * You can specify multiple "aheaders" by concatenating several of
           them, with each aheader seperated by a '0d0a'x.
           For example:
             rh='Header Add H1: my name is Gus '
             rh=rh||'0d0a'x||'Header Add  S1: Her name is Sally'
             foo=sre_command(rh)
         
          * If you use two Header Adds with the same header_name, the
            second will be concatenated onto the first. To replace
            a header, first use Drop and then use Add.
    
          * sre_command('Header ...') always returns a '1'.
    
    
    
    
    ''''''''''''''''
    > NODATA command
    
      Send a null response.
    
      Syntax:
    
         NODATA [NOWAIT] [NORESPONSE]
    
      No data are to be sent; the response is complete.  
      This command is intended to be used when only a header, 
      or nothing at all, is to be returned to the client.
    
      If NORESPONSE is specified, then no response line and header will be
      sent either, even for an HTTP/1.0 or later request; the connection will
      be closed (unless persistent).  This option could be used for testing,
      or if (say) a faulty client was sending repeat messages.
    
      The NOWAIT keyword may be used to force the current connection to be
      closed after any response is sent, even if a persistent connection had
      been requested.
    
      Notes:
        * NODATA is a completion command
    
    
    
    ''''''''''''''''
    > READ 
       
      Read the request headers or the request body.
    
      Syntax:
         status=sre_command('READ HEAD|BODY [ENABLE_CE_GZIP] [SUPPRESS_TE_GZIP]')
    
      READ is used to read the request headers, or the request body.
      The two options are only used with BODY:
    
      ENABLE_CE_GZIP enables UnGZIP of a request body that is gzipped,
      and that contain a Content-Encoding: GZIP header.
    
      SUPPRESS_TE_GZIP disables  UnGZIP of a request body that is gzipped,
      and that contain a Transfer-Encoding: GZIP header.
    
      By default, ungzip is done for "GZIP as a transfer encoding", but
      not for GZIP as a content encoding.
    
      Examples:
            hdrs=sre_command('READ HEADER')
            abody=sre_command('READ BODY ENABLE_CE_GZIP')
    
      Notes:
        * when SUPPRESS_TE_GZIP is not specified, and an unknown
          transfer-encoding is encounted, a 501 Unimplemented response
          is automatically generated.
    
        * when ENABLE_CE_GZIP is specified, and an unknown content-encoding 
          is encountered, a 415 Unsupported Media Type response
          is automatically generated.
    
        * when an error occurs, a '' is returned.  You can check
          to see if this is a real error by using
             EXTRACT('READBODY_STATUS')
          which will return one of the following words ) words:
             none       if the request is not POST or PUT
             pending    request body has not yet been read
             completed  request body was successfully read
             error      an error occurred when reading the body, and the
                        connection was closed
           
      In addition, A REQUEST_ERROR variable contains the "error status"
      of this connection. It can be checked with Extract('REQUEST_ERROR').
      REQUEST_ERROR will have a number of possible values, with a value
      of ' ' meaning "no error".
    
    ''''''''''''''''
    > RESPONSE 
    
       RESPONSE is used to change the response line. 
    
       Syntax:
         aa=sre_command('RESPONSE response line ')
      where 
          response_line is your desired response line.
    
      Example:  
         aa=sre_command('RESPONSE http/1.1 206 Partial Content')
    
    
    
      Notes:
         *  By default, Sre2000 sends a response line of:
               http/1.1 200 Ok
         *  sre_command('RESPONSE ...) always returns a '1'
      
       
    
    
    ''''''''''''''''
    > SET 
    
      SET is used to set "connection specific" values of several variables.
    
      Syntax:
         status=sre_command('SET option',avalue)
      where 
        option is one of:
             LIMITTIMEINACTIVE
             LIMITTIMEWAIT
             LIMITTIMETOTAL
             LIMITBODY
             DATADIR
      avalue is the new "connection specific" value  
    
      Examples:
         status=sre_command('SET DATADIR','e:\special\doc')
         status=sre_command('SET LIMITTIMETOTAL ',1000)
    
      Notes:
        * these do NOT effect the default values -- they only effect the
           current (possibly multiple request) transaction.
        * EXTRACT can be used to read these "modified" values
        * to permanently change these variables, you must change
          SRE2000.CFG (say, by running Sre2000 -m from an OS/2 prompt).
    
    
    ''''''''''''''''
    > SEND 
    
      SEND is used to build multipart messages, or to send pieces of a response
      as it is being built.
    
      Syntax:
         result=sre_command('SEND [TYPE content-type] ')
          ....  
         result=Sre_command('SEND COMPLETE [NOWAIT]')
    
      The basic idea is that all "completion codes" (STRING, VAR, 
      FILE, CONTROL, and NODATA) between a 'SEND ' and a 'SEND COMPLETE' 
      will NOT mean "end of response".
    
       Instead, the start of a response (the response line and response headers) is
       sent to the client when the first SEND is  issued, and the response is 
       completed when a 'SEND COMPLETE' is recieved.
    
       Typically, the response headers  (and perhaps the response line) are
       specified before the first call to SEND. However, you can specify the
       type/subtype (and perhaps a boundary string) in the SEND command by 
       including a TYPE modifier.
    
       Examples:
         status=sre_command('SEND TYPE text/plain')
         status=sre_command('SEND TYPE multipart/mixed; boundary=This_string_sePerates')
    
       SEND COMPLETE ends the request -- you can force the connection to be closed 
       by including a NOWAIT option. For example:
          response_code=sre_command('SEND COMPLETE')
          response_code=sre_command('SEND NOWAIT COMPLETE')
    
      Note that within the boundaries of a SEND and a SEND COMPLETE:
       a) All header specifications are ignored (including TYPE), and NOWAIT 
          is ignored. If you  want to specify different types for each part of 
          a multipart response, you can use VAR (you can also use VAR to
          include boundary lines).
      b)  The status returned is either the number of bytes sent, or a negative 
          error code.
      c)  The ERASE modifier of a FILE command is ignored (temporary files will not
          be deleted).
      
      Reminder: SEND is NOT used to return responses to multiple requests on a 
                single "maintained" connection. Instead, SEND can be used
                to return multiple "parts" within a single "multi-part aware"
                request.
    
    ''''''''''''''''
    > STRING
    
     STRING is used to send a short string to the client. 
    
     Syntax:
      STRING string
    
      The single string is returned to the client as a simple text/html
      response.
    
      The STRING command can be used to return a simple message to the client.
       Multiple lines can be sent, if necessary, by embedding a CR-LF sequence
       ('0d0a'x) to separate lines.  
    
      Example:
           stat=sre_command('STRING Hello World! ')
     
      Notes:
        * STRING is a completion command
        * The STRING mode of SRE_COMMAND will always return two numbers, 
          seperated by a   space -- a status code and  the bytes sent. For example:
            200 15161
    
    '''''''''''
    > VAR command
    
     Return a "variable" to the client. 
      Syntax:
    
        VAR [NOWAIT][CHUNK][QUICKPOST] [TYPE content-type] 
     with
        varname
     as a second argument.
    
      The contents of the Rexx variable named by 'varname' will be sent to the
      client.  'varname' is a standard REXX variable, as it would be written in 
      the  filter.
    
      The optional keywords may be specified, in any order, and have the
      following effects:
    
      o NOWAIT -- forces the current connection to be closed after any
        response is sent, even if a persistent connection had been requested.
    
      o QUICKPOST --immediately return "anticipated status" information prior to
        responding to the client. This can speed up throughput, since
        the filter can exit (releasing memory) prior to completion of response.
        Though potentially wrong (say, if  a client kills a connection) this
        "anticipated" information is often sufficient for logging purposes.
    
      o TYPE  xxx -- xxx is the "mimetype" of this resource. 
        Sre2000 will include a Content-type response header that uses
        xxx. For example:
               type text/plain
        will cause Sre2000 to add a
            Content-type: text/plain
        response header.
    
    
     Example:
    
      * Returning an HTML document to a Web client:
    
           /* This is Rexx code */
           doc=' .... '          /* may be large */
           stat=sre_command('var type text/html name ', doc)      /* return the data */
    
           return
    
    Notes:
    
        * The VAR mode of SRE_COMMAND will always return two numbers, 
          seperated by a   space -- a status code and  the bytes sent. 
          For  example:  200 15161
            
       *  Sre2000 will generate a header automatically if the TYPE option 
          is specified. You can also use the HEADER option to specify
          a content-type.
     
       *  When using CHUNK, you should NOT include a content-length
          header, and you SHOULD include a "transfer-encoding: chunked" header.
    
       *  VAR is a "completion code"
    
     
    
    SRE_TRACKIT: Set and get "tracking" variables. In many cases, you can get multiple variables for multiple clients; or set multiple variables for a single client. Syntax: aval=sre_trackit(varname,value,client,verify) where varname: one, or several (space delimited) ,"tracking" variables to set/get. Alternatively, a * or a **. value: the value. If '', then "get" value; otherwise set the value. If varname contains several variables, then value should contain one word per variable. client: optional -- the "client id" to which this variable applies. Or, a list of clients. If not included, the client id of the current connection is used verify: If verify is set, then the Audit Daemon will compare the transaction associated with "client" equals the value of "verify". Verify should NOT be used with a multiple-valued "client" Returns: If setting a variable, returns 1. If reading a variable, returns a CRLF ('0d0a'x) delimited list of values, with each line containg Client_id Varname: value For example: 2 BYTESREAD: 215 Note that the their is no trailing for the "last" value. Hence, for a one-variable-for-one-client request, a single line response is returned. Special options: * When getting the value of an undefined variable, a ' ' is returned. * Setting VARNAME='*' results in a "list of currently defined variables" (or, several lines of "currently defined variables for each of several clients) * Setting VARNAME='**' results in a list of the values of the defined variables for each of the several (or just one) clients. This is especially useful if you might be defining different variables for different clients. It also avoids some timing issues -- you get a better snapshot of the "state of the clients". * If you specify multiple clients and multiple variables, the values for a client are grouped together. For example, a response might look like: 1 VAR1: value 1 1 VAR2: value 2 3 VAR1: value 1a 3 VAR2: 4 VAR1: try later 4 VAR2: try sooner Note that the ' ' for 3 VAR1: might mean "variable has not been set". * The "Client_ID Varname:" prefix is designed to ensure proper assignation of values when multiple-client, multiple-variable requests are given. For example: clist=sre_localvars('CLIENTLIST') stuff=sre_trackit('CLIENTADDR SELECTOR',,clist) will result in a 2 * #_of_active_clients line response; sorting out which line belongs to which "client and variable" is easily done with the Client_ID and varname. * Reminder: Do NOT use VERIFY with multiple clients. * For more details on "tracking", see Appendix 6. Examples: foo=sre_trackit('BYTESSENT_REQ',100) foo=sre_trackit('START_TIME') foo=sre_trackit('BYTESENT_REQ',100,3) foo=sre_trackit('AB CD','13 55') foo=sre_trackit('BYTESSENT BYTESREAD',,'1 5') alist=sre_trackit('*')
    SERVERNAME: return the servername SERVERNAME will return the servername. This may be a host specific servername. Syntax: sname=servername() sname=servername('default') If 'default' is specified, then the "canonical" (default) servername for this computer is returned.

    Appendix 1: The Sre2000 request cache

    The Sre2000 "request cache" is used as a "proxy like" mechanism for quickly returning a response. It is used for static resources that are associated with non-temporary files on your hard drive.

    Basically, the request cache matches a URI to a file. If such a match exists (if a cache hit occurs), the Sre2000 will return the file to the client, without "calling the filter". By not calling the filter, hence avoiding request resolution overhead, responses can be sent from the request cache substantially quicker -- 50% time savings are not uncommon.

    Entries are automatically created in the request cache when:

    1. Sre2000 used a 'FILE' mode to respond to a prior request for this URI,
    2. caching is not explicitily suppressed (on a selector specific basis),
    3. the file is not temporary
    4. and, of course, request caching is enabled.

    For more details on 'FILE' mode, see the description of the FILE option in SRE_COMMAND.

    Use of the request cache does have a few drawbacks :

  • The request cache requires memory resources
  • The request cache should not be used with dynamic resources
  • Auditing of responses resolved "from the request cache" may be incomplete.
  • These concerns are addressed via the use of the several REQ_CACHE* variables. With these REQ_CACHE* parameters, you can .. Please see the description of these REQ_CACHE* parameters for the details. You can also read CACHING.DOC for a general overview of caching on the WWW.

    Appendix 2: Basic copyright and it's never our fault disclaimer:

      Copyright 2000 by Daniel Hellerstein. 
    
      Permission to use this program for any purpose is hereby granted 
      without fee, provided that the author's name not be used in
      advertising or publicity pertaining to distribution of the software 
      without specific written prior permision.
    
      Use of this product, or portions of this product, is subject to the 
      following:
         1)  Portions of the code are adapted from other authors' work
             (these are noted where appropriate); you'll need to contact these 
             other authors for appropriate permissions.
         2)  SRE-http uses several 3rd party dynamic libraries and executables:
             i) Quercus System's REXXLIB procedure library.  The
                license for REXXLIB gives the author the right to distribute 
                REXXLIB without charge.  This right may NOT extend to 
                redistributors (though as of April 2000 it appears that
                REXXLIB has been released to the public domain). 
                Please contact Quercus Systems for details.
         3)  We, the authors of Sre2000 and any potentially affiliated 
             institutions, disclaim any and all liability for damages due 
             to the use, misuse, or failure of the product or subsets of 
             the product.
    
             *   In particular, Sre2000 and related product are NOT     *
             *   guaranteed to be secure.                                 *
    
             We do design and code our product with careful attention to potential
             security holes, and and we try to quickly fix any problems (or 
             potential problems) that may be discovered. However, SRE-http's 
             fundamental design precept is "open-source", with security an 
             important secondary consideration.
    
                If you REQUIRE a highly secure web-server, you should
                carefully review and test SRE2000. In other words,
                you may need to choose a different server.
    
      Furthermore you may also charge a reasonable re-distribution fee for
      Sre2000; with the understanding that this does not remove the
      work from the public domain and that the above provisos remain in effect.
    
        THIS SOFTWARE PACKAGE IS PROVIDED "AS IS" WITHOUT EXPRESS
        OR IMPLIED WARRANTY.
        THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE PACKAGE,
        INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
        IN NO EVENT SHALL THE AUTHOR (Daniel Hellerstein) OR ANY PERSON OR
        INSTITUTION ASSOCIATED WITH THIS PRODUCT BE LIABLE FOR ANY
        SPECIAL,INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
        RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
        OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
        IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE PACKAGE.
    
    
       Sre2000 was developed on the personal time of Daniel Hellerstein,
       and is not supported, approved, or in any way an official product
       of my employer.
    
       Lastly, if you would like to modify Sre2000, please contact the 
       authors for the source code (Daniel Hellerstein, danielh@crosslink.net).
    
    

    Appendix 3: Running Sre2000 in loopback mode

    The following description is taken from the GoServe documentation, with a few minor changes.
    Sre2000 and your favorite browser can be run on a stand-alone machine that is not connected to a network, provided that TCP/IP is installed and the loopback driver is started. This is especially useful for developing Web pages offline, or for demonstrations. To do this, two additions are needed to a standard TCP/IP installation.
    1. To the file called 'HOSTS' (no extension) in your \TCPIP\ETC, or in \MPTN\ETC, directory add the line:
      127.0.0.1 loopy
      where 'loopy' is the name by which you want your machine to be known when using the loopback connection. This name can be a single word (e.g., 'loopy'), or an internet-style name (e.g., 'loopy.my.org'). It's a good idea to have both formats, on two lines:
             127.0.0.1  loopy.my.org
             127.0.0.1  loopy
      Note: In general, check the value of the ETC environment variable to find out where the HOST file should be placed.

      If there is no \xxx\ETC\HOSTS file, create one.

    2. Before running Sre2000, execute the command:
      ifconfig lo 127.0.0.1
      This only needs to be run once, so can be run from STARTUP.CMD or from any command referenced in your Startup folder. Note that the second word is the lowercase of the two letters 'L' and 'O'.
    Once set up, you can then connect to Sre2000 on your own machine using (for example) the URL:
    http://loopy

    You can also carry out step 2 above by using the TCP/IP configuration notebook. On the 'Network' page, click on 'loopback interface', then check 'Enable interface' and 'Manually, using', then enter '127.0.0.1' as the 'IP address'.

    The loopback address will be active even when connected to a network, so you can always connect to Sre2000 running on the same machine using the loopback name that you chose, provided that your browser does not have a proxy or SOCKS server enabled (the proxy won't be able to find your local loopback address).

    Even if you are not connected to a network, your browser should not have a proxy or SOCKS server enabled (or it will try and use the network to find it before checking the HOSTS file).


    Appendix 4: Using SRE2000.DLL

    Sre2000 uses SRE2000.DLL -- a "REXX callable DLL" to provide several services, such as storage of static variables and maintenance of caches. The following briefly describes their usage:
      SRELoadFuncs Load the Sre2000 functions.
      SREDropFuncs Drop the Sre2000 functions.
      SRE_LOCALVARS Get/save connection specific information
      SRE_SYSVARS Get/save "system" variables
      SRE_CACHE1 A cache that can be used by your filter
      SRE_CACHE_IPNAME Get/save entries to the IP name cache.
      SRE_REQ_CACHE Get/save entries to the "request" cache
      SRE_MD5S_CACHE Get/save entries to the MD5 cache
      SRE_SAVEVALS Save "values" to the "statistics buffer"
      SRE_COUNTVARS Augment a counter variable
      SRE_HOSTINFO Get/save "host nickname" information
      SRE_PAUSE Signals Sre2000 to pause.
      SRE_SHUTDOWN Signals Sre2000 to shutdown

    In greater detail ...

    SRELoadFuncs:
      Load the Sre2000 functions.  
    
      Example:
    
     if rxfuncquery('SRE_REQ_CACHE')=1  then do
      FOO=RXFuncAdd('SRELoadFuncs', 'Sre2000', 'SRELoadFuncs')
      if foo=1 then do
           say "ERROR: could not find SRE2000.DLL " 
          exit
      end 
      call SRELoadFuncs
     end
    
    SREDropFuncs:
      Drop the Sre2000 functions.
    
      Example:
    
    
       call SREDropFuncs
    
    SRE_LOCALVARS:
       Get/save connection specific information.
    
       Usages:
        *  set a "connection specific" variable. 
               STATUS=SRE_LOCALVARS(VARNAME,AVALUE)
           where
               varname: 25 character or less variable name (case insensitive)
               avalue: 80 character or less value
               status: 1 if success, otherwise an error message
    
        *  read a connection specific variable
               AVALUE=SRE_LOCALVARS(VARNAME)
            where varname's value was set by a prior call
            Note that if varname was not set (for this connection),
            a ' ' is returned.
    
        *   selector for this connection (actually, for the most recent
            request on this connection), or of a request-thread tid
              ASEL=SRE_LOCALVAS('SEL'[',,TID])
          
        *   host nickname for this request, or of a request-thread tid
               AHOST=SRE_LOCALVARS('HOST_NICKNAME'[,,TID])
    
        *   socket used for this connection, or of a request-thread tid
              ASOCKET=SRE_LOCALVARS('SOCKET'[,,TID])
    
        *    numeric ip address of client using this connection, or
             of request-thread tid
              AIP=SRE_LOCALVARS('CLIENTADDR'[,,TID])
    
        *   total number of active clients
               NCLIENTS=SRE_LOCALVARS('!CLIENTS')
    
        *   list of active clients, by "client slot"
               CLIST=SRE_LOCALVARS('CLIENT_LIST')
    
        *   id of current client, or of client on "request thread tid"
               CLIENTID=SRE_LOCALVARS('CLIENT'[,,TID])
               Note that the 2nd argument is empty
    
        *   "request" thread id of a "client", give a client id
               ASLOT=SRE_LOCALVARS('TID',CLIENTID)
    
        *   initialization info and summary of current connections
              INFO=SRE_LOCALVARS('!INFO')
    
        *   detailed information on a client, by client id
              INFO=SRE_LOCALVARS('!INFO',CLIENTID)
    
        *  is this client still active (or has the connection been closed)
              isactive=sre_localvars('!COMPLETED')
            Or, to refer to a client associated with a given thread id:
              ISACTIVE=SRE_LOCALVARS('!COMPLETED',,ATID)
              Note that the 2nd argument is empty
    
    SRE_SYSVARS:
       Read or set a system variable.  Once set, a system variable can
       be modified, but it can not be removed.
    
      Usages:
          
      * set a system variable
          stat=sre_sysvars(varname,avalue)
        where
            varname is up to 25 characters (case insensitive)
            avalue is up to 132 characters        
            stat is equal to avalue if successful, otherwise an error 
    
          In general, setting a variable in SRE_SYSVARS should only be
          done in a serial fashion (by one thread at a time), but reading
          can be done simultaneously.
    
      * read a system variable
          stat=sre_sysvars(varname[,,no_var_message)
        where
           no_var_message is displayed if there is no system variable with a name
           of varname. If no_var_message is not specified, a ' ' is used
           when there is no such variable.
    
       * info on number of, and value of, system variables
           info=sre_sysvars('!INFO')
    
    
    SRE_CACHE1    -- A cache that can be used by your filter
    and
    SRE_CACHE_IPNAME -- The IP name cache.
    
      Both of these have the same structure. SRE_CACHE_IPNAME is used by Sre2000
      to support the "IP name (DNS lookup) cache".  SRE_CACHE1 can be used
      by filter writers. For example, SREhttp/2 uses SRE_CACHE1 to support 
      a username/password cache.
    
      Both caches are LIFO, once filled the oldest entry is removed -- irrespective
      of intensity of use (they are LRU caches).
    
      These caches can be read simultanteously, but should be written
      serially. Ideally, a single persistent thread (a daemon) should
      handle writing to both caches.
    
      Usages:
    
       * Initialize cache1 
            stat=sre_cache1('!STARTUP',cachesize)
         where
            cachesize is the maximum number of entries (after which
            oldest entries are replaced).
            stat is 'ok' if success, otherwise an error message.
       
       * Add value to cache
            stat=sre_cache1(avar,avalue)
            stat=sre_cache_ipname(ipnumber,ipname)
         where
            avar,ipnumber can be up to 50 characters (case insensitive)
            avalue, ipname can be up to 80 characters
    
        Avalue will be avalue, or an error message.
    
       * Read value from cache
           avalue=sre_cache1(avar)
           ipname=sre_cache_ipname(ipnumber)
    
       * info on number of, and values of, cache variables
           info=sre_cache1('!INFO')
           info=sre_cache_ipname('!INFO')
    
       * clear all values from cache
           info=sre_cache1('!RESET')
           info=sre_cache_ipname('!RESET')
    
    SRE_REQ_CACHE   -- Get/save entries to the "request" cache
    and
    SRE_MD5S_CACHE  -- Get/save entries to the MD5 cache
    
      Both of these have the same structure. SRE_REQ_CACHE is used by Sre2000
      to support the "request cache", SRE_MD5S_CACHE supports the MD5 cache.
    
      These caches can be read simultanteously, but should be written
      serially. Ideally, a single persistent thread (a daemon) should
      handle writing to both caches.
    
      These are LRU caches -- when full, a "filled" message is returned.
      When filled, the user should either stop adding elements, or should
      purge old elements.
    
      Usages:
      * Add item to MD5 cache
           stat=sre_md5s_cache(filename,md5value[,filled_message])
        where
            filename is an up to 60 character (case insensitive) "file name"
            md5value is an md5 hash of up to 60 characters
            stat is md5value when succesful, an error messsage,
            or "filled_message" if the cache is filled. If filled_message
            is not specified, and the cache is filled, a ' ' is returned.
    
      * Add item to request cache
           stat=sre_req_cache(selector,req_info[,filled_message])
        where
           selector is up to 80 characters long
           req_info is up to 280 characters long
    
       * purge old entries
            stat=sre_md5s_cache('!PRUNE')
            stat=sre_req_cache('!PRUNE')
    
       * mark an entry for removal. It will not be used in searches,
         but it's space only becomes useable after a !PRUNE.
            stat=sre_md5s_cache('!REMOVE',filename)
            stat=sre_req_cache('!REMOVE',selector)
    
       * info on number of, and values of, cache variables
           info=sre_req_cache('!INFO')
           info=sre_md5s_cache('!INFO')
    
       * basic info on number of cache variables
           info=sre_req_cache('!STATUS')
           info=sre_md5s_cache('!STATUS')
    
       * clear all values from cache
           info=sre_req_cache('!RESET')
           info=sre_md5s_cache('!RESET')
    
    SRE_SAVEVALS    -- Save "values" to the "statistics buffer"
    
       The statistics buffer is used to store a vector of the
       most recent values of a variable, such as the number of
       bytes returned.  This vector is lifo, with oldest entries
       removed first.  
    
       One can perform statistics on this buffer -- say, the mean
       number of bytes in the last 100 responses.
    
       Note: the size of the statistics buffer, and the number of 
       variables that can be tracked, are set by the MAXSTATVALS
       variable.  There are currently three variables established
       by Sre2000 (TOTAL_TIME, START_TRANSMIT_TIME, BYTES) -- you
       can specify more by modifying the USER_STATS parameter.
    
      Usages:
      *  Add a value to the list
           stat=sre_savevals(avalue,varname)
        where
          avalue is a number
          varname is a variable name
          stat is 'ok' if success, otherwise an error message
            
      * clear all values for this variable
         stat=sre_savevals('CLEAR',varname)
    
      * initialization info and summary of current connections
         info=sre_savevals('!INFO')
    
      * The following return statistics (either a single number, or
        two numbers); or an error message (say, if no such varname)
    
          nobs=sre_savevals('NOBS',varname) -- # of observations 
          amean=sre_savevals('SUM',varname) -- sum (across NOBS observations)
          asd=sre_savevals('SD',varname)    -- standard deviation
          minmax=sre_savevals('MINMAX',varname) -- the min, and max, values
    
             nobs is a number, or an error message (if no such varname)
    
    
    SRE_COUNTVARS   -- Augment a counter variable
       
        Sre2000 maintains counter variables. The maximum number of
        counter variables is specified by the MAXCOUNTERS parameters.
        Note that Sre2000 establishes 6 counter variables:
          BYTESREADTOTAL, BYTESSENTTOTAL, TRANSACTIONS, REQUESTS, LIMITS, ERRORS 
     
    
       * Create a counter variable
           stat=sre_countvars(countervar[,initvalue]
         where
            countervar is up to 25 characters (case insensitive)
            initvalue is the value to start with. If not specified,
            the counter is initialized to 0
            stat is initvalue if success (or 0, if no initvalue);
            and an error message otherwise.
    
       * Get current value of a counter variable
           avalue=sre_countvars(countervar]
    
         Note: if countervar is not specified, it will be created
               (with a value of 0)
    
       * Add to counter variable
             newvalue=sre_countvars(countevar,value_to_add)
         where
            value_to_add is a number
    
         Note: if countervar is not specified, it will be created
               (with a value of value_to_add)
    
       * reset a counter to 0
           info=sre_countvars(countervar,'RESET')
    
       * info on number of, and values of, counter variables
           info=sre_countvars('!INFO')
           info=sre_countvars('!INFO')
    
    SRE_HOSTINFO    -- Get/save "host nickname" information
        Return info associated with a host. This is used by Sre2000
        to store host-nickname and host-datadir info on a "Host:" specific
        basis.
      
       Usages:
       
       * Creating a host entry
          stat=sre_hostinfo(ipname,nick_name,datadir)
         where
              ipname is up to 80 characters long
              nick_name is up to 16 characters long
              datadir is up to 80 characters long
    
        * Find host info
           results=sre_hostinfo(ipname)
    
           results will contain the ipname, host_nickname, and host_datadir
           in a comma delimited list. Of, if no such ipname, results will
           be set to ' '.                                          
    
       * initialization info
          info=sre_hostinfo('!INFO')
    
       * list currently specified hosts
          info=sre_hostinfo('!LIST')
    
    SRE_PAUSE:
       Set or read the "pause" flag. At Sre2000 startup, the pause flag
       has a value of '0'
       
       Usages:
        * set pause flag
            stat=sre_pause(amessage)
         where
            amessage is up to 80 characters long
            stat is 'ok' if success, otherwise an error messsage
    
       * read pause flag
           ispause=sre_pause()
    
       Note that Sre2000 will check the pause flag before accepting a new
       connection. If it is NOT equal to '0', Sre2000 will pause (and
       wait for it to be set to '0').
    
    SRE_SHUTDOWN
       Calling SRE_SHUTDOWN with any value will signal Sre2000 to exit.
    
       For example:
              foo=sre_shutdown(1)
    
       Using
         stat=sre_shutdown() returns the value of the shutdown flag -- a 
         non '0' value means "shutdown has been signaled".
    
                   

    Appendix 5: Using a fast filter

    In many cases, one can divide a site's resources into "simple resources" (such as static images), and more complicated resources (such as dynamic documents, and access controlled documents). In general, simple resources can be handled by short (hence, faster) filter. Thus, throughput could be greatly improved if one could use a "simple and fast" filter for requests for these "simple" resources, and use a longer (and slower) filter for more complicated requests.

    The FAST_FILTER option allows you to do this. If you specify FAST_FILTER, then Sre2000 will:

    1. first call the FAST_FILTER.
    2. if the fast filter is able to handle the request, Sre2000 exits (or waits for the next request on a maintained connection)
    3. otherwise, Sre2000 calls the "normal" filter
    This does involve a tradeoff -- slower response time for "complicated" requests (since the fast-filter has to be called first), but quicker response time for "simple" requests.

    Fast-filters are essentially the same as normal filters, they are sent the same arguments, and can access the same parameters and functions. There is one difference -- the fast-filter needs to inform Sre2000 as to whether it was successful or not.

    To do this, the fast filter should return either:
       not successful -- the normal filter should be called
       1   success. Sre2000 can close the connection, or wait for next request on a maintained connection
    An example of a fast-filter, FASTFILT.RXX, is included with SRE2000.


    Appendix 6: Tracking client status

    When enabled (with the TRACKING_ON parameter), Sre2000 will maintain information on the current status of each client. This information is stored in the Audit Daemon, and can be read (or modified) by using the SRE_TRACKIT procedure.

    Note that a shared daemon is used to store this information. Therefore, it may not be completely up to date -- when reading parameters, the actual parameters are not read; rather, their values as of their most recent update is used.

    Many of the variables that are "tracked" are also available via Sre2000 "EXTRACT" procedure. However, EXTRACT is designed to be used to obtain values of a client (where a client is synonymous with a connection) "own" variables.

    Basically, SRE_TRACKIT makes it easy to find status information for other clients.

    Currently, the following client-specific parameters are set by SRE2000.
       BYTESSENT_REQ bytes sent for this request (possibly reset if multiple requests per connection)
       BYTESREAD_REQ bytes read for this request (possibly reset if multiple requests per connection)
       CLIENTADDR dotted numeric IP address of the client
       RECIEVE RECIEVE can take the following values 0 - not currently sending >0 - amount to be received
       READHEAD Read header data. READHEAD can take the following values:
      0   Not yet read
      START   Currently reading header
      END   header has been read
       READBODY Read body data. READBODY can take the following values:
      0 Not yet read
      START Currently reading body
      END Body has been read
       REQUEST the request (within a transaction, starting with 1)
       SELECTOR the full request selector (as recieved from the client)
       SEND Currently "sending" information to client. SEND can take the following values:
       0   not currently sending
       >0   sending this many bytes
       -1   timeout occurred on most recent send
       -2   error occurred on most recent send
       STATUS Current action being undertaken.

    STATUS may take the following values:
       START
       ERROR_CONN_CLOSE
       ERROR_LIMIT
       ERROR_417 (expectation failed)
       ERROR_TIMEOUT
       ERROR_NO_HOST (Host: missing from http/1.1 query)
       REQ_CACHE_USED (request-cache used)
       PROCESS_xxx (xxx is one of the SRE_COMMAND options)

       TRANSACTION the transaction

    In addition, you can set your own "connection specific" values by using SRE_TRACKIT.