Protocols ========= Purpose ------- A protocol handler starts a connection process and defines the protocol logic executed in this process. Writing a protocol handler -------------------------- All protocol handlers must implement the `ranch_protocol` behavior which defines a single callback, `start_link/4`. This callback is responsible for spawning a new process for handling the connection. It receives four arguments: the listener's pid, the socket, the transport handler being used and the protocol options defined in the call to `ranch:start_listener/6`. This callback must return `{ok, Pid}`, with `Pid` the pid of the new process. The newly started process can then freely initialize itself. However, it must call `ranch:accept_ack/1` before doing any socket operation. This will ensure the connection process is the owner of the socket. It expects the listener's pid as argument. ``` erlang ok = ranch:accept_ack(ListenerPid). ``` If your protocol code requires specific socket options, you should set them while initializing your connection process and before starting `ranch:accept_ack/1`. You can use `Transport:setopts/2` for that purpose. Following is the complete protocol code for the example found in `examples/tcp_echo/`. ``` erlang -module(echo_protocol). -behaviour(ranch_protocol). -export([start_link/4]). -export([init/4]). start_link(ListenerPid, Socket, Transport, Opts) -> Pid = spawn_link(?MODULE, init, [ListenerPid, Socket, Transport, Opts]), {ok, Pid}. init(ListenerPid, Socket, Transport, _Opts = []) -> ok = ranch:accept_ack(ListenerPid), loop(Socket, Transport). loop(Socket, Transport) -> case Transport:recv(Socket, 0, 5000) of {ok, Data} -> Transport:send(Socket, Data), loop(Socket, Transport); _ -> ok = Transport:close(Socket) end. ```