Link to the M2Web Notebook to see a demonstration application and discussion of MHTTP with links to MUMPS and the World Wide Web.
| 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.
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=4For DTM version 4.x it would be:
620: GBUF /callmask=32861:svroutine="%mHTTP":bufsize=4Also 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.
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("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
^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
^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.
| %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.
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