OGI is an acronym for "occam Gateway Interface". Functionally, it's much like a CGI (Common Gateway Interface), but instead of being an OS process (script, executable, whatever) it's an occam process network. When a request is made to the occam web-server for a CGI, it sets up an OS environment and runs that CGI. When a request is made for an OGI, the relevant file (shared library) is loaded into the running web-server and the new process attached and run. The web-server and the OGI communicate using occam channels (with a well-defined protocol).
Two occam protocols are defined for communicating with an OGI:
PROTOCOL OGI.LINK.IN IS CONNECTION; INT::BYTE: PROTOCOL OGI.LINK.OUT CASE persist; BOOL conn; CONNECTION :The OGI itself is defined with the following header:
PROC ogimain (VAL DPROCESS me, CHAN OF ANY x.in, x.out)This is the standard interface for all dynamic processes in occam. That is, a process desciptor (which OGIs will never need to use), an array of input channels and an array of output channels. The "actual" interface transported in this is extracted with the following re-typings:
CHAN OF OGI.LINK.IN in RETYPES x.in: CHAN OF OGI.LINK.OUT out RETYPES x.out:The incomming data is always a new request, held in the CONNECTION type, followed by any query-string passed (stuff after the ? in the URI). The outgoing link has two CASEs. The `persist' case should be sent as soon as possible, and indicates whether this OGI should remain loaded. For most simple things, this is probably best left as FALSE since there are a finite number of OGI handling processes in the web-server itself (to which OGIs attach). Once the request has been processed and results sent to the client, etc., the OGI should pass the CONNECTION back to the web-server with the `conn' output case.
Here is the complete code for the simple test OGI:
#INCLUDE "socklib.inc" #USE "sock.lib" #INCLUDE "httplib.inc" #USE "http.lib" #INCLUDE "dynproc.inc" #INCLUDE "../connection.inc" PROC ogimain (VAL DPROCESS me, CHAN OF ANY x.in, x.out) CONNECTION conn: BYTE q.str: INT q.size: CHAN OF OGI.LINK.IN in RETYPES x.in: CHAN OF OGI.LINK.OUT out RETYPES x.out: INT res: SEQ in ? conn; q.size::q.str out ! persist; FALSE CHAN OF HTTP.PROTO c: PAR http.process (c, conn[sock]) SEQ c ! init.ok VAL BYTE ct IS "text/html": c ! content.type; (SIZE ct)::ct c ! end.headers c ! begin.html c ! begin.head VAL BYTE ct IS "testing the OGI stuff": c ! title; (SIZE ct)::ct c ! end.head c ! begin.body VAL BYTE ct IS "hello world!": c ! html; HTML.H2; (SIZE ct)::ct c ! line.break VAL BYTE ct IS "The query string was [": c ! html; HTML.NONE; (SIZE ct)::ct IF q.size > 0 c ! html; HTML.TT; q.size::q.str TRUE SKIP c ! html; HTML.NONE; 3::"]*c*n" c ! end.body c ! end.html c ! finish out ! conn; conn :Most of this program is communicating with the `http.process', which provides a fairly simple way of generating HTML down a socket.