17 July 2001

SRE2001: An Internet Server for OS/2

Abstract SRE2001 is an Internet server for OS/2. More precisely, SRE2001 provides a set of functions and capabilties that allow you to implement a web server through a "filter" program that is written in REXX. In addition to a fairly simple filter include with SRE20001, 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 SRE2001
  4. Configuring SRE2001
    1. Description of SRE2001 configuation parameters.
    2. Detailed description of SRE2001 parameters
  5. Using SRE2001
    1. Arguments sent to the filter
    2. The SRE2001 functions
    3. The SRE2001 functions: full descriptions
  6. Appendices
    1. Appendix 1: Basic copyright and it's never our fault disclaimer
    2. Appendix 2: Using SRE2001's request cache
    3. Appendix 3: Running SRE2001 in loopback mode
    4. Appendix 4: Using a fast filter
    5. Appendix 5: Tracking client status

1) Introduction

SRE2001 is an Internet server for OS/2. More precisely, SRE2001 provides a set of functions and capabilties that allow you to implement a web server through a filter program that is written in REXX. In addition to a fairly simple filter that comes with SRE2001, there are several publically available filters, such as SREhttp/2 ( http://www.srehttp.org). Or, or you can write your own filter!

SRE2001 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, SRE2001 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 SRE2001.

In comparison with GoServe, the primary advantage of SRE2001 is increased support for http/1.1 functions, including a greatly improved cache. Just as important, SRE2001 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!

Of course, there is a disclaimer ..

Before choosing & using SRE2001, you must read the disclaimer (in appendix 1). Basically, SRE2001 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 SRE2001 has no security holes or is free from other potentials for failure.

2) Installation

The easiest way to install SRE2001 is to use the installation program.
  1. UnZIP SRE2001.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 SRE2001.zip to E:\TEMP:
       E:\TEMP>install
  4. You will be asked to enter a working directory -- this is where SRE2001 will be installed.

Notes


3) Starting SRE2001

To start SRE2001,
  1. Open an OS/2 box
  2. CD to the working directory
  3. Run SRE2001
    For example, assuming the working directory is D:\SERVER:
          D:\SERVER>SRE2001
  4. SRE2001 will start, and after some initializations a text-based status screen will be displayed.

Notes


3.a) Using the SRE Watch monitor

The SRE Watch program offers another means of running SRE2001.

SREWATCH will start SRE2001, and will the monitor its status. If SRE Watch detects that SRE2001 has crashed (or is otherwise hopelessly hung), it will attempt to kill, and then restart, SRE2001. In fact, you can even tell SRE Watch to reboot the machine when things get bad enough.

Since there are transient conditions that can crash SRE2001 (for example, there is a very rare bug in the MD5 procedure that will crash SRE2001), the use of SREWATCH is highly recommended for those running unattended servers.

For example: run SREWATCH.CMD from your STARTUP.CMD file, and enable the SRE Watch "reboot if necessary" option,
To run SRE Watch, run the SREWATCH.CMD program (located in the SRE2001 working directory) instead of SRE2001.CMD. You might need to set a few parameters (in SREWATCH.CMD) before the first time you run it, but most people can use it as delivered.

4) Configuring SRE2001

SRE2001 uses a single configuration file: SRE2001.CFG. SRE2001.CFG is a text file that you can modify using any text editor (such as EPM). You can also modify SRE2001 by entering, from an OS/2 prompt:
      SRE2001 -m
You will be presented, in a sequential fashion, with a list of the most important SRE2001 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
      SRE2001 -mall
you will be presented with a list of all the parameters contained in SRE2001.CFG, many of which you'll never need to change.

SRE2001.CFG is located in the CFG subdirectory.


4) Description of SRE2001 configuation parameters.

The variables set in SRE2001.CFG are:
AUDITFILE File containing audit and status information
AUDIT_ITEMS Specifies what is written to the AUDITFILE
AUDIT_DELAY Time span (in minutes) to wait before writing to audit file
DAEMON_MANAGER Name of a "daemon manager" program, or 0.
DATADIR The default "data" directory (your site's root directory)
DEFAULT_SOCKET_TIMEOUT Time to wait on a socket, in seconds
ERRORFILE Name of the error log file.
FILTER Name of the filter program
FAST_FILTER Name of "fast-filter" program
INIT_PROC File containing an initialization procedure, or 0
LIMITBODY Maximum size of request body (in Kbytes)
LIMITCLIENTS Maximum simultaneous connections
LIMITHEADER Maximum size of request headers (in Kbytes)
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)
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_CALL_ANYWAYS Call the filter even if request cache is used
REQ_CACHE_ENABLE Enable the request cache
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
STATUS_MESSAGE Short message (displayed on side of status screen)
TRACKING_ON Enable SRE2001'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 "SRE2001 -m").

Notes


4a) Detailed description of SRE2001 parameters

The following provides a more detailed description of the SRE2001.CFG parameters.
AUDITFILE
Where to write audit items (as specified by AUDIT_ITEMS) to. Should be a relative filename; relative to the SRE2001 working directory. By default, it's LOG\AUDIT.LOG.

