f0e3a37633e5d5378c59872bfe493a18874eaa73
[src/app-framework-binder.git] / doc / writing-afb-plugins.md
1 HOWTO WRITE a PLUGIN for AFB-DAEMON
2 ===================================
3     version: 1
4     Date:    24 mai 2016
5     Author:  José Bollo
6
7 TABLE-OF-CONTENT-HERE
8
9 Summary
10 -------
11
12 The binder afb-daemon serves files through
13 the HTTP protocol and offers access to API's through
14 HTTP or WebSocket protocol.
15
16 The plugins are used to add API's to afb-daemon.
17 This part describes how to write a plugin for afb-daemon.
18 Excepting this summary, this part is intended to be read
19 by developpers.
20
21 Before going into details, through a tiny example,
22 a short overview plugins basis is needed.
23
24 ### Nature of a plugin
25
26 A plugin is a separate piece of code made of a shared library.
27 The plugin is loaded and activated by afb-daemon when afb-daemon
28 starts.
29
30 Technically, a plugin is not linked to any library of afb-daemon.
31  
32 ### Live cycle of a plugin within afb-daemon
33
34 The plugins are loaded and activated when afb-daemon starts.
35
36 At start, the plugin initialise itself.
37 If it fails to initialise then afb-daemon stops.
38
39 Conversely, if it success to initialize, it must declare
40 a name, that must be unique, and a list of API's verbs.
41
42 When initialized, the functions implementing the API's verbs
43 of the plugin are activated on call.
44
45 At the end, nothing special is done by afb-daemon.
46 Consequently, developpers of plugins should use 'atexit'
47 or 'on_exit' during initialisation if they need to
48 perform specific actions when stopping.
49
50 ### Content of a plugin
51
52 For afb-daemon, a plugin contains 2 different
53 things: names and functions.
54
55 There is two kind of names:
56  - the name of the plugin,
57  - the names of the verbs.
58
59 There is two kind of functions:
60  - the initialisation function
61  - functions implementing verbs
62
63 Afb-daemon translates the name of the method that is
64 invoked to a pair of API and verb names. For example,
65 the method named **foo/bar** translated to the API
66 name **foo** and the verb name **bar**.
67 To serve it, afb-daemon search the plugin that record
68 the name **foo** and if it also recorded the verb **bar**,
69 it calls the implementation function declared for this verb.
70
71 Afb-daemon make no distinction between lower case
72 and upper case when searching for a method.
73 Thus, The names **TicTacToe/Board** and **tictactoe/borad**
74 are equals.
75
76 #### The name of the plugin
77
78 The name of the plugin is also known as the name
79 of the API that defines the plugin.
80
81 This name is also known as the prefix.
82
83 The name of a plugin MUST be unique within afb-daemon.
84
85 For example, when a client of afb-daemon
86 calls a method named **foo/bar**. Afb-daemon
87 extracts the prefix **foo** and the suffix **bar**.
88 **foo** is the API name and must match a plugin name,
89 the plugin that implements the verb **bar**.
90
91 #### Names of verbs
92
93 Each plugin exposes a set of verbs that can be called
94 by client of afb-daemon.
95
96 The name of a verb MUST be unique within a plugin.
97
98 Plugins link verbs to functions that are called
99 when clients emit requests for that verb.
100
101 For example, when a client of afb-daemon
102 calls a method named **foo/bar**.
103
104 #### The initialisation function
105
106 The initialisation function serves several purposes.
107
108 1. It allows afb-daemon to check the version
109 of the plugin using the name of the initialisation
110 functions that it found. Currently, the initialisation
111 function is named **pluginAfbV1Register**. It identifies
112 the first version of plugins.
113
114 2. It allows the plugin to initialise itself.
115
116 3. It serves to the plugin to declare names, descriptions,
117 requirements and implmentations of the verbs that it exposes.
118
119 #### Functions implementing verbs
120
121 When a method is called, afb-daemon constructs a request
122 object and pass it to the implementation function for verb
123 within the plugin of the API.
124
125 An implementation function receives a request object that
126 is used to get arguments of the request, to send
127 answer, to store session data.
128
129 A plugin MUST send an answer to the request.
130
131 But it is not mandatory to send the answer
132 before to return from the implementing function.
133 This behaviour is important for implementing
134 asynchronous actions.
135
136 Implementation functions that always reply to the request
137 before returning are named *synchronous implementations*.
138 Those that don't always reply to the request before
139 returning are named *asynchronous implementations*.
140
141 Asynchronous implementations typically initiate an
142 asynchronous action and record to send the reply
143 on completion of this action.
144
145 The Tic-Tac-Toe example
146 -----------------------
147
148 This part explains how to write an afb-plugin.
149 For the sake of being practical we will use many
150 examples from the tic-tac-toe example.
151 This plugin example is in *plugins/samples/tic-tac-toe.c*.
152
153 This plugin is named ***tictactoe***.
154
155 Choosing names
156 --------------
157
158 The designer of a plugin must defines names for its plugin
159 (or its API) and for the verbs of its API. He also
160 must defines names for arguments given by name.
161
162 While forging names, the designer should take into account
163 the rules for making valid names and some rules that make
164 the names easy to use across plaforms.
165
166 The names and strings used ALL are UTF-8 encoded.
167
168 ### Names for API (plugin)
169
170 The names of the API are checked.
171 All characters are authorised except:
172
173 - the control characters (\u0000 .. \u001f)
174 - the characters of the set { ' ', '"', '#', '%', '&',
175   '\'', '/', '?', '`', '\x7f' }
176
177 In other words the set of forbidden characters is
178 { \u0000..\u0020, \u0022, \u0023, \u0025..\u0027,
179   \u002f, \u003f, \u0060, \u007f }.
180
181 Afb-daemon make no distinction between lower case
182 and upper case when searching for an API by its name.
183
184 ### Names for verbs
185
186 The names of the verbs are not checked.
187
188 However, the validity rules for verb's names are the
189 same as for API's names except that the dot (.) character
190 is forbidden.
191
192 Afb-daemon make no distinction between lower case
193 and upper case when searching for an API by its name.
194
195 ### Names for arguments
196
197 The names for arguments are not restricted and can be
198 anything.
199
200 The arguments are searched with the case sensitive
201 string comparison. Thus the names "index" and "Index"
202 are not the same.
203
204 ### Forging names widely available
205
206 The key names of javascript object can be almost
207 anything using the arrayed notation:
208
209         object[key] = value
210
211 That is not the case with the dot notation:
212
213         object.key = value
214
215 Using the dot notation, the key must be a valid javascript
216 identifier.
217
218 For this reason, the chosen names should better be
219 valid javascript identifier.
220
221 It is also a good practice, even for arguments, to not
222 rely on the case sensitivity and to avoid the use of
223 names different only by the case.
224
225 Options to set when compiling plugins
226 -------------------------------------
227
228 Afb-daemon provides a configuration file for *pkg-config*.
229 Typing the command
230
231         pkg-config --cflags afb-daemon
232
233 will print the flags to use for compiling, like this:
234
235         $ pkg-config --cflags afb-daemon
236         -I/opt/local/include -I/usr/include/json-c 
237
238 For linking, you should use
239
240         $ pkg-config --libs afb-daemon
241         -ljson-c
242
243 As you see, afb-daemon automatically includes dependency to json-c.
244 This is done through the **Requires** keyword of pkg-config.
245
246 If this behaviour is a problem, let us know.
247
248 Header files to include
249 -----------------------
250
251 The plugin *tictactoe* has the following lines for its includes:
252
253         #define _GNU_SOURCE
254         #include <stdio.h>
255         #include <string.h>
256         #include <json-c/json.h>
257         #include <afb/afb-plugin.h>
258
259 The header *afb/afb-plugin.h* includes all the features that a plugin
260 needs except two foreign header that must be included by the plugin
261 if it needs it:
262
263 - *json-c/json.h*: this header must be include to handle json objects;
264 - *systemd/sd-event.h*: this must be include to access the main loop;
265 - *systemd/sd-bus.h*: this may be include to use dbus connections.
266
267 The *tictactoe* plugin does not use systemd features so it is not included.
268
269 When including *afb/afb-plugin.h*, the macro **_GNU_SOURCE** must be
270 defined.
271
272 Writing a synchronous verb implementation
273 -----------------------------------------
274
275 The verb **tictactoe/board** is a synchronous implementation.
276 Here is its listing:
277
278         /*
279          * get the board
280          */
281         static void board(struct afb_req req)
282         {
283                 struct board *board;
284                 struct json_object *description;
285
286                 /* retrieves the context for the session */
287                 board = board_of_req(req);
288                 INFO(afbitf, "method 'board' called for boardid %d", board->id);
289
290                 /* describe the board */
291                 description = describe(board);
292
293                 /* send the board's description */
294                 afb_req_success(req, description, NULL);
295         }
296
297 This examples show many aspects of writing a synchronous
298 verb implementation.
299
300 ### The incoming request
301
302 For any implementation,  the request is received by a structure of type
303 **struct afb_req**.
304
305 ***Important: note that this is a PLAIN structure, not a pointer to a structure.***
306
307 This structure, here named *req*, is used
308
309 *req* is used to get arguments of the request, to send
310 answer, to store session data.
311
312 This object and its interface is defined and documented
313 in the file names *afb/afb-req-itf.h*
314
315 The above example uses 2 times the request object *req*.
316
317 The first time, it is used for retrieving the board attached to
318 the session of the request.
319
320 The second time, it is used to send the reply: an object that
321 describes the current board.
322
323 ### Associating an object to the session for the plugin
324
325 When the plugin *tic-tac-toe* receives a request, it musts regain
326 the board that describes the game associated to the session.
327
328 For a plugin, having data associated to a session is a common case.
329 This data is called the context of the plugin for the session.
330 For the plugin *tic-tac-toe*, the context is the board.
331
332 The requests *afb_req* offer four functions for
333 storing and retrieving the context associated to the session.
334
335 These functions are:
336
337 - **afb_req_context_get**:
338   retrieves the context data stored for the plugin.
339
340 - **afb_req_context_set**:
341   store the context data of the plugin.
342
343 - **afb_req_context**:
344   retrieves the context data of the plugin,
345   if needed, creates the context and store it.
346
347 - **afb_req_context_clear**:
348   reset the stored data.
349
350 The plugin *tictactoe* use a convenient function to retrieve
351 its context: the board. This function is *board_of_req*:
352
353         /*
354          * retrieves the board of the request
355          */
356         static inline struct board *board_of_req(struct afb_req req)
357         {
358                 return afb_req_context(req, (void*)get_new_board, (void*)release_board);
359         }
360
361 This function is very simple because it merely wraps
362 a call to the function **afb_req_context**, providing
363 all needed arguments.
364 The casts are required to avoid a warning when compiling.
365
366 Here is the definition of the function **afb_req_context**
367
368         /*
369          * Gets the pointer stored by the plugin for the session of 'req'.
370          * If the stored pointer is NULL, indicating that no pointer was
371          * already stored, afb_req_context creates a new context by calling
372          * the function 'create_context' and stores it with the freeing function
373          * 'free_context'.
374          */
375         static inline void *afb_req_context(struct afb_req req, void *(*create_context)(), void (*free_context)(void*))
376         {
377                 void *result = afb_req_context_get(req);
378                 if (result == NULL) {
379                         result = create_context();
380                         afb_req_context_set(req, result, free_context);
381                 }
382                 return result;
383         }
384
385 This powerful function ensures that the context exists and is
386 stored for the session.
387
388 The function **get_new_board** creates a new board and set its
389 count of use to 1. The boards are counting their count of use
390 to free there ressources when no more used.
391
392 The function **release_board** 
393
394 ### Sending the reply to a request
395
396 Getting argument of invocation
397 ------------------------------
398
399 How to build a plugin
400 ---------------------
401
402 Afb-daemon provides a The packaging of afb-daemon
403
404