aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2016-05-27 22:18:26 +0200
committerJosé Bollo <jose.bollo@iot.bzh>2016-05-27 22:18:26 +0200
commitd96d0533b8326570db57d13b8f808bc62d1a7fa4 (patch)
treedeee50d324e9b8a44f832f4ac77370cee2e42e61
parentb81bab801d1a39cce7254b0c056d991412ec4331 (diff)
improves documentation
Change-Id: Idbd1b735571c2e35daed23d43f8d5d3990881533 Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r--doc/FAQ.html2
-rw-r--r--doc/FAQ.md2
-rw-r--r--doc/afb-daemon-vocabulary.html2
-rw-r--r--doc/afb-daemon-vocabulary.md2
-rw-r--r--doc/afb-plugin-writing.html202
-rw-r--r--doc/afb-plugin-writing.md179
-rw-r--r--include/afb/afb-plugin.h21
-rw-r--r--plugins/samples/HelloWorld.c4
-rw-r--r--plugins/samples/tic-tac-toe.c4
9 files changed, 300 insertions, 118 deletions
diff --git a/doc/FAQ.html b/doc/FAQ.html
index ffda81af..98337815 100644
--- a/doc/FAQ.html
+++ b/doc/FAQ.html
@@ -8,7 +8,7 @@
<h1>Frequently Asked Question about AFB-DAEMON</h1>
<pre><code>version: 1
-Date: 26 mai 2016
+Date: 27 mai 2016
Author: José Bollo
</code></pre>
diff --git a/doc/FAQ.md b/doc/FAQ.md
index 93647311..61105823 100644
--- a/doc/FAQ.md
+++ b/doc/FAQ.md
@@ -1,7 +1,7 @@
Frequently Asked Question about AFB-DAEMON
==========================================
version: 1
- Date: 26 mai 2016
+ Date: 27 mai 2016
Author: José Bollo
TABLE-OF-CONTENT-HERE
diff --git a/doc/afb-daemon-vocabulary.html b/doc/afb-daemon-vocabulary.html
index 096f5076..fadd1dee 100644
--- a/doc/afb-daemon-vocabulary.html
+++ b/doc/afb-daemon-vocabulary.html
@@ -8,7 +8,7 @@
<h1>Vocabulary for AFB-DAEMON</h1>
<pre><code>version: 1
-Date: 26 mai 2016
+Date: 27 mai 2016
Author: José Bollo
</code></pre>
diff --git a/doc/afb-daemon-vocabulary.md b/doc/afb-daemon-vocabulary.md
index 71771947..8427b736 100644
--- a/doc/afb-daemon-vocabulary.md
+++ b/doc/afb-daemon-vocabulary.md
@@ -1,7 +1,7 @@
Vocabulary for AFB-DAEMON
=========================
version: 1
- Date: 26 mai 2016
+ Date: 27 mai 2016
Author: José Bollo
TABLE-OF-CONTENT-HERE
diff --git a/doc/afb-plugin-writing.html b/doc/afb-plugin-writing.html
index 9a98ffe9..9873b626 100644
--- a/doc/afb-plugin-writing.html
+++ b/doc/afb-plugin-writing.html
@@ -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>
@@ -265,6 +265,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>
@@ -344,60 +410,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>
@@ -879,7 +891,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 +1208,85 @@ 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.
+ */
+void afb_daemon_broadcast_event(struct afb_daemon daemon, const char *name, struct json_object *object);
+</code></pre>
+
+<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>/<em>
+ * signals a change of the board
+ </em>/
+static void changed(struct board <em>board, const char </em>reason)
+{
+ struct waiter <em>waiter, </em>next;
+ struct json_object *description;</p>
+
+<pre><code>/* 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>}</p>
+
<a name="How.to.build.a.plugin"></a>
<h2>How to build a plugin</h2>
diff --git a/doc/afb-plugin-writing.md b/doc/afb-plugin-writing.md
index 734b15a5..7861021b 100644
--- a/doc/afb-plugin-writing.md
+++ b/doc/afb-plugin-writing.md
@@ -178,6 +178,65 @@ This plugin example is in *plugins/samples/tic-tac-toe.c*.
This plugin is named ***tictactoe***.
+Dependencies when compiling
+---------------------------
+
+Afb-daemon provides a configuration file for *pkg-config*.
+Typing the command
+
+ pkg-config --cflags afb-daemon
+
+will print the flags to use for compiling, like this:
+
+ $ pkg-config --cflags afb-daemon
+ -I/opt/local/include -I/usr/include/json-c
+
+For linking, you should use
+
+ $ pkg-config --libs afb-daemon
+ -ljson-c
+
+As you see, afb-daemon automatically includes dependency to json-c.
+This is done through the **Requires** keyword of pkg-config
+because almost all plugin will use **json-c**.
+
+If this behaviour is a problem, let us know.
+
+Internally, afb-daemon uses **libsystemd** 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 **libsystemd**.
+
+> 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.
+
+Header files to include
+-----------------------
+
+The plugin *tictactoe* has the following lines for its includes:
+
+ #define _GNU_SOURCE
+ #include <stdio.h>
+ #include <string.h>
+ #include <json-c/json.h>
+ #include <afb/afb-plugin.h>
+
+The header *afb/afb-plugin.h* includes all the features that a plugin
+needs except two foreign header that must be included by the plugin
+if it needs it:
+
+- *json-c/json.h*: this header must be include to handle json objects;
+- *systemd/sd-event.h*: this must be include to access the main loop;
+- *systemd/sd-bus.h*: this may be include to use dbus connections.
+
+The *tictactoe* plugin does not use systemd features so it is not included.
+
+When including *afb/afb-plugin.h*, the macro **_GNU_SOURCE** must be
+defined.
+
Choosing names
--------------
@@ -248,53 +307,6 @@ It is also a good practice, even for arguments, to not
rely on the case sensitivity and to avoid the use of
names different only by the case.
-Options to set when compiling plugins
--------------------------------------
-
-Afb-daemon provides a configuration file for *pkg-config*.
-Typing the command
-
- pkg-config --cflags afb-daemon
-
-will print the flags to use for compiling, like this:
-
- $ pkg-config --cflags afb-daemon
- -I/opt/local/include -I/usr/include/json-c
-
-For linking, you should use
-
- $ pkg-config --libs afb-daemon
- -ljson-c
-
-As you see, afb-daemon automatically includes dependency to json-c.
-This is done through the **Requires** keyword of pkg-config.
-
-If this behaviour is a problem, let us know.
-
-Header files to include
------------------------
-
-The plugin *tictactoe* has the following lines for its includes:
-
- #define _GNU_SOURCE
- #include <stdio.h>
- #include <string.h>
- #include <json-c/json.h>
- #include <afb/afb-plugin.h>
-
-The header *afb/afb-plugin.h* includes all the features that a plugin
-needs except two foreign header that must be included by the plugin
-if it needs it:
-
-- *json-c/json.h*: this header must be include to handle json objects;
-- *systemd/sd-event.h*: this must be include to access the main loop;
-- *systemd/sd-bus.h*: this may be include to use dbus connections.
-
-The *tictactoe* plugin does not use systemd features so it is not included.
-
-When including *afb/afb-plugin.h*, the macro **_GNU_SOURCE** must be
-defined.
-
Writing a synchronous verb implementation
-----------------------------------------
@@ -755,7 +767,7 @@ The description of the plugin is defined as below.
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" },
@@ -920,10 +932,81 @@ journal, syslog or kmsg. (See man sd-daemon).
Sending events
--------------
+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.
+
+The plugin *tic-tac-toe* broadcasts events when the board changes.
+This is done in the function **changed**:
+
+ /*
+ * 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->daemon, reason, description);
+ }
+
+The description of the changed board is pushed via the daemon interface.
+
+Within the plugin *tic-tac-toe*, the *reason* indicates the origin of
+the change. For the function **afb_daemon_broadcast_event**, the second
+parameter is the name of the broadcasted event. The third argument is the
+object that is transmitted with the event.
+
+The function **afb_daemon_broadcast_event** is defined as below:
+
+ /*
+ * 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.
+ */
+ void afb_daemon_broadcast_event(struct afb_daemon daemon, const char *name, struct json_object *object);
+
+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 **move** and then the clients receive the event **tictactoe/move**.
+
+> 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.
+
Writing an asynchronous verb implementation
-------------------------------------------
+/*
+ * 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->waiters;
+ board->waiters = NULL;
+ while (waiter != NULL) {
+ next = waiter->next;
+ afb_req_success(waiter->req, json_object_get(description), reason);
+ afb_req_unref(waiter->req);
+ free(waiter);
+ waiter = next;
+ }
+
+ afb_event_sender_push(afb_daemon_get_event_sender(afbitf->daemon), reason, description);
+}
How to build a plugin
---------------------
diff --git a/include/afb/afb-plugin.h b/include/afb/afb-plugin.h
index cad55fbe..3d16c7ad 100644
--- a/include/afb/afb-plugin.h
+++ b/include/afb/afb-plugin.h
@@ -56,10 +56,10 @@ enum AFB_plugin_version
*/
enum AFB_session_v1
{
- AFB_SESSION_NONE = 0, /* no session and no authentification required */
- AFB_SESSION_CREATE = 1, /* obsolete */
- AFB_SESSION_CLOSE = 2, /* closes the session after authentification */
- AFB_SESSION_RENEW = 4, /* refreshes the token after authentification */
+ AFB_SESSION_NONE = 0, /* nothing required */
+ AFB_SESSION_CREATE = 1, /* Obsolete */
+ AFB_SESSION_CLOSE = 2, /* After token authentification, closes the session at end */
+ AFB_SESSION_RENEW = 4, /* After token authentification, refreshes the token at end */
AFB_SESSION_CHECK = 8, /* Requires token authentification */
AFB_SESSION_LOA_GE = 16, /* check that the LOA is greater or equal to the given value */
@@ -67,12 +67,13 @@ enum AFB_session_v1
AFB_SESSION_LOA_EQ = 48, /* check that the LOA is equal to the given value */
AFB_SESSION_LOA_SHIFT = 6, /* shift for LOA */
- AFB_SESSION_LOA_MASK = 3, /* mask for LOA */
+ AFB_SESSION_LOA_MASK = 7, /* mask for LOA */
AFB_SESSION_LOA_0 = 0, /* value for LOA of 0 */
AFB_SESSION_LOA_1 = 64, /* value for LOA of 1 */
AFB_SESSION_LOA_2 = 128, /* value for LOA of 2 */
AFB_SESSION_LOA_3 = 192, /* value for LOA of 3 */
+ AFB_SESSION_LOA_4 = 256, /* value for LOA of 4 */
AFB_SESSION_LOA_LE_0 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_0, /* check LOA <= 0 */
AFB_SESSION_LOA_LE_1 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_1, /* check LOA <= 1 */
@@ -208,6 +209,16 @@ static inline struct sd_bus *afb_daemon_get_system_bus(struct afb_daemon daemon)
}
/*
+ * 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.
+ */
+static inline void afb_daemon_broadcast_event(struct afb_daemon daemon, const char *name, struct json_object *object)
+{
+ return afb_event_sender_push(afb_daemon_get_event_sender(daemon), name, object);
+}
+
+/*
* Send a message described by 'fmt' and following parameters
* to the journal for the verbosity 'level'.
* 'file' and 'line' are indicators of position of the code in source files.
diff --git a/plugins/samples/HelloWorld.c b/plugins/samples/HelloWorld.c
index 78a1eafd..fe117846 100644
--- a/plugins/samples/HelloWorld.c
+++ b/plugins/samples/HelloWorld.c
@@ -54,8 +54,8 @@ static void pingBug (struct afb_req request)
static void pingEvent(struct afb_req request)
{
json_object *query = afb_req_json(request);
- afb_event_sender_push(afb_daemon_get_event_sender(interface->daemon), "event", query);
- ping(request, json_object_get(query), "event");
+ afb_daemon_broadcast_event(interface->daemon, "event", json_object_get(query));
+ ping(request, query, "event");
}
diff --git a/plugins/samples/tic-tac-toe.c b/plugins/samples/tic-tac-toe.c
index 79aaaf58..c372e99f 100644
--- a/plugins/samples/tic-tac-toe.c
+++ b/plugins/samples/tic-tac-toe.c
@@ -299,7 +299,7 @@ static void changed(struct board *board, const char *reason)
waiter = next;
}
- afb_event_sender_push(afb_daemon_get_event_sender(afbitf->daemon), reason, description);
+ afb_daemon_broadcast_event(afbitf->daemon, reason, description);
}
/*
@@ -586,7 +586,7 @@ static void wait(struct afb_req req)
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" },