AUDIT_DELAY
How many minutes to wait when writing to audit file. This is a "lazy write" parameter -- SRE2001 will store this many minutes worth of AUDIT output, and write it to the audit file all at once.

You can use fractional values. For example:
    AUDIT_DELAY=0.25
means "write to audit file every 15 seconds"

Notes:


AUDIT_ITEMS
Specifiy what additional events to write to audit file. Should contain a space delimited list of options. Supported options are: 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
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"
REQUEST
The request string. For example:       R : 1A 00:25:06: GET /samples/daemons.doc HTTP/1.1
RESET
A reset has occurred. For example:
      RESET : 21:34:52 5 Jul 2001
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

Note that you can use the SRE_AUDIT function to write custom messages to the AUDIT file.

DAEMON_MANAGER
Name of a "daemon manager" program. This should be a relative filename (relative to the SRE2001 working directory); it will be launched as a permanent thread under the SRE2001 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:

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:

ERRORFILE
The file where errors are recorded to. By default, this is log/errors.log

FILTER
Name of the filter program. Should be a filename relative to the SRE2001 working directory. Example: FILTER = SREhttp2.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 4.
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 SRE2001 \BIN 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

Notes:

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

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 SRE2001 will wait for a new request to arrive. This wait occurs after a prior request has been resolved.

Example: LIMITTIMEWAIT=10

Notes:

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

Example: LIMITTIMEINACTIVE=20

Notes:

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

Thus, MAXCOUNTERS should be at least 10.

Examples: MAXCOUNTERS=30

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, SRE2001 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 SRE2001 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, SRE2001 maintains statistics on the following measures:
    TOTAL_TIME,START_TRANSMIT_TIME, BYTES.
SRE2001 also retains the most recent values of CLIENTADDR (dotted numeric address) and REQUEST (the request line).

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), SRE2001 maintains an "MD5" cache. The MD5 cache is used for "permanent" files -- when SRE2001 is asked to compute an MD5 for such a file, SRE2001 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 SRE2001.CFG file)

Examples:
      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=nn enable, with nn the time-to-live of each entry, in days. Thus, REQ_CACHE_ENABLE=1 means "enable the cache, each item has 24 hour lifespan"
REQ_CACHE_ENABLE=0 do NOT attempt to resolve requests from the request cache

REQ_CACHE_CALL_ANYWAYS
For auditing and other purposes, SRE2001 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 1 Always call the filter (same as *)
REQ_CACHECALL_ANYWAYS A_LIST Call the filter if any of the "abbreviations" 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 SRE2001 installation directory). You might want to place it in the LOG subdirectory of the working directory.

Example: REQ_CACHE_HITFILE=LOG\CACHEHIT.LOG

REQ_CACHE_RECORD
Record cache hits to the REQ_CACHE hitfile.

As an alternative to "calling the filter anyways", SRE2001 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:
0Do NOT use the cache-hit file
mmm Use the cache hit file, and save results very mmm minutes
Example: REQ_CACHE_RECORD = 5

Notes:

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 (that is, just check etag and date)

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 = SRE2001 for OS/2, ver 1.04

Notes:

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

Example: SERVER_SOFTWARE_SHORT= SRE2001

Notes:

STATUS_ITEMS
Specify what to display on the status screen. SRE2001 can display several types of dynamic information on it's status screen (the status screen is what SRE2001 displays while it is running).

STATUS_ITEMS should be a space delimited list containing one or more of the following tokens:

ERRORS, CONNECTION, CLIENTS, CLOCK, LASTACCEPT, LIMITS, PEAK, STATS, VERBOSE
where:
CLIENTS report number of currently active connections
CONNECTION report each connection
CLOCK display current time
ERRORS report cumulative number of errors.
LASTACCEPT display time of most recent connection
LIMITS report cumulative number of timeouts
PEAK report peak number of connections
STATS report summary statistics
VERBOSE report various other items

STATUS_MESSAGE
A message displayed on the side of the status screen. Only the first 12 characters are used.

TRACKING_ON
Enable SRE2001's "client tracking" facility.
    TRACKING_ON = 0 suppress
    TRACKING_ON = 1 enable

The tracking facility instructs SRE2001 to store "status" and other "tracking" information. You can the retrieve this tracking information, on a client specific basis, by using SRE_TRACKIT.

For more details on tracking, see Appendix 5.

UNALLOWED_FILE
A file name (relative to the SRE2001 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, you can use * as a wildcard for an octet. That is,
125.22.*.1 matches 125.22.0.1 to 125.22.255.1

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 -- SRE2001 will check the UNALLOWED_FILE about once a minute.


5) Using SRE2001

This section is meant for those interested in writing custom filters for SRE2001. 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 SRE2001 filters.

