module Rpc_server:RPC serverssig
..end
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.
exception Connection_lost
type
t
type
session
type
connection_id
type
connector =
| |
Localhost of |
(* | 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. Note: The service is only locally reachable. | *) |
| |
Portmapped |
(* | The service is installed on every network interface; the port is chosen by the operating system; the program is registered with the portmapper | *) |
| |
Internet of |
(* | The service is installed on the passed interface/port combination. Use Unix.inet_addr_any to listen on all network interfaces. Use port 0 to automatically choose the port number. | *) |
| |
Unix of |
(* | 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 |
(* | The service listens on the given file descriptor. | *) |
| |
Dynamic_descriptor of |
(* | The service listens on the returned file descriptor. | *) |
type
binding_sync = {
|
sync_name : |
(* | procedure name | *) |
|
sync_proc : |
(* | the function that implements the procedure | *) |
type
binding_async = {
|
async_name : |
(* | procedure name | *) |
|
async_invoke : |
(* | A function that is called when the procedure is called | *) |
type
binding =
| |
Sync of |
(* | bind a synchonous procedure | *) |
| |
Async of |
(* | bind an asynchonous procedure | *) |
val create : ?program_number:Rtypes.uint4 ->
?version_number:Rtypes.uint4 ->
Unixqueue.event_system ->
connector ->
Rpc.protocol ->
Rpc.mode -> Rpc_program.t -> binding list -> int -> t
create2
or one of its variants.
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:
connector
, protocol=Tcp
, mode=Socket
:
creates a classic TCP server socket that allows multiple
stream connections at the same timeconnector=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)protocol=Udp
, mode=Socket
:
creates a UDP server socket that allows serving multiple datagramsconnector = Descriptor _
the file descriptor is not opened by
this module and not closed. The other connector
s work automatically
regarding this point, i.e. descriptors are opened and closed as
necessary.
connector = Dynamic_descriptor
: The open descriptor is closed after use.
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 waiting connections if a classic Tcp server socket is used; other connection types ignore this number.
The optional arguments ?program_number
and ?version_number
override
the numbers specified in the passed program.
Notes on servers:
create
function may block if the connector is Portmappedclass type socket_config =object
..end
val default_socket_config : socket_config
class default_socket_config :socket_config
typemode2 =
[ `Multiplexer_endpoint of Rpc_transport.rpc_multiplex_controller
| `Socket of Rpc.protocol * connector * socket_config
| `Socket_endpoint of Rpc.protocol * Unix.file_descr ]
create2
:
`Socket_endpoint(proto,fd)
: Socket fd
is a connected socket
descriptor used for communication. proto
determines the
encapsulation; should be Tcp
for stream sockets and Udp
for
datagram sockets.`Multiplexer_endpoint m
: m
is an RPC multiplex controller.`Socket(proto, conn, config)
: Opens or uses a server socket
according to conn
. proto
determines the
encapsulation; should be Tcp
for stream sockets and Udp
for
datagram sockets. config
specifies configuration details.val create2 : mode2 -> Unixqueue.event_system -> t
mode2
argument. This kind of server
does initially not have any bindings.val bind : ?program_number:Rtypes.uint4 ->
?version_number:Rtypes.uint4 ->
Rpc_program.t -> binding list -> t -> unit
binding list
. If the portmapper
must be informed, this action is started (and continued in the
background). One can bind several programs in several versions to the
same server.val unbind : ?program_number:Rtypes.uint4 ->
?version_number:Rtypes.uint4 -> Rpc_program.t -> t -> unit
val bound_programs : t -> Rpc_program.t list
val get_event_system : session -> Unixqueue.event_system
val get_connection_id : session -> connection_id
val get_xid : session -> Rtypes.uint4
val get_socket_name : session -> Unix.sockaddr
val get_peer_name : session -> Unix.sockaddr
val get_conn_socket_name : connection_id -> Unix.sockaddr
val get_conn_peer_name : connection_id -> Unix.sockaddr
val get_server : session -> t
val get_main_socket_name : t -> Unix.sockaddr
val get_protocol : t -> Rpc.protocol
val get_srv_event_system : t -> Unixqueue.unix_event_system
typerule =
[ `Accept
| `Accept_limit_length of int * rule
| `Deny
| `Drop
| `Reject ]
val set_session_filter : t -> (Unix.sockaddr -> rule) -> unit
`Deny: TCP connections are immediately closed; UDP packets are dropped `Drop: The call is dropped (it does not allocate memory) `Reject: A response is sent back that the call is rejected (unauthorized) `Accept: The call is accepted without limitation (the default if no filter is installed) `Accept_limit_length(n,r): If the call is longer than n bytes, the rule r will be applied
The parameter of the filter function is the socket address of the client.
The intention of filters is to prevent denial of service attacks. A simple but good filter for TCP servers is set_filter srv (fun _ -> (`Accept_limit_length(n,`Deny)) which accepts messages up to n bytes without limit, and denies longer messages. n is the length of the longest sensible message.
For UDP servers, there is an implicit limit of 8000 bytes, so it is not necessary to care about this.
Another application is to restrict which systems can contact this server, based on the IP address of the client.
Note that this is not a protection against distributed denial of service
attacks.
val set_session_filter_2 : t ->
(Unix.sockaddr -> connection_id -> rule) -> unit
set_session_filter
, but the filter gets as second argument the
connection ID.val reply : session -> Xdr.xdr_value -> unit
NOTES:
reply
.
Unreplied calls do not allocate memory.reply
several times for the same
session.val reply_error : session -> Rpc.server_error -> unit
reply
, but an error condition is sent back to the caller.val set_exception_handler : t -> (exn -> unit) -> unit
NOTES ABOUT EXCEPTIONS:
val set_onclose_action : t -> (connection_id -> unit) -> unit
Descriptor
connectors when the socket should be closed
(for these connectors the socket is not closed by this module).
Note that this action only applies to closed connections. It will not be executed for closed sockets in general (closed master socket, closed datagram socket).
If several onclose actions are set, they will be executed in reverse
order.
val set_timeout : t -> float -> unit
val stop_server : ?graceful:bool -> t -> unit
graceful
: If true, the shutdown procedure is deferred until all
responses have been transferred back to the caller. This includes
any responses added to the message queue in the current callback.
New calls are not accepted.
val stop_connection : t -> connection_id -> unit
Descriptor
). Nothing happens for datagram-oriented
servers (mode = Udp).type
auth_result =
| |
Auth_positive of |
| |
Auth_negative of |
typeauth_peeker =
[ `None
| `Peek_descriptor of Unix.file_descr -> string option
| `Peek_multiplexer of
Rpc_transport.rpc_multiplex_controller -> string option ]
class type auth_method =object
..end
val set_auth_methods : t -> auth_method list -> unit
auth_none
.
If none of the methods apply, the call is rejected (Auth_too_weak).val auth_none : auth_method
get_user
will return "".val auth_too_weak : auth_method
val auth_transport : auth_method
val get_user : session -> string
val get_auth_method : session -> auth_method
val verbose : bool -> unit
val debug_internals_log : (string -> unit) option Pervasives.ref
val debug_service_log : (string -> unit) option Pervasives.ref
The verbose
function simply sets these functions.