M2Web 1.2 - MUMPS Web Server

MHTTP is a Web server based on M technology. As such it is written primarily in MUMPS (with a small amount of Assembler) to serve M data and processing over TCP/IP using HyperText Transfer Protocol (HTTP), the essential protocol of the World Wide Web.

Link to the M2Web Notebook to see a demonstration application and discussion of MHTTP with links to MUMPS and the World Wide Web.

Contents

Distribution

The distribution package is a self-extracting zip file which contains the following files:
 
TCPIP.EXE A zcall module 
TCPIP.ASM Assembler source for the zcall. 
HTTP.RSA A DTM routine archive that contains source for the server routines.
HTTP6.OBJ A DTM routine archive file containing routine object code for GBUF device handlers for use with DTM version 6.x. 
HTTP4.OBJ A DTM routine archive that contains DTM version 4.x object code for the device handlers. 
HTTP.GSA A DTM global archive that contains the ^http global. 
HTTP.DOC Documentation in Word 6 format. 
DEFAULT.HTM The VMTH home page. 
IMAGE\* Various images used in the home page. 
SOUNDS\* Various sounds used in the home page. 

Create a directory (c:\http is a good choice) and run "mhttp -d" from the DOS command line in that directory to decompress the file.

Disclaimer

This software is distributed "as is" without any warranty or guarantee : the user accepts any and all risks associated with its use. Neither the VMTH, nor the University of California will be held responsible for any problems that result from the use of this software. This software can be distributed freely to anyone, provided that all the materials listed above are included (including any source). This software may not be sold, and may not be incorporated into any commercial product without prior written consent.

Software Requirements and Installation

The MHTTP server should run under DT-MAX, versions 4.3 or later, although this version has only been tested with version 6.3-6.6. It requires FTP's PC/TCP kernel (or OnNet, if running in the Windows environment). I believe that any version of the kernel 2.04 or later will work, but this version was developed and tested with PC/TCP 4.0 (and OnNet 2.0). The Wollongong TCP/IP stack is NOT supported. The DTM license must be able to run a process for each HTTP device defined (but these do not count as user jobs).

The TCP/IP GBUF devices that the server uses must be defined in a contiguous range of numbers, such as 620-635. Plan to define at least 8 devices. The server is designed to handle up to 64 devices, but 24-32 devices is probably the practical limit. Specify these in the file where the other devices are defined (MUMPS.DEV, DTM.INI, etc.). For DTM version 6.x the definition would be:

 620: GBUF /svroutine="%mHTTP":bufsize=4

For DTM version 4.x it would be:
 620: GBUF /callmask=32861:svroutine="%mHTTP":bufsize=4

Also make sure that there are sufficient file devices (10-19) defined. Generally, there should be the same number of file devices as there are of HTTP devices.

Configure the DTM startup to load the TCPIP.EXE zcall , install the M routines from the *.RSA files with the %rload utility and load the ^http global from the HTTP.GSA file using %gload. Create the directory that will contain your DOS file web pages (e.g. c:\http), and define it as the default for the server. This can be done with the following M command:

set ^http("defpath","default",$znode)="c:\http"

Once configured, start the server with the following command:

 j start^%zHTTP(d1,d2,log):(name="WWW server")
where d1 is the first TCP/IP device, and d2 is the last. The log parameter is optional and is described below.

You will also probably need to configure PC/TCP kernel for more resources. Our server has the following parameters in the [pctcp kernel] section of the PCTCP.INI file:

large-packets=24
small-packets=48
tcp-connections=24
udp-connections=6
window=4380

The default configuration of the OnNet product should work fine.

Configuring the Server

The MHTTP server conforms to the HTTP 1.0 specification draft and supports the GET, HEAD and POST methods. One important limitation to note is that the server does not currently support META HTTP-EQUIV directives in HTML documents. There is an alternative means of providing response header information which is described below in the miscellaneous section. The server also will not maintain open connections to the client: the connection is closed as soon as the requested data is sent. This means that server-push dynamic updating is not supported.

By default, the server is configured to only deliver disk files. Additional configuration is necessary to integrate user M routines to process URLs. User routines that are called to process URLs can pass data back to the server (for transmission to the client) via a DOS file, a local variable (or array), or a global. The rtnhtml routine is provided to demonstrate how this is done.

The operation of the server is largely controlled by the ^http global. The global has the following structure:

^http("resource",resource) = Mroutine Defines "resources" to the server.

^http("defpath",resource,$znode) = path Defines file system paths for file system resources.

^http("trans",trans) = request_info Log of all requests to the server.

^http("nosec")=1 Disables security for all resource.

^http("types",code) = content_type Defines MIME content types.