Before proceeding, consider this short introduction to how SRE2001 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. SRE2001 (the main thread) recieves a TCP/IP request from a client.
  2. SRE2001 launches a daemon (the "transaction daemon"), which reads the request line, request headers, and (possibly) the request body.
  3. The transaction daemon launches another daemon (the "request daemon"). This daemon calls the "filter", and provides several arguments that give information about the request -- such as 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 SRE2001, the filter can use function calls to request additional information (such as the value of specific request headers) from SRE2001. Operationally, these function calls commumicate with the "transaction daemon".
    In some sense, one can think of SRE2001 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 daemon what to send. The transaction daemon 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 daemon that it is done, and exits (the request daemon immediately ends).
  8. The transaction daemon 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 daemon records some transaction information, and exits.
Thus, there are two important sets of information provided by SRE2001 -- the arguments, and the functions.
Note: "daemons" are independent threads. Actually, in order to avoid operating system overhead, daemons are "recycled", so that rather then ending, they go into a dormant state and await re-invocation.

5a) Arguments sent to the filter

The filter is called using:
    foo=sre_filter(source,request,sel,host_stuff,id_info,reqnum,authh,ISALIVE) Where the following arguments are:
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
id_info used to expedite processing of some SRE2001 functions
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 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 ' ' (if a host-nickname was not defined for this host)
datadir the "default data directory". If no host_nickname is available, this will be the value specified by the DATADIR parameter (in SRE2001.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:

ID_INFO
Request and transaction daemon identifier information. Several SRE2001 functions (such as SRE_REQUEST_INFO) will run just-a-bit-faster when you supply them with this parameter.
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 SRE2001 functions

The following lists the SRE2001 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.

CACHED return whether the current request was satisfied from the cache
COMPLETED return whether current request has been completed
DATADIR return the default (or host specific) data directory
CLIENTNAME do a DNS lookup of an IP name
EXTRACT returns settings of several SRE2001 variables.
REQFIELD returns the 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_REQUEST_INFO read "id" info for a request.
SRE_TRACKIT set and get client specific tracking info
SRE_CACHE manipulate "caches"
SRE_QUEUE manipulate "queues"
SRE_QUEUE_STATS compute statistics on values stored in a queue
SRE_COUNTVARS manipulate counter variables
SRE_EVENTVARS manipulate event variables
SRE_HOSTINFO read & set host information
SRE_WRITE_ERROR write a message to the error log and to the status screen
SRE_WRITE_MESSAGE write a message to the status screen
SRE_SAY write a message to the status screen
SERVERNAME return the servername

Advanced Users Note The SREAPI.TXT file (in the DOC subdirectory) contains further details on working with SRE2001.

5c) The SRE2001 functions: full descriptions

CACHED: return whether current request was resolved from the request cache
CACHED will return a 1 if the current request was resolved using information from the request cache.
Otherwise, it returns a 0.
Syntax:
   iscached=cached()
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(transaction_id)
transaction_id is optional-- it is used if you want to lookup the completion status of the request running under a given transaction. If not specified, then the "current request" is checked.

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).
Syntax:
  cname=clientname()
  cname=clientname('151.22.51.76')
SRE2001 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. In fact, it may be dynamic to the request.
Syntax:
   sname=datadir()     
   sname=datadir('host')    
   sname=datadir('default')    
If 'host' is specified, then the default host-specifc data directory (as set in SRE2001.CFG, or as specified by a calls to SRE_HOSTINFO) is returned.

If 'default' is specified, the default data directory is returned (as specified in SRE2001.CFG).

If no argument is given, then either:

  • a request specific datadir (as may be set by a SRE_COMMAND)
  • a host specific data directory
  • the default data directory (with the request specific datadir returned if available, otherwise the host specific, otherwise the default)

Notes:

  • SRE_COMMAND('SET DATADIR ',adir) can be used to set the "request- specific" value returned by datadir().

