aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/README.md32
-rw-r--r--docs/REVISIONS.md14
-rw-r--r--docs/SUMMARY.md9
-rw-r--r--docs/afb-binding-references.md283
-rw-r--r--docs/afb-binding-writing.md180
-rw-r--r--docs/afb-daemon-debugging.md2
-rw-r--r--docs/afb-daemon-vocabulary.md6
-rw-r--r--docs/afb-migration-to-binding-v3.md110
-rw-r--r--docs/afb-migration-v1-to-v2.md7
-rw-r--r--docs/afb-overview.md6
-rw-r--r--docs/annexes.md5
-rw-r--r--docs/migration-to-binding-v3.sed68
12 files changed, 502 insertions, 220 deletions
diff --git a/docs/README.md b/docs/README.md
index 94dc16aa..503b8545 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,13 +1,19 @@
-Document revisions
-==================
-
-| Date | Version | Designation  | Author |
-|--------------|------------|----------------------------------------------|-------------------------------------------------------|
-| 23 May 2016 | 0.9 | Initial release | J. Bollo [ IoT.bzh ] <br/> M. Bachmann [ IoT.bzh ] |
-| 30 May 2016 | 1.0 | Master document edition, final review | S. Desneux [ IoT.bzh ] <br/> F. Ar Foll [ IoT.bzh ] |
-| 21 Sept 2016 | 2.0 | Updated with new sections (events,widgets) | J. Bollo [ IoT.bzh ] <br/> S. Desneux [ IoT.bzh ] |
-| 12 Dec 2016 | 2.1 | Updated for CC Release | S. Desneux [ IoT.bzh ] |
-| 14 Dec 2016 | 3.0 | Minor fixes, alignment with CC version | S. Desneux [ IoT.bzh ] |
-| 20 Mar 2017 | 3.1 | Systemd integration | J. Bollo [ IoT.bzh ] <br/> S. Desneux [ IoT.bzh ] |
-| 21 Jun 2017 | 4.0 | Update for AGL DD | J. Bollo [ IoT.bzh ] <br/> S. Desneux [ IoT.bzh ] |
-| 21 Sep 2017 | 4.99-EERC1 | Update for AGL EE-RC1 | J. Bollo [ IoT.bzh ] <br/> S. Desneux [ IoT.bzh ] |
+
+# AGL Framework Binder
+
+This project provides the binder component of the the microservice architecture
+of Automotive Grade Linux (AGL).
+
+This project is available there https://git.automotivelinux.org/src/app-framework-binder/
+
+It can be cloned with **git clone https://git.automotivelinux.org/src/app-framework-binder**.
+
+## License and copying
+
+This software is an open source software funded by LinuxFoundation and Renesas.
+
+This software is delivered under the terms of the open source license Apache 2.
+
+This license is available in the file LICENSE-2.0.txt or on the worl wide web at the
+location https://opensource.org/licenses/Apache-2.0
+
diff --git a/docs/REVISIONS.md b/docs/REVISIONS.md
new file mode 100644
index 00000000..00787b02
--- /dev/null
+++ b/docs/REVISIONS.md
@@ -0,0 +1,14 @@
+Document revisions
+==================
+
+| Date | Version | Designation  | Author |
+|--------------|:----------:|----------------------------------------------|-------------------------------------------------------|
+| 23 May 2016 | 0.9 | Initial release | J. Bollo [ IoT.bzh ] <br/> M. Bachmann [ IoT.bzh ] |
+| 30 May 2016 | 1.0 | Master document edition, final review | S. Desneux [ IoT.bzh ] <br/> F. Ar Foll [ IoT.bzh ] |
+| 21 Sept 2016 | 2.0 | Updated with new sections (events,widgets) | J. Bollo [ IoT.bzh ] <br/> S. Desneux [ IoT.bzh ] |
+| 12 Dec 2016 | 2.1 | Updated for CC Release | S. Desneux [ IoT.bzh ] |
+| 14 Dec 2016 | 3.0 | Minor fixes, alignment with CC version | S. Desneux [ IoT.bzh ] |
+| 20 Mar 2017 | 3.1 | Systemd integration | J. Bollo [ IoT.bzh ] <br/> S. Desneux [ IoT.bzh ] |
+| 21 Jun 2017 | 4.0 | Update for AGL DD | J. Bollo [ IoT.bzh ] <br/> S. Desneux [ IoT.bzh ] |
+| 21 Sep 2017 | 4.99-EERC1 | Update for AGL EE-RC1 | J. Bollo [ IoT.bzh ] <br/> S. Desneux [ IoT.bzh ] |
+| 14 Jun 2018 | 5.99-FFRC1 | Update for AGL FF-RC1 | J. Bollo [ IoT.bzh ] |
diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md
index 44b06f8d..580660ea 100644
--- a/docs/SUMMARY.md
+++ b/docs/SUMMARY.md
@@ -1,14 +1,15 @@
# Summary
-* [Document revisions](README.md)
* [Binder Overview](afb-introduction.md)
+* [Binder daemon vocabulary](afb-daemon-vocabulary.md)
* [How to write a binding ?](afb-binding-writing.md)
* [Binding references](afb-binding-references.md)
-* [Migration from v1 to v2](afb-migration-v1-to-v2.md)
* [Binder events guide](afb-events-guide.md)
* [Binder Application writing guide](afb-application-writing.md)
-* [Binder daemon vocabulary](afb-daemon-vocabulary.md)
* [Annexes](annexes.md)
+ * [Migration to binding v3](afb-migration-to-binding-v3.md)
* [Installing the binder on a desktop](afb-desktop-package.md)
* [Options of afb-daemon](afb-daemon-options.md)
- * [Debugging afb-daemon](afb-daemon-debugging.md)
+ * [Debugging binder and bindings](afb-daemon-debugging.md)
+ * [(LEGACY) guide to migrate bindings from v1 to v2](afb-migration-v1-to-v2.md)
+* [Document revisions](REVISIONS.md)
diff --git a/docs/afb-binding-references.md b/docs/afb-binding-references.md
index 0e30ffe7..4ff0f042 100644
--- a/docs/afb-binding-references.md
+++ b/docs/afb-binding-references.md
@@ -2,47 +2,98 @@
## Structure for declaring binding
-### struct afb_binding_v2
+### afb_binding_t
-The main structure, of type **afb_binding_v2**, for describing the binding
-must be exported under the name **afbBindingV2**.
+The main structure, of type **afb_binding_t**, for describing the binding
+must be exported under the name **afbBindingExport**.
This structure is defined as below.
```C
-/*
- * Description of the bindings of type version 2
+typedef struct afb_binding_v3 afb_binding_t;
+```
+
+Where:
+
+```C
+/**
+ * Description of the bindings of type version 3
*/
-struct afb_binding_v2
+struct afb_binding_v3
{
- const char *api; /* api name for the binding */
- const char *specification; /* textual openAPIv3 specification of the binding */
- const char *info; /* some info about the api, can be NULL */
- const struct afb_verb_v2 *verbs; /* array of descriptions of verbs terminated by a NULL name */
- int (*preinit)(); /* callback at load of the binding */
- int (*init)(); /* callback for starting the service */
- void (*onevent)(const char *event, struct json_object *object); /* callback for handling events */
- unsigned noconcurrency: 1; /* avoids concurrent requests to verbs */
+ /** api name for the binding, can't be NULL */
+ const char *api;
+
+ /** textual specification of the binding, can be NULL */
+ const char *specification;
+
+ /** some info about the api, can be NULL */
+ const char *info;
+
+ /** array of descriptions of verbs terminated by a NULL name, can be NULL */
+ const struct afb_verb_v3 *verbs;
+
+ /** callback at load of the binding */
+ int (*preinit)(struct afb_api_x3 *api);
+
+ /** callback for starting the service */
+ int (*init)(struct afb_api_x3 *api);
+
+ /** callback for handling events */
+ void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object);
+
+ /** userdata for afb_api_x3 */
+ void *userdata;
+
+ /** space separated list of provided class(es) */
+ const char *provide_class;
+
+ /** space separated list of required class(es) */
+ const char *require_class;
+
+ /** space separated list of required API(es) */
+ const char *require_api;
+
+ /** avoids concurrent requests to verbs */
+ unsigned noconcurrency: 1;
};
```
-### struct afb_verb_v2
+### struct afb_verb_t
-Each verb is described with a structure of type **afb_verb_v2**
+Each verb is described with a structure of type **afb_verb_t**
defined below:
```C
-/*
- * Description of one verb of the API provided by the binding
- * This enumeration is valid for bindings of type version 2
+typedef struct afb_verb_v3 afb_verb_t;
+```
+
+```C
+/**
+ * Description of one verb as provided for binding API version 3
*/
-struct afb_verb_v2
+struct afb_verb_v3
{
- const char *verb; /* name of the verb */
- void (*callback)(struct afb_req req); /* callback function implementing the verb */
- const struct afb_auth *auth; /* required authorization */
- const char *info; /* some info about the verb, can be NULL */
- uint32_t session; /* authorization and session requirements of the verb */
+ /** name of the verb, NULL only at end of the array */
+ const char *verb;
+
+ /** callback function implementing the verb */
+ void (*callback)(afb_req_t_x2 *req);
+
+ /** required authorization, can be NULL */
+ const struct afb_auth *auth;
+
+ /** some info about the verb, can be NULL */
+ const char *info;
+
+ /**< data for the verb callback */
+ void *vcbdata;
+
+ /** authorization and session requirements of the verb */
+ uint16_t session;
+
+ /** is the verb glob name */
+ uint16_t glob: 1;
};
```
@@ -55,55 +106,91 @@ The **session** flags is one of the constant defined below:
- AFB_SESSION_LOA_3 : Requires the LOA to be 3 or more
- AFB_SESSION_CHECK : Requires the token to be set and valid
- AFB_SESSION_REFRESH : Implies a token refresh
-- AFB_SESSION_CLOSE : Implies cloing the session
+- AFB_SESSION_CLOSE : Implies closing the session after request processed
-The LOA (Level Of Assurance) is set, by binding, using the function **afb_req_session_set_LOA**.
+The LOA (Level Of Assurance) is set, by binding api, using the function **afb_req_session_set_LOA**.
-### struct afb_auth and enum afb_auth_type
+The session can be closed, by binding api, using the function **afb_req_session_close**.
-The structure **afb_auth** is used within verb description to
+### afb_auth_t and afb_auth_type_t
+
+The structure **afb_auth_t** is used within verb description to
set security requirements.
The interpretation of the structure depends on the value of the field **type**.
```C
+typedef struct afb_auth afb_auth_t;
+
+/**
+ * Definition of an authorization entry
+ */
struct afb_auth
{
- const enum afb_auth_type type;
- union {
- const char *text;
- const unsigned loa;
- const struct afb_auth *first;
- };
- const struct afb_auth *next;
+ /** type of entry @see afb_auth_type */
+ enum afb_auth_type type;
+
+ union {
+ /** text when @ref type == @ref afb_auth_Permission */
+ const char *text;
+
+ /** level of assurancy when @ref type == @ref afb_auth_LOA */
+ unsigned loa;
+
+ /** first child when @ref type in { @ref afb_auth_Or, @ref afb_auth_And, @ref afb_auth_Not } */
+ const struct afb_auth *first;
+ };
+
+ /** second child when @ref type in { @ref afb_auth_Or, @ref afb_auth_And } */
+ const struct afb_auth *next;
};
+
```
The possible values for **type** is defined here:
```C
-/*
- * Enum for Session/Token/Assurance middleware.
+typedef enum afb_auth_type afb_auth_type_t;
+
+/**
+ * Enumeration for authority (Session/Token/Assurance) definitions.
+ *
+ * @see afb_auth
*/
enum afb_auth_type
{
- afb_auth_No = 0, /** never authorized, no data */
- afb_auth_Token, /** authorized if token valid, no data */
- afb_auth_LOA, /** authorized if LOA greater than data 'loa' */
- afb_auth_Permission, /** authorized if permission 'text' is granted */
- afb_auth_Or, /** authorized if 'first' or 'next' is authorized */
- afb_auth_And, /** authorized if 'first' and 'next' are authorized */
- afb_auth_Not, /** authorized if 'first' is not authorized */
- afb_auth_Yes /** always authorized, no data */
+ /** never authorized, no data */
+ afb_auth_No = 0,
+
+ /** authorized if token valid, no data */
+ afb_auth_Token,
+
+ /** authorized if LOA greater than data 'loa' */
+ afb_auth_LOA,
+
+ /** authorized if permission 'text' is granted */
+ afb_auth_Permission,
+
+ /** authorized if 'first' or 'next' is authorized */
+ afb_auth_Or,
+
+ /** authorized if 'first' and 'next' are authorized */
+ afb_auth_And,
+
+ /** authorized if 'first' is not authorized */
+ afb_auth_Not,
+
+ /** always authorized, no data */
+ afb_auth_Yes
};
```
Example:
```C
-static const struct afb_auth _afb_auths_v2_monitor[] = {
- { .type = afb_auth_Permission, .text = "urn:AGL:permission:monitor:public:set" },
- { .type = afb_auth_Permission, .text = "urn:AGL:permission:monitor:public:get" },
- { .type = afb_auth_Or, .first = &_afb_auths_v2_monitor[1], .next = &_afb_auths_v2_monitor[0] }
+static const afb_auth_t myauth[] = {
+ { .type = afb_auth_Permission, .text = "urn:AGL:permission:me:public:set" },
+ { .type = afb_auth_Permission, .text = "urn:AGL:permission:me:public:get" },
+ { .type = afb_auth_Or, .first = &myauth[1], .next = &myauth[0] }
};
```
@@ -115,17 +202,18 @@ to **sd_bus** features.
```C
/*
- * Retrieves the common systemd's event loop of AFB
+ * Retrieves the common systemd's event loop of AFB
+ *
*/
struct sd_event *afb_daemon_get_event_loop();
/*
- * Retrieves the common systemd's user/session d-bus of AFB
+ * Retrieves the common systemd's user/session d-bus of AFB if active
*/
struct sd_bus *afb_daemon_get_user_bus();
/*
- * Retrieves the common systemd's system d-bus of AFB
+ * Retrieves the common systemd's system d-bus of AFB if active or NULL
*/
struct sd_bus *afb_daemon_get_system_bus();
```
@@ -155,7 +243,7 @@ int afb_daemon_broadcast_event(const char *name, struct json_object *object);
*
* See afb_event_is_valid to check if there is an error.
*/
-struct afb_event afb_daemon_make_event(const char *name);
+afb_event_t afb_daemon_make_event(const char *name);
```
The following function is used by logging macros and should normally
@@ -319,7 +407,7 @@ It must be used when creating events.
*
* Returns 0 if not valid or 1 if valid.
*/
-int afb_event_is_valid(struct afb_event event);
+int afb_event_is_valid(afb_event_t event);
```
The two following functions are used to broadcast or push
@@ -336,7 +424,7 @@ event with its data.
*
* Returns the count of clients that received the event.
*/
-int afb_event_broadcast(struct afb_event event, struct json_object *object);
+int afb_event_broadcast(afb_event_t event, struct json_object *object);
/*
* Pushes the 'event' with the data 'object' to its observers.
@@ -348,18 +436,29 @@ int afb_event_broadcast(struct afb_event event, struct json_object *object);
*
* Returns the count of clients that received the event.
*/
-int afb_event_push(struct afb_event event, struct json_object *object);
+int afb_event_push(afb_event_t event, struct json_object *object);
+```
+
+The following function remove one reference to the event.
+
+```C
+/*
+ * Decrease the reference count of the event.
+ * After calling this function, the event
+ * MUST NOT BE USED ANYMORE.
+ */
+void afb_event_unref(afb_event_t event);
```
-The following function destiys the event.
+The following function add one reference to the event.
```C
/*
- * Drops the data associated to the 'event'
+ * Decrease the reference count of the event.
* After calling this function, the event
* MUST NOT BE USED ANYMORE.
*/
-void afb_event_drop(struct afb_event event);
+void afb_event_unref(afb_event_t event);
```
This function allows to retrieve the exact name of the event.
@@ -368,7 +467,7 @@ This function allows to retrieve the exact name of the event.
/*
* Gets the name associated to the 'event'.
*/
-const char *afb_event_name(struct afb_event event);
+const char *afb_event_name(afb_event_t event);
```
## Functions of class afb_req
@@ -381,7 +480,7 @@ This function checks the validity of the **req**.
*
* Returns 0 if not valid or 1 if valid.
*/
-int afb_req_is_valid(struct afb_req req);
+int afb_req_is_valid(afb_req_t req);
```
The following functions retrieves parameters of the request.
@@ -399,7 +498,7 @@ The following functions retrieves parameters of the request.
* an HTTP POST of Content-Type "application/json". In that case, the
* argument of name "" receives the value of the body of the HTTP request.
*/
-struct afb_arg afb_req_get(struct afb_req req, const char *name);
+afb_arg_t afb_req_get(afb_req_t req, const char *name);
/*
* Gets from the request 'req' the string value of the argument of 'name'.
@@ -408,7 +507,7 @@ struct afb_arg afb_req_get(struct afb_req req, const char *name);
*
* Shortcut for: afb_req_get(req, name).value
*/
-const char *afb_req_value(struct afb_req req, const char *name);
+const char *afb_req_value(afb_req_t req, const char *name);
/*
* Gets from the request 'req' the path for file attached to the argument of 'name'.
@@ -417,13 +516,13 @@ const char *afb_req_value(struct afb_req req, const char *name);
*
* Shortcut for: afb_req_get(req, name).path
*/
-const char *afb_req_path(struct afb_req req, const char *name);
+const char *afb_req_path(afb_req_t req, const char *name);
/*
* Gets from the request 'req' the json object hashing the arguments.
* The returned object must not be released using 'json_object_put'.
*/
-struct json_object *afb_req_json(struct afb_req req);
+struct json_object *afb_req_json(afb_req_t req);
```
The following functions emit the reply to the request.
@@ -439,7 +538,7 @@ The following functions emit the reply to the request.
* Thus, in the case where 'obj' should remain available after
* the function returns, the function 'json_object_get' shall be used.
*/
-void afb_req_success(struct afb_req req, struct json_object *obj, const char *info);
+void afb_req_success(afb_req_t req, struct json_object *obj, const char *info);
/*
* Same as 'afb_req_success' but the 'info' is a formatting
@@ -449,7 +548,7 @@ void afb_req_success(struct afb_req req, struct json_object *obj, const char *in
* Thus, in the case where 'obj' should remain available after
* the function returns, the function 'json_object_get' shall be used.
*/
-void afb_req_success_f(struct afb_req req, struct json_object *obj, const char *info, ...);
+void afb_req_success_f(afb_req_t req, struct json_object *obj, const char *info, ...);
/*
* Same as 'afb_req_success_f' but the arguments to the format 'info'
@@ -459,30 +558,30 @@ void afb_req_success_f(struct afb_req req, struct json_object *obj, const char *
* Thus, in the case where 'obj' should remain available after
* the function returns, the function 'json_object_get' shall be used.
*/
-void afb_req_success_v(struct afb_req req, struct json_object *obj, const char *info, va_list args);
+void afb_req_success_v(afb_req_t req, struct json_object *obj, const char *info, va_list args);
/*
* Sends a reply of kind failure to the request 'req'.
* The status of the reply is set to 'status' and an
- * informationnal comment 'info' (can also be NULL) can be added.
+ * informational comment 'info' (can also be NULL) can be added.
*
* Note that calling afb_req_fail("success", info) is equivalent
* to call afb_req_success(NULL, info). Thus even if possible it
* is strongly recommended to NEVER use "success" for status.
*/
-void afb_req_fail(struct afb_req req, const char *status, const char *info);
+void afb_req_fail(afb_req_t req, const char *status, const char *info);
/*
* Same as 'afb_req_fail' but the 'info' is a formatting
* string followed by arguments.
*/
-void afb_req_fail_f(struct afb_req req, const char *status, const char *info, ...);
+void afb_req_fail_f(afb_req_t req, const char *status, const char *info, ...);
/*
* Same as 'afb_req_fail_f' but the arguments to the format 'info'
* are given as a variable argument list instance.
*/
-void afb_req_fail_v(struct afb_req req, const char *status, const char *info, va_list args);
+void afb_req_fail_v(afb_req_t req, const char *status, const char *info, va_list args);
```
The following functions handle the session data.
@@ -492,14 +591,14 @@ The following functions handle the session data.
* Gets the pointer stored by the binding for the session of 'req'.
* When the binding has not yet recorded a pointer, NULL is returned.
*/
-void *afb_req_context_get(struct afb_req req);
+void *afb_req_context_get(afb_req_t req);
/*
* Stores for the binding the pointer 'context' to the session of 'req'.
* The function 'free_context' will be called when the session is closed
* or if binding stores an other pointer.
*/
-void afb_req_context_set(struct afb_req req, void *context, void (*free_context)(void*));
+void afb_req_context_set(afb_req_t req, void *context, void (*free_context)(void*));
/*
* Gets the pointer stored by the binding for the session of 'req'.
@@ -508,7 +607,7 @@ void afb_req_context_set(struct afb_req req, void *context, void (*free_context)
* the function 'create_context' and stores it with the freeing function
* 'free_context'.
*/
-void *afb_req_context(struct afb_req req, void *(*create_context)(), void (*free_context)(void*));
+void *afb_req_context(afb_req_t req, void *(*create_context)(), void (*free_context)(void*));
/*
* Frees the pointer stored by the binding for the session of 'req'
@@ -516,13 +615,13 @@ void *afb_req_context(struct afb_req req, void *(*create_context)(), void (*free
*
* Shortcut for: afb_req_context_set(req, NULL, NULL)
*/
-void afb_req_context_clear(struct afb_req req);
+void afb_req_context_clear(afb_req_t req);
/*
* Closes the session associated with 'req'
* and delete all associated contexts.
*/
-void afb_req_session_close(struct afb_req req);
+void afb_req_session_close(afb_req_t req);
/*
* Sets the level of assurance of the session of 'req'
@@ -530,7 +629,7 @@ void afb_req_session_close(struct afb_req req);
* security policies.
* Returns 1 on success or 0 if failed.
*/
-int afb_req_session_set_LOA(struct afb_req req, unsigned level);
+int afb_req_session_set_LOA(afb_req_t req, unsigned level);
```
The 4 following functions must be used for asynchronous handling requests.
@@ -541,14 +640,14 @@ The 4 following functions must be used for asynchronous handling requests.
* This function MUST be called by asynchronous implementations
* of verbs if no reply was sent before returning.
*/
-void afb_req_addref(struct afb_req req);
+void afb_req_addref(afb_req_t req);
/*
* Substracts one to the count of references of 'req'.
* This function MUST be called by asynchronous implementations
* of verbs after sending the asynchronous reply.
*/
-void afb_req_unref(struct afb_req req);
+void afb_req_unref(afb_req_t req);
/*
* Stores 'req' on heap for asynchronous use.
@@ -556,7 +655,7 @@ void afb_req_unref(struct afb_req req);
* The count of reference to 'req' is incremented on success
* (see afb_req_addref).
*/
-struct afb_stored_req *afb_req_store(struct afb_req req);
+struct afb_stored_req *afb_req_store(afb_req_t req);
/*
* Retrieves the afb_req stored at 'sreq'.
@@ -565,7 +664,7 @@ struct afb_stored_req *afb_req_store(struct afb_req req);
* function 'afb_req_unref' should be called on the result
* after that the asynchronous reply if sent.
*/
-struct afb_req afb_req_unstore(struct afb_stored_req *sreq);
+afb_req_t afb_req_unstore(struct afb_stored_req *sreq);
```
The two following functions are used to associate client with events
@@ -577,14 +676,14 @@ The two following functions are used to associate client with events
* to the 'event'.
* Returns 0 in case of successful subscription or -1 in case of error.
*/
-int afb_req_subscribe(struct afb_req req, struct afb_event event);
+int afb_req_subscribe(afb_req_t req, afb_event_t event);
/*
* Revokes the subscription established to the 'event' for the client
* link identified by 'req'.
* Returns 0 in case of successful subscription or -1 in case of error.
*/
-int afb_req_unsubscribe(struct afb_req req, struct afb_event event);
+int afb_req_unsubscribe(afb_req_t req, afb_event_t event);
```
The following functions must be used to make request in the name of the
@@ -609,7 +708,7 @@ client (with its permissions).
* - 'afb_req_subcall_sync' the synchronous version
*/
void afb_req_subcall(
- struct afb_req req,
+ afb_req_t req,
const char *api,
const char *verb,
struct json_object *args,
@@ -634,7 +733,7 @@ void afb_req_subcall(
* - 'afb_req_subcall' that doesn't keep request alive automatically.
* - 'afb_req_subcall_sync' the synchronous version
*/
-static inline void afb_req_subcall_req(struct afb_req req, const char *api, const char *verb, struct json_object *args, void (*callback)(void *closure, int iserror, struct json_object *result, struct afb_req req), void *closure)
+static inline void afb_req_subcall_req(afb_req_t req, const char *api, const char *verb, struct json_object *args, void (*callback)(void *closure, int iserror, struct json_object *result, afb_req_t req), void *closure)
{
req.itf->subcall_req(req.closure, api, verb, args, callback, closure);
}
@@ -656,7 +755,7 @@ static inline void afb_req_subcall_req(struct afb_req req, const char *api, cons
* - 'afb_req_subcall' that doesn't keep request alive automatically.
*/
int afb_req_subcall_sync(
- struct afb_req req,
+ afb_req_t req,
const char *api,
const char *verb,
struct json_object *args,
@@ -691,7 +790,7 @@ Instead, you should use the macros:
* INFO 6 Informational
* DEBUG 7 Debug-level messages
*/
-void afb_req_verbose(struct afb_req req, int level, const char *file, int line, const char * func, const char *fmt, ...);
+void afb_req_verbose(afb_req_t req, int level, const char *file, int line, const char * func, const char *fmt, ...);
```
The functions below allow a binding involved in the platform security
@@ -705,7 +804,7 @@ application identity.
*
* Returns 1 if the permission is granted or 0 otherwise.
*/
-int afb_req_has_permission(struct afb_req req, const char *permission);
+int afb_req_has_permission(afb_req_t req, const char *permission);
/*
* Get the application identifier of the client application for the
@@ -716,7 +815,7 @@ int afb_req_has_permission(struct afb_req req, const char *permission);
*
* The returned value if not NULL must be freed by the caller
*/
-char *afb_req_get_application_id(struct afb_req req);
+char *afb_req_get_application_id(afb_req_t req);
/*
* Get the user identifier (UID) of the client application for the
@@ -724,7 +823,7 @@ char *afb_req_get_application_id(struct afb_req req);
*
* Returns -1 when the application can not be identified.
*/
-int afb_req_get_uid(struct afb_req req);
+int afb_req_get_uid(afb_req_t req);
```
## Logging macros
diff --git a/docs/afb-binding-writing.md b/docs/afb-binding-writing.md
index aad422c4..69090e3d 100644
--- a/docs/afb-binding-writing.md
+++ b/docs/afb-binding-writing.md
@@ -51,14 +51,21 @@ The binder makes no distinctions between upper case and lower case
latin letters.
So **API/VERB** matches **Api/Verb** or **api/verb**.
-Actually it exists 2 ways of writing ***bindings***.
+## Versions of the bindings
+
+Since introduction of the binder, the way how bindings are written
+evolved a little. While changing, attention was made to ensure binary
+compatibility between the different versions.
+
+Actually it exists 3 ways of writing ***bindings***.
You can either write:
-- a binding version 1 (not recommended);
-- a binding version 2 (RECOMMENDED).
+- a binding version 1 (not more supported);
+- a binding version 2 (not recommended);
+- a binding version 3 (RECOMMENDED).
A ***binder*** loads and runs any of these version in any combination.
-This document explain how to write bindings version 2.
+This document explain how to write bindings version 3.
<!-- pagebreak -->
@@ -67,21 +74,21 @@ This document explain how to write bindings version 2.
This is the code of the binding **tuto-1.c**:
```C
- 1 #define AFB_BINDING_VERSION 2
+ 1 #define AFB_BINDING_VERSION 3
2 #include <afb/afb-binding.h>
3
- 4 void hello(afb_req req)
+ 4 void hello(afb_req_t req)
5 {
6 AFB_REQ_DEBUG(req, "hello world");
- 7 afb_req_success(req, NULL, "hello world");
+ 7 afb_req_reply(req, NULL, NULL, "hello world");
8 }
9
- 10 const afb_verb_v2 verbs[] = {
+ 10 const afb_verb_t verbs[] = {
11 { .verb="hello", .callback=hello },
12 { .verb=NULL }
13 };
14
- 15 const afb_binding_v2 afbBindingV2 = {
+ 15 const afb_binding_t afbBindingExport = {
16 .api = "tuto-1",
17 .verbs = verbs
18 };
@@ -93,12 +100,18 @@ Compiling:
gcc -fPIC -shared tuto-1.c -o tuto-1.so $(pkg-config --cflags-only-I afb-daemon)
```
+> Note: the variable environment variable PKG_CONFIG_PATH might be necessary
+> tuned to get **pkg-config** working properly
+
Running:
```bash
afb-daemon --binding tuto-1.so --port 3333 --token ''
```
+At this point, afb-daemon has started, it loaded the binding tuto-1.so and now
+listen at localhost on the port 3333.
+
Testing using **curl**:
```bash
@@ -133,18 +146,15 @@ This shows basic things:
The lines 1 and 2 show how to get the include file **afb-binding.h**.
```C
- 1 #define AFB_BINDING_VERSION 2
+ 1 #define AFB_BINDING_VERSION 3
2 #include <afb/afb-binding.h>
```
-You must define the version of ***binding*** that you are using.
-This is done line 1 where we define that this is the version 2.
+You must define the version of ***binding*** that you are using.
+This is done line 1 where we define that this is the version 3 (earlier
+versions 1 and 2 are deprecated).
-If you don't define it, a warning message is prompted by the compiler
-and the version is switched to version 1.
-This behaviour is temporarily and enables to continue to use previously written
-***binding*** without change but it will change in some future when
-***bindings*** V1 will become obsoletes.
+If you don't define it, an error is reported and the compilation aborts.
To include **afb-binding.h** successfully, the include search path
should be set correctly if needed (not needed only if installed in
@@ -156,81 +166,54 @@ Setting the include path is easy using **pkg-config**:
pkg-config --cflags-only-I afb-daemon
```
-Note for **C++** developers:
-
-- The ***binder*** currently expose only **C** language **API**.
- The file **afb/afb-binding.h** isn't **C++** ready.
-
-You should use the construct **extern "C"** as below:
+> Note for **C++** developers:
+>
+> The ***binder*** currently expose a draft version of **C++** api.
+> To get it include the file <**afb/afb-binding**> (without **.h**).
-```C
- #define AFB_BINDING_VERSION 2
- extern "C" {
- #include <afb/afb-binding.h>
- }
-```
-
-Future version of the ***binder*** will include a **C++**
-interface.
-Until it is available, please, use the above construct.
### Declaring the API of the binding
Lines 10 to 18 show the declaration of the ***binding***.
-The ***binder*** knows that this is a ***binding*** version 2 because
-it finds the exported symbol **afbBindingV2** that is expected to be
-a structure of type **afb_binding_v2**.
+The ***binder*** knows that this is a ***binding*** because
+it finds the exported symbol **afbBindingExport** that is expected to be
+a structure of type **afb_binding_t**.
```C
- 10 const afb_verb_v2 verbs[] = {
+ 10 const afb_verb_t verbs[] = {
11 { .verb="hello", .callback=hello },
12 { .verb=NULL }
13 };
14
- 15 const afb_binding_v2 afbBindingV2 = {
+ 15 const afb_binding_t afbBindingExport = {
16 .api = "tuto-1",
17 .verbs = verbs
18 };
```
-The structure **afbBindingV2** actually tells that:
+The structure **afbBindingExport** actually tells that:
- the exported **API** name is **tuto-1** (line 16)
- the array of verbs is the above defined one
-The exported list of verb is specified by an array of structures,
-each describing a verb, ended with a verb NULL (line 12).
+The exported list of verb is specified by an array of structures of
+type **afb_verb_t**, each describing a verb, ended with a verb NULL (line 12).
The only defined verb here (line 11) is named **hello** (field **.verb**)
and the function that handle the related request is **hello**
(field **.callback**).
-Note that you can explicitly mark the fact that these are
-struct by typing the **struct** as below:
-
-```C
- 10 const struct afb_verb_v2 verbs[] = {
- 11 { .verb="hello", .callback=hello },
- 12 { .verb=NULL }
- 13 };
- 14
- 15 const struct afb_binding_v2 afbBindingV2 = {
- 16 .api = "tuto-1",
- 17 .verbs = verbs
- 18 };
-```
-
### Handling binder's requests
As shown above this is by default the common include directory where
the AGL stuff is installed.
```C
- 4 void hello(afb_req req)
+ 4 void hello(afb_req_t req)
5 {
6 AFB_REQ_DEBUG(req, "hello world");
- 7 afb_req_success(req, NULL, "hello world");
+ 7 afb_req_reply(req, NULL, NULL, "hello world");
8 }
```
@@ -241,18 +224,15 @@ with the argument **req** that handles the client request.
The callback has to treat synchronously or asynchronously the request and
should at the end emit a reply for the request.
-Here, the callback for **tuto-1/hello** replies a successful answer
-(line 7) to the request **req**.
-The second parameter (here NULL) is a json object that is sent to the client with the reply.
-The third parameter is also sent with the reply and is a string
-called info that can be used as some meta data.
+At the line 7, the callback for **tuto-1/hello** replies to the request **req**.
+Parameters of the reply are:
-Here again, you can explicitly mark the fact that
-**afb_req** is a structure by declaring **hello** as below:
+ 1. The first parameter is the replied request
+ 2. The second parameter is a json object (here NULL)
+ 3. The third parameter is the error string indication (here NULL: no error)
+ 4. The fourth parameter is an informative string (that can be NULL) that can be used to provide meta data.
-```C
- 4 void hello(struct afb_req req)
-```
+The 3 last parameters are sent back to the client as the reply content.
<!-- pagebreak -->
@@ -268,43 +248,43 @@ This is the code of the binding **tuto-2.c**:
```C
1 #include <string.h>
2 #include <json-c/json.h>
- 3
- 4 #define AFB_BINDING_VERSION 2
+ 3
+ 4 #define AFB_BINDING_VERSION 3
5 #include <afb/afb-binding.h>
- 6
- 7 afb_event event_login, event_logout;
- 8
- 9 void login(afb_req req)
+ 6
+ 7 afb_event_t event_login, event_logout;
+ 8
+ 9 void login(afb_req_t req)
10 {
11 json_object *args, *user, *passwd;
12 char *usr;
- 13
+ 13
14 args = afb_req_json(req);
15 if (!json_object_object_get_ex(args, "user", &user)
16 || !json_object_object_get_ex(args, "password", &passwd)) {
17 AFB_REQ_ERROR(req, "login, bad request: %s", json_object_get_string(args));
- 18 afb_req_fail(req, "bad-request", NULL);
+ 18 afb_req_reply(req, NULL, "bad-request", NULL);
19 } else if (afb_req_context_get(req)) {
20 AFB_REQ_ERROR(req, "login, bad state, logout first");
- 21 afb_req_fail(req, "bad-state", NULL);
+ 21 afb_req_reply(req, NULL, "bad-state", NULL);
22 } else if (strcmp(json_object_get_string(passwd), "please")) {
23 AFB_REQ_ERROR(req, "login, unauthorized: %s", json_object_get_string(args));
- 24 afb_req_fail(req, "unauthorized", NULL);
+ 24 afb_req_reply(req, NULL, "unauthorized", NULL);
25 } else {
26 usr = strdup(json_object_get_string(user));
27 AFB_REQ_NOTICE(req, "login user: %s", usr);
28 afb_req_session_set_LOA(req, 1);
29 afb_req_context_set(req, usr, free);
- 30 afb_req_success(req, NULL, NULL);
+ 30 afb_req_reply(req, NULL, NULL, NULL);
31 afb_event_push(event_login, json_object_new_string(usr));
32 }
33 }
- 34
- 35 void action(afb_req req)
+ 34
+ 35 void action(afb_req_t req)
36 {
37 json_object *args, *val;
38 char *usr;
- 39
+ 39
40 args = afb_req_json(req);
41 usr = afb_req_context_get(req);
42 AFB_REQ_NOTICE(req, "action for user %s: %s", usr, json_object_get_string(args));
@@ -319,46 +299,46 @@ This is the code of the binding **tuto-2.c**:
51 afb_req_unsubscribe(req, event_logout);
52 }
53 }
- 54 afb_req_success(req, json_object_get(args), NULL);
+ 54 afb_req_reply(req, json_object_get(args), NULL, NULL);
55 }
- 56
- 57 void logout(afb_req req)
+ 56
+ 57 void logout(afb_req_t req)
58 {
59 char *usr;
- 60
+ 60
61 usr = afb_req_context_get(req);
62 AFB_REQ_NOTICE(req, "login user %s out", usr);
63 afb_event_push(event_logout, json_object_new_string(usr));
64 afb_req_session_set_LOA(req, 0);
65 afb_req_context_clear(req);
- 66 afb_req_success(req, NULL, NULL);
+ 66 afb_req_reply(req, NULL, NULL, NULL);
67 }
- 68
- 69 int preinit()
+ 68
+ 69 int preinit(afb_api_t api)
70 {
- 71 AFB_NOTICE("preinit");
+ 71 AFB_API_NOTICE(api, "preinit");
72 return 0;
73 }
- 74
- 75 int init()
+ 74
+ 75 int init(afb_api_t api)
76 {
- 77 AFB_NOTICE("init");
- 78 event_login = afb_daemon_make_event("login");
- 79 event_logout = afb_daemon_make_event("logout");
+ 77 AFB_API_NOTICE(api, "init");
+ 78 event_login = afb_api_make_event(api, "login");
+ 79 event_logout = afb_api_make_event(api, "logout");
80 if (afb_event_is_valid(event_login) && afb_event_is_valid(event_logout))
81 return 0;
- 82 AFB_ERROR("Can't create events");
+ 82 AFB_API_ERROR(api, "Can't create events");
83 return -1;
84 }
- 85
- 86 const afb_verb_v2 verbs[] = {
+ 85
+ 86 const afb_verb_t verbs[] = {
87 { .verb="login", .callback=login },
88 { .verb="action", .callback=action, .session=AFB_SESSION_LOA_1 },
89 { .verb="logout", .callback=logout, .session=AFB_SESSION_LOA_1 },
90 { .verb=NULL }
91 };
- 92
- 93 const afb_binding_v2 afbBindingV2 = {
+ 92
+ 93 const afb_binding_t afbBindingExport = {
94 .api = "tuto-2",
95 .specification = NULL,
96 .verbs = verbs,
diff --git a/docs/afb-daemon-debugging.md b/docs/afb-daemon-debugging.md
index dd5fd64b..4cf62bea 100644
--- a/docs/afb-daemon-debugging.md
+++ b/docs/afb-daemon-debugging.md
@@ -1,4 +1,4 @@
-# Debugging afb-daemon and its bindings
+# Debugging binder and bindings
When compiled with the symbol AGL_DEVEL defined, the ***binder***
understand the 2 configuration variables:
diff --git a/docs/afb-daemon-vocabulary.md b/docs/afb-daemon-vocabulary.md
index 6c51f124..efe53d20 100644
--- a/docs/afb-daemon-vocabulary.md
+++ b/docs/afb-daemon-vocabulary.md
@@ -24,10 +24,6 @@ assurance that the services can expect from the session.
The exact definition of the meaning of these levels and how to use it remains to
be achieved.
-## Plugin
-
-Old name for binding, see binding.
-
## Request
A request is an invocation by a client to a binding method using a message
@@ -51,7 +47,7 @@ It can serve many client.
Each one attached to one session.
The framework establishes connection between the services and the clients.
-Using DBus currently but other protocols are considered.
+Using sockets currently but other protocols are considered.
## Session
diff --git a/docs/afb-migration-to-binding-v3.md b/docs/afb-migration-to-binding-v3.md
new file mode 100644
index 00000000..8f1e678c
--- /dev/null
+++ b/docs/afb-migration-to-binding-v3.md
@@ -0,0 +1,110 @@
+Migration to binding V3
+=======================
+
+The ***binding*** interface evolved from version 1 to version 2
+for the following reasons:
+
+- integration of the security requirements within the bindings
+- simplification of the API (after developer feedbacks)
+- removal of obscure features, cleanup
+
+The ***binder*** can run ***bindings*** v1, v2 and/or v3 in any combination.
+Thus moving from v1 or v2 to v3 is not enforced at this time. But ...
+
+In the face to face meeting of Karlsruhe it was decided to remove support
+of bindings v1 and to deprecate the use of bindings v2.
+
+So at the end, **IT IS HIGHLY NEEDED TO SWITCH TO VERSION 3**
+
+This guide covers the migration of bindings from version 2 to version 3.
+
+The migration from version 1 is not treated here because bindings version 1
+are very old and probably does not exist anymore. If needed you can refer
+to the old [guide to migrate bindings from v1 to v2](afb-migration-v1-to-v2.md).
+
+
+Differences between version 2 and version 3
+-------------------------------------------
+
+### in v3 all is api
+
+The version 3 introduce the concept of "API" that gather what was called before
+the daemon and the service. This is the new concept that predates the 2 others.
+
+The concept of API is intended to allow the definition of multiple APIs
+by a same "binding" (a dynamically loaded library).
+
+Because there is potentially several "API", the functions that were without
+context in bindings version 2 need now to tell what API is consumer.
+
+To be compatible with version 2, the bindings v3 still have a default hidden
+context: the default API named **afbBindingV3root**.
+
+To summarize, the functions of class **daemon** and **service** use the default
+hidden API.
+
+It is encouraged to avoid use of functions of class **daemon** and **service**.
+You should replace these implicit calls to explicit **api** calls that
+reference **afbBindingV3root**.
+
+Same thing for the logging macros: **AFB_ERROR**, **AFB_WARNING**,
+**AFB_NOTICE**, **AFB_INFO**, **AFB_DEBUG** that becomes respectively
+**AFB_API_ERROR**, **AFB_API_WARNING**, **AFB_API_NOTICE**, **AFB_API_INFO**,
+**AFB_API_DEBUG**.
+
+Example of 2 equivalent writes:
+
+```C
+ AFB_NOTICE("send stress event");
+ afb_daemon_broadcast_event(stressed_event, NULL);
+```
+
+or
+
+```C
+ AFB_API_NOTICE(afbBindingV3root, "send stress event");
+ afb_api_broadcast_event(afbBindingV3root, stressed_event, NULL);
+```
+
+### the reply mechanism predates success and fail
+
+### subcall has more power
+
+Task list for the migration
+---------------------------
+
+This task list is:
+
+1. Use the automatic migration procedure described below
+2. Adapt the init and preinit functions
+3. Consider to change to use the new reply
+4. Consider to change to use the new (sub)call
+
+The remaining chapters explain these task with more details.
+
+Automatic migration!
+--------------------
+
+A tiny **sed** script is intended to perform a first pass on the code that
+you want to upgrade. It can be down using **curl** and applied using **sed**
+as below.
+
+```bash
+BASE=https://git.automotivelinux.org/src/app-framework-binder/tree
+SED=migration-to-binding-v3.sed
+curl -o $SED $BASE/docs/$SED
+sed -i -f $SED file1 file2 file3...
+```
+
+This automatic action does most of the boring job nut not all the job.
+The remaining of this guide explains the missing part.
+
+Adapt the init and preinit functions
+------------------------------------
+
+Consider to change to use the new reply
+---------------------------------------
+
+Consider to change to use the new (sub)call
+-------------------------------------------
+
diff --git a/docs/afb-migration-v1-to-v2.md b/docs/afb-migration-v1-to-v2.md
index f3182918..9a43454e 100644
--- a/docs/afb-migration-v1-to-v2.md
+++ b/docs/afb-migration-v1-to-v2.md
@@ -1,6 +1,11 @@
-Migration from binding V1 to binding V2
+[LEGACY] Migration from binding V1 to binding V2
=======================================
+> LEGACY!!! IT IS NOT EXPECTED THAT YOU STILL NEED THIS GUIDE.
+>
+> THIS GUIDE WILL BE REMOVED IN A NEAR FUTURE
+
+
The ***binding*** interface evolved from version 1 to version 2
for the following reasons:
diff --git a/docs/afb-overview.md b/docs/afb-overview.md
index 0cff24cc..2682d8d1 100644
--- a/docs/afb-overview.md
+++ b/docs/afb-overview.md
@@ -6,14 +6,14 @@ the services that it needs.
It provides a fast way to securely offer APIs to applications
written in any language and running almost anywhere.
-- The ***binder*** is developed for AGL.
+- The ***binder*** is developed for AGL (Automotive Grade Linux) but it is not bound to AGL.
- The ***binder*** is the usual name.
- The binary is named **afb-daemon**.
- The name **afb-daemon** stands for ***Application Framework Binder Daemon***.
The word *daemon*, here, denote the fact that the ***binder*** makes witchcraft to
-connect applications to their expected services.
-(note: that usually the term of daemon denotes background process but not here).
+connect applications to their expected services. (note: that usually the term of
+daemon denotes background process but not here).
Each ***binder*** **afb-daemon** is in charge to bind one instance of
an application or service to the rest of the system, applications and services.
diff --git a/docs/annexes.md b/docs/annexes.md
index 2304bfb0..10952e0f 100644
--- a/docs/annexes.md
+++ b/docs/annexes.md
@@ -1,4 +1,7 @@
# Annexes
+* [Migration to binding v3](afb-migration-to-binding-v3.md)
+* [Options of afb-daemon](afb-daemon-options.md)
* [Installing the binder on a desktop](afb-desktop-package.md)
-* [Options of afb-daemon](afb-daemon-options.md) \ No newline at end of file
+* [Debugging afb-daemon](afb-daemon-debugging.md)
+* [(LEGACY) guide to migrate bindings from v1 to v2](afb-migration-v1-to-v2.md).
diff --git a/docs/migration-to-binding-v3.sed b/docs/migration-to-binding-v3.sed
new file mode 100644
index 00000000..a6682051
--- /dev/null
+++ b/docs/migration-to-binding-v3.sed
@@ -0,0 +1,68 @@
+#######################################################################################
+# Script sed for migrating from AFB_BINDING_VERSION 2 to AFB_BINDING_VERSION 3
+# See http://docs.automotivelinux.org/docs/apis_services/en/dev/reference/af-binder/afb-migration-to-ibinding-v3.html
+#######################################################################################
+# update the version
+# ------------------
+s:\(\<AFB_BINDING_VERSION[[:blank:]]\{1,\}\)2\>:\13:
+
+# update common types
+# -------------------
+s:\<\(struct[[:blank:]]\{1,\}\)\{0,1\}afb_req\>:afb_req_t:g
+s:\<\(struct[[:blank:]]\{1,\}\)\{0,1\}afb_event\>:afb_event_t:g
+s:\<\(struct[[:blank:]]\{1,\}\)\{0,1\}afb_verb_v2\>:afb_verb_t:g
+s:\<\(struct[[:blank:]]\{1,\}\)\{0,1\}afb_binding_v2\>:afb_binding_t:g
+
+# update common names
+# -------------------
+s:\<afbBindingV2\>:afbBindingExport:g
+
+# very special
+# ------------
+s:( *afb_req_t *) *{ *NULL *, *NULL *}:NULL:g
+
+# special dynapi
+# --------------
+s:\(\<AFB_BINDING_VERSION[[:blank:]]\{1,\}\)0\>:\13:
+/^[[:blank:]]*# *define *\<AFB_BINDING_WANT_DYNAPI\>/d
+s:\<\(struct[[:blank:]]\{1,\}\)\{0,1\}afb_dynapi\>\([[:blank:]]*\)\*:afb_api_t\2:g
+s:\<\(struct[[:blank:]]\{1,\}\)\{0,1\}afb_request\>\([[:blank:]]*\)\*:afb_req_t\2:g
+s:\<\(struct[[:blank:]]\{1,\}\)\{0,1\}afb_eventid\>\([[:blank:]]*\)\*:afb_event_t\2:g
+s:\<afb_request_:afb_req_:g
+s:\<afb_dynapi_:afb_api_:g
+s:\<afb_eventid_:afb_event_:g
+s:\<AFB_DYNAPI_:AFB_API_:g
+s:\<AFB_REQUEST_:AFB_REQ_:g
+s:\<afbBindingVdyn\>:afbBindingV3entry:g
+s:\<dynapi\>:api:g
+s:\<eventid\>:event:g
+s:\<afb_api_make_eventid\>:afb_api_make_event:g
+s:\<afb_api_new_api\>:-!&:g
+s:\<afb_api_sub_verb\>:afb_api_del_verb:g
+
+# udate legacy calls
+# ------------------
+s:\<afb_req_subcall\(_req\)\>:afb_req_subcall_legacy:g
+s:\<afb_req_subcall_sync\>:afb_req_subcall_sync_legacy:g
+s:\<afb_api_call\>:afb_api_call_legacy:g
+s:\<afb_api_call_sync\>:afb_api_call_sync_legacy:g
+s:\<afb_req_store\>:afb_req_addref:g
+s:\<afb_req_unstore\> *( *\(.*\) *):\1:g
+s:\<afb_daemon_\([a-z_0-9]* *(\):afb_api_\1afbBindingV3root,:g
+s:\<afb_daemon_\([a-z_0-9]* *(\):afb_api_\1afbBindingV3root,:g
+s:\<afb_service_call_\([a-z_0-9]*\)\( *(\):afb_api_\1_legacy\2afbBindingV3root,:g
+s:\<afb_service_\([a-z_0-9]* *(\):afb_api_\1afbBindingV3root,:g
+s:\<AFB_\(\(ERROR\|WARNING\|NOTICE\|INFO\|DEBUG\)\> *(\):AFB_API_\1afbBindingV3root,:g
+
+# special app-controller
+# ----------------------
+s:\<_\(AFB_SYSLOG_LEVEL_[A-Z]*\)_\>:\1:g
+
+# UNSAFES (uncomment it if optimistic)
+# --------------
+#s:\<afb_req_fail\(_[fv]\)\{0,1\}\>\( *([^,]*\):afb_req_reply\1\2, NULL:g
+#s:\<afb_req_success\(_[fv]\)\{0,1\}\>\( *([^,]*,[^,]*\):afb_req_reply\1\2, NULL:g
+#
+#s:\<afb_api_add_verb\>[^)]*:&, 0:g ;# dynapi
+#s:\<afb_api_del_verb\>[^)]*:&, NULL:g ;# dynapi
+#######################################################################################