HTTP Resources

The server attempts to match a request for a URL to a resource defined in ^http("resource"). It does this by seeing if the first piece of the URL (following the system name) is defined. If so, the associated M routine is called to process the URL. For example, if the following is defined:

^http("resource","routine")="^rtnhtml"

the rtnhtml routine will be called to process a URL such as http://www.server/routine/user/mycode. If the resource is not defined in ^http("resource"), it is assumed to reference the disk file system. Also, any URL that has no resource specified will be mapped to the "default" resource. Any disk file URL with a null last piece will have "default.htm" appended to it. Examples:

http://www.server/photo.gif becomes http://www.server/default/photo.gif

and

http://www.server/ becomes http://www.server/default/default.htm

URL-to-file mapping

Any disk file resource that is not in the default path must have its own path defined in ^http("defpath"). The server uses his structure to map URLs to the file system. For example, if the "images" resource has the following path defined:

^http("defpath","images",$znode)="c:\graphics\public\images"

then the URL:

http://images/jpeg/gorilla.jpg

will be mapped to the file:

c:\graphics\public\images\jpeg\gorilla.jpg

Any disk file resource that doesn't have its own path will have the default path prepended to it. For example, if the "images" resource is NOT defined, and the default path is:

^http("defpath","default",$znode)="c:\http"

then the above URL becomes:

c:\http\images\jpeg\gorilla.jpg

Security

The server has a security component that is dependent upon our user database and is therefore not useful in general. Server security has been disabled for this distribution, but it can be easily added back in if you have a defined policy and mechanism for handling it.

Transaction log

Every request to the server is logged in ^http("trans"). If the log parameter is specified during startup, the log will also contain the full request header and server response header. The log consists of a sequence of records, one for each request. Each record contains a number of tab delimited fields and has the following format:

^http("trans",seq_nr) = <ip_addr, h, user, request, ret_code, $zerr>

where:
 
ip_addr is the IP address of the client 
h is $H (converted to a decimal) 
user is the user id - always null when security is disabled. 
request is the method (GET, POST, etc.) followed by the URL 
ret_code is the HTTP response code 
$zerr is any error that might have occurred while processing the URL 

Currently, there are no utilities for exploring the log. There also is no mechanism for clearing out the log - it will grow indefinitely.

Type codes

The type codes defined in ^http("types") are used to translate file type extensions to MIME content types used in the response header. These codes are also used by resource M routines to tell the server what type of data is being returned. The codes can be expanded as necessary.

Miscellaneous

The server depends on some local variables that should not be altered (except for %sethead) or killed by user-defined M routines. They all begin with a "%" and are lower-case. Some locals that might be useful to programmers are:
 
%ip the client's IP address 
%agent the client's browser ID 
%referer the URL that pointed to the current URL 
%cookie Netscape specific data - check their web pages for details 

A special variable, %sethead, allows user-defined M code to specify response header information to be returned to the client. This variable may or may not be defined. If it is defined, it contents MUST be preserved, but can be appended to. Multiple lines must be separated with a CR/LF, and %sethead should not have a leading or trailing CR/LR. An example of its use is:

set %sethead="Expires: Fri, 15 Mar 1996 18:00:00 GMT"
As mentioned before, the META HTTP-EQUIV directives are not currently supported, but it would be feasible for a programmer to scan HTML files for these directive and place them in the %sethead local.

Theory of Operation

The HTTP server is a collection of M processes: a single master process and one agent process for every TCP/IP HTTP device. The master process constantly checks that all the agent processes are running (and starts any that aren't) and make sure that there is an active listen on the network. It retains ownership of all the TCP/IP devices that are not actively in use.

When an agent process starts, it passes a pointer to the device control block (of the TCP/IP device) to the zcall module. It then opens and initializes the device, passes ownership back to the master job, and sets a flag in the device block to indicate that the device is available for use. The agent process then waits for the device to become free.

The master process puts up the initial listen on the network. A procedure in the zcall module is called to handle all asynchronous events for the HTTP devices and detects when a connection is made. It then searches the device blocks for an available device, initiates a new listen on the first free device it finds and releases ownership (from the master job). The agent process which handles that device acquires ownership and waits for a connection. When the agent process detects a connection, it processes the HTTP request, closes the connection, reopens the device, returns ownership to the master job and flags it as available again.

Because the zcall event handler puts up a new listen as soon as an incoming connection is made, the HTTP server is able to maintain a perpetual listen state.

If an agent process should halt, the master server will restart it (within a about a minute). If the master job halts, all the agent jobs will also halt.

Edwin Clubb
UC Davis, VMTH Computer Services
egclubb@vmth.ucdavis.edu