adds documentation for websocket C clients
[src/app-framework-binder.git] / doc / afb-plugin-writing.html
index 9a98ffe..b80006f 100644 (file)
@@ -8,7 +8,7 @@
 <h1>HOWTO WRITE a PLUGIN for AFB-DAEMON</h1>
 
 <pre><code>version: 1
-Date:    27 mai 2016
+Date:    29 mai 2016
 Author:  José Bollo
 </code></pre>
 
@@ -18,14 +18,14 @@ Author:  José Bollo
   <li><a href="#Summary">Summary</a>
   <ul>
    <li><a href="#Nature.of.a.plugin">Nature of a plugin</a></li>
-   <li><a href="#Kinds.of.plugins">Kinds of plugins</a>
+   <li><a href="#Class.of.plugins">Class of plugins</a>
    <ul>
-    <li><a href="#Application.plugins">Application plugins</a></li>
-    <li><a href="#Service.plugins">Service plugins</a></li>
+    <li><a href="#Application-plugins">Application-plugins</a></li>
+    <li><a href="#Service-plugins">Service-plugins</a></li>
    </ul>
    </li>
-   <li><a href="#Live.cycle.of.a.plugin.within.afb-daemon">Live cycle of a plugin within afb-daemon</a></li>
-   <li><a href="#Content.of.a.plugin">Content of a plugin</a>
+   <li><a href="#Live.cycle.of.plugins.within.afb-daemon">Live cycle of plugins within afb-daemon</a></li>
+   <li><a href="#Plugin.Contend">Plugin Contend</a>
    <ul>
     <li><a href="#The.name.of.the.plugin">The name of the plugin</a></li>
     <li><a href="#Names.of.verbs">Names of verbs</a></li>
@@ -37,6 +37,8 @@ Author:  José Bollo
   </ul>
   </li>
   <li><a href="#The.Tic-Tac-Toe.example">The Tic-Tac-Toe example</a></li>
+  <li><a href="#Dependencies.when.compiling">Dependencies when compiling</a></li>
+  <li><a href="#Header.files.to.include">Header files to include</a></li>
   <li><a href="#Choosing.names">Choosing names</a>
   <ul>
    <li><a href="#Names.for.API..plugin.">Names for API (plugin)</a></li>
@@ -45,8 +47,6 @@ Author:  José Bollo
    <li><a href="#Forging.names.widely.available">Forging names widely available</a></li>
   </ul>
   </li>
-  <li><a href="#Options.to.set.when.compiling.plugins">Options to set when compiling plugins</a></li>
-  <li><a href="#Header.files.to.include">Header files to include</a></li>
   <li><a href="#Writing.a.synchronous.verb.implementation">Writing a synchronous verb implementation</a>
   <ul>
    <li><a href="#The.incoming.request">The incoming request</a></li>
@@ -85,101 +85,90 @@ Author:  José Bollo
 <a name="Summary"></a>
 <h2>Summary</h2>
 
-<p>The binder afb-daemon serves files through
-the HTTP protocol and offers access to API&rsquo;s through
+<p>The binder afb-daemon serves files through HTTP protocol
+and offers to developers the capability to expose application APIs through
 HTTP or WebSocket protocol.</p>
 
-<p>The plugins are used to add API&rsquo;s to afb-daemon.
+<p>Binder plugins are used to add API to afb-daemon.
 This part describes how to write a plugin for afb-daemon.
 Excepting this summary, this part is intended to be read
-by developpers.</p>
+by developers.</p>
 
-<p>Before going into details, through a tiny example,
-a short overview plugins basis is needed.</p>
+<p>Before moving further through an example, here after
+a short overview of binder plugins fundamentals.</p>
 
 <a name="Nature.of.a.plugin"></a>
 <h3>Nature of a plugin</h3>
 
-<p>A plugin is a separate piece of code made of a shared library.
-The plugin is loaded and activated by afb-daemon when afb-daemon
-starts.</p>
+<p>A plugin is an independent piece of software, self contain and expose as a dynamically loadable library.
+A plugin is loaded by afb-daemon that exposes contained API dynamically at runtime.</p>
 
-<p>Technically, a plugin is not linked to any library of afb-daemon.</p>
+<p>Technically, a binder plugins does not reference and is not linked with any library from afb-daemon.</p>
 
