Module Netcgi_jserv


module Netcgi_jserv: sig .. end
AJP Connection management

type t 
The type of an AJP server

type auth = {
   auth_challenge_length : int; (*The length of the challenge*)
   auth_secret : string; (*The shared secret (password)*)
}
Authentication record
type controlpipe = [ `Allocate | `Descriptor of Unix.file_descr | `None ] 
The type of the control pipe
exception Server_is_down
The AJP server is not connected with the web server
exception Signal_shutdown
The web server signals to shut down the AJP server
exception Signal_restart
The web server signals to restart the AJP server
val server_init : ?backlog:int -> ?reuseaddr:bool -> Unix.inet_addr -> int -> Unix.file_descr
Initializes the AJP server by listening on a TCP port. The inet_addr is the address to listen on (e.g. Unix.inet_addr_any), and the integer is the port. The function returns the file descriptor of the master socket.


backlog : Length of the backlog queue (connections not yet accepted by the AJP server)
reuseaddr : Whether to reuse the port
val server_loop : ?controlpipe:[ `Allocate | `Descriptor of Unix.file_descr | `None ] ->
?onrestart:(t -> unit) ->
?onshutdown:(t -> unit) ->
?select_accept:(Unix.file_descr list ->
Unix.file_descr ->
Unix.file_descr list * Unix.file_descr option) ->
?allow_hosts:Unix.inet_addr list ->
(t ->
auth option ->
Netchannels.in_obj_channel -> Netchannels.out_obj_channel -> unit) ->
auth option -> Unix.file_descr -> unit
Accepts connection coming from the web server on the file_descr, and calls the connection handler.

The connection handler is the function

 t -> auth option -> in_obj_channel -> out_obj_channel -> unit 
where The connection handler serves the complete connection, and must close the two channels when it is done. It can return normally, but it is also possible to raise the following exceptions:

There is an alternate way to indicate these two signals for multi-threaded servers, i.e. for servers that create a new thread for every connection. Obviously, it is not possible to raise the mentioned exceptions, as the thread context is different. The work around is to call Netcgi_jserv.signal_restart and Netcgi_jserv.signal_shutdown.


controlpipe : The control pipe is used to indicate "restart" or "shutdown" when the request handler is running in another thread or process than the server loop. The default is `Allocate and means that a new control pipe is allocated. The value `None means that no control pipe is created, and as a consequence, that the functions signal_restart and signal_shutdown will not work. The value `Descriptor means that the functions signal_restart and signal_shutdown write their messages to this descriptor, but the server loop ignores any messages.
onrestart : this function is called when a "restart" is performed. The default is (fun _ -> ())
onshutdown : the function is called when a "shutdown" is performed. The default is (fun _ -> ())
select_accept : This function is called when the server waits until a file descriptor becomes readable, and when it waits until a new connection begins. The function has two arguments: First the list of file descriptors to wait for, and second the master socket it listens to. The function must block until one of the file descriptors in the list becomes readable, or there is a new connection (or both). The result is a pair; the left component is the list of file descriptors that are readable, and the right component is the new slave socket for the connection (or None). The default is:
   (fun sel sock -> 
      let sel',_,_ = restart (Unix.select (sock::sel) [] []) (-1.0) in 
      let sel'' = List.filter (fun fd -> fd <> sock) sel' in
      let slave = 
        if List.mem sock sel' then 
          Some(fst(restart Unix.accept sock))
        else
          None in
      (sel'', slave)
   )
   
(where restart handles EINTR errors from Unix.select).

Note that even the select_accept function is allowed to raise the exceptions Signal_shutdown and Signal_restart.

allow_hosts : The list of IP addresses that are allowed to connect to this service. The empty list (the default) means that any address is allowed. (Net masks are not supported)
val server : ?backlog:int ->
?reuseaddr:bool ->
?controlpipe:controlpipe ->
?onrestart:(t -> unit) ->
?onshutdown:(t -> unit) ->
?select_accept:(Unix.file_descr list ->
Unix.file_descr ->
Unix.file_descr list * Unix.file_descr option) ->
?allow_hosts:Unix.inet_addr list ->
(t ->
auth option ->
Netchannels.in_obj_channel -> Netchannels.out_obj_channel -> unit) ->
auth option -> Unix.inet_addr -> int -> unit
The function server simply calls server_init first to get the file descriptor from the port specification, and it then calls server_loop to process the requests.
val signal_restart : t -> unit
Signals the server that a "restart" must be done. This works only if signal_restart is not called from the same thread as the server! If it is called from the same thread, signal_restart will block infinitely.
val signal_shutdown : t -> unit
Signals the server that a "shutdown" must be done. This works only if signal_restart is not called from the same thread as the server! If it is called from the same thread, signal_restart will block infinitely.
val read_control_pipe : Unix.file_descr -> 'a
Reads the next message from the control pipe, and raises either Signal_restart or Signal_shutdown. It is also possible that the function raises End_of_file. It is not possible that the function returns normally.
val random_8bits : unit -> int
Returns the next byte of the PRNG
val prng_init : ?lock:(unit -> unit) -> ?unlock:(unit -> unit) -> string -> unit
Initializes the PRNG and seeds it with the passed key.

lock, unlock: By default, the PRNG is not reentrant. This can be changed by passing a mutex as follows:

     let mutex = Mutex.create() in
     let lock() = Mutex.lock mutex in
     let unlock() = Mutex.unlock mutex in
     prng_init ~lock ~unlock seed; 

val prng_init_from_file : ?lock:(unit -> unit) ->
?unlock:(unit -> unit) -> ?length:int -> string -> unit
Initializes the PRNG and seeds it with the contents of the passed file. Only the first ~length bytes of the file are used (or fewer if the file is shorter). length defaults to 256. For some operating systems, there is a device /dev/random that can easily be used to seed the PRNG:
   prng_init_from_file ~length:8 "/dev/random" 

lock, unlock: same meaning as in prng_init.

val parse_properties : string -> (string * string) list
Parses a property file and returns it as alist
val jvm_emu_main : ((string * string) list ->
auth option -> Unix.inet_addr -> int -> unit) ->
unit
This function fakes the "java" command (JVM startup). It interprets Sys.argv as follows: The property file is parsed, and the following properties are used: Other properties are ignored.

Finally, the passed function is called. The first argument is the property list, the second argument is the authentication record (or None), the third argument is the inet_addr ("bindaddress"), and the fourth argument is the port. The task of this function is to set up the server socket and to accept incoming connections.


Example

A simple single-threaded server looks as follows:

 let onconnect srv =
   Netcgi_jserv_ajp12.serve_connection
     (fun zone servlet env -> ... )
 in
 jvm_emu_main
   (fun props auth addr port ->
      server 
        ~onrestart 
        ~onshutdown
        onconnect 
        auth 
        addr
        port);;