summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/en/cowboy/2.0/guide/architecture/index.html2
-rw-r--r--docs/en/cowboy/2.0/guide/ws_handlers.asciidoc273
-rw-r--r--docs/en/cowboy/2.0/guide/ws_handlers/index.html270
-rw-r--r--docs/en/cowboy/2.0/guide/ws_protocol/index.html2
4 files changed, 341 insertions, 206 deletions
diff --git a/docs/en/cowboy/2.0/guide/architecture/index.html b/docs/en/cowboy/2.0/guide/architecture/index.html
index df1e201c..6f2015d6 100644
--- a/docs/en/cowboy/2.0/guide/architecture/index.html
+++ b/docs/en/cowboy/2.0/guide/architecture/index.html
@@ -128,7 +128,7 @@ only processing short-lived requests.</p></div>
<nav style="margin:1em 0">
<a style="float:left" href="http://ninenines.eu/docs/en/cowboy/2.0/guide/ws_handlers/">
- Handling Websocket connections
+ Websocket handlers
</a>
diff --git a/docs/en/cowboy/2.0/guide/ws_handlers.asciidoc b/docs/en/cowboy/2.0/guide/ws_handlers.asciidoc
index 1411ab6c..e1a7c252 100644
--- a/docs/en/cowboy/2.0/guide/ws_handlers.asciidoc
+++ b/docs/en/cowboy/2.0/guide/ws_handlers.asciidoc
@@ -1,20 +1,22 @@
[[ws_handlers]]
-== Handling Websocket connections
+== Websocket handlers
-A special handler is required for handling Websocket connections.
-Websocket handlers allow you to initialize the connection,
-handle incoming frames from the socket, handle incoming Erlang
-messages and then clean up on termination.
+Websocket handlers provide an interface for upgrading HTTP/1.1
+connections to Websocket and sending or receiving frames on
+the Websocket connection.
-Websocket handlers essentially act as a bridge between the client
-and the Erlang system. They will typically do little more than
-socket communication and decoding/encoding of frames.
+As Websocket connections are established through the HTTP/1.1
+upgrade mechanism, Websocket handlers need to be able to first
+receive the HTTP request for the upgrade, before switching to
+Websocket and taking over the connection. They can then receive
+or send Websocket frames, handle incoming Erlang messages or
+close the connection.
-=== Initialization
+=== Upgrade
-First, the `init/2` callback is called. This callback is common
-to all handlers. To establish a Websocket connection, this function
-must return a `ws` tuple.
+The `init/2` callback is called when the request is received.
+To establish a Websocket connection, you must switch to the
+`cowboy_websocket` module:
[source,erlang]
----
@@ -22,15 +24,36 @@ init(Req, State) ->
{cowboy_websocket, Req, State}.
----
-Upon receiving this tuple, Cowboy will switch to the code
-that handles Websocket connections and perform the handshake
-immediately.
+Cowboy will perform the Websocket handshake immediately. Note
+that the handshake will fail if the client did not request an
+upgrade to Websocket.
-If the sec-websocket-protocol header was sent with the request
-for establishing a Websocket connection, then the Websocket
-handler *must* select one of these subprotocol and send it
-back to the client, otherwise the client might decide to close
-the connection, assuming no correct subprotocol was found.
+The Req object becomes unavailable after this function returns.
+Any information required for proper execution of the Websocket
+handler must be saved in the state.
+
+=== Subprotocol
+
+The client may provide a list of Websocket subprotocols it
+supports in the sec-websocket-protocol header. The server *must*
+select one of them and send it back to the client or the
+handshake will fail.
+
+For example, a client could understand both STOMP and MQTT over
+Websocket, and provide the header:
+
+----
+sec-websocket-protocol: v12.stomp, mqtt
+----
+
+If the server only understands MQTT it can return:
+
+----
+sec-websocket-protocol: mqtt
+----
+
+This selection must be done in `init/2`. An example usage could
+be:
[source,erlang]
----
@@ -39,10 +62,10 @@ init(Req, State) ->
undefined ->
{ok, Req, State};
Subprotocols ->
- case lists:keymember(<<"mychat2">>, 1, Subprotocols) of
+ case lists:keymember(<<"mqtt">>, 1, Subprotocols) of
true ->
Req2 = cowboy_req:set_resp_header(<<"sec-websocket-protocol">>,
- <<"mychat2">>, Req),
+ <<"mqtt">>, Req),
{ok, Req2, State};
false ->
{stop, Req, State}
@@ -50,42 +73,50 @@ init(Req, State) ->
end.
----
-It is not recommended to wait too long inside the `init/2`
-function. Any extra initialization may be done after returning by
-sending yourself a message before doing anything. Any message sent
-to `self()` from `init/2` is guaranteed to arrive before
-any frames from the client.
+=== Post-upgrade initialization
+
+Cowboy has separate processes for handling the connection
+and requests. Because Websocket takes over the connection,
+the Websocket protocol handling occurs in a different
+process than the request handling.
-It is also very easy to ensure that this message arrives before
-any message from other processes by sending it before registering
-or enabling timers.
+This is reflected in the different callbacks Websocket
+handlers have. The `init/2` callback is called from the
+temporary request process and the `websocket_` callbacks
+from the connection process.
-// @todo This doesn't even work.
+This means that some initialization cannot be done from
+`init/2`. Anything that would require the current pid,
+or be tied to the current pid, will not work as intended.
+The optional `websocket_init/1` can be used instead:
[source,erlang]
----
-init(Req, State) ->
- self() ! post_init,
- %% Register process here...
- {cowboy_websocket, Req, State}.
-
-websocket_info(post_init, State) ->
- %% Perform post_init initialization here...
+websocket_init(State) ->
+ erlang:start_timer(1000, self(), <<"Hello!">>),
{ok, State}.
----
-=== Handling frames from the client
+All Websocket callbacks share the same return values. This
+means that we can send frames to the client right after
+the upgrade:
+
+[source,erlang]
+----
+websocket_init(State) ->
+ {reply, {text, <<"Hello!">>}, State}.
+----
+
+=== Receiving frames
Cowboy will call `websocket_handle/2` whenever a text, binary,
-ping or pong frame arrives from the client. Note that in the
-case of ping and pong frames, no action is expected as Cowboy
-automatically replies to ping frames.
+ping or pong frame arrives from the client.
-The handler can decide to send frames to the socket, stop
-or just continue without sending anything.
+The handler can handle or ignore the frames. It can also
+send frames back to the client or stop the connection.
The following snippet echoes back any text frame received and
-ignores all others.
+ignores all others:
[source,erlang]
----
@@ -95,16 +126,20 @@ websocket_handle(_Frame, State) ->
{ok, State}.
----
-=== Handling Erlang messages
+Note that ping and pong frames require no action from the
+handler as Cowboy will automatically reply to ping frames.
+They are provided for informative purposes only.
+
+=== Receiving Erlang messages
Cowboy will call `websocket_info/2` whenever an Erlang message
arrives.
-The handler can decide to send frames to the socket, stop
-or just continue without sending anything.
+The handler can handle or ignore the messages. It can also
+send frames to the client or stop the connection.
-The following snippet forwards any `log` message to the socket
-and ignores all others.
+The following snippet forwards log messages to the client
+and ignores all others:
[source,erlang]
----
@@ -114,60 +149,68 @@ websocket_info(_Info, State) ->
{ok, State}.
----
-=== Sending frames to the socket
+=== Sending frames
-Cowboy allows sending either a single frame or a list of
-frames to the socket, in which case the frames are sent
-sequentially. Any frame can be sent: text, binary, ping,
-pong or close frames.
+// @todo So yeah, reply makes no sense. Maybe change it to send. Sigh.
-The following example sends three frames using a single `reply`
-tuple.
+All `websocket_` callbacks share return values. They may
+send zero, one or many frames to the client.
+
+To send nothing, just return an ok tuple:
[source,erlang]
----
-websocket_info(hello_world, State) ->
+websocket_info(_Info, State) ->
+ {ok, State}.
+----
+
+To send one frame, return a reply tuple with the frame to send:
+
+[source,erlang]
+----
+websocket_info(_Info, State) ->
+ {reply, {text, <<"Hello!">>}, State}.
+----
+
+You can send frames of any type: text, binary, ping, pong
+or close frames.
+
+To send many frames at once, return a reply tuple with the
+list of frames to send:
+
+[source,erlang]
+----
+websocket_info(_Info, State) ->
{reply, [
{text, "Hello"},
{text, <<"world!">>},
{binary, <<0:8000>>}
- ], State};
-%% More websocket_info/2 clauses here...
+ ], State}.
----
-Note that the payload for text and binary frames is of type
-`iodata()`, meaning it can be either a `binary()` or an
-`iolist()`.
+They are sent in the given order.
-Sending a `close` frame will immediately initiate the closing
-of the Websocket connection. Be aware that any additional
-frames sent by the client or any Erlang messages waiting to
-be received will not be processed. Also note that when replying
-a list of frames that includes close, any frame found after the
-close frame will not be sent.
-
-=== Ping and timeout
+=== Keeping the connection alive
-The biggest performance improvement you can do when dealing
-with a huge number of Websocket connections is to reduce the
-number of timers that are started on the server. A common use
-of timers when dealing with connections is for sending a ping
-every once in a while. This should be done exclusively on the
-client side. Indeed, a server handling one million Websocket
-connections will perform a lot better when it doesn't have to
-handle one million extra timers too!
+Cowboy will automatically respond to ping frames sent by
+the client. They are still forwarded to the handler for
+informative purposes, but no further action is required.
-Cowboy will automatically respond to ping frames sent by the
-client. It will still forward the frame to the handler for
-informative purpose, but no further action is required.
+Cowboy does not send ping frames itself. The handler can
+do it if required. A better solution in most cases is to
+let the client handle pings. Doing it from the handler
+would imply having an additional timer per connection and
+this can be a considerable cost for servers that need to
+handle large numbers of connections.
-Cowboy can be configured to automatically close the Websocket
-connection when no data arrives on the socket. It is highly
-recommended to configure a timeout for it, as otherwise you
-may end up with zombie "half-connected" sockets that may
-leave the process alive forever.
+Cowboy can be configured to close idle connections
+automatically. It is highly recommended to configure
+a timeout here, to avoid having processes linger longer
+than needed.
-A good timeout value is 60 seconds.
+The `init/2` callback can set the timeout to be used
+for the connection. For example, this would make Cowboy
+close connections idle for more than 60 seconds:
[source,erlang]
----
@@ -178,21 +221,47 @@ init(Req, State) ->
This value cannot be changed once it is set. It defaults to
`infinity`.
-=== Hibernate
+// @todo Perhaps the default should be changed.
-Most tuples returned from handler callbacks can include an
-extra value `hibernate`. After doing any necessary operations
-following the return of the callback, Cowboy will hibernate
-the process.
+=== Saving memory
-It is highly recommended to hibernate processes that do not
-handle much traffic. It is a good idea to hibernate all
-connections by default and investigate only when you start
-noticing increased CPU usage.
+The Websocket connection process can be set to hibernate
+after the callback returns.
-=== Supporting older browsers
+Simply add an `hibernate` field to the ok or reply tuples:
+
+[source,erlang]
+----
+websocket_init(State) ->
+ {ok, State, hibernate}.
+
+websocket_handle(_Frame, State) ->
+ {ok, State, hibernate}.
-Unfortunately Websocket is a relatively recent technology,
-which means that not all browsers support it. A library like
-https://github.com/ninenines/bullet[Bullet] can be used to
-emulate Websocket connections on older browsers.
+websocket_info(_Info, State) ->
+ {reply, {text, <<"Hello!">>}, State, hibernate}.
+----
+
+It is highly recommended to write your handlers with
+hibernate enabled, as this allows to greatly reduce the
+memory usage. Do note however that an increase in the
+CPU usage or latency can be observed instead, in particular
+for the more busy connections.
+
+=== Closing the connection
+
+The connection can be closed at any time, either by telling
+Cowboy to stop it or by sending a close frame.
+
+To tell Cowboy to close the connection, use a stop tuple:
+
+[source,erlang]
+----
+websocket_info(_Info, State) ->
+ {stop, State}.
+----
+
+Sending a `close` frame will immediately initiate the closing
+of the Websocket connection. Note that when sending a list of
+frames that include a close frame, any frame found after the
+close frame will not be sent.
diff --git a/docs/en/cowboy/2.0/guide/ws_handlers/index.html b/docs/en/cowboy/2.0/guide/ws_handlers/index.html
index a5c84e49..21c22712 100644
--- a/docs/en/cowboy/2.0/guide/ws_handlers/index.html
+++ b/docs/en/cowboy/2.0/guide/ws_handlers/index.html
@@ -9,7 +9,7 @@
<meta name="generator" content="Hugo 0.16" />
- <title>Nine Nines: Handling Websocket connections</title>
+ <title>Nine Nines: Websocket handlers</title>
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic' rel='stylesheet' type='text/css'>
@@ -67,21 +67,23 @@
<div class="row">
<div id="docs" class="span9 maincol">
-<h1 class="lined-header"><span>Handling Websocket connections</span></h1>
-
-<div class="paragraph"><p>A special handler is required for handling Websocket connections.
-Websocket handlers allow you to initialize the connection,
-handle incoming frames from the socket, handle incoming Erlang
-messages and then clean up on termination.</p></div>
-<div class="paragraph"><p>Websocket handlers essentially act as a bridge between the client
-and the Erlang system. They will typically do little more than
-socket communication and decoding/encoding of frames.</p></div>
+<h1 class="lined-header"><span>Websocket handlers</span></h1>
+
+<div class="paragraph"><p>Websocket handlers provide an interface for upgrading HTTP/1.1
+connections to Websocket and sending or receiving frames on
+the Websocket connection.</p></div>
+<div class="paragraph"><p>As Websocket connections are established through the HTTP/1.1
+upgrade mechanism, Websocket handlers need to be able to first
+receive the HTTP request for the upgrade, before switching to
+Websocket and taking over the connection. They can then receive
+or send Websocket frames, handle incoming Erlang messages or
+close the connection.</p></div>
<div class="sect1">
-<h2 id="_initialization">Initialization</h2>
+<h2 id="_upgrade">Upgrade</h2>
<div class="sectionbody">
-<div class="paragraph"><p>First, the <code>init/2</code> callback is called. This callback is common
-to all handlers. To establish a Websocket connection, this function
-must return a <code>ws</code> tuple.</p></div>
+<div class="paragraph"><p>The <code>init/2</code> callback is called when the request is received.
+To establish a Websocket connection, you must switch to the
+<code>cowboy_websocket</code> module:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 3.1.8
by Lorenzo Bettini
@@ -89,14 +91,34 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #000000">init</span></span>(<span style="color: #009900">Req</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-&gt;</span>
{<span style="color: #FF6600">cowboy_websocket</span>, <span style="color: #009900">Req</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
-<div class="paragraph"><p>Upon receiving this tuple, Cowboy will switch to the code
-that handles Websocket connections and perform the handshake
-immediately.</p></div>
-<div class="paragraph"><p>If the sec-websocket-protocol header was sent with the request
-for establishing a Websocket connection, then the Websocket
-handler <strong>must</strong> select one of these subprotocol and send it
-back to the client, otherwise the client might decide to close
-the connection, assuming no correct subprotocol was found.</p></div>
+<div class="paragraph"><p>Cowboy will perform the Websocket handshake immediately. Note
+that the handshake will fail if the client did not request an
+upgrade to Websocket.</p></div>
+<div class="paragraph"><p>The Req object becomes unavailable after this function returns.
+Any information required for proper execution of the Websocket
+handler must be saved in the state.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_subprotocol">Subprotocol</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The client may provide a list of Websocket subprotocols it
+supports in the sec-websocket-protocol header. The server <strong>must</strong>
+select one of them and send it back to the client or the
+handshake will fail.</p></div>
+<div class="paragraph"><p>For example, a client could understand both STOMP and MQTT over
+Websocket, and provide the header:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>sec-websocket-protocol: v12.stomp, mqtt</code></pre>
+</div></div>
+<div class="paragraph"><p>If the server only understands MQTT it can return:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>sec-websocket-protocol: mqtt</code></pre>
+</div></div>
+<div class="paragraph"><p>This selection must be done in <code>init/2</code>. An example usage could
+be:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 3.1.8
by Lorenzo Bettini
@@ -107,49 +129,61 @@ http://www.gnu.org/software/src-highlite -->
<span style="color: #000080">undefined</span> <span style="color: #990000">-&gt;</span>
{<span style="color: #FF6600">ok</span>, <span style="color: #009900">Req</span>, <span style="color: #009900">State</span>};
<span style="color: #009900">Subprotocols</span> <span style="color: #990000">-&gt;</span>
- <span style="font-weight: bold"><span style="color: #0000FF">case</span></span> <span style="font-weight: bold"><span style="color: #000000">lists:keymember</span></span>(<span style="color: #990000">&lt;&lt;</span><span style="color: #FF0000">"mychat2"</span><span style="color: #990000">&gt;&gt;</span>, <span style="color: #993399">1</span>, <span style="color: #009900">Subprotocols</span>) <span style="font-weight: bold"><span style="color: #0000FF">of</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">case</span></span> <span style="font-weight: bold"><span style="color: #000000">lists:keymember</span></span>(<span style="color: #990000">&lt;&lt;</span><span style="color: #FF0000">"mqtt"</span><span style="color: #990000">&gt;&gt;</span>, <span style="color: #993399">1</span>, <span style="color: #009900">Subprotocols</span>) <span style="font-weight: bold"><span style="color: #0000FF">of</span></span>
<span style="color: #000080">true</span> <span style="color: #990000">-&gt;</span>
<span style="color: #009900">Req2</span> <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #000000">cowboy_req:set_resp_header</span></span>(<span style="color: #990000">&lt;&lt;</span><span style="color: #FF0000">"sec-websocket-protocol"</span><span style="color: #990000">&gt;&gt;</span>,
- <span style="color: #990000">&lt;&lt;</span><span style="color: #FF0000">"mychat2"</span><span style="color: #990000">&gt;&gt;</span>, <span style="color: #009900">Req</span>),
+ <span style="color: #990000">&lt;&lt;</span><span style="color: #FF0000">"mqtt"</span><span style="color: #990000">&gt;&gt;</span>, <span style="color: #009900">Req</span>),
{<span style="color: #FF6600">ok</span>, <span style="color: #009900">Req2</span>, <span style="color: #009900">State</span>};
<span style="color: #000080">false</span> <span style="color: #990000">-&gt;</span>
{<span style="color: #FF6600">stop</span>, <span style="color: #009900">Req</span>, <span style="color: #009900">State</span>}
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span><span style="color: #990000">.</span></tt></pre></div></div>
-<div class="paragraph"><p>It is not recommended to wait too long inside the <code>init/2</code>
-function. Any extra initialization may be done after returning by
-sending yourself a message before doing anything. Any message sent
-to <code>self()</code> from <code>init/2</code> is guaranteed to arrive before
-any frames from the client.</p></div>
-<div class="paragraph"><p>It is also very easy to ensure that this message arrives before
-any message from other processes by sending it before registering
-or enabling timers.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_post_upgrade_initialization">Post-upgrade initialization</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Cowboy has separate processes for handling the connection
+and requests. Because Websocket takes over the connection,
+the Websocket protocol handling occurs in a different
+process than the request handling.</p></div>
+<div class="paragraph"><p>This is reflected in the different callbacks Websocket
+handlers have. The <code>init/2</code> callback is called from the
+temporary request process and the <code>websocket_</code> callbacks
+from the connection process.</p></div>
+<div class="paragraph"><p>This means that some initialization cannot be done from
+<code>init/2</code>. Anything that would require the current pid,
+or be tied to the current pid, will not work as intended.
+The optional <code>websocket_init/1</code> can be used instead:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 3.1.8
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000000">init</span></span>(<span style="color: #009900">Req</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-&gt;</span>
- <span style="font-weight: bold"><span style="color: #000080">self</span></span>() <span style="color: #990000">!</span> <span style="color: #FF6600">post_init</span>,
- <span style="font-style: italic"><span style="color: #9A1900">%% Register process here...</span></span>
- {<span style="color: #FF6600">cowboy_websocket</span>, <span style="color: #009900">Req</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span>
-
-<span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #FF6600">post_init</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-&gt;</span>
- <span style="font-style: italic"><span style="color: #9A1900">%% Perform post_init initialization here...</span></span>
+<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_init</span></span>(<span style="color: #009900">State</span>) <span style="color: #990000">-&gt;</span>
+ <span style="font-weight: bold"><span style="color: #000000">erlang:start_timer</span></span>(<span style="color: #993399">1000</span>, <span style="font-weight: bold"><span style="color: #000080">self</span></span>(), <span style="color: #990000">&lt;&lt;</span><span style="color: #FF0000">"Hello!"</span><span style="color: #990000">&gt;&gt;</span>),
{<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
+<div class="paragraph"><p>All Websocket callbacks share the same return values. This
+means that we can send frames to the client right after
+the upgrade:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_init</span></span>(<span style="color: #009900">State</span>) <span style="color: #990000">-&gt;</span>
+ {<span style="color: #FF6600">reply</span>, {<span style="color: #FF6600">text</span>, <span style="color: #990000">&lt;&lt;</span><span style="color: #FF0000">"Hello!"</span><span style="color: #990000">&gt;&gt;</span>}, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
</div>
</div>
<div class="sect1">
-<h2 id="_handling_frames_from_the_client">Handling frames from the client</h2>
+<h2 id="_receiving_frames">Receiving frames</h2>
<div class="sectionbody">
<div class="paragraph"><p>Cowboy will call <code>websocket_handle/2</code> whenever a text, binary,
-ping or pong frame arrives from the client. Note that in the
-case of ping and pong frames, no action is expected as Cowboy
-automatically replies to ping frames.</p></div>
-<div class="paragraph"><p>The handler can decide to send frames to the socket, stop
-or just continue without sending anything.</p></div>
+ping or pong frame arrives from the client.</p></div>
+<div class="paragraph"><p>The handler can handle or ignore the frames. It can also
+send frames back to the client or stop the connection.</p></div>
<div class="paragraph"><p>The following snippet echoes back any text frame received and
-ignores all others.</p></div>
+ignores all others:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 3.1.8
by Lorenzo Bettini
@@ -159,17 +193,20 @@ http://www.gnu.org/software/src-highlite -->
{<span style="color: #FF6600">reply</span>, <span style="color: #009900">Frame</span>, <span style="color: #009900">State</span>};
<span style="font-weight: bold"><span style="color: #000000">websocket_handle</span></span>(<span style="color: #009900">_Frame</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-&gt;</span>
{<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
+<div class="paragraph"><p>Note that ping and pong frames require no action from the
+handler as Cowboy will automatically reply to ping frames.
+They are provided for informative purposes only.</p></div>
</div>
</div>
<div class="sect1">
-<h2 id="_handling_erlang_messages">Handling Erlang messages</h2>
+<h2 id="_receiving_erlang_messages">Receiving Erlang messages</h2>
<div class="sectionbody">
<div class="paragraph"><p>Cowboy will call <code>websocket_info/2</code> whenever an Erlang message
arrives.</p></div>
-<div class="paragraph"><p>The handler can decide to send frames to the socket, stop
-or just continue without sending anything.</p></div>
-<div class="paragraph"><p>The following snippet forwards any <code>log</code> message to the socket
-and ignores all others.</p></div>
+<div class="paragraph"><p>The handler can handle or ignore the messages. It can also
+send frames to the client or stop the connection.</p></div>
+<div class="paragraph"><p>The following snippet forwards log messages to the client
+and ignores all others:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 3.1.8
by Lorenzo Bettini
@@ -182,57 +219,63 @@ http://www.gnu.org/software/src-highlite -->
</div>
</div>
<div class="sect1">
-<h2 id="_sending_frames_to_the_socket">Sending frames to the socket</h2>
+<h2 id="_sending_frames">Sending frames</h2>
<div class="sectionbody">
-<div class="paragraph"><p>Cowboy allows sending either a single frame or a list of
-frames to the socket, in which case the frames are sent
-sequentially. Any frame can be sent: text, binary, ping,
-pong or close frames.</p></div>
-<div class="paragraph"><p>The following example sends three frames using a single <code>reply</code>
-tuple.</p></div>
+<div class="paragraph"><p>All <code>websocket_</code> callbacks share return values. They may
+send zero, one or many frames to the client.</p></div>
+<div class="paragraph"><p>To send nothing, just return an ok tuple:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-&gt;</span>
+ {<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
+<div class="paragraph"><p>To send one frame, return a reply tuple with the frame to send:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 3.1.8
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #FF6600">hello_world</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-&gt;</span>
+<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-&gt;</span>
+ {<span style="color: #FF6600">reply</span>, {<span style="color: #FF6600">text</span>, <span style="color: #990000">&lt;&lt;</span><span style="color: #FF0000">"Hello!"</span><span style="color: #990000">&gt;&gt;</span>}, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
+<div class="paragraph"><p>You can send frames of any type: text, binary, ping, pong
+or close frames.</p></div>
+<div class="paragraph"><p>To send many frames at once, return a reply tuple with the
+list of frames to send:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-&gt;</span>
{<span style="color: #FF6600">reply</span>, [
{<span style="color: #FF6600">text</span>, <span style="color: #FF0000">"Hello"</span>},
{<span style="color: #FF6600">text</span>, <span style="color: #990000">&lt;&lt;</span><span style="color: #FF0000">"world!"</span><span style="color: #990000">&gt;&gt;</span>},
{<span style="font-weight: bold"><span style="color: #000080">binary</span></span>, <span style="color: #990000">&lt;&lt;</span><span style="color: #993399">0</span><span style="color: #990000">:</span><span style="color: #993399">8000</span><span style="color: #990000">&gt;&gt;</span>}
- ], <span style="color: #009900">State</span>};
-<span style="font-style: italic"><span style="color: #9A1900">%% More websocket_info/2 clauses here...</span></span></tt></pre></div></div>
-<div class="paragraph"><p>Note that the payload for text and binary frames is of type
-<code>iodata()</code>, meaning it can be either a <code>binary()</code> or an
-<code>iolist()</code>.</p></div>
-<div class="paragraph"><p>Sending a <code>close</code> frame will immediately initiate the closing
-of the Websocket connection. Be aware that any additional
-frames sent by the client or any Erlang messages waiting to
-be received will not be processed. Also note that when replying
-a list of frames that includes close, any frame found after the
-close frame will not be sent.</p></div>
+ ], <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
+<div class="paragraph"><p>They are sent in the given order.</p></div>
</div>
</div>
<div class="sect1">
-<h2 id="_ping_and_timeout">Ping and timeout</h2>
+<h2 id="_keeping_the_connection_alive">Keeping the connection alive</h2>
<div class="sectionbody">
-<div class="paragraph"><p>The biggest performance improvement you can do when dealing
-with a huge number of Websocket connections is to reduce the
-number of timers that are started on the server. A common use
-of timers when dealing with connections is for sending a ping
-every once in a while. This should be done exclusively on the
-client side. Indeed, a server handling one million Websocket
-connections will perform a lot better when it doesn&#8217;t have to
-handle one million extra timers too!</p></div>
-<div class="paragraph"><p>Cowboy will automatically respond to ping frames sent by the
-client. It will still forward the frame to the handler for
-informative purpose, but no further action is required.</p></div>
-<div class="paragraph"><p>Cowboy can be configured to automatically close the Websocket
-connection when no data arrives on the socket. It is highly
-recommended to configure a timeout for it, as otherwise you
-may end up with zombie "half-connected" sockets that may
-leave the process alive forever.</p></div>
-<div class="paragraph"><p>A good timeout value is 60 seconds.</p></div>
+<div class="paragraph"><p>Cowboy will automatically respond to ping frames sent by
+the client. They are still forwarded to the handler for
+informative purposes, but no further action is required.</p></div>
+<div class="paragraph"><p>Cowboy does not send ping frames itself. The handler can
+do it if required. A better solution in most cases is to
+let the client handle pings. Doing it from the handler
+would imply having an additional timer per connection and
+this can be a considerable cost for servers that need to
+handle large numbers of connections.</p></div>
+<div class="paragraph"><p>Cowboy can be configured to close idle connections
+automatically. It is highly recommended to configure
+a timeout here, to avoid having processes linger longer
+than needed.</p></div>
+<div class="paragraph"><p>The <code>init/2</code> callback can set the timeout to be used
+for the connection. For example, this would make Cowboy
+close connections idle for more than 60 seconds:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 3.1.8
by Lorenzo Bettini
@@ -245,25 +288,48 @@ http://www.gnu.org/software/src-highlite -->
</div>
</div>
<div class="sect1">
-<h2 id="_hibernate">Hibernate</h2>
+<h2 id="_saving_memory">Saving memory</h2>
<div class="sectionbody">
-<div class="paragraph"><p>Most tuples returned from handler callbacks can include an
-extra value <code>hibernate</code>. After doing any necessary operations
-following the return of the callback, Cowboy will hibernate
-the process.</p></div>
-<div class="paragraph"><p>It is highly recommended to hibernate processes that do not
-handle much traffic. It is a good idea to hibernate all
-connections by default and investigate only when you start
-noticing increased CPU usage.</p></div>
+<div class="paragraph"><p>The Websocket connection process can be set to hibernate
+after the callback returns.</p></div>
+<div class="paragraph"><p>Simply add an <code>hibernate</code> field to the ok or reply tuples:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_init</span></span>(<span style="color: #009900">State</span>) <span style="color: #990000">-&gt;</span>
+ {<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>, <span style="color: #FF6600">hibernate</span>}<span style="color: #990000">.</span>
+
+<span style="font-weight: bold"><span style="color: #000000">websocket_handle</span></span>(<span style="color: #009900">_Frame</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-&gt;</span>
+ {<span style="color: #FF6600">ok</span>, <span style="color: #009900">State</span>, <span style="color: #FF6600">hibernate</span>}<span style="color: #990000">.</span>
+
+<span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-&gt;</span>
+ {<span style="color: #FF6600">reply</span>, {<span style="color: #FF6600">text</span>, <span style="color: #990000">&lt;&lt;</span><span style="color: #FF0000">"Hello!"</span><span style="color: #990000">&gt;&gt;</span>}, <span style="color: #009900">State</span>, <span style="color: #FF6600">hibernate</span>}<span style="color: #990000">.</span></tt></pre></div></div>
+<div class="paragraph"><p>It is highly recommended to write your handlers with
+hibernate enabled, as this allows to greatly reduce the
+memory usage. Do note however that an increase in the
+CPU usage or latency can be observed instead, in particular
+for the more busy connections.</p></div>
</div>
</div>
<div class="sect1">
-<h2 id="_supporting_older_browsers">Supporting older browsers</h2>
+<h2 id="_closing_the_connection">Closing the connection</h2>
<div class="sectionbody">
-<div class="paragraph"><p>Unfortunately Websocket is a relatively recent technology,
-which means that not all browsers support it. A library like
-<a href="https://github.com/ninenines/bullet">Bullet</a> can be used to
-emulate Websocket connections on older browsers.</p></div>
+<div class="paragraph"><p>The connection can be closed at any time, either by telling
+Cowboy to stop it or by sending a close frame.</p></div>
+<div class="paragraph"><p>To tell Cowboy to close the connection, use a stop tuple:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000000">websocket_info</span></span>(<span style="color: #009900">_Info</span>, <span style="color: #009900">State</span>) <span style="color: #990000">-&gt;</span>
+ {<span style="color: #FF6600">stop</span>, <span style="color: #009900">State</span>}<span style="color: #990000">.</span></tt></pre></div></div>
+<div class="paragraph"><p>Sending a <code>close</code> frame will immediately initiate the closing
+of the Websocket connection. Note that when sending a list of
+frames that include a close frame, any frame found after the
+close frame will not be sent.</p></div>
</div>
</div>
diff --git a/docs/en/cowboy/2.0/guide/ws_protocol/index.html b/docs/en/cowboy/2.0/guide/ws_protocol/index.html
index faf642bb..17d873d1 100644
--- a/docs/en/cowboy/2.0/guide/ws_protocol/index.html
+++ b/docs/en/cowboy/2.0/guide/ws_protocol/index.html
@@ -150,7 +150,7 @@ the listener.</p></div>
<a style="float:right" href="http://ninenines.eu/docs/en/cowboy/2.0/guide/ws_handlers/">
- Handling Websocket connections
+ Websocket handlers
</a>
</nav>