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