EXTRACT: returns settings of several SRE2001 variables.
EXTRACT is used to obtain values of the SRE2001 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,id_info)
where:
id_info optional -- the "id info" of the transaction/request you want information from. If not specified, use the current transaction/request.
varname is one of the following variables.
BYTESREAD the number of bytes received from the network, so far during the current transaction.
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.
BYTESSENT the number of bytes sent to the network, so far during the current transaction.
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.
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.
CLIENTMETHOD the method (verb) being invoked by the client. For example, "GET" or "POST".
CLIENTPORT the client's port number used for the connection.
CLIENTPROTOCOL the protocol being used by the client. For example, "HTTP/1.0".
CLIENTS the number of clients currently connected.
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.
DATADIR_DEFAULT The default value of datadir (as set in SRE2001.CFG).
ELAPSED the elapsed time, in seconds, since the current transaction started (that is, when the network connection was accepted).
ERRORS the count of errors detected.
BROKEN the count of broken connections (connections closed by the client)
FILTER the name of the Rexx filter.
HOST_NICKNAME the "host nickname" assigned to this "host" If no host nicknames are assigned, returns a ''
GMTOFFSET the GMT offset (in seconds).
LASTADDRESS IP address (numeric) of the most recent client
LASTACCEPT timestamp of the last accepted connection [format: yyyy.mm.dd hh:mm:ss].
LASTIDLE timestamp of when SRE2001 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 SRE2001.CMD).
LASTSECOND time now, in the same format [yyyy.mm.dd hh:mm:ss] as the other LASTxxxx items.
LASTSTART timestamp of when this instance of SRE2001 was started [format: yyyy.mm.dd hh:mm:ss].
LASTRESET timestamp of last RESET ALL "CONTROL" command [format: yyyy.mm.dd hh:mm:ss].
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.
LIMITBODY Connection specific maximum size of request body (as sent by a POST or PUT request), in kB
LIMITBODY_DEFAULT Default value of LIMITBODY
LIMITCLIENTS maximum number of client connections allowed concurrently [1 through 200 -- to increase max size, set the MAXCLIENTS value in SRE2001.CFG).
LIMITHEADER Maximum size of headers (including the request line), in kB
LIMITTIMEINACTIVE Connection specific maximum time, in seconds, for which SRE2001 will allow a client to remain connected but inactive (that is, without sending or reading data) [0 through LIMITTIMETOTAL].
LIMITTIMEINACTIVE_DEFAULT The default value of the above.
LIMITTIMETOTAL Connection specific maximum time, in seconds, for which SRE2001 will allow a client to remain connected, even if active [LIMITTIMEINACTIVE through 1E+9].
LIMITTIMETOTAL_DEFAULT default value of the above
LIMITTIMEWAIT Connection specific maximum time, in seconds, for which SRE2001 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].
LIMITTIMEWAIT_DEFAULT default value of the above
LISTEN_SOCKET the socket bound to the http port. This is the socket that SRE2001 SOCKLISTEN's to
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.
PEAKCLIENTS the maximum number of clients that were connected simultaneously.
READWAITTIME average read wait time (seconds).
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'.
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 transaction # 115, request 1 would yield:
    REQUEST: 115A
    REQUEST_NUMERIC: 1151
For transaction # 4312, request 3 would yield:
    REQUEST: 4312C
    REQUEST_NUMERIC: 43123

REQUESTS the number of HTTP requests read since SRE2001 was started.
REQUEST_ERROR most recent connection error (for this connection) or '', if no connection.
RESPONSE_CODE the response code (i.e.; 200, 404, 301). If response not yet send, returns '000'.
RESPONSETIME average response time (seconds).
RESPONSEOVER number of connections over which RESPONSETIME and READWAITTIME have been averaged.
SELECTOR the selector string: the Universal Resource Indicator, as recieved from the client (that is, the leading / is retained, and without url unpacking)
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.
SERVERPORT the server's port number used for the connection (for example, 80 for default HTTP).
SERVERPROTOCOL always returns "http/1.1"
SERVERSOFTWARE the level of the server software (for example "SRE2001 ver 1.04"). This is the same as returned by the function calls SERVER() .
TRANSACTION the unique number for this transaction (connection). This is incremented as each client connects to the server. Note that each transaction may yield several requests (though not concurrently).
TRANSACTIONS the number of transactions since SRE-http was started.
Notes:

  • The following "GoServe EXTRACTABLE" variables are not supported.
    • GMTSET -- GMT MUST be available
    • FASTFILE -- Instead, see the REQ_CACHE* parameters in SRE2001.CFG
    • FASTFILTER -- Instead, see the REQ_CACHE* parameters in SRE2001.CFG
    • NETBUFFER -- May be supported later
    • TRACE -- Instead, see the AUDIT_ITEMS parameter in SRE2001.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 SRE2001.CFG) can be used to obtain much of this information.
  • Also note that the GOSERVE QUERY command is NOT supported by SRE2001.

REQFIELD: Read request headers
Reads one (or several) request header(s).

Syntax:
    avalue=reqfield(header_name,ith,id_info)

where:
header_name the name of a request header.
For example: "User-Agent", "Authorization", "If-Modified-Since", or "X-Option1"
Header_name is case insensitive
ith Optional. Ith instance of this header_name. If not speciifed, all instances of header_name will be concatenated and returned.
id_info Optional. Including the "id_info" (say, as supplied to the filter) will speed things up a bit.
Actually, header_name can be a space delimited list of names.
For example:
    oo=reqfield('TE ACCEPT-ENCODING')
Note that you can NOT combine "list of headernames" with "ith instance"

When asking for several headers, each header will be seperated by a '01'x character. Thus, in the above example you could use:
    parse var oo is_te '01'x accept_enc
to obtain the "TE" and the "ACCEPT-ENCODING" request headers.

Note:

  • If header_name='!ALL', then a list of all the request headers is returned

SRE_AUDIT: Write "audit messages"
Write a message to the audit file (or to the screen or pmprintf window)

Syntax:
    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
brief Optional. If 1, then write a "briefer" message (don't write time and process identifiers).

whereto should be a 3 character long string of 0's and 1's

  • character 1: audit file
  • character 2: pmprintf window
  • character 3: status screen
For example: 101 means write to audit_file and to screen

Special values of whereto:

  • ' ' = write to audit_file and to pmprintf (the default)
  • '0' = write to audit_file only
  • '1' = write to audit_file and to screen

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).

