Просмотр исходного кода

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.
Loïc Hoguin 11 лет назад
Родитель
Сommit
d2318c0a28
8 измененных файлов с 588 добавлено и 2 удалено
  1. 2 2
      README.md
  2. 171 0
      manual/ranch.md
  3. 28 0
      manual/ranch_app.md
  4. 35 0
      manual/ranch_protocol.md
  5. 97 0
      manual/ranch_ssl.md
  6. 47 0
      manual/ranch_tcp.md
  7. 197 0
      manual/ranch_transport.md
  8. 11 0
      manual/toc.md

+ 2 - 2
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
 -------

+ 171 - 0
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.

+ 28 - 0
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.

+ 35 - 0
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.

+ 97 - 0
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.

+ 47 - 0
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.

+ 197 - 0
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.

+ 11 - 0
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)