diff options
author | José Bollo <jose.bollo@iot.bzh> | 2016-05-27 22:18:26 +0200 |
---|---|---|
committer | José Bollo <jose.bollo@iot.bzh> | 2016-05-27 22:18:26 +0200 |
commit | d96d0533b8326570db57d13b8f808bc62d1a7fa4 (patch) | |
tree | deee50d324e9b8a44f832f4ac77370cee2e42e61 | |
parent | b81bab801d1a39cce7254b0c056d991412ec4331 (diff) |
improves documentation
Change-Id: Idbd1b735571c2e35daed23d43f8d5d3990881533
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r-- | doc/FAQ.html | 2 | ||||
-rw-r--r-- | doc/FAQ.md | 2 | ||||
-rw-r--r-- | doc/afb-daemon-vocabulary.html | 2 | ||||
-rw-r--r-- | doc/afb-daemon-vocabulary.md | 2 | ||||
-rw-r--r-- | doc/afb-plugin-writing.html | 202 | ||||
-rw-r--r-- | doc/afb-plugin-writing.md | 179 | ||||
-rw-r--r-- | include/afb/afb-plugin.h | 21 | ||||
-rw-r--r-- | plugins/samples/HelloWorld.c | 4 | ||||
-rw-r--r-- | plugins/samples/tic-tac-toe.c | 4 |
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> @@ -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 <stdio.h> +#include <string.h> +#include <json-c/json.h> +#include <afb/afb-plugin.h> +</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 <stdio.h> -#include <string.h> -#include <json-c/json.h> -#include <afb/afb-plugin.h> -</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->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->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); +</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" }, |