Syntax:
   status=SRE_COMMAND('ACOMMAND option')

where:

ACOMMAND can be one of:
ALIVE AUDIT CONTROL FILE HEADER NODATA READ REPSONSE SEND SET VAR
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:
   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 SRE2001 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:

  • RESET [BYTES] [REQUESTS] [RESPONSE] [TRANSACTIONS] [LIMITS] [ERRORS] [BROKEN] [ALL]

    The specified SRE2001 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.

  • 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 SRE2001 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 result string is either placed in a variable or returned to the client:

    4. If 'VAR' was specified, the result string is returned to the caller.
    5. 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).
    6. 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 options 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:
    vv=sre_command('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, SRE2001 will look for it in the SRE2001 working directory).

The optional keywords may be specified, in any order, and have the following effects:

  • CHUNK -- send the file using a chunked format
  • ERASE -- the file is a temporary file, and should be erased after being sent.
  • 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.
  • NOWAIT -- forces the current connection to be closed after any response is sent, even if a persistent connection had been requested.
  • 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.
  • TYPE xxx -- xxx is the "mimetype" of this resource. SRE2001 will include a Content-type response header that uses xxx.
    For example:
        type text/plain
    will cause SRE2001 to add a
        Content-type: text/plain
    response header.
  • NOCACHE -- prevents this FILE URI from being added to the request cache. See Appendix 2 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.
  • SRE2001 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 specify 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'
  • 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:
    vv=sre_command('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]')

where:
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 contains 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, SRE2001 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
and
    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 SRE2001.CFG (say, by running SRE2001 -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:
    1. 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).
    2. The status returned is either the number of bytes sent, or a negative error code.
    3. 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:
        vv=sre_command('STRING string',header)

  • The single string is returned to the client as a simple text/html response.
  • The header is optional. If included, it should be a short sentence to display at the top of the screen.
  • 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 the contents of a "variable" to the client.

    Syntax:
        ff=sre_command(' VAR [NOWAIT][CHUNK][QUICKPOST] [TYPE content-type ', varname]

    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:

    • NOWAIT -- forces the current connection to be closed after any response is sent, even if a persistent connection had been requested.
    • 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.
    • CHUNK -- send the contents of the variable using a chunked format
    • TYPE xxx -- xxx is the "mimetype" of this resource. SRE2001 will include a Content-type response header that uses xxx.
      For example:
          type text/plain
      will cause SRE2001 to add a
          Content-type: text/plain
      response header.
    Example (returning an HTML document to a Web client) :
      /* This is Rexx code */
      mydoc=' Hello world! '          /* may be large */
      stat=sre_command('var type text/html  ', mydoc)     
      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 6236
    • SRE2001 will generate a header automatically if the TYPE option is specified. You can also use the HEADER option of SRE_COMMAND to specify a content-type.
    • When using CHUNK, you should NOT include a content-length header, and you SHOULD specify a "transfer-encoding: chunked" header.
    • VAR is a "completion code"

    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.

    SRE_CACHE: Write/read entries in a cache
    Caches are used to store semi-permanent variables. Each cache is allocated a fixed number of slots (one slot per variable), As you add variables, eventually all the slots will be taken. At that point, a LRU (least recently used algorithim) is used to remove the oldest variables, thereby freeing up slots for new variables (about 30% of the oldest variables are removed during this "pruning").

    For example, SRE_CACHE is used to implement the MD5, Request, and IPNAME caches of SRE2001. Note that "queues" are also implemented in SRE2001 -- caches differ from queues in several ways: you can lookup specific entries, and an LRU algorithim is used to discard old values.

    Syntax:
        val=sre_cache(cache_name,action,varname,avalue,time_to_live,ownid)
    where
    cache_name The name of a cache.
    Examples of cache_names: MD5 IPNAME REQUEST
    action What to do. Possible actions include: CREATE RESET WRITE ADD READ PRUNE REMOVE STATUS LIST
    varname variable name to store in the cache.
    Case insensitive, and must NOT contain spaces.
    avalue value of this variable
    Time-to-live In fractions of a day, is the desired lifespan of the cache entry.
    This can be used to remove cache entries, even if they are not necessarily the "least recently used". It can NOT be used to protect a "least recently used" entry.
    Ownid Optional, it's the "id" of the caller. Or, set to 0 to mean "don't bother responding" (typically used with action of WRITE or ADD)
    The supported "actions" are:
    CREATE create a cache
    varname should be the length of the cache.
    If varname is not specified, a default size of 500 is used. Returns: 1 on success
    RESET clear all items in acache.
    If varname is specified, reset the size of the queue to varname.
    Returns: 1 on success
    WRITE create, or change value of, varname; using avalue
    Returns either 'OK 'value or 'ERROR 'error_message
    ADD create a numeric variable, or add avalue to existing numeric variable
    Returns either 'OK 'value or 'ERROR 'error_message
    Note that if you try to ADD to a non-numeric value, an error occurs.
    READ return the value of avar. If avar is not defined, return avalue (if avalue is not specified, return ' ').
    Returns the value
    PRUNE remove 30% of the cache, using a LRU algorithim
    Returns 'Ok 'Num_left_in_cache
    REMOVE remove the entry for varname. REMOVED entries are deleted when a PRUNE is issued (till then, they just occupy space, but are not read)
    Return 'Ok removed' or 'Error no entry'
    STATUS returns 1 line of status info:
    'Active_entries='nactive', Max_entries='cache_size', Last_reset='last_reset
     
    LIST xxx returns list of items in a cache. Syntax depends on the value of xxx:
    If xxx=' '
       #entries_in_cache (crlf)
       varname','last_read_timestamp','expiration_time','#reads','value (crlf)
       ...
    IF xxx='VAL'
       #entries_in_cache (crlf)
       value (crlf)
       ...
    IF xxx='VAL'
       #entries_in_cache (crlf)
       varname (crlf)
       ...
    
    IF xxx='BOTH'
       varname','value (crlf)
       ...
    
    IF xxx='THREE'
       varname','#reads','value (crlf)
       ...
    
    
    Note: if you specify a varname, it will be used as a seperator. For example, using '09'x will use a TAB as a seperator (this is useful if you have multiple line values stored in the cache). There is one proviso: you can not use '01'x as a seperator.
    Examples:

    • goo=sre_cache('REQUEST','WRITE','REQ1','foo/bar/hello',0.1,0)
    • aval=SRE_CACHE('REQUEST','READ','VAR1',,,own_id)

    SRE_QUEUE: Write/read entries in a queue
    Queues are used to store semi-permanent variables. Each queue is allocated a fixed number of slots (one slot per variable), As you add variables, eventually all the slots will be taken. At that point, a LIFO (last in first out) algorithim is used to free up space -- with one value removed. Items on a queue are NOT referenced by variable name, though they can be read by position number (however, this position number will change as items are added to the queue).

    For example, SRE_QUEUE is used to implement the various statistics reported on SRE2001's status screen.

    Note that "caches" are also implemented in SRE2001 -- see SRE_CACHE for the details.

    Syntax:
        val=sre_queue(queue_name,action,avalue,ownid)

    where:
    queue_name The name of a queue.
    Examples of queue_name: BYTES TOTAL_TIME START_TRANSMIT_TIME
    action Possible actions: CREATE RESET PUSH QUEUE POP PEEK READ STATUS LIST
    avalue A value to store. If you intend to use SRE_QUEUE_STATS on this queue, these values must be numeric.
    ownid optional, it's the "id" of the caller. Or, set to 0 to mean "don't bother responding" (typically used with action of PUSH or QUEUE)
    The supported actions are:
    CREATE create a queue aval is the length of the queue. If aval is not specified, a default of 600 is used. Returns: 1 on success
    RESET clear all items in aqueue If avalue is specified, reset the size of the queue to avalue. Returns: 1 on success
    PUSH add aval to top of queue (will be first out on a pop) Returns either 'OK 'value or 'ERROR 'error_message
    QUEUE add aval to bottom of queue (will be last out on pops) Returns either 'OK 'value or 'ERROR 'error_message
    POP pop top value from queue (remove the value). If queue is empty, return '' or the value of aval.
    PEEK look at top value from queue (do not remove) If queue is empty, return '' or the value of aval.
    READ nnn look at the nnn'th value from queue; where 1 is the bottom value (the last value before queue is emptied)
    STATUS returns 1 line of status info:
    '#_entries='nentries', Max_entries='queue_size
    LIST returns list of queues, using
        #entries_in_queue (crlf)
        value (crlf)
        ...
    Examples:
        foo=sre_queue('REQUEST','QUEUE',request_line,0)
        nextval=sre_queue('DELETEME','POP')

    SRE_QUEUE_STATS: Compute statistics on values stored in a queue
    SRE_QUEUE_STATS is used to compute simple statistics on values stored in a queue. Of course, this should only be used with queues that are known to contain ONLY numeric values!

    Syntax:
        val=sre_queue_stats(queue_name,action,nentries,ownid)

    where:
    queue_name name of queue. Examples include: BYTES TOTAL_TIME START_TRANSMIT_TIME If the queue_name doesn't exists, error
    action stat to compute. Currently supported: NUM MEAN MAX MIN SD SUM.
    If nentries specified, NUM is <= NENTRIES
    nentries Number of entries to use. If not specified, then use all entries available in the queue.
    ownid optional.
    Examples:
        foo=sre_queue_stats('TOTAL_TIME','MEAN',100,own_id)

    SRE_REQUEST_INFO
    Read "id" info for a request.

    Syntax:
        aval=sre_request_info(avar,tid,ownid)

    where:
    avar variable to lookup
    tid optional. The request identifier. If not specified, lookup info for the current request. Or, the tid can be the "id_info" (provided as the 5th argument to the filter) -- using this can speed up processing a bit.
    ownid optional. The caller's "own id". This can speed up some lookups a little bit.

    Supported variables include:
    CLIENT return client ip address of this request
    OWN return "own id" of this request
    TRAN return transaction id of this request
    NTH the transaction number (which will be the same for maintained-connection requests)
    SOCK socket of this request
    HOST host name
    SEL selector
    START starttime (date & second)
    PARENTID the thread id of this requests "parent" (a transaction daemon)
    Note that these are "abbreviation matches". For example, CLIENTADDR is the same as CLIENT

    Example:

  • parse value sre_request_info(,'CLIENT SOCK START ') with aclient ',' asock ',' started_at
  • Notes:

    • If tid is not specified, look up info from the current request. This assumes that sre_request_info is called as part of "request processing", and NOT as part of a non-request related daemon.
      Otherwise, it must be the thread-id of a currently-active request daemon (NOT the thread id of a transaction daemon).
    • You can specify multiple variables names (in a space delimited list) -- a comma (",") delimited list of values will be returned (in the order specified).

    SRE_SAY Write to lines 18 to 23 of the status scrren.
    Example:
        call sre_say("this is my message to you, rudy. ")

    SRE_COUNTVARS: set and get "counter" variables
    This is used to set global counters variables (such as a running count of bytes sent). Several special counter variables are stored in the OS/2 environment for quick (though not totally up-to-date retrieval).
    These "quicklist" variables are: BYTESREADTOTAL BYTESSENTTOTAL TRANSACTIONS REQUESTS LIMITS ERRORS CACHEHITS

    Syntax:
        foo=sre_countvars(varname,avalue,ownid)

    where:
    varname the counter variable. If you begin varname with a "=" (without the ") then "force" a read from the cache (rather then from the enviroment) -- this only applies to the quicklist variables.
    avalue the value to add If avalue is not specified, then return current value of varname
    If avalue = RESET, then reset the counter to 0.
    ownid optional, the clients "own_id". This is used ONLY if you are reading the value of a non "quick list" counter. If not specified, an own_id will be generated automatically.

    SRE_HOSTINFO: read & set host information
    SRE_HOSTINFO is used to read the host-nickname and default data directory for a host name. Host names are typically domain names (such as foo.bar.net), but they can also be dotted IP addresses (such as 125.221.51.2), or "intranet" addresses (such mymachine).

    To support multi-hosting (one server supporting multiple domains), SRE2001 uses the idea of a "host nickname". Every request is compared against the list of defined hosts. If a match is found, the host-nickname and the default data diretory are returned. The filter can then use this information to determine where to get a file from, where to store logging information, etc etc etc.

    Although SRE2001 supplies the filter with this information (see section 5a), you can also use SRE_HOSTINFO to look it up. Furthermore, although you can use the INITHOST.RXX INIT_PROC (see INITHOST.RXX in the BIN subdirectory) to define Host entries, you can also use SRE_HOSTINFO.

    SRE_HOSTINFO has two modes: read and set.

    • READ: To search for a matching, use
         match=sre_hostinfo(a_host)
      If a match is found, the following is returned:
         a_host,host_nickname,default_datadir
    • SET: To add a host entry to the list of hosts, use
          astat=sre_hostinfo(a_host,host_nickname,default_datadir)
      For example:
          astat=sre_hostinfo("MYSITE.FOO.ORG","MYSITE_X",'E:\WEBS\ME")
      ASTAT will be 1 if success, 0 if falure.
    You can also get the list of currently defined host using hinfo_list=sre_hostinfo('!LIST') -- a space delimited list of hosts are returned (you can then lookup each host using calls to SRE_HOSTINFO)

    SRE_EVENTVARS: set and get "event" variables
    This is used to store event variables.

    Event variables are variables whose value changes frequently (such as the time the most recent connection was accepted). These are NOT necessarily numeric values (i.e.; it could be a timestamp, or a client a IP address).
    As with Counter variables, a "quicklist" is maintained of events that are also stored in the environment.
    These are: LASTACCEPT LASTIDLE LASTRESET LASTADDRESS

    Syntax:
        foo=sre_eventvars(varname,avalue,ownid)

    where:
    varname the event variable. If you begin varname with a "=" (without the ") then "force" a read from the cache (rather then from the enviroment) -- this only applies to the quicklist variables.
    avalue the value to store If avalue is not specified, then return current value of varname
    ownid optional, the clients "own_id". This is used ONLY if you are reading the value of a non "quick list" event. If not specified, an own_id will be generated automatically.
    Notes:

    • One could also use SRE_VALUE for event-like variables

    SRE_TRACKIT: set and get "tracking" variables
    Syntax:
        aval=sre_trackit(varname,avalue,record_id,record_name,ownid)

    where
    varname the "tracking" variable to set/get
    value the value. If '', then "get" value; otherwise set the value
    record_id the id of the record to read variables from. If not specified, use the current thread id.
    record_name optional. Record_name if included, will be compared to the "assigned name" for this "record" -- an error is returned if there is no match.
    ownid optional. You can include this "ownid" if READING tracking info from a request thread (i.e.; from a filter) Or, set to 0 to suppress reply (i.e.; on !CLEAR or a variable set)
    Notes:
    • To set "record_name", use either:
      1. foo=sre_trackit('!NAME',assigned_id,record_name)
      2. foo=sre_trackit('!INIT',assigned_id,record_name)
    • Special Varnames include:
      • !INIT = initialize a record (possibly with a record_name)
      • !CLEAR = clear all variables assigned to record
      • * = list variables
      • ** = list variables and their values (crlf delimited list)
      • !NAME = set the "record_name" of this record
    • Multiple variable names. You can set, or read multiple variables on a single call. To do this, use a space delimited list of varnames.
      Setting : if setting multiple variables, use a space delimited list of values. Thus, setting multiple variables can only be used with "1 word values"
      Reading when reading multiple variables, each value will be seperated by a crlf ('0d0a'x). Thus, you read have multiple word values, but not multiple line values.
      Thus, if you want to set multiple word (or multiple line) values, you can must do it one variable at a time. Similarly, you must read multiple line values one variable at a time.
    • Special record_id
      • * = list all active record_ids (space delimited list)
      • ** = list all record ids, and currently defined variables Each record & varnames-for-record are on a seperate (CRLF delimited) line. List of varnames are space delimited.
      • *** = list all record ids, and currently defined variable and their values. Each record's variables/value pairs are in a block of lines, with each block seperated by a blank line.
        Thus, the structure is
           record_id
           var1 = val1
           var2 = val2
           ..
           varn = valn
              record_id
           etc.
    Examples:
    • foo=sre_trackit('READHEAD','END' ,mytid,mytid,0)
    • foo=sre_trackit('VAR1 VAR2 ','125 MARS',25)
    • aval=sre_trackit('VAR10',,,,ownid)

    SRE_WRITE_MESSAGE
    Write a message string (up to 2 lines, 70 characters per line) to the SRE2001 status screen message area).

    Example:
        call sre_write_message(' Hello cruel world? ')

    SRE_WRITE_ERROR
    Write an error message (up to 2 lines, 70 characters per line). This will be written to
    1. the SRE2001 status screen "error messages" area
    2. the PMPRINTF window
    3. the ERRORS.LOG file
    Example:
        call sre_write_error('Foo1: got a BAR error')

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

      Copyright 2000,2001 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 SRE2001 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, SRE2001 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 SRE2001. In other words,
                you may need to choose a different server.
    
      Furthermore you may also charge a reasonable re-distribution fee for
      SRE2001; 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.
    
       Lastly, if you would like to modify SRE2001, please contact the
       authors for the source code (Daniel Hellerstein, danielh@crosslink.net).
    

    Appendix 2: The SRE2001 request cache

    The SRE2001 "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 SRE2001 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 substantially 
    quicker -- 50% time savings are not uncommon.
    
    Entries are automatically created in the request cache when:
    
      1. SRE2001 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 ..
    
       * set the maximum size of the cache (a Least Recently Used algoritihim
         is used to remove old entries)
       * set the level of auditing -- either by calling the filter anyways, or
         by using a "cache hit log"
       * enable checking of request headers to determine whether or not the
         cache should be checked.
    
    Please see the description of these REQ_CACHE* parameters (in section 4) 
    for the details.
    

    Appendix 3: Running SRE2001 in loopback mode

         The following description is taken from the GoServe
         documentation, with a few minor changes.
    
    SRE2001 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 SRE2001, 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 SRE2001 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 (say, by running TCPCFG or TCPCFG2 from a command prompt). 
    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 SRE2001 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 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 SRE2001 will:
    
      1. first call the FAST_FILTER.
      2. if the fast filter is able to handle the request, SRE2001 exits (or
         waits for the next request on a maintained connection)
      3. otherwise, SRE2001 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 SRE2001 as to whether it
    was successful or not.
    
    To do this, the fast filter should return either:
       0    not successful -- the normal filter should be called
    
       1    success. SRE2001 can close the connection, or wait for next
            request on a maintained connection
    
    An example of a fast-filter, FASTFILT.RXX, is included with SRE2001.
    

    Appendix 5: Tracking client status

    When enabled (with the TRACKING_ON parameter), SRE2001 will maintain
    information on the current status of each client. This information is
    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 SRE2001
    "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 SRE2001.
    
       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:
    
                         PENDING Waiting to read
                         ACTIVE  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
                      timeout  timeout occurred on most recent send
                       broken  client broke the connection
                       error   error when sending
                         ok    piece succesfully sent
    
       SENDPIECES     # of pieces sent
                            0     -- send mode not activated
                            START -- send mode activated
                            END   -- send mode completed
                            number -- number of pieces sent
    
       STATUS         Current action being undertaken.
    
                      STATUS may take the following values:
                          START
                          ERROR_CONN_CLOSE
                          ERROR_LIMIT
                          WAITING 
                          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)
                          SNIPE   (ALT-s "sniping" is currently active)
    
       TRANSACTION    the transaction
    
    In addition, you can set your own "connection specific" values by using
    SRE_TRACKIT.