From d2318c0a286daf51b4fe8afc5c6a232eee71ca72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Mon, 25 Nov 2013 15:02:42 +0100 Subject: Add a manual This is the manual for what is going to be in 1.0. It includes two things that are not in the code yet: the shutdown option and the accept_ack transport callback. --- README.md | 4 +- manual/ranch.md | 171 ++++++++++++++++++++++++++++++++++++++++ manual/ranch_app.md | 28 +++++++ manual/ranch_protocol.md | 35 ++++++++ manual/ranch_ssl.md | 97 +++++++++++++++++++++++ manual/ranch_tcp.md | 47 +++++++++++ manual/ranch_transport.md | 197 ++++++++++++++++++++++++++++++++++++++++++++++ manual/toc.md | 11 +++ 8 files changed, 588 insertions(+), 2 deletions(-) create mode 100644 manual/ranch.md create mode 100644 manual/ranch_app.md create mode 100644 manual/ranch_protocol.md create mode 100644 manual/ranch_ssl.md create mode 100644 manual/ranch_tcp.md create mode 100644 manual/ranch_transport.md create mode 100644 manual/toc.md diff --git a/README.md b/README.md index fafd1cc..570d27d 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,9 @@ to close any of the currently opened sockets. Getting started --------------- - * [Read the guide](http://ninenines.eu/docs/en/ranch/HEAD/guide/) + * [Read the guide](http://ninenines.eu/docs/en/ranch/HEAD/guide) + * [Check the manual](http://ninenines.eu/docs/en/ranch/HEAD/manual) * Look at the examples in the `examples/` directory - * Build API documentation with `make docs`; open `doc/index.html` Support ------- diff --git a/manual/ranch.md b/manual/ranch.md new file mode 100644 index 0000000..cf4ebe5 --- /dev/null +++ b/manual/ranch.md @@ -0,0 +1,171 @@ +ranch +===== + +The `ranch` module provides functions for starting and +manipulating Ranch listeners. + +Types +----- + +### max_conns() = non_neg_integer() | infinity + +> Maximum number of connections allowed on this listener. +> +> This is a soft limit. The actual number of connections +> might be slightly above the limit due to concurrency +> when accepting new connections. Some connections may +> also be removed from this count explicitly by the user +> code. + +### ref() = any() + +> Unique name used to refer to a listener. + +Exports +------- + +### accept_ack(Ref) -> ok + +> Types: +> * Ref = ref() +> +> Acknowledge that the connection is accepted. +> +> This function MUST be used by a connection process to inform +> Ranch that it initialized properly and let it perform any +> additional operations before the socket can be safely used. + +### child_spec(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts) + -> supervisor:child_spec() + +> Types: +> * Ref = ref() +> * NbAcceptors = non_neg_integer() +> * Transport = module() +> * TransOpts = any() +> * Protocol = module() +> * ProtoOpts = any() +> +> Return child specifications for a new listener. +> +> This function can be used to embed a listener directly +> in an application instead of letting Ranch handle it. + +### get_max_connections(Ref) -> MaxConns + +> Types: +> * Ref = ref() +> * MaxConns = max_conns() +> +> Return the max number of connections allowed for the given listener. + +### get_port(Ref) -> Port + +> Types: +> * Ref = ref() +> * Port = inet:port_number() +> +> Return the port for the given listener. + +### get_protocol_options(Ref) -> ProtoOpts + +> Types: +> * Ref = ref() +> * ProtoOpts = any() +> +> Return the protocol options set for the given listener. + +### remove_connection(Ref) -> ok + +> Types: +> * Ref = ref() +> +> Do not count this connection when limiting the number of connections. +> +> You can use this function for long-running connection processes +> which spend most of their time idling rather than consuming +> resources. This allows Ranch to accept a lot more connections +> without sacrificing the latency of the system. +> +> This function may only be called from a connection process. + +### set_max_connections(Ref, MaxConns) -> ok + +> Types: +> * Ref = ref() +> * MaxConns = max_conns() +> +> Set the max number of connections for the given listener. +> +> The change will be applied immediately. If the new value is +> smaller than the previous one, Ranch will not kill the extra +> connections, but will wait for them to terminate properly. + +### set_protocol_options(Ref, ProtoOpts) -> ok + +> Types: +> * Ref = ref() +> * ProtoOpts = any() +> +> Set the protocol options for the given listener. +> +> The change will be applied immediately for all new connections. +> Old connections will not receive the new options. + +### start_listener(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts) + -> {ok, pid()} | {error, badarg} + +> Types: +> * Ref = ref() +> * NbAcceptors = non_neg_integer() +> * Transport = module() +> * TransOpts = any() +> * Protocol = module() +> * ProtoOpts = any() +> +> Start listening for connections using the given transport +> and protocol. Returns the pid for this listener's supervisor. +> +> There are five additional transport options that apply +> regardless of transport. They allow configuring how the +> connections are supervised, rate limited and allow using +> an already open listening socket. +> +> The `ack_timeout` option defines how long post-accept socket +> initialization should take at a maximum. It defaults to `5000`. +> +> The `connection_type` option defines the type of process +> that will handle the connection. It can be either `worker` +> or `supervisor`. It defaults to `worker`. +> +> The `max_connections` option determines how many active +> connections are allowed before Ranch starts throttling +> the accept rate. This is a soft limit. It defaults to `1024`. +> Using the value `infinity` will disable this functionality +> entirely. +> +> The `shutdown` option determines the policy used with +> regards to connection processes when shutting down the listener. +> It can be either a positive integer indicating the max number +> of ms the supervisor will wait before forcibly killing the +> children, or the atom `brutal_kill`. It defaults to `5000`. +> +> The `socket` option allow passing an already open listening +> socket. In this case, Ranch will not call `Transport:listen/1` +> and so none of the transport specific options apply. + +### stop_listener(Ref) -> ok | {error, not_found} + +> Types: +> * Ref = ref() +> +> Stop the given listener. +> +> The listener is stopped gracefully, first by closing the +> listening port, then by stopping the connection processes. +> These processes are stopped according to the `shutdown` +> transport option, which may be set to brutally kill all +> connection processes or give them some time to stop properly. +> +> This function does not return until the listener is +> completely stopped. diff --git a/manual/ranch_app.md b/manual/ranch_app.md new file mode 100644 index 0000000..380931c --- /dev/null +++ b/manual/ranch_app.md @@ -0,0 +1,28 @@ +The Ranch Application +===================== + +Socket acceptor pool for TCP protocols. + +Dependencies +------------ + +The `ranch` application has no particular dependency required +to start. + +It has optional dependencies that are only required when +listening for SSL connections. The dependencies are `crypto`, +`asn1`, `public_key` and `ssl`. They are started automatically +if they weren't before. + +Environment +----------- + +The `ranch` application defines one application environment +configuration parameter. + + - profile (false) + - When enabled, Ranch will start `etop` profiling automatically. + +You can use the `ranch_app:profile_output/0` function to stop +profiling and output the results to the files `procs.profile` +and `total.profile`. Do not use in production. diff --git a/manual/ranch_protocol.md b/manual/ranch_protocol.md new file mode 100644 index 0000000..3e8b62e --- /dev/null +++ b/manual/ranch_protocol.md @@ -0,0 +1,35 @@ +ranch_protocol +============== + +The `ranch_protocol` behaviour defines the interface used +by Ranch protocols. + +Types +----- + +None. + +Callbacks +--------- + +### start_link(Ref, Socket, Transport, ProtoOpts) -> {ok, pid()} + +> Types: +> * Ref = ranch:ref() +> * Socket = any() +> * Transport = module() +> * ProtoOpts = any() +> +> Start a new connection process for the given socket. +> +> The only purpose of this callback is to start a process that +> will handle the socket. It must spawn the process, link and +> then return the new pid. This function will always be called +> from inside a supervisor. +> +> If any other value is returned, the supervisor will close the +> socket and assume no process has been started. +> +> Do not perform any operation in this callback, as this would +> block the supervisor responsible for starting connection +> processes and degrade performance severely. diff --git a/manual/ranch_ssl.md b/manual/ranch_ssl.md new file mode 100644 index 0000000..d8bb140 --- /dev/null +++ b/manual/ranch_ssl.md @@ -0,0 +1,97 @@ +ranch_ssl +========= + +The `ranch_ssl` module implements an SSL Ranch transport. + +Types +----- + +### opts() = [{backlog, non_neg_integer()} + | {cacertfile, string()} + | {cacerts, [Der::binary()]} + | {cert, Der::binary()} + | {certfile, string()} + | {ciphers, [ssl:erl_cipher_suite()] | string()} + | {fail_if_no_peer_cert, boolean()} + | {hibernate_after, integer() | undefined} + | {ip, inet:ip_address()} + | {key, Der::binary()} + | {keyfile, string()} + | {next_protocols_advertised, [binary()]} + | {nodelay, boolean()} + | {password, string()} + | {port, inet:port_number()} + | {raw, non_neg_integer(), non_neg_integer(), non_neg_integer() | binary()} + | {reuse_session, fun()} + | {reuse_sessions, boolean()} + | {secure_renegotiate, boolean()} + | {verify, ssl:verify_type()} + | {verify_fun, {fun(), InitialUserState::term()}}] + +> Listen options. +> +> This does not represent the entirety of the options that can +> be set on the socket, but only the options that should be +> set independently of protocol implementation. + +Option descriptions +------------------- + +Specifying a certificate is mandatory, either through the `cert` +or the `certfile` option. None of the other options are required. + +The default value is given next to the option name. + + - backlog (1024) + - Max length of the queue of pending connections. + - cacertfile + - Path to PEM encoded trusted certificates file used to verify peer certificates. + - cacerts + - List of DER encoded trusted certificates. + - cert + - DER encoded user certificate. + - certfile + - Path to the PEM encoded user certificate file. May also contain the private key. + - ciphers + - List of ciphers that clients are allowed to use. + - fail_if_no_peer_cert (false) + - Whether to refuse the connection if the client sends an empty certificate. + - hibernate_after (undefined) + - Time in ms after which SSL socket processes go into hibernation to reduce memory usage. + - ip + - Interface to listen on. Listen on all interfaces by default. + - key + - DER encoded user private key. + - keyfile + - Path to the PEM encoded private key file, if different than the certfile. + - next_protocols_advertised + - List of protocols to send to the client if it supports the Next Protocol extension. + - nodelay (true) + - Whether to enable TCP_NODELAY. + - password + - Password to the private key file, if password protected. + - port (0) + - TCP port number to listen on. 0 means a random port will be used. + - reuse_session + - Custom policy to decide whether a session should be reused. + - reuse_sessions (false) + - Whether to allow session reuse. + - secure_renegotiate (false) + - Whether to reject renegotiation attempts that do not conform to RFC5746. + - verify (verify_none) + - Use `verify_peer` to request a certificate from the client. + - verify_fun + - Custom policy to decide whether a client certificate is valid. + +Note that the client will not send a certificate unless the +value for the `verify` option is set to `verify_peer`. This +means that the `fail_if_no_peer_cert` only apply when combined +with the `verify` option. The `verify_fun` option allows +greater control over the client certificate validation. + +The `raw` option is unsupported. + +Exports +------- + +None. diff --git a/manual/ranch_tcp.md b/manual/ranch_tcp.md new file mode 100644 index 0000000..d0f6054 --- /dev/null +++ b/manual/ranch_tcp.md @@ -0,0 +1,47 @@ +ranch_tcp +========= + +The `ranch_tcp` module implements a TCP Ranch transport. + +Note that due to bugs in OTP up to at least R16B02, it is +recommended to disable async threads when using the +`sendfile` function of this transport, as it can make +the threads stuck indefinitely. + +Types +----- + +### opts() = [{backlog, non_neg_integer()} + | {ip, inet:ip_address()} + | {nodelay, boolean()} + | {port, inet:port_number()} + | {raw, non_neg_integer(), non_neg_integer(), non_neg_integer() | binary()}] + +> Listen options. +> +> This does not represent the entirety of the options that can +> be set on the socket, but only the options that should be +> set independently of protocol implementation. + +Option descriptions +------------------- + +None of the options are required. + +The default value is given next to the option name. + + - backlog (1024) + - Max length of the queue of pending connections. + - ip + - Interface to listen on. Listen on all interfaces by default. + - nodelay (true) + - Whether to enable TCP_NODELAY. + - port (0) + - TCP port number to listen on. 0 means a random port will be used. + +The `raw` option is unsupported. + +Exports +------- + +None. diff --git a/manual/ranch_transport.md b/manual/ranch_transport.md new file mode 100644 index 0000000..7eb350d --- /dev/null +++ b/manual/ranch_transport.md @@ -0,0 +1,197 @@ +ranch_transport +=============== + +The `ranch_transport` behaviour defines the interface used +by Ranch transports. + +Types +----- + +### sendfile_opts() = [{chunk_size, non_neg_integer()}] + +> Options used by the sendfile function and callbacks. +> +> Allows configuring the chunk size, in bytes. Defaults to 8191 bytes. + +Callbacks +--------- + +### accept(LSocket, Timeout) + -> {ok, CSocket} | {error, closed | timeout | atom() | tuple()} + +> Types: +> * LSocket = CSocket = any() +> * Timeout = timeout() +> +> Accept a connection on the given listening socket. +> +> The `accept_ack` callback will be used to initialize the socket +> after accepting the connection. This is most useful when the +> transport is not raw TCP, like with SSL for example. + +### accept_ack(CSocket, Timeout) -> ok + +> Types: +> * CSocket = any() +> * Timeout = timeout() +> +> Perform post-accept initialization of the connection. +> +> This function will be called by connection processes +> before performing any socket operation. It allows +> transports that require extra initialization to perform +> their task and make the socket ready to use. + +### close(CSocket) -> ok + +> Types: +> * CSocket = any() +> +> Close the given socket. + +### controlling_process(CSocket, Pid) + -> ok | {error, closed | not_owner | atom()} + +> Types: +> * CSocket = any() +> * Pid = pid() +> +> Change the controlling process for the given socket. +> +> The controlling process is the process that is allowed to +> perform operations on the socket, and that will receive +> messages from the socket when active mode is used. When +> the controlling process dies, the socket is closed. + +### listen(TransOpts) -> {ok, LSocket} | {error, atom()} + +> Types: +> * TransOpts = any() +> * LSocket = any() +> +> Listen for connections on the given port. +> +> The port is given as part of the transport options under +> the key `port`. Any other option is transport dependent. +> +> The socket returned by this call can then be used to +> accept connections. It is not possible to send or receive +> data from the listening socket. + +### messages() -> {OK, Closed, Error} + +> Types: +> * OK = Closed = Error = atom() +> +> Return the atoms used to identify messages sent in active mode. + +### name() -> Name + +> Types: +> * Name = atom() +> +> Return the name of the transport. + +### peername(CSocket) -> {ok, {IP, Port}} | {error, atom()} + +> Types: +> * CSocket = any() +> * IP = inet:ip_address() +> * Port = inet:port_number() +> +> Return the IP and port of the remote endpoint. + +### recv(CSocket, Length, Timeout) + -> {ok, Packet} | {error, closed | timeout | atom()} + +> Types: +> * CSocket = any() +> * Length = non_neg_integer() +> * Timeout = timeout() +> * Packet = iodata() | any() +> +> Receive data from the given socket when in passive mode. +> +> Trying to receive data from a socket that is in active mode +> will return an error. +> +> A length of 0 will return any data available on the socket. +> +> While it is possible to use the timeout value `infinity`, +> this is highly discouraged as this could cause your process +> to get stuck waiting for data that will never come. This may +> happen when a socket becomes half-open due to a crash of the +> remote endpoint. Wi-Fi going down is another common culprit +> of this issue. + +### send(CSocket, Packet) -> ok | {error, atom()} + +> Types: +> * CSocket = any() +> * Packet = iodata() +> +> Send data to the given socket. + +### sendfile(CSocket, File) + -> sendfile(CSocket, File, 0, 0, []) +### sendfile(CSocket, File, Offset, Bytes) + -> sendfile(CSocket, File, Offset, Bytes, []) +### sendfile(CSocket, File, Offset, Bytes, SfOpts) + -> {ok, SentBytes} | {error, atom()} + +> Types: +> * CSocket = any() +> * File = file:filename_all() | file:fd() +> * Offset = non_neg_integer() +> * Bytes = SentBytes = non_neg_integer() +> * SfOpts = sendfile_opts() +> +> Send data from a file to the given socket. +> +> The file may be sent full or in parts, and may be specified +> by its filename or by an already open file descriptor. +> +> Transports that manipulate TCP directly may use the +> `file:sendfile/{2,4,5}` function, which calls the sendfile +> syscall where applicable (on Linux, for example). Other +> transports can use the `sendfile/6` function exported from +> this module. + +### setopts(CSocket, TransOpts) -> ok | {error, atom()} + +> Types: +> * CSocket = any() +> * TransOpts = any() +> +> Change transport options for the given socket. +> +> This is mainly useful for switching to active or passive mode. + +### sockname(CSocket) -> {ok, {IP, Port}} | {error, atom()} + +> Types: +> * CSocket = any() +> * IP = inet:ip_address() +> * Port = inet:port_number() +> +> Return the IP and port of the local endpoint. + +Exports +------- + +### sendfile(Transport, CSocket, File, Offset, Bytes, SfOpts) + -> {ok, SentBytes} | {error, atom()} + +> Types: +> * Transport = module() +> * CSocket = any() +> * File = file:filename_all() | file:fd() +> * Offset = non_neg_integer() +> * Bytes = SentBytes = non_neg_integer() +> * SfOpts = sendfile_opts() +> +> Send data from a file to the given socket. +> +> This function emulates the function `file:sendfile/{2,4,5}` +> and may be used when transports are not manipulating TCP +> directly. diff --git a/manual/toc.md b/manual/toc.md new file mode 100644 index 0000000..af99d14 --- /dev/null +++ b/manual/toc.md @@ -0,0 +1,11 @@ +Ranch Function Reference +======================== + +The function reference documents the public interface of Ranch. + + * [The Ranch Application](ranch_app.md) + * [ranch](ranch.md) + * [ranch_protocol](ranch_protocol.md) + * [ranch_ssl](ranch_ssl.md) + * [ranch_tcp](ranch_tcp.md) + * [ranch_transport](ranch_transport.md) -- cgit v1.2.3