-<a name="Kinds.of.plugins"></a>
-<h3>Kinds of plugins</h3>
+<a name="Class.of.plugins"></a>
+<h3>Class of plugins</h3>
 
-<p>There is two kinds of plugins: application plugins and service
-plugins.</p>
+<p>Application binder supports two kinds of plugins: application plugins and service
+plugins. Technically both class of plugin are equivalent and coding API is shared. Only sharing mode and security context diverge.</p>
 
-<a name="Application.plugins"></a>
-<h4>Application plugins</h4>
+<a name="Application-plugins"></a>
+<h4>Application-plugins</h4>
 
-<p>Application plugins are intended to be instanciated for each
-application: when an application using that plugin is started,
-its binder starts a new instance of the plugin.</p>
+<p>Application-plugins implements the glue in between application&rsquo;s UI and services. Every AGL application
+has a corresponding binder that typically activates one or many plugins to interface the application logic with lower platform services.
+When an application is started by AGL application framework, a dedicate binder is started that loads/activates application plugin(s).
+The API expose by application-plugin are executed within corresponding application security context.</p>
 
-<p>It means that the application plugins mainly have only one
-context to manage for one client.</p>
+<p>Application plugins generally handle a unique context for a unique client. As the application framework start
+a dedicated instance of afb_daemon for each AGL application, if a given plugin is used within multiple application each of those
+application get a new and private instance of this &ldquo;shared&rdquo; plugin.</p>
 
-<a name="Service.plugins"></a>
-<h4>Service plugins</h4>
+<a name="Service-plugins"></a>
+<h4>Service-plugins</h4>
 
-<p>Service plugins are intended to be instanciated only one time
-only and connected to many clients.</p>
+<p>Service-plugins enable API activation within corresponding service security context and not within calling application context.
+Service-plugins are intended to run as a unique instance that is shared in between multiple clients.</p>
 
-<p>So either it does not manage context at all or otherwise,
-if it manages context, it should be able to manage one context
-per client.</p>
+<p>Service-plugins can either be stateless or manage client context. When managing context each client get a private context.</p>
 
-<p>In details, it may be useful to have service plugins at a user
-level.</p>
+<p>Sharing may either be global to the platform (ie: GPS service) or dedicated to a given user (ie: preference management)</p>
 
-<a name="Live.cycle.of.a.plugin.within.afb-daemon"></a>
-<h3>Live cycle of a plugin within afb-daemon</h3>
+<a name="Live.cycle.of.plugins.within.afb-daemon"></a>
+<h3>Live cycle of plugins within afb-daemon</h3>
 
-<p>The plugins are loaded and activated when afb-daemon starts.</p>
+<p>Application and service plugins are loaded and activated each time a new afb-daemon is started.</p>
 
-<p>At start, the plugin initialise itself.
-If it fails to initialise then afb-daemon stops.</p>
+<p>At launch time, every loaded plugin initialise itself.
+If a single plugin initialisation fail corresponding instance of afb-daemon self aborts.</p>
 
-<p>Conversely, if it success to initialize, it must declare
-a name, that must be unique, and a list of API&rsquo;s verbs.</p>
+<p>Conversely, when plugin initialisation succeeds, it should register
+its unique name and the list of API verbs it exposes.</p>
 
-<p>When initialized, the functions implementing the API&rsquo;s verbs
-of the plugin are activated on call.</p>
+<p>When initialised, on request from clients plugin&rsquo;s function corresponding to expose API verbs
+are activated by the afb-daemon instance attached to the application or service.</p>
 
-<p>At the end, nothing special is done by afb-daemon.
-Consequently, developpers of plugins should use &lsquo;atexit&rsquo;
-or &lsquo;on_exit&rsquo; during initialisation if they need to
-perform specific actions when stopping.</p>
+<p>At exit time, no special action is enforced by afb-daemon. When a specific actions is required at afb-daemon stop,
+developers should use &lsquo;atexit/on_exit&rsquo; during plugin initialisation sequence to register a custom exit function.</p>
 
-<a name="Content.of.a.plugin"></a>
-<h3>Content of a plugin</h3>
+<a name="Plugin.Contend"></a>
+<h3>Plugin Contend</h3>
 
-<p>For afb-daemon, a plugin contains 2 different
-things: names and functions.</p>
+<p>Afb-daemon&rsquo;s plugin register two classes of objects: names and functions.</p>
 
