Go to the first, previous, next, last section, table of contents.


The Rpc_server module

Rpc_server module:

Like the client, the RPC server module is programmed on top of the Unixqueue event system. It pushes itself on an existing Unixqueue as a new service that accepts RPC calls, forwards them to configurable functions, and sends the replies back. The server module can manage two kinds of RPC functions: synchronous and asynchronous. Synchronous functions compute their result immediately and thus the result can be sent back just after the evaluation of the function has finished. In contrast to this, asynchronous functions only get noticed about the call and need not to know immediately what should be answered. Typically, an asynchronous function initiates a second communication channel and its result depends on what happens on the second channel. The communication on this channel is done in an asynchronous way, too, and can be managed by the same event system that carries out the RPC service. After several input or output events, the result has somehow been computed, and the answer can be sent back to the original caller. To do so, the asynchronous RPC function invokes 'reply' together with the necessary session IDs that identify the answer among all answers.

open Rtypes
open Xdr
open Rpc
exception Connection_lost

raised by the 'reply' function if the connection to the original caller has been lost in the meantime.

type t

represents a server for an RPC program

type session

identifies a pair of a call and a reply

type connector =
    Localhost of int

The service is installed on 'localhost' and listens on the given port number. A number of 0 means that the port is chosen by the operating system

  | Portmapped

The service is installed on 'localhost'; the port is chosen by the operating system; the program is registered with the portmapper

  | Unix of string

The service is installed on a Unix domain socket. Note: the socket path must not exist when the server is started, and the socket must be unlinked when the server terminates.

  | Descriptor of Unix.file_descr

The service listens on the given file descriptor.

type binding_sync =
    { sync_name : string;                  (* procedure name *)
      sync_proc : xdr_value -> xdr_value   (* the function that implements the
					    * procedure
					    *)
    }	
type binding_async =
    { async_name : string;                 (* procedure name *)
      async_invoke : session -> xdr_value -> unit

A function that is called when the procedure is called

    }	
 	    
type binding =
    Sync of binding_sync     (* bind a synchonous procedure *)
  | Async of binding_async   (* bind an asynchonous procedure *)

val create : 
    Unixqueue.event_system   (* the underlying event queue *)
    -> connector             (* the address of the service *)
    -> protocol              (* Tcp: stream-oriented; Udp: datagram-oriented *)
    -> mode                  (* Socket: serve multiple connections/datagrams;
			      * BiPipe: serve only a single connection
			      *)
    -> Rpc_program.t         (* The specification of the program *)
    -> binding list          (* The procedures *)
    -> int                   (* maximum number of parallel connections *)
    -> t

Creates a new server that is pushed onto the event queue. The 'connector', 'protocol' and 'mode' values control the network type of the server. Note that not all combinations are valid; the following can be used: - any connector, protocol=Tcp, mode=Socket: creates a classical Tcp server socket that allows multiple stream connections at the same time - connector=Descriptor s, protocol=Tcp, mode=BiPipe: (where s is one half of a socketpair) creates a stream socket that is the endpoint of a point-to-point stream connection (bidirectional pipe) - any Internet namespace connector, protocol=Udp, mode=Socket: creates a Udp server socket that allows serving multiple datagrams

Note: If connector = Descriptor _ the file descriptor is not opened by this module and not closed. The other 'connectors' work automatically regarding this point, i.e. descriptors are opened and closed as necessary.

The 'Rpc_program.t' specifies the procedures that are available and their signatures. The 'binding list' should contain for every procedure name the function that handles calls of the procedures. The remaining integer is the maximum number of parallel connections if a classical Tcp server socket is used; other connection types ignore this number.

NOTES ON SERVERS: - servers that allow multiple connections never terminate by themselves (but you can force termination by raising an Abort exception, for example from a procedure) - servers for only one connection (endpoint of a bidirectional pipe) terminate if they see an EOF on the stream; in this case the stream is closed by the server - authentication is not yet possible - servers are not yet prepared for proper signal handling - servers are not yet prepared for multi-threaded environments - the 'create' function may block

val get_event_system : session -> Unixqueue.event_system

Find out the event system that contains the 'session'

val reply : session -> xdr_value -> unit

Asynchronous procedures can reply their results with this function. NOTES: - As with synchronous procedures, the transfer is not reliable since the connection may be broken at any time - If it is already known that the connection is down, a Connection_lost exception is raised.

val set_exception_handler : t -> (exn -> unit) -> unit

Sets the exception handler for the server. The exception handler gets most exceptions raised by the functions that are bound to procedures. The exception handler does not get Abort exceptions and any exceptions resulting from I/O problems.

NOTES ABOUT EXCEPTIONS: - The default exception handler just prints the exception on stderr. - I/O problems usually lead to an 'Abort' of the whole server.

val stop_server : t -> unit

raises an exception such that the server is stopped. Can be used from any procedure or from any signal handler.

val verbose : bool -> unit

Set whether you want debug messages or not

Caution! This function is not protected against concurrent invocations from several threads.


Go to the first, previous, next, last section, table of contents.