module Procord_connection:sig
..end
Unix.stdin
for input and Unix.stdout
or
Unix.stderr
for output; or simulate a connection through pipes.type 'a
t
You may associate your own data with each connection.
Parameter 'a
is the type of the data that is associated with the
socket.
val connect : ?timeout:float ->
?ping:string -> string -> int -> 'a -> 'a t
Usage: connect ?timeout ?ping hostname port data
timeout
: If the connection has been idle (nothing received)
for timeout
seconds, disconnect automatically.ping
: If the connection has been idle (nothing received)
for timeout /. 2.
seconds, send this message automatically.
Ignored if timeout
is unspecified.val update : 'a t -> unit
type
state =
| |
Connecting |
(* | Waiting for the connection to be established. | *) |
| |
Connected |
(* | Connection successful and still alive. | *) |
| |
Disconnecting |
(* | Finishing sending, will be disconnected just after. | *) |
| |
Disconnected of |
(* | Connection failed, lost, closed or reset by peer.
If the error is None , the socket was closed locally.
The strings are, respectively, the name of the function which
failed and the string argument to the function, if any.
Warning: there may still be data to be | *) |
val state : 'a t -> state
update
.val alive : 'a t -> bool
Return true
if state
is Connecting
, Connected
or Disconnecting
.
Return false
if state
is Disconnected
.
val send : 'a t -> string -> unit
The data is put in the connection buffer.
Call update
regularly to ensure the data is sent eventually.
You may call send
while the connection is establishing.
The data will be sent eventually if you call update
.
You may call send
after the socket is disconnected, but nothing will
happen.
val receive : 'a t -> int -> string option
Usage: receive connection length
If at least length
bytes are available in the connection
buffer, return length
bytes (not more, not less). Else, return
None
.
Calling receive
while the connection is establishing returns None
.
Note that there might still be bytes to read even if the socket is
disconnected.
val receive_poll : 'a t -> int -> int -> string option
receive
, but do not remove the data from the buffer.
Usage: receive_poll connection offset length
If at least offset + length
bytes are available in the connection
buffer, return length
bytes (not more, not less) starting at offset
.
Else, return None
.
val receive_poll_part : 'a t -> int -> int -> string
receive_poll
, but may receive less data than requested.
Usage: receive_poll connection offset length
Return at most length
bytes starting at offset
in the buffer,
possibly 0
.
val receive_all : 'a t -> string
receive
, but receive everything.
Usage: receive_all connection
Receive everything which is available in the buffer, possibly nothing.
val receive_part : 'a t -> int -> string
receive
, but may receive less data than requested.
Usage: receive_part connection length
If at least length
bytes are available from the buffer, receive
length
bytes. Else, receive as much bytes as possible, possibly 0
.
val receive_forget : 'a t -> int -> unit
receive
, but do not actually return the received data.
This is more efficient if you do not need the data.
val receive_buffer_length : 'a t -> int
val receive_buffer_empty : 'a t -> bool
val close : 'a t -> unit
val close_nicely : ?timeout:float -> 'a t -> unit
Disconnecting
.timeout
: If specified, do not wait more than timeout
seconds.
As usual, the wait is non-blocking: call update
until the socket
is disconnected.
val data : 'a t -> 'a
val timeout : 'a t -> float option
timeout
argument which was passed to connect
or custom
.module Sync:sig
..end
val remote_address : 'a t -> Unix.sockaddr
val make_address : string -> Unix.inet_addr
type 'a
set
Sets are mutable lists of connections.
It could be argued that it would be easy to make this immutable.
However, there is only one set of connection at any given time; it
makes no sense to have several which live together. If a connection
is closed, it should not be used anymore. Having the set mutable
reflects this fact.
val empty_set : unit -> 'a set
val accept_into_set : ?timeout:float ->
?ping:string ->
Unix.file_descr ->
(Unix.sockaddr -> 'a option) -> 'a set -> unit
Usage: accept_into_set ?timeout ?ping socket make_data connections
Function make_data
is given the address of the remote peer,
and shall return Some data
where data
is the data to
associate with the connection, or None
to close the connection
immediately.
See Procord_connection.connect
for the meaning of timeout
and ping
, which
are applied to accepted connections.
May raise Unix_error (EBADF, ...)
.
val update_set : 'a set -> unit
val iter : 'a set -> ('a t -> unit) -> unit
Unix.select
can be tricky.
It is easy to give the wrong set of file descriptors, resulting in
unwanted delays or, on the opposite, the program using all the CPU.
This section provides facilities to call Unix.select
correctly
on sockets.
First, define a waiter
. You may do it once and for all for connections
using waiter
, even for servers using waiter_of_listening_socket
and waiter_of_set
. Then, just call wait
.
type
waiter
wait
function.val waiter : 'a t -> waiter
The waiter will wait on the socket:
Connected
;Connecting
(to detect connection
or errors) or if the socket is Connected
and there is something
to send;Connecting
(although
this may not be necessary) or if it is Connected
.update
on
the connection.val waiter_of_listening_socket : Unix.file_descr -> waiter
The waiter will wait on the socket for reading and for exceptional conditions.
In other words, it will wait until it is worth calling Unix.accept
on the socket.
val waiter_of_set : 'a set -> waiter
The waiter will behave as if waiter_of_list
was called on the list of
waiters for all connections of a set. This list may change as the
set grows and shrinks.
In other words, it will wait until it is worth calling update_set
on the set of connections.
val waiter_custom : ?read:Unix.file_descr list ->
?write:Unix.file_descr list ->
?except:Unix.file_descr list -> unit -> waiter
The waiter will wait:
read
;write
;except
.val waiter_of_list : waiter list -> waiter
The waiter will wait until one of the waiters in the list wants to
stop waiting.
val instanciate_waiter : waiter ->
Unix.file_descr list * Unix.file_descr list * Unix.file_descr list
Unix.select
from a waiter.
Allows you to call Unix.select
yourself.
val wait : ?timeout:float -> waiter -> bool
timeout
: If specified, stop waiting after timeout
seconds.
Return true
if something happened, false
in case of timeout.
val wait' : ?timeout:float -> waiter -> unit
wait
but ignore the result.val custom : ?timeout:float ->
?ping:string ->
?input:Unix.file_descr ->
?output:Unix.file_descr ->
?remote_address:Unix.sockaddr -> 'a -> 'a t
Similar to connect
, but instead of taking an address as input, take
file descriptors.
input
: The file descriptor to read or receive data from.
If unspecified, no data will ever be received.output
: The file descriptor to write or send data to.
If unspecified, data sent will be ignored.remote_address
: The address returned by remote_address
.
The default value is a dummy one, ADDR_UNIX ""
.