-<p>There is two kind of names:
- - the name of the plugin,
- - the names of the verbs.</p>
+<p>Plugins declare categories of names:
+ - A unique plugin name,
+ - Multiple API verb&rsquo;s names.</p>
 
-<p>There is two kind of functions:
- - the initialisation function
- - functions implementing verbs</p>
+<p>Plugins declare two categories of functions:
+ - initialisation function
+ - API functions implementing verbs</p>
 
-<p>Afb-daemon translates the name of the method that is
-invoked to a pair of API and verb names. For example,
-the method named <strong>foo/bar</strong> translated to the API
-name <strong>foo</strong> and the verb name <strong>bar</strong>.
-To serve it, afb-daemon search the plugin that record
-the name <strong>foo</strong> and if it also recorded the verb <strong>bar</strong>,
-it calls the implementation function declared for this verb.</p>
+<p>Afb-daemon parses URI requests to extract plugin name and API verb.
+As an example, URI <strong>foo/bar</strong> translates to API verb named <strong>bar</strong> within plugin named <strong>foo</strong>.
+To serve such a request, afb-daemon looks for an active plugin named <strong>foo</strong> and then within this plugin for an API verb named <strong>bar</strong>.
+When find afb-daemon calls corresponding function with attached parameter if any.</p>
 
-<p>Afb-daemon make no distinction between lower case
-and upper case when searching for a method.
-Thus, The names <strong>TicTacToe/Board</strong> and <strong>tictactoe/borad</strong>
-are equals.</p>
+<p>Afb-daemon ignores letter case when parsing URI. Thus <strong>TicTacToe/Board</strong> and <strong>tictactoe/board</strong> are equivalent.</p>
 
 <a name="The.name.of.the.plugin"></a>
 <h4>The name of the plugin</h4>
@@ -265,6 +254,72 @@ This plugin example is in <em>plugins/samples/tic-tac-toe.c</em>.</p>
 
 <p>This plugin is named <strong><em>tictactoe</em></strong>.</p>
 
+<a name="Dependencies.when.compiling"></a>
+<h2>Dependencies when compiling</h2>
+
+<p>Afb-daemon provides a configuration file for <em>pkg-config</em>.
+Typing the command</p>
+
+<pre><code>pkg-config --cflags afb-daemon
+</code></pre>
+
+<p>will print the flags to use for compiling, like this:</p>
+
+<pre><code>$ pkg-config --cflags afb-daemon
+-I/opt/local/include -I/usr/include/json-c 
+</code></pre>
+
+<p>For linking, you should use</p>
+
+<pre><code>$ pkg-config --libs afb-daemon
+-ljson-c
+</code></pre>
+
+<p>As you see, afb-daemon automatically includes dependency to json-c.
+This is done through the <strong>Requires</strong> keyword of pkg-config
+because almost all plugin will use <strong>json-c</strong>.</p>
+
+<p>If this behaviour is a problem, let us know.</p>
+
+<p>Internally, afb-daemon uses <strong>libsystemd</strong> for its event loop
+and for its binding to D-Bus.
+Plugins developpers are encouraged to also use this library.
+But it is a matter of choice.
+Thus there is no dependency to <strong>libsystemd</strong>.</p>
+
+<blockquote><p>Afb-daemon provides no library for plugins.
+The functions that the plugin need to have are given
+to the plugin at runtime through pointer using read-only
+memory.</p></blockquote>
+
+<a name="Header.files.to.include"></a>
+<h2>Header files to include</h2>
+
+<p>The plugin <em>tictactoe</em> has the following lines for its includes:</p>
+
+<pre><code>#define _GNU_SOURCE
+#include &lt;stdio.h&gt;
+#include &lt;string.h&gt;
+#include &lt;json-c/json.h&gt;
+#include &lt;afb/afb-plugin.h&gt;
+</code></pre>
+
+<p>The header <em>afb/afb-plugin.h</em> includes all the features that a plugin
+needs except two foreign header that must be included by the plugin
+if it needs it:</p>
+
+<ul>
+<li><em>json-c/json.h</em>: this header must be include to handle json objects;</li>
+<li><em>systemd/sd-event.h</em>: this must be include to access the main loop;</li>
+<li><em>systemd/sd-bus.h</em>: this may be include to use dbus connections.</li>
+</ul>
+
+
+<p>The <em>tictactoe</em> plugin does not use systemd features so it is not included.</p>
+
+<p>When including <em>afb/afb-plugin.h</em>, the macro <strong>_GNU_SOURCE</strong> must be
+defined.</p>
+
 <a name="Choosing.names"></a>
 <h2>Choosing names</h2>
 
