A Server.t represents a TCP server listening on a socket.
close t starts closing the listening socket, and returns a deferred that becomes
determined after Fd.close_finished fd on the socket's fd. It is guaranteed that
t's client handler will never be called after close t. It is ok to call close
multiple times on the same t; calls subsequent to the initial call will have no
effect, but will return the same deferred as the original call.
With ~close_existing_connections:true, close closes the sockets of all existing
connections. close does not (and cannot) stop the handlers handling the
connections, but they will of course be unable to write to or read from the socket.
The result of close becomes determined when all the socket file descriptors are
closed and the socket's fd is closed.
close_finished becomes determined after Fd.close_finished fd on the socket's fd,
i.e. the same deferred that close returns. close_finished differs from close
in that it does not have the side effect of initiating a close.
is_closed t returns true iff close t has been called.
Options for server creation:
backlog is the number of clients that can have a connection pending, as with
Unix.Socket.listen. Additional connections may be rejected, ignored, or enqueued
anyway, depending on OS, version, and configuration.
max_connections is the maximum number of clients that can be connected
simultaneously. The server will not call accept unless the number of clients is
less than max_connections, although of course potential clients can have a
connection pending.
on_handler_error determines what happens if the handler throws an exception. The
default is `Raise. If an exception is raised by on_handler_error (either
explicitely via `Raise, or in the closure passed to `Call) no further
connections will be accepted.
create where_to_listen handler starts a server listening to a socket as specified
by where_to_listen. It returns a server once the socket is ready to accept
connections. The server calls handler address socket for each client that
connects. If the deferred returned by handler is ever determined, or handler
raises an exception, then socket is closed.
The server will stop accepting and close the listening socket when an error handler
raises (either via `Raise or `Call f where f raises), or if close is
called.
create where_to_listen handler is a convenience wrapper around create_sock that
pass a reader and writer for the client socket to the callback. If the deferred
returned by handler is ever determined, or handler raises an exception, then the
reader and writer are closed.
buffer_age_limit passes on to the underlying writer option of the same name.
listening_socket t accesses the listening socket, which should be used with care.
An anticipated use is with Udp.bind_to_interface_exn. Accepting connections on
the socket directly will circumvent max_connections and on_handler_error,
however, and is not recommended.
set_drop_incoming_connections configures whether each incoming connection will be
immediately dropped or not. This is a hack to effectively get a "pause listening"
feature. We can't reliably use backlog and max_num_connections to reject
incoming connections. For example, if we reach max_num_connections, we won't call
accept but OS might still establish TCP connection. The client will see the
connection as established but no data will be exchanged and we'd have to rely on TCP
retransmit timeouts to close the connection. In many cases we would prefer to
accept and then immediately close the connection. This is an intermediate solution
until we do a more principled solution (but much more complicated) when we close the
listening socket and then later bind and listen again when we decide to unpause
the server.
drop_incoming_connections is set to false.