WASD Web Services - Scripting

11 - Raw TCP/IP Socket

next previous contents full-page

For detached and subprocess scripting the raw TCP/IP socket can be made available for scripts to transfer data directly to the client. The socket BGnnnn: device name is made available via the CGI variable WWW_GATEWAY_BG. This is enabled using the [DclGatewayBg] configuration directive. As it is a completely raw stream it cannot be used, and is not made available for SSL ("https:") encrypted requests.


Although one might imagine this direct transfer to be significantly more efficient than the standard script mailbox the test-bench indicates that to all purposes it provides a negligable improvement in throughput, even under high load. It probably only translates into measurable benefits for scripts producing large quantities of output (for instance hundreds of thousands or millions of bytes). For the average script the overhead of opening a stream to the raw TCP/IP device (which is not insignificant) and complications of the callout requirements isn't worth the effort. Still, it's there if someone wants or requires it.

The socket is created shareable between processes, and so a channel may be assigned by the script subprocess and have data written to it. The data is raw, in the sense the script must provide all carriage control, etc. All data transfered this way is outside of the server and so may not be WATCHed, etc.

The script must supply a full HTTP response. This means a NPH-style header (2.2.2 - Non-Parsed-Header Output) and body, with full carriage-control as required, etc. The server must be notified that the script is using the gateway device, by providing a CGI callout (6 - CGI Callouts) before any script output and after output is concluded. The first callout provides the response HTTP status code, the second the number of bytes transfered. These are also required for correct logging of the request. If a channel to the BG: device is opened it should always be closed when it is finished with. Failure to do so could lead to resource starvation for the server.

The WASD_ROOT:[SRC.OTHER]GATEWAY_BG_EXAMPLE.COM example script demonstrates the use of the raw socket from DCL. The priciples can be applied to any scripting laguage.

The following code fragment shows the essential requirements using the C language.

int  byteCount;
char  *gatewayBg;

/* see if there's a raw socket available */
if (gatewayBg = getenv ("WWW_GATEWAY_BG"))
   /* yes, begin a callout */
   fputs (getenv("CGIPLUSESC"), stdout);
   fflush (stdout);

   /* notify of script response and HTTP status */
   fprintf (stdout, "GATEWAY-BEGIN: %d", 200);
   fflush (stdout);

   /* reopen <stdout> to the raw TCP/IP device */
   if ((stdout = freopen (gatewayBgPtr, "w", stdout, "ctx=bin")) == NULL)
      exit (vaxc$errno);

byteCount = fprintf (stdout,
"HTTP/1.0 200 OK\n\
Content-Type: text/plain\n\

... processing to <stdout>
   e.g. byteCount += fprintf (stdout, "Hello world!\n");

if (gatewayBg)
   /* reopen <stdout> so that it's communicating via the mailbox again */
   if ((stdout = freopen ("SYS$OUTPUT:", "w", stdout, "ctx=rec")) == NULL)
      exit (vaxc$errno);

   /* continue callout, notify of request data transfered */
   fprintf (stdout, "GATEWAY-END: %d", byteCount);
   fflush (stdout);

   /* end the callout */
   fputs (getenv("CGIPLUSEOT"), stdout);
   fflush (stdout);

Carriage Control

By default the TCP/IP BG device driver supplies a <CR><LF> sequence as carriage control for each record. This supports record-oriented output such as DCL and various VMS utilities but is an issue when needing to output a binary object such as a large graphic. The CGI callout (6 - CGI Callouts) GATEWAY-CCL: directive allows the device carriage control to be set and reset programmatically. A value of 1 enables a <CR><LF> with each record, while 0 disables it. This is analagous to the APACHE$SET_CCL utility.

Not Supported?

Not all vendor's TCP/IP package BG drivers, or not all older versions, may support the C_SHARE option when creating sockets. Symptoms may range from it being ignored (and the script being unable to open a channel to the BGnnnn: device) to an error being reported as the socket is being created (and the server being unable to start at all). If this occurs merely disable the [DclGatewayBg] configuration option. Script output is of course still available via the standard script output mailbox.

For portability scripts that use the raw socket for output should always use a construct similar to the above example code so only to redirect output when the GATEWAY_BG device is indicated as available.

next previous contents full-page