aboutsummaryrefslogtreecommitdiffstats
path: root/guide/protocols.md
diff options
context:
space:
mode:
Diffstat (limited to 'guide/protocols.md')
-rw-r--r--guide/protocols.md61
1 files changed, 61 insertions, 0 deletions
diff --git a/guide/protocols.md b/guide/protocols.md
new file mode 100644
index 0000000..7db8fec
--- /dev/null
+++ b/guide/protocols.md
@@ -0,0 +1,61 @@
+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.
+```