#!/usr/local/bin/tops -s /usr/local/tops/sys -u /opt/mytops/usr/
{
   File tops_http
   February 2005

   Copyright (C) 2005  Dale R. Williamson

   Running the program as a daemon, this script listens on port 80 for 
   an HTTP request, forwards it to Apache web server running with these
   directives (directives are made in file /etc/apache/httpd.conf):
      BindAddress 127.0.0.1
      Port 9880
   and then sends the HTTP response to the requestor.
}
\-----------------------------------------------------------------------

   CATMSG push no catmsg

\-----------------------------------------------------------------------

\  Logging.

\  A log file is defined for SYSOUT using word set_sysout:
      "HOME" env "tops_http.log" catpath "LOG" book LOG set_sysout

\  Display some starting lines in the log file:
      "-" 80 cats nl dot nl
      "PID " getpid int$ cat spaced date cat dot nl

\  Make sure Apache is listening:
   ontheweb (f) 
   IF 9880 port_listening not
      IF " tops_http: halting; Apache server port 9880 is not listening"
         . nl HALT
      THEN
   THEN

\-----------------------------------------------------------------------

\  Words.

   "tops_http.v" filefound IF (qFile) source THEN
   "msgComm" missing IF "dog.v" source THEN
 
\  Word HTTPput is the default to service HTTP requests.  

\  In word HTTPput, define the HTTP provider and port (Apache web server
\  listening on port 9880, consistent with Apache directives shown      
\  above):
   ontheweb (f) 
   IF \ Apache on 127.0.0.1:9880:
      "127.0.0.1" "HTTPput" "PROVIDER" bank
      9880 "HTTPput" "PORT" bank
   ELSE "WSERVER" ptr "HTTPput" "PROVIDER" bank
      UDEF "HTTPput" "PORT" bank
   THEN

\  The following line defines this server as an HTTP server:
      0 "SERVE_F" "TYPE" bank \ HTTP type

\  Bank the ptr to the word that services HTTP requests into word 
\  SERVE_F, the word the program runs on every request to SERVER.
      "REQUESTrun" exists? 
      IF "REQUESTrun" 
      ELSE "HTTPput" (default) 
      THEN ptr (n)
      (n) "SERVE_F" "SERVICE" bank \ ptr to word that services requests

\  Use word APP_CLIENT_ALLOW and its default file, usrpath/ACCESS, to 
\  define hosts that are not allowed to connect:
      "APP_CLIENT_ALLOW" missing
      IF " APP_CLIENT_ALLOW not present.  Halting" . nl exit THEN

\  To hook word APP_CLIENT_ALLOW into the program, bank its ptr into 
\  word CLIENT_ALLOW, the word the program runs on every connect:
      "APP_CLIENT_ALLOW" ptr "CLIENT_ALLOW" "APP_CLIENT_ALLOW" bank

\-----------------------------------------------------------------------

   pull catmsg

   ontheweb (f)
   IF 80 ELSE 9880 THEN "PORT" book

   ontheweb (f)
   IF PORT "SERVER-CYCLE" "PORT" bank
      1 20 / "SERVER-CYCLE" PLAY 
   THEN
   NIST_SYNC
   4096 netrate

\  Start the server:
   "*" PORT DSERVER

   private halt

\-----------------------------------------------------------------------

   Word remoteprompt allows interactive work right on the stack of this
   running daemon.  

   Here is an example of connecting an instance of this program to the 
   daemon started above, and running word remoteprompt to virtually 
   move to the stack of the daemon (which is indicated by the prompt 
   tops@socket3 rather the ready prompt).  

   Different view points are displayed by word clients when it is run 
   at the ready prompt versus at the tops@socket3 prompt (the daemon 
   server).  The "Clients:" list on the daemon shows us connected on 
   socket 6 and a foreign client connected on socket 5 with an HTTP 
   request being served:

      [dale@clacker] /opt > tops
               Tops 2.4.3
      Tue Feb 22 23:18:05 PST 2005
      [tops@clacker] ready > IPloop 80 CLIENT "S" book
   
      [tops@clacker] ready > clients [our session]
       Server local is off
       Clients:
        socket 3, port  80, conn C>S, 127.0.0.1 dale clacker

      [tops@clacker] ready > S remoteprompt
      tops@socket3 > clients [now on SERVER]
       Server local is listening on port 80
       Clients:
        socket 5, port 32882, conn S<F, XXX.XX.148.191 GET /index.html HTTP/1.1
        socket 6, port 32884, conn S<C, 127.0.0.1 LOGIN dale clacker
      tops@socket3 > [pressing Esc-q returns to our session]

      [tops@clacker] ready > 

   Notes:
      C>S indicates us as a client connected to the server 
      S<C indicates this is a server with client (us, this program) 
         connected 
      S<F indicates this is a server with client foreign (not this
         program) connected