@@ -304,7 +359,7 @@ and upper case when searching for an API by its name.</p>
 <p>The names of the verbs are not checked.</p>
 
 <p>However, the validity rules for verb&rsquo;s names are the
-same as for API&rsquo;s names except that the dot (.) character
+same as for API names except that the dot (.) character
 is forbidden.</p>
 
 <p>Afb-daemon make no distinction between lower case
@@ -344,60 +399,6 @@ valid javascript identifier.</p>
 rely on the case sensitivity and to avoid the use of
 names different only by the case.</p>
 
-<a name="Options.to.set.when.compiling.plugins"></a>
-<h2>Options to set when compiling plugins</h2>
-
-<p>Afb-daemon provides a configuration file for <em>pkg-config</em>.
-Typing the command</p>
-
-<pre><code>pkg-config --cflags afb-daemon
-</code></pre>
-
-<p>will print the flags to use for compiling, like this:</p>
-
-<pre><code>$ pkg-config --cflags afb-daemon
--I/opt/local/include -I/usr/include/json-c 
-</code></pre>
-
-<p>For linking, you should use</p>
-
-<pre><code>$ pkg-config --libs afb-daemon
--ljson-c
-</code></pre>
-
-<p>As you see, afb-daemon automatically includes dependency to json-c.
-This is done through the <strong>Requires</strong> keyword of pkg-config.</p>
-
-<p>If this behaviour is a problem, let us know.</p>
-
-<a name="Header.files.to.include"></a>
-<h2>Header files to include</h2>
-
-<p>The plugin <em>tictactoe</em> has the following lines for its includes:</p>
-
-<pre><code>#define _GNU_SOURCE
-#include &lt;stdio.h&gt;
-#include &lt;string.h&gt;
-#include &lt;json-c/json.h&gt;
-#include &lt;afb/afb-plugin.h&gt;
-</code></pre>
-
-<p>The header <em>afb/afb-plugin.h</em> includes all the features that a plugin
-needs except two foreign header that must be included by the plugin
-if it needs it:</p>
-
-<ul>
-<li><em>json-c/json.h</em>: this header must be include to handle json objects;</li>
-<li><em>systemd/sd-event.h</em>: this must be include to access the main loop;</li>
-<li><em>systemd/sd-bus.h</em>: this may be include to use dbus connections.</li>
-</ul>
-
-
-<p>The <em>tictactoe</em> plugin does not use systemd features so it is not included.</p>
-
-<p>When including <em>afb/afb-plugin.h</em>, the macro <strong>_GNU_SOURCE</strong> must be
-defined.</p>
-
 <a name="Writing.a.synchronous.verb.implementation"></a>
 <h2>Writing a synchronous verb implementation</h2>
 
@@ -600,12 +601,20 @@ failure replies.</p>
  * The status of the reply is automatically set to "success".
  * Its send the object 'obj' (can be NULL) with an
  * informationnal comment 'info (can also be NULL).
+ *
+ * For conveniency, the function calls 'json_object_put' for 'obj'.
+ * Thus, in the case where 'obj' should remain available after
+ * the function returns, the function 'json_object_get' shall be used.
  */
 void afb_req_success(struct afb_req req, struct json_object *obj, const char *info);
 
 /*
  * Same as 'afb_req_success' but the 'info' is a formatting
  * string followed by arguments.
+ *
+ * For conveniency, the function calls 'json_object_put' for 'obj'.
+ * Thus, in the case where 'obj' should remain available after
+ * the function returns, the function 'json_object_get' shall be used.
  */
 void afb_req_success_f(struct afb_req req, struct json_object *obj, const char *info, ...);
 </code></pre>
