fd75ba56178e251e5e1be41c7cd5bcc51aff6700
[src/app-framework-binder.git] / docs / afb-migration-v1-to-v2.md
1 Migration from binding V1 to binding V2
2 =======================================
3
4 The ***binding*** interface evolved from version 1 to version 2
5 for the following reasons:
6
7  - integration of the security requirements within the bindings
8  - simplification of the API (after developer feedbacks)
9  - removal of obscure features, cleanup
10
11 The ***binder*** can run ***bindings*** v1 and/or v2 in any combination.
12 Thus moving from v1 to v2 is not enforced. There is no real need.
13
14 More, it is possible to write a dual ***binding***: a ***binding*** that
15 implements the version 1 AND the version 2.
16
17 However, IT IS HIGHLY RECOMMENDED TO SWITCH TO ONLY VERSION 2:
18
19  - any new development SHOULD start using ***binding*** V2
20  - existing ***bindings*** SHOULD migrate to the version 2
21
22 This guide covers the migration of bindings from version 1 to version 2.
23
24 It also explains some of the rationale taken when migrating from version 1 to version 2.
25
26 In the future, if ***binding*** api evolves to fresh versions (3, 4, ...)
27 it might be necessarily to write bindings implementing more than
28 just one version. For example, a ***binding*** being v2 AND v3 will resolve
29 the issue of running on older AND newer version of AGL. This should always
30 be possible even if more complicated.
31
32 Important things to known when migrating
33 ----------------------------------------
34
35 One of the most important change when migrating from v1 to v2 is
36 that many functions use an hidden *common* variable.
37 This affects the functions of the following classes:
38
39  - functions of class **daemon**:
40     * functions starting with **afb_daemon_...**
41     * functions for logging: **ERROR**, **WARNING**, **NOTICE**, **INFO**, **DEBUG**
42  - functions of class **service**:
43     * functions starting with **afb_service_...**
44  - callback functions:
45     * the register function (that is removed)
46     * the service init function
47     * the onevent function
48
49 For these functions, the first parameter is now implicit.
50
51 Let takes an example. For ***binding*** v1 you had to write:
52
53 ```C
54         afb_daemon_broadcast_event(afbitf->daemon, reason, description);
55 ```
56
57 For ***binding*** v2, you simply write:
58
59 ```C
60         afb_daemon_broadcast_event(reason, description);
61 ```
62
63 This simplification is possible because the header files included for the bindings
64 now provide a common variable for storing the **daemon** and **service** data.
65
66 As a programmer, you shouldn't care much about that hidden variable.
67 It simplifies the job, that's all and that is the reason of the change.
68
69 An other important difference is between the version 1 and the version 2 is
70 on how the ***binding***'s **API** is documented. The version 2 emphasis the
71 **OpenAPI v3** description of the **API**. For this reason, to avoid
72 duplication of descriptions, only one description is expected: the **OpenAPI** one.
73
74 Task list for the migration
75 ---------------------------
76
77 This task list is:
78
79  1. Enforce use of binding v2 by setting **AFB_BINDING_VERSION**
80  2. Rewrite the main structure and the list of exported verbs
81  3. Adapt the init and callback functions
82  4. Removes the first parameter of functions of classes **daemon**
83     and **service**
84  5. Consider where to emit logs for requests
85  6. Take care of store/unstore changes
86  7. Consider use of synchronous (sub)call requests
87  8. Optionally, removes explicit struct
88
89 The remaining chapters explain these task with more details.
90
91 Enforce use of binding v2 by setting AFB_BINDING_VERSION
92 --------------------------------------------------------
93
94 By defining **AFB_BINDING_VERSION** to **2** you switch to version 2.
95 This is done as below.
96
97 ```C
98 #define AFB_BINDING_VERSION 2
99 #include <afb/afb-binding.h>
100 ```
101
102 After that you will get many errors when compiling.
103
104 Rewrite the main structures and the list of exported verbs
105 ---------------------------------------------------------
106
107 The structures describing the ***binding** changed from version 1 to version 2.
108
109 The structure for describing verbs changed to include security
110 requirements. In version 1 it was:
111
112 ```C
113 struct afb_verb_desc_v1
114 {
115        const char *name;                       /* name of the verb */
116        enum afb_session_flags_v1 session;      /* authorization and session requirements of the verb */
117        void (*callback)(struct afb_req req);   /* callback function implementing the verb */
118        const char *info;                       /* textual description of the verb */
119 };
120 ```
121
122 In version 2 it becomes:
123
124 ```C
125 struct afb_verb_v2
126 {
127         const char *verb;                       /* name of the verb */
128         void (*callback)(struct afb_req req);   /* callback function implementing the verb */
129         const struct afb_auth *auth;            /* required authorization */
130         uint32_t session;                       /* authorization and session requirements of the verb */
131 };
132
133 ```
134
135 The migration of instances of that structure requires the following actions:
136
137  - rename field **name** to **verb**
138  - remove field **info**
139  - adapt field **session** if needed
140  - set field **auth** to NULL
141
142 Example:
143
144 ```C
145  { .name= "new",   .session= AFB_SESSION_NONE, .callback= new,   .info= "Starts a new game" }
146 ```
147
148 Becomes
149
150 ```C
151  { .verb = "new",   .session = AFB_SESSION_NONE, .callback = new, .auth = NULL }
152 ```
153
154 The field **auth** can be set to a value describing the requested
155 authorization.
156
157 The main describing structure also changed. In version 1 it was:
158
159 ```C
160 struct afb_binding_desc_v1
161 {
162        const char *info;                       /* textual information about the binding */
163        const char *prefix;                     /* required prefix name for the binding */
164        const struct afb_verb_desc_v1 *verbs;   /* array of descriptions of verbs terminated by a NULL name */
165 };
166 ```
167
168 In version 2 it becomes:
169
170 ```C
171 struct afb_binding_v2
172 {
173         const char *api;                        /* api name for the binding */
174         const char *specification;              /* textual specification of the binding */
175         const struct afb_verb_v2 *verbs;        /* array of descriptions of verbs terminated by a NULL name */
176         int (*preinit)();                       /* callback at load of the binding */
177         int (*init)();                          /* callback for starting the service */
178         void (*onevent)(const char *event, struct json_object *object); /* callback for handling events */
179         unsigned noconcurrency: 1;              /* avoids concurrent requests to verbs */
180 };
181 ```
182
183 The migration of instances of that structure requires the following actions:
184
185  - declare, explore, name the structure as ```const struct afb_binding_v2 afbBindingV2```
186  - rename the field **prefix** to **api**
187  - remove the field **info**
188  - setup the fields **preinit**, **init**, **onevent** according to the next section
189  - set the field **noconcurrency** to the right value:
190     * to 1 if you want to avoid concurrent calls to verbs.
191     * to 0 if you allow concurrent calls to verbs.
192
193 Example:
194
195 ```C
196 static const struct afb_binding plugin_desc = {
197         .type = AFB_BINDING_VERSION_1,
198         .v1 = {
199                 .info = "Minimal Hello World Sample",
200                 .prefix = "hello",
201                 .verbs = verbs
202         }
203 ```
204 Becomes:
205
206 ```C
207 const struct afb_binding_v2 afbBindingV2 = {
208         .api = "hello",
209         .specification = NULL,
210         .verbs = verbs,
211         .preinit = preinit,
212         .init = init
213 };
214 ```
215
216 The **binder** now relies only on the exported names
217 to deduce the type of the binding. This make the main
218 structure more simple.
219
220 Adapt the init and callback functions
221 -------------------------------------
222
223 The ***bindings*** version 1 defined 3 exported functions:
224
225  - **afbBindingV1Register**
226  - **afbBindingV1ServiceInit**
227  - **afbBindingV1ServiceEvent**
228
229 These function should not be exported any more and there definition changed.
230
231 The function **afbBindingV1Register** is no more used to describe the binding.
232 When a binding has to take actions when it is loaded, it must set the field
233 **preinit** of the structure **afbBindingV2**. This field, this preinit, might
234 be used to check features at load. When it returns a negative number, the
235 ***binder*** stops before initializing any ***binding***.
236
237 The function **afbBindingV1ServiceInit** is replaced by the field **init**
238 of the structure **afbBindingV2**. The init function should return 0 in case
239 of success or a negative error code in case of problem. It is called during
240 initialization of services.
241
242 The function **afbBindingV1ServiceEvent**is replaced by the field **onevent**
243 of the structure **afbBindingV2**.
244
245 The two functions **afbBindingV1Register** and **afbBindingV1ServiceInit**,
246 were taking as parameter the ***binder*** interface and the service interface respectively.
247 These interfaces are now managed hiddenly for the **binding** by the **binder**.
248 So the variable that ***bindings*** version used to store the ***binder*** interface
249 and the service interface are no more needed and can be removed.
250
251 Example:
252
253 ```C
254 const struct afb_binding_interface *interface;
255 struct afb_service service;
256
257 static const struct afb_binding plugin_desc = {
258         .type = AFB_BINDING_VERSION_1,
259         .v1 = {
260                 .info = "Minimal Hello World Sample",
261                 .prefix = "hello",
262                 .verbs = verbs
263         }
264 }
265
266 const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf)
267 {
268         interface = itf;
269         NOTICE(interface, "binding register");
270         return &plugin_desc;
271 }
272
273 int afbBindingV1ServiceInit(struct afb_service svc)
274 {
275         service = svc;
276         NOTICE(interface, "binding init");
277         return 0;
278 }
279
280 void afbBindingV1ServiceEvent(const char *event, struct json_object *object)
281 {
282         NOTICE(interface, "onevent %s", event);
283 }
284 ```
285
286 Becomes:
287
288 ```C
289 static int preinit()
290 {
291         AFB_NOTICE("binding preinit (was register)");
292         return 0;
293 }
294
295 static int init()
296 {
297         AFB_NOTICE("binding init");
298         return 0;
299 }
300
301 static void onevent(const char *event, struct json_object *object)
302 {
303         AFB_NOTICE("onevent %s", event);
304 }
305
306 const struct afb_binding_v2 afbBindingV2 = {
307         .api = "hello",
308         .specification = NULL,
309         .verbs = verbs,
310         .preinit = preinit,
311         .init = init,
312         .onevent = onevent
313 };
314 ```
315
316 The two functions **afbBindingV1Register** and **afbBindingV1ServiceInit**,
317 were taking as parameter the ***binder*** interface and the service interface respectively.
318 These interfaces are now managed hiddenly for the **binding** by the **binder**.
319 So the variable that ***bindings*** version used to store the ***binder*** interface
320 and the service interface are no more needed and can be removed.
321
322 On the above example the following lines were removed:
323 ```C
324 const struct afb_binding_interface *interface;
325 struct afb_service service;
326
327         interface = itf;
328
329         service = svc;
330 ```
331
332
333
334 Removes the first parameter of functions of classes **daemon** and **service**
335 ------------------------------------------------------------------------------
336
337 As explained before, many functions loose there first
338 arguments, this are the functions of the following classes:
339
340  - functions of class **daemon**:
341     * functions starting with **afb_daemon_...**
342     * functions for logging: **ERROR**, **WARNING**, **NOTICE**, **INFO**, **DEBUG**
343  - functions of class **service**:
344     * functions starting with **afb_service_...**
345  - callback functions:
346     * the register function (that is removed)
347     * the service init function
348     * the onevent function
349
350 For these functions, the first parameter is now implicit.
351
352 Example:
353
354 ```C
355         afb_daemon_broadcast_event(afbitf->daemon, reason, description);
356 ```
357
358 Becomes:
359
360 ```C
361         afb_daemon_broadcast_event(reason, description);
362 ```
363
364 Also, to avoid possible conflicts, we introduced prefixed logging functions:
365 the macros **ERROR**, **WARNING**, **NOTICE**, **INFO**, **DEBUG** have now
366 a prefixed version: **AFB\_ERROR**, **AFB\_WARNING**, **AFB\_NOTICE**,
367 **AFB\_INFO**, **AFB\_DEBUG**. It is now recommended to use the prefixed version.
368
369 Example:
370
371 ```C
372         NOTICE(interface, "hello plugin comes to live");
373 ```
374
375 Become:
376
377 ```C
378         NOTICE("hello plugin comes to live");
379 ```
380
381 or, better:
382
383 ```C
384         AFB_NOTICE("hello plugin comes to live");
385 ```
386
387 To remove definition of the un-prefixed versions of logging macros **ERROR**, **WARNING**,
388 **NOTICE**, **INFO**, **DEBUG** and just define **AFB_BINDING_PRAGMA_NO_VERBOSE_UNPREFIX**
389 before to include **afb/afb-binding.h**.
390
391 ```C
392 #define AFB_BINDING_PRAGMA_NO_VERBOSE_UNPREFIX
393 #define AFB_BINDING_VERSION 2
394 #include <afb/afb-binding.h>
395 ```
396
397 Consider where to emit logs for requests
398 ----------------------------------------
399
400 The ***bindings*** v2 now allows to emit log messages associated to ***requests***.
401 This feature is valuable when debugging because it allows to return
402 side information associated to a ***request***.
403
404 The defined macros for logging to requests are: **AFB_REQ_ERROR**,
405 **AFB_REQ_WARNING**, **AFB_REQ_NOTICE**, **AFB_REQ_INFO**, **AFB_REQ_DEBUG**.
406
407 We encourage the use of these new logging facilities everywhere it makes sense.
408
409 Example:
410
411 ```C
412         INFO(afbitf, "method 'new' called for boardid %d", board->id);
413 ```
414
415 Might become:
416
417 ```C
418         AFB_REQ_INFO(req, "method 'new' called for boardid %d", board->id);
419 ```
420
421 Take care of store/unstore change
422 ---------------------------------
423
424 For efficiency, the version 2 redefined how storing/un-storing of
425 requests works. Storing request is needed for asynchronous handling
426 of requests.
427
428 For ***bindings*** version, the signature of the functions were:
429
430 ```C
431 struct afb_req *afb_req_store(struct afb_req req);
432 struct afb_req afb_req_unstore(struct afb_req *req);
433 ```
434
435 For version 2 it becomes
436
437 ```C
438 struct afb_stored_req *afb_req_store(struct afb_req req);
439 struct afb_req afb_req_unstore(struct afb_stored_req *sreq);
440 ```
441
442 Where the structure ```struct afb_stored_req``` is opaque.
443
444 It should require few code change.
445
446 Also check the following chapter that explain that asynchronous (sub)calls
447 can be replaced by synchronous one, avoiding the need to store/unstore
448 requests.
449
450 Consider use of synchronous (sub)call requests
451 ----------------------------------------------
452
453 ***Bindings*** can emit requests for themselves (calls) or for
454 their clients (subcalls). With ***bindings*** version 2 comes
455 also synchronous requests for both cases.
456
457 So when migrating to bindings version 2, a developer can consider
458 to replace the asynchronous requests (with asynchronous call back)
459 by synchronous ones.
460
461 See functions ***afb_service_call_sync*** and ***afb_req_subcall_sync***.
462
463 Optionally, removes explicit struct
464 -----------------------------------
465
466 The new definitions now includes **typedefs** for common
467 structures, as shown on below sample:
468
469 ```C
470 typedef struct afb_daemon               afb_daemon;
471 typedef struct afb_event                afb_event;
472 typedef struct afb_arg                  afb_arg;
473 typedef struct afb_req                  afb_req;
474 typedef struct afb_service              afb_service;
475 ```
476
477 So you can remove the keyword **struct** if it bores you.
478
479 Example:
480
481 ```C
482 static void verb(struct afb_req req)
483 {
484         ...
485 }
486 ```
487
488 Might become:
489
490 ```C
491 static void verb(afb_req req)
492 {
493         ...
494 }
495 ```
496
497 Example of migration
498 --------------------
499
500 The first ***binding*** that migrated from v1 to v2 was
501 the sample **HelloWorld**. Here is shown the differences between
502 the version 1 and the version 2.
503
504 ```diff
505 diff --git a/bindings/samples/HelloWorld.c b/bindings/samples/HelloWorld.c
506 index c6fa779..505aee3 100644
507 --- a/bindings/samples/HelloWorld.c
508 +++ b/bindings/samples/HelloWorld.c
509 @@ -21,9 +21,9 @@
510
511  #include <json-c/json.h>
512
513 +#define AFB_BINDING_VERSION 2
514  #include <afb/afb-binding.h>
515
516 -const struct afb_binding_interface *interface;
517  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
518
519  struct event
520 @@ -79,7 +80,7 @@ static int event_add(const char *tag, const char *name)
521          strcpy(e->tag, tag);
522
523          /* make the event */
524 -       e->event = afb_daemon_make_event(interface->daemon, name);
525 +       e->event = afb_daemon_make_event(name);
526          if (!e->event.closure) { free(e); return -1; }
527
528          /* link */
529 @@ -140,7 +141,7 @@ static void pingBug (struct afb_req request)
530  static void pingEvent(struct afb_req request)
531  {
532          json_object *query = afb_req_json(request);
533 -       afb_daemon_broadcast_event(interface->daemon, "event", json_object_get(query));
534 +       afb_daemon_broadcast_event("event", json_object_get(query));
535          ping(request, json_object_get(query), "event");
536  }
537
538 @@ -288,38 +289,43 @@ static void exitnow (struct afb_req request)
539          exit(0);
540  }
541
542 +static int preinit()
543 +{
544 +       AFB_NOTICE("hello binding comes to live");
545 +       return 0;
546 +}
547 +
548 +static int init()
549 +{
550 +       AFB_NOTICE("hello binding starting");
551 +       return 0;
552 +}
553 +
554  // NOTE: this sample does not use session to keep test a basic as possible
555  //       in real application most APIs should be protected with AFB_SESSION_CHECK
556 -static const struct afb_verb_desc_v1 verbs[]= {
557 -  {"ping"     , AFB_SESSION_NONE, pingSample  , "Ping Application Framework"},
558 -  {"pingfail" , AFB_SESSION_NONE, pingFail    , "Fails"},
559 -  {"pingnull" , AFB_SESSION_NONE, pingNull    , "Return NULL"},
560 -  {"pingbug"  , AFB_SESSION_NONE, pingBug     , "Do a Memory Violation"},
561 -  {"pingJson" , AFB_SESSION_NONE, pingJson    , "Return a JSON object"},
562 -  {"pingevent", AFB_SESSION_NONE, pingEvent   , "Send an event"},
563 -  {"subcall",   AFB_SESSION_NONE, subcall     , "Call api/verb(args)"},
564 -  {"subcallsync",   AFB_SESSION_NONE, subcallsync     , "Call api/verb(args)"},
565 -  {"eventadd",  AFB_SESSION_NONE, eventadd    , "adds the event of 'name' for the 'tag'"},
566 -  {"eventdel",  AFB_SESSION_NONE, eventdel    , "deletes the event of 'tag'"},
567 -  {"eventsub",  AFB_SESSION_NONE, eventsub    , "subscribes to the event of 'tag'"},
568 -  {"eventunsub",AFB_SESSION_NONE, eventunsub  , "unsubscribes to the event of 'tag'"},
569 -  {"eventpush", AFB_SESSION_NONE, eventpush   , "pushs the event of 'tag' with the 'data'"},
570 -  {"exit",      AFB_SESSION_NONE, exitnow     , "exits from afb-daemon"},
571 -  {NULL}
572 +static const struct afb_verb_v2 verbs[]= {
573 +  { "ping"     ,    pingSample , NULL, AFB_SESSION_NONE },
574 +  { "pingfail" ,    pingFail   , NULL, AFB_SESSION_NONE },
575 +  { "pingnull" ,    pingNull   , NULL, AFB_SESSION_NONE },
576 +  { "pingbug"  ,    pingBug    , NULL, AFB_SESSION_NONE },
577 +  { "pingJson" ,    pingJson   , NULL, AFB_SESSION_NONE },
578 +  { "pingevent",    pingEvent  , NULL, AFB_SESSION_NONE },
579 +  { "subcall",      subcall    , NULL, AFB_SESSION_NONE },
580 +  { "subcallsync",  subcallsync, NULL, AFB_SESSION_NONE },
581 +  { "eventadd",     eventadd   , NULL, AFB_SESSION_NONE },
582 +  { "eventdel",     eventdel   , NULL, AFB_SESSION_NONE },
583 +  { "eventsub",     eventsub   , NULL, AFB_SESSION_NONE },
584 +  { "eventunsub",   eventunsub , NULL, AFB_SESSION_NONE },
585 +  { "eventpush",    eventpush  , NULL, AFB_SESSION_NONE },
586 +  { "exit",         exitnow    , NULL, AFB_SESSION_NONE },
587 +  { NULL}
588  };
589
590 -static const struct afb_binding plugin_desc = {
591 -       .type = AFB_BINDING_VERSION_1,
592 -       .v1 = {
593 -               .info = "Minimal Hello World Sample",
594 -               .prefix = "hello",
595 -               .verbs = verbs
596 -       }
597 +const struct afb_binding_v2 afbBindingV2 = {
598 +       .api = "hello",
599 +       .specification = NULL,
600 +       .verbs = verbs,
601 +       .preinit = preinit,
602 +       .init = init
603  };
604
605 -const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf)
606 -{
607 -       interface = itf;
608 -       NOTICE(interface, "hello plugin comes to live");
609 -       return &plugin_desc;
610 -}
611 ```