@@ -621,16 +630,29 @@ void afb_req_success_f(struct afb_req req, struct json_object *obj, const char *
  * Note that calling afb_req_fail("success", info) is equivalent
  * to call afb_req_success(NULL, info). Thus even if possible it
  * is strongly recommanded to NEVER use "success" for status.
+ *
+ * For conveniency, the function calls 'json_object_put' for 'obj'.
+ * Thus, in the case where 'obj' should remain available after
+ * the function returns, the function 'json_object_get' shall be used.
  */
 void afb_req_fail(struct afb_req req, const char *status, const char *info);
 
 /*
  * Same as 'afb_req_fail' but the 'info' is a formatting
  * string followed by arguments.
+ *
+ * For conveniency, the function calls 'json_object_put' for 'obj'.
+ * Thus, in the case where 'obj' should remain available after
+ * the function returns, the function 'json_object_get' shall be used.
  */
 void afb_req_fail_f(struct afb_req req, const char *status, const char *info, ...);
 </code></pre>
 
+<blockquote><p>For conveniency, these functions call <strong>json_object_put</strong> to release the object <strong>obj</strong>
+that they send. Then <strong>obj</strong> can not be used after calling one of these reply functions.
+When it is not the expected behaviour, calling the function <strong>json_object_get</strong> on the object <strong>obj</strong>
+before cancels the effect of <strong>json_object_put</strong>.</p></blockquote>
+
 <a name="Getting.argument.of.invocation"></a>
 <h2>Getting argument of invocation</h2>
 
@@ -879,7 +901,7 @@ const struct AFB_interface *afbitf;
 static const struct AFB_verb_desc_v1 plugin_verbs[] = {
    /* VERB'S NAME     SESSION MANAGEMENT          FUNCTION TO CALL  SHORT DESCRIPTION */
    { .name= "new",   .session= AFB_SESSION_NONE, .callback= new,   .info= "Starts a new game" },
-   { .name= "play",  .session= AFB_SESSION_NONE, .callback= play,  .info= "Tells the server to play" },
+   { .name= "play",  .session= AFB_SESSION_NONE, .callback= play,  .info= "Asks the server to play" },
    { .name= "move",  .session= AFB_SESSION_NONE, .callback= move,  .info= "Tells the client move" },
    { .name= "board", .session= AFB_SESSION_NONE, .callback= board, .info= "Get the current board" },
    { .name= "level", .session= AFB_SESSION_NONE, .callback= level, .info= "Set the server level" },
@@ -1196,9 +1218,169 @@ journal, syslog or kmsg. (See man sd-daemon).</p>
 <a name="Sending.events"></a>
 <h2>Sending events</h2>
 
+<p>Since version 0.5, plugins can broadcast events to any potential listener.
+This kind of bradcast is not targeted. Event targeted will come in a future
+version of afb-daemon.</p>
+
+<p>The plugin <em>tic-tac-toe</em> broadcasts events when the board changes.
+This is done in the function <strong>changed</strong>:</p>
+
+<pre><code>/*
+ * signals a change of the board
+ */
+static void changed(struct board *board, const char *reason)
+{
+        ...
+        struct json_object *description;
+
+        /* get the description */
+        description = describe(board);
+
+        ...
+
+        afb_daemon_broadcast_event(afbitf-&gt;daemon, reason, description);
+}
+</code></pre>
+
+<p>The description of the changed board is pushed via the daemon interface.</p>
+
+<p>Within the plugin <em>tic-tac-toe</em>, the <em>reason</em> indicates the origin of
+the change. For the function <strong>afb_daemon_broadcast_event</strong>, the second
+parameter is the name of the broadcasted event. The third argument is the
+object that is transmitted with the event.</p>
+
+<p>The function <strong>afb_daemon_broadcast_event</strong> is defined as below:</p>
+
+<pre><code>/*
+ * Broadcasts widely the event of 'name' with the data 'object'.
+ * 'object' can be NULL.
+ * 'daemon' MUST be the daemon given in interface when activating the plugin.
+ *
+ * For conveniency, the function calls 'json_object_put' for 'object'.
+ * Thus, in the case where 'object' should remain available after
+ * the function returns, the function 'json_object_get' shall be used.
+ */
+void afb_daemon_broadcast_event(struct afb_daemon daemon, const char *name, struct json_object *object);
+</code></pre>
+
+<blockquote><p>Be aware, as for reply functions, the <strong>object</strong> is automatically released using
+<strong>json_object_put</strong> by the function. Then call <strong>json_object_get</strong> before
+calling <strong>afb_daemon_broadcast_event</strong> to keep <strong>object</strong> available
+after the returning of the function.</p></blockquote>
+
+<p>In fact the event name received by the listener is prefixed with
+the name of the plugin. So when the change occurs after a move, the
+reason is <strong>move</strong> and then the clients receive the event <strong>tictactoe/move</strong>.</p>
+
+<blockquote><p>Note that nothing is said about the case sensitivity of event names.
+However, the event is always prefixed with the name that the plugin
+declared, with the same case, followed with a slash /.
+Thus it is safe to compare event using a case sensitive comparison.</p></blockquote>
+
 <a name="Writing.an.asynchronous.verb.implementation"></a>
 <h2>Writing an asynchronous verb implementation</h2>
 
+<p>The <em>tic-tac-toe</em> example allows two clients or more to share the same board.
+This is implemented by the verb <strong>join</strong> that illustrated partly the how to
+retrieve arguments.</p>
+
+<p>When two or more clients are sharing a same board, one of them can wait
+until the state of the board changes. (This coulded also be implemented using
+events because an even is generated each time the board changes).</p>
+
+<p>In this case, the reply to the wait is sent only when the board changes.
+See the diagram below:</p>
+
+<pre><code>CLIENT A       CLIENT B         TIC-TAC-TOE
+   |              |                  |
+   +--------------|-----------------&gt;| wait . . . . . . . .
+   |              |                  |                     .
+   :              :                  :                      .
+   :              :                  :                      .
+   |              |                  |                      .
+   |              +-----------------&gt;| move . . .           .
+   |              |                  |          V           .
+   |              |&lt;-----------------+ success of move      .
+   |              |                  |                    .
+   |&lt;-------------|------------------+ success of wait  &lt;
+</code></pre>
+
+<p>Here, this is an invocation of the plugin by an other client that
+unblock the suspended <em>wait</em> call.
+But in general, this will be a timer, a hardware event, the sync with
+a concurrent process or thread, &hellip;</p>
+
+<p>So the case is common, this is an asynchronous implementation.</p>
+
+<p>Here is the listing of the function <strong>wait</strong>:</p>
+
+<pre><code>static void wait(struct afb_req req)
+{
+        struct board *board;
+        struct waiter *waiter;
+
+        /* retrieves the context for the session */
+        board = board_of_req(req);
+        INFO(afbitf, "method 'wait' called for boardid %d", board-&gt;id);
+
+        /* creates the waiter and enqueues it */
+        waiter = calloc(1, sizeof *waiter);
+        waiter-&gt;req = req;
+        waiter-&gt;next = board-&gt;waiters;
+        afb_req_addref(req);
+        board-&gt;waiters = waiter;
+}
+</code></pre>
+
+<p>After retrieving the board, the function adds a new waiter to the
+current list of waiters and returns without sending a reply.</p>
+
+<p>Before returning, it increases the reference count of the
+request <strong>req</strong> using the function <strong>afb_req_addref</strong>.</p>
+
+<blockquote><p>When the implentation of a verb returns without sending a reply,
+it <strong>MUST</strong> increment the reference count of the request
+using <strong>afb_req_addref</strong>. If it doesn&rsquo;t bad things can happen.</p></blockquote>
+
+<p>Later, when the board changes, it calls the function <strong>changed</strong>
+of <em>tic-tac-toe</em> with the reason of the change.</p>
+
+<p>Here is the full listing of the function <strong>changed</strong>:</p>
+
+<pre><code>/*
+ * signals a change of the board
+ */
+static void changed(struct board *board, const char *reason)
+{
+        struct waiter *waiter, *next;
+        struct json_object *description;
+
+        /* get the description */
+        description = describe(board);
+
+        waiter = board-&gt;waiters;
+        board-&gt;waiters = NULL;
+        while (waiter != NULL) {
+                next = waiter-&gt;next;
+                afb_req_success(waiter-&gt;req, json_object_get(description), reason);
+                afb_req_unref(waiter-&gt;req);
+                free(waiter);
+                waiter = next;
+        }
+
+        afb_event_sender_push(afb_daemon_get_event_sender(afbitf-&gt;daemon), reason, description);
+}
+</code></pre>
+
+<p>The list of waiters is walked and a reply is sent to each waiter.
+After the sending the reply, the reference count of the request
+is decremented using <strong>afb_req_unref</strong> to allow its resources to be freed.</p>
+
+<blockquote><p>The reference count <strong>MUST</strong> be decremented using <strong>afb_req_unref</strong> because,
+otherwise, there is a leak of resources.
+It must be decremented <strong>AFTER</strong> the sending of the reply, because, otherwise,
+bad things may happen.</p></blockquote>
+
 <a name="How.to.build.a.plugin"></a>
 <h2>How to build a plugin</h2>