From 17a6011775e8c6d1536994f8b9cd4fa2f99791f7 Mon Sep 17 00:00:00 2001
From: fulup <fulup.arfoll@iot.bzh>
Date: Wed, 18 Oct 2017 11:31:33 +0200
Subject: 1st V2/pre-V3 version

---
 ctl-lib/CMakeLists.txt |   2 +-
 ctl-lib/ctl-action.c   | 119 +++++++----
 ctl-lib/ctl-config.c   | 122 ++++++-----
 ctl-lib/ctl-config.h   |  87 ++++----
 ctl-lib/ctl-control.c  |  43 ++++
 ctl-lib/ctl-event.c    |  94 +++++++++
 ctl-lib/ctl-lua.c      | 564 ++++++++++++++++++++++++++++---------------------
 ctl-lib/ctl-lua.h      |  15 +-
 ctl-lib/ctl-onload.c   |  28 +--
 ctl-lib/ctl-plugin.c   |  64 +++---
 ctl-lib/ctl-plugin.h   | 176 +++++++++++++--
 ctl-lib/ctl-timer.c    |  28 +--
 ctl-lib/ctl-timer.h    |   8 +-
 13 files changed, 886 insertions(+), 464 deletions(-)
 create mode 100644 ctl-lib/ctl-control.c
 create mode 100644 ctl-lib/ctl-event.c

diff --git a/ctl-lib/CMakeLists.txt b/ctl-lib/CMakeLists.txt
index 6f765d8..2630b94 100644
--- a/ctl-lib/CMakeLists.txt
+++ b/ctl-lib/CMakeLists.txt
@@ -30,7 +30,7 @@ endif(CONTROL_SUPPORT_LUA)
 PROJECT_TARGET_ADD(ctl-utilities)
 
     # Define project Targets
-    ADD_LIBRARY(${TARGET_NAME} STATIC ctl-action.c ctl-config.c ctl-onload.c ctl-plugin.c ${CTL_LUA_SOURCE})
+    ADD_LIBRARY(${TARGET_NAME} STATIC ctl-action.c ctl-config.c ctl-onload.c ctl-plugin.c ctl-control.c ctl-event.c ${CTL_LUA_SOURCE})
 
     # Library dependencies (include updates automatically)
     TARGET_LINK_LIBRARIES(${TARGET_NAME}
diff --git a/ctl-lib/ctl-action.c b/ctl-lib/ctl-action.c
index b24269c..fa0fa6f 100644
--- a/ctl-lib/ctl-action.c
+++ b/ctl-lib/ctl-action.c
@@ -24,11 +24,18 @@
 
 #include "ctl-config.h"
 
+PUBLIC int ActionLabelToIndex(CtlActionT*actions, const char* actionLabel) {
 
-PUBLIC int ActionExecOne(CtlActionT* action, json_object *queryJ) {
-    int err;
+    for (int idx = 0; actions[idx].label; idx++) {
+        if (!strcasecmp(actionLabel, actions[idx].label)) return idx;
+    }
+    return -1;
+}
 
 
+PUBLIC void ActionExecOne(CtlSourceT *source, CtlActionT* action, json_object *queryJ) {
+    int err;
+    
     switch (action->type) {
         case CTL_TYPE_API:
         {
@@ -51,92 +58,123 @@ PUBLIC int ActionExecOne(CtlActionT* action, json_object *queryJ) {
                 }
             }
             
-            json_object_object_add(queryJ, "label", json_object_new_string(action->source.label));
+            json_object_object_add(queryJ, "label", json_object_new_string(source->label));
 
-            int err = afb_service_call_sync(action->api, action->call, queryJ, &returnJ);
+            int err = AFB_ServiceSync(action->api, action->exec.subcall.api, action->exec.subcall.verb, queryJ, &returnJ);
             if (err) {
-                static const char*format = "ActionExecOne(Api) api=%s verb=%s args=%s";
-                AFB_ERROR(format, action->api, action->call, action->source.label);
-                goto OnErrorExit;
+                AFB_ApiError(action->api, "ActionExecOne(AppFw) label=%s api=%s verb=%s args=%s", source->label, action->exec.subcall.api, action->exec.subcall.verb, json_object_get_string(action->argsJ));
             }
             break;
         }
 
 #ifdef CONTROL_SUPPORT_LUA
         case CTL_TYPE_LUA:
-            err = LuaCallFunc(action, queryJ);
+            err = LuaCallFunc(source, action, queryJ);
             if (err) {
-                AFB_ERROR("ActionExecOne(Lua) label=%s func=%s args=%s", action->source.label, action->call, json_object_get_string(action->argsJ));
-                goto OnErrorExit;
+                AFB_ApiError(action->api, "ActionExecOne(Lua) label=%s func=%s args=%s", source->label, action->exec.lua.funcname, json_object_get_string(action->argsJ));
             }
             break;
 #endif
 
         case CTL_TYPE_CB:
-            err = (*action->actionCB) (&action->source, action->argsJ, queryJ);
+            err = (*action->exec.cb.callback) (source, action->argsJ, queryJ);
             if (err) {
-                AFB_ERROR("ActionExecOne(Callback) label%s func=%s args=%s", action->source.label, action->call, json_object_get_string(action->argsJ));
-                goto OnErrorExit;
+                AFB_ApiError(action->api, "ActionExecOne(Callback) label%s plugin=%s function=%s args=%s", source->label, action->exec.cb.plugin->label, action->exec.cb.funcname, json_object_get_string(action->argsJ));
             }
             break;
 
         default:
         {
-            AFB_ERROR("ActionExecOne(unknown) API type label=%s", action->source.label);
-            goto OnErrorExit;
+            AFB_ApiError(action->api, "ActionExecOne(unknown) API type label=%s", source->label);
+            break;
         }
     }
+}
 
-    return 0;
 
-OnErrorExit:
-    return -1;
+// Direct Request Call in APIV3 
+#ifdef AFB_BINDING_PREV3
+STATIC void ActionDynRequest (AFB_ReqT request) {
+   
+   // retrieve action handle from request and execute the request
+   json_object *queryJ = afb_request_json(request);
+   CtlActionT* action  = (CtlActionT*)afb_request_get_vcbdata(request);
+   
+    CtlSourceT source;
+    source.label = action->label;
+    source.request = request;
+    source.api  = action->api;
+    
+   // provide request and execute the action
+   ActionExecOne(&source, action, queryJ);   
 }
-
+#endif
 
 // unpack individual action object
 
-PUBLIC int ActionLoadOne(CtlActionT *action, json_object *actionJ) {
-    char *api = NULL, *verb = NULL, *lua = NULL;
+PUBLIC int ActionLoadOne(AFB_ApiT apiHandle, CtlActionT *action, json_object *actionJ, int exportApi) {
     int err, modeCount = 0;
-    json_object *callbackJ=NULL;
+    json_object *callbackJ=NULL, *luaJ=NULL, *subcallJ=NULL;
 
-    err = wrap_json_unpack(actionJ, "{ss,s?s,s?o,s?s,s?s,s?s,s?o !}"
-            , "label", &action->source.label, "info", &action->source.info, "callback", &callbackJ, "lua", &lua, "api", &api, "verb", &verb, "args", &action->argsJ);
+    err = wrap_json_unpack(actionJ, "{ss,s?s,s?o,s?o,s?o,s?o !}"
+            , "label", &action->label, "info", &action->info, "callback", &callbackJ, "lua", &luaJ, "subcall", &subcallJ, "args", &action->argsJ);
     if (err) {
-        AFB_ERROR("ACTION-LOAD-ONE Missing something label|info|callback|lua|(api+verb)|args in:\n--  %s", json_object_get_string(actionJ));
+        AFB_ApiError(apiHandle,"ACTION-LOAD-ONE Action missing label|[info]|[callback]|[lua]|[subcall]|[args] in:\n--  %s", json_object_get_string(actionJ));
         goto OnErrorExit;
     }
+    
+    // save per action api handle
+    action->api = apiHandle;
+    
+    // in API V3 each control is optionally map to a verb            
+#ifdef AFB_BINDING_PREV3
+    if (apiHandle && exportApi) {
+        err = afb_dynapi_add_verb(apiHandle, action->label, action->info, ActionDynRequest, action, NULL, 0);
+        if (err) {
+            AFB_ApiError(apiHandle,"ACTION-LOAD-ONE fail to register API verb=%s", action->label);
+            goto OnErrorExit;
+        }
+        action->api = apiHandle;
+    }
+#endif   
 
-    if (lua) {
-        action->type = CTL_TYPE_LUA;
-        action->call = lua;
+    if (luaJ) {        
         modeCount++;
+        action->type = CTL_TYPE_LUA;
+        err = wrap_json_unpack(luaJ, "{s?s,s:s !}", "load", &action->exec.lua.load, "func", &action->exec.lua.funcname);
+        if (err) {
+            AFB_ApiError(apiHandle,"ACTION-LOAD-ONE Lua missing [load]|func in:\n--  %s", json_object_get_string(luaJ));
+            goto OnErrorExit;
+        }
     }
 
-    if (api && verb) {
-        action->type = CTL_TYPE_API;
-        action->api = api;
-        action->call = verb;
+    if (subcallJ) {
         modeCount++;
+        action->type = CTL_TYPE_API;
+        
+        err = wrap_json_unpack(luaJ, "{s?s,s:s !}", "api", &action->exec.subcall.api, "verb", &action->exec.subcall.verb);
+        if (err) {
+            AFB_ApiError(apiHandle,"ACTION-LOAD-ONE Subcall missing [load]|func in:\n--  %s", json_object_get_string(luaJ));
+            goto OnErrorExit;
+        }        
     }
 
     if (callbackJ) {
+        modeCount++;
         action->type = CTL_TYPE_CB;
         modeCount++;        
-        err = PluginGetCB (action, callbackJ);
-        if (err) goto OnErrorExit;
-        
+        err = PluginGetCB (apiHandle, action, callbackJ);
+        if (err) goto OnErrorExit;       
     }
 
     // make sure at least one mode is selected
     if (modeCount == 0) {
-        AFB_ERROR("ACTION-LOAD-ONE No Action Selected lua|callback|(api+verb) in %s", json_object_get_string(actionJ));
+        AFB_ApiError(apiHandle,"ACTION-LOAD-ONE No Action Selected lua|callback|(api+verb) in %s", json_object_get_string(actionJ));
         goto OnErrorExit;
     }
 
     if (modeCount > 1) {
-        AFB_ERROR("ACTION-LOAD-ONE:ToMany arguments lua|callback|(api+verb) in %s", json_object_get_string(actionJ));
+        AFB_ApiError(apiHandle,"ACTION-LOAD-ONE:ToMany arguments lua|callback|(api+verb) in %s", json_object_get_string(actionJ));
         goto OnErrorExit;
     }
     return 0;
@@ -145,7 +183,7 @@ OnErrorExit:
     return 1;
 };
 
-PUBLIC CtlActionT *ActionLoad(json_object *actionsJ) {
+PUBLIC CtlActionT *ActionConfig(AFB_ApiT apiHandle, json_object *actionsJ, int exportApi) {
     int err;
     CtlActionT *actions;
 
@@ -156,13 +194,14 @@ PUBLIC CtlActionT *ActionLoad(json_object *actionsJ) {
 
         for (int idx = 0; idx < count; idx++) {
             json_object *actionJ = json_object_array_get_idx(actionsJ, idx);
-            err = ActionLoadOne(&actions[idx], actionJ);
+                    
+            err = ActionLoadOne(apiHandle, &actions[idx], actionJ, exportApi);
             if (err) goto OnErrorExit;
         }
 
     } else {
         actions = calloc(2, sizeof (CtlActionT));
-        err = ActionLoadOne(&actions[0], actionsJ);
+        err = ActionLoadOne(apiHandle, &actions[0], actionsJ, exportApi);
         if (err) goto OnErrorExit;
     }
 
diff --git a/ctl-lib/ctl-config.c b/ctl-lib/ctl-config.c
index b7c0d54..2b5d345 100644
--- a/ctl-lib/ctl-config.c
+++ b/ctl-lib/ctl-config.c
@@ -21,6 +21,8 @@
 #define _GNU_SOURCE
 #include <stdio.h>
 #include <string.h>
+#include <sys/time.h>
+
 
 #include "filescan-utils.h"
 #include "ctl-config.h"
@@ -28,16 +30,36 @@
 
 // Load control config file
 
-PUBLIC char* CtlConfigSearch(const char *dirList) {
-    int index, err;
-    char controlFile [CONTROL_MAXPATH_LEN];
+PUBLIC int CtlConfigMagicNew() {
+  static int InitRandomDone=0;
+
+  if (!InitRandomDone) {
+    struct timeval tv;
+    InitRandomDone=1;
+    gettimeofday(&tv,NULL);
+    srand ((int)tv.tv_usec);
+  }
+  
+  return ((long)rand());
+}
 
-    strncpy(controlFile, CONTROL_CONFIG_PRE "-", CONTROL_MAXPATH_LEN);
+PUBLIC  json_object* CtlConfigScan(const char *dirList, const char *prefix) {
+    char controlFile [CONTROL_MAXPATH_LEN];
+    strncpy(controlFile, prefix, CONTROL_MAXPATH_LEN);
     strncat(controlFile, GetBinderName(), CONTROL_MAXPATH_LEN);
 
     // search for default dispatch config file
     json_object* responseJ = ScanForConfig(dirList, CTL_SCAN_RECURSIVE, controlFile, ".json");
 
+    return responseJ;
+}
+
+PUBLIC char* CtlConfigSearch(AFB_ApiT apiHandle, const char *dirList, const char *prefix) {
+    int index, err;
+    
+    // search for default dispatch config file
+    json_object* responseJ = CtlConfigScan (dirList, prefix);
+
     // We load 1st file others are just warnings
     for (index = 0; index < json_object_array_length(responseJ); index++) {
         json_object *entryJ = json_object_array_get_idx(responseJ, index);
@@ -46,18 +68,16 @@ PUBLIC char* CtlConfigSearch(const char *dirList) {
         char*fullpath;
         err = wrap_json_unpack(entryJ, "{s:s, s:s !}", "fullpath", &fullpath, "filename", &filename);
         if (err) {
-            AFB_ERROR("CTL-INIT HOOPs invalid JSON entry= %s", json_object_get_string(entryJ));
+            AFB_ApiError(apiHandle, "CTL-INIT HOOPs invalid JSON entry= %s", json_object_get_string(entryJ));
             return NULL;
         }
 
         if (index == 0) {
-            if (strcasestr(filename, controlFile)) {
-                char filepath[CONTROL_MAXPATH_LEN];
-                strncpy(filepath, fullpath, sizeof (filepath));
-                strncat(filepath, "/", sizeof (filepath));
-                strncat(filepath, filename, sizeof (filepath));
-                return (strdup(filepath));
-            }
+            char filepath[CONTROL_MAXPATH_LEN];
+            strncpy(filepath, fullpath, sizeof (filepath));
+            strncat(filepath, "/", sizeof (filepath));
+            strncat(filepath, filename, sizeof (filepath));
+            return (strdup(filepath));
         }
     }
 
@@ -65,15 +85,16 @@ PUBLIC char* CtlConfigSearch(const char *dirList) {
     return NULL;
 }
 
-PUBLIC int CtlConfigExec(CtlConfigT *ctlConfig) {
+PUBLIC int CtlConfigExec(AFB_ApiT apiHandle, CtlConfigT *ctlConfig) {
+    
     // best effort to initialise everything before starting
     if (ctlConfig->requireJ) {
 
         void DispatchRequireOneApi(json_object * bindindJ) {
             const char* requireBinding = json_object_get_string(bindindJ);
-            int err = afb_daemon_require_api(requireBinding, 1);
+            int err = AFB_RequireApi(apiHandle, requireBinding, 1);
             if (err) {
-                AFB_WARNING("CTL-LOAD-CONFIG:REQUIRE Fail to get=%s", requireBinding);
+                AFB_ApiWarning(apiHandle, "CTL-LOAD-CONFIG:REQUIRE Fail to get=%s", requireBinding);
             }
         }
 
@@ -87,14 +108,14 @@ PUBLIC int CtlConfigExec(CtlConfigT *ctlConfig) {
     }
 
 #ifdef CONTROL_SUPPORT_LUA
-    int err= LuaConfigExec();
+    int err= LuaConfigExec(apiHandle);
     if (err) goto OnErrorExit;
 #endif
 
     // Loop on every section and process config
     int errcount=0;
     for (int idx = 0; ctlConfig->sections[idx].key != NULL; idx++) {
-        errcount += ctlConfig->sections[idx].loadCB(&ctlConfig->sections[idx], NULL);
+        errcount += ctlConfig->sections[idx].loadCB(apiHandle, &ctlConfig->sections[idx], NULL);
     }
     return errcount;
 
@@ -102,73 +123,66 @@ OnErrorExit:
     return 1;
 }
 
-PUBLIC CtlConfigT *CtlConfigLoad(const char* filepath, CtlSectionT *sections) {
+PUBLIC CtlConfigT *CtlLoadMetaData(AFB_ApiT apiHandle, const char* filepath) {
     json_object *ctlConfigJ;
-    CtlConfigT *ctlConfig;
+    CtlConfigT *ctlHandle=NULL;
     int err;
 
-#ifdef CONTROL_SUPPORT_LUA
-    err= LuaConfigLoad();
-    if (err) goto OnErrorExit;
-#endif
-
-    // Search for config in filepath  
-    filepath = CtlConfigSearch(filepath);
-
-    if (!filepath) {
-        AFB_ERROR("CTL-LOAD-CONFIG No JSON Config found invalid JSON %s ", filepath);
-        goto OnErrorExit;
-    }
-
     // Load JSON file
     ctlConfigJ = json_object_from_file(filepath);
     if (!ctlConfigJ) {
-        AFB_ERROR("CTL-LOAD-CONFIG Not invalid JSON %s ", filepath);
+        AFB_ApiError(apiHandle, "CTL-LOAD-CONFIG Not invalid JSON %s ", filepath);
         goto OnErrorExit;
     }
 
-    AFB_INFO("CTL-LOAD-CONFIG: loading config filepath=%s", filepath);
+    AFB_ApiInfo(apiHandle, "CTL-LOAD-CONFIG: loading config filepath=%s", filepath);
 
     json_object *metadataJ;
     int done = json_object_object_get_ex(ctlConfigJ, "metadata", &metadataJ);
     if (done) {
-        ctlConfig = calloc(1, sizeof (CtlConfigT));
-        err = wrap_json_unpack(metadataJ, "{ss,ss,ss,s?s,s?o !}", "label", &ctlConfig->label, "version", &ctlConfig->version
-                , "api", &ctlConfig->api, "info", &ctlConfig->info, "require", &ctlConfig->requireJ);
+        ctlHandle = calloc(1, sizeof (CtlConfigT));
+        err = wrap_json_unpack(metadataJ, "{ss,ss,ss,s?s,s?o !}", "label", &ctlHandle->label, "version", &ctlHandle->version
+                , "api", &ctlHandle->api, "info", &ctlHandle->info, "require", &ctlHandle->requireJ);
         if (err) {
-            AFB_ERROR("CTL-LOAD-CONFIG:METADATA Missing something label|api|version|[info]|[require] in:\n-- %s", json_object_get_string(metadataJ));
+            AFB_ApiError(apiHandle, "CTL-LOAD-CONFIG:METADATA Missing something label|api|version|[info]|[require] in:\n-- %s", json_object_get_string(metadataJ));
             goto OnErrorExit;
         }
-
-        // Should replace this with API name change
-        if (ctlConfig->api) {
-            err = afb_daemon_rename_api(ctlConfig->api);
-            if (err) AFB_WARNING("Fail to rename api to:%s", ctlConfig->api);
-        }
-        
     }
+    
+    ctlHandle->configJ = ctlConfigJ;   
+    return ctlHandle;
+    
+OnErrorExit:
+    if (ctlHandle) free(ctlHandle);
+    return NULL;
+}
+
+PUBLIC int CtlLoadSections(AFB_ApiT apiHandle, CtlConfigT *ctlHandle, CtlSectionT *sections) {
+    int err;
+
+#ifdef CONTROL_SUPPORT_LUA
+    err= LuaConfigLoad(apiHandle);
+    if (err) goto OnErrorExit;
+#endif
 
-    //load config sections
     err = 0;
-    ctlConfig->sections = sections;
+    ctlHandle->sections = sections;
     for (int idx = 0; sections[idx].key != NULL; idx++) {
         json_object * sectionJ;
-        int done = json_object_object_get_ex(ctlConfigJ, sections[idx].key, &sectionJ);
+        int done = json_object_object_get_ex(ctlHandle->configJ, sections[idx].key, &sectionJ);
         if (!done) {
-            AFB_ERROR("CtlConfigLoad: fail to find '%s' section in config '%s'", sections[idx].key, filepath);
+            AFB_ApiError(apiHandle, "CtlConfigLoad: fail to find '%s' section in config '%s'", sections[idx].key, ctlHandle->label);
             err++;
         } else {
-            err += sections[idx].loadCB(&sections[idx], sectionJ);
+            err += sections[idx].loadCB(apiHandle, &sections[idx], sectionJ);
         }
-
     }
     if (err) goto OnErrorExit;
 
-    return (ctlConfig);
+    return 0;
 
 OnErrorExit:
-    free(ctlConfig);
-    return NULL;
+    return 1;
 }
 
 
diff --git a/ctl-lib/ctl-config.h b/ctl-lib/ctl-config.h
index 2e3a16a..09c573f 100644
--- a/ctl-lib/ctl-config.h
+++ b/ctl-lib/ctl-config.h
@@ -22,13 +22,10 @@
 #define _CTL_CONFIG_INCLUDE_
 
 #define _GNU_SOURCE
-#define AFB_BINDING_VERSION 2
-#include <afb/afb-binding.h>
-#include <json-c/json.h>
-#include <filescan-utils.h>
-#include <wrap-json.h>
 
 #include "ctl-plugin.h"
+#include <filescan-utils.h>
+#include <wrap-json.h>
 
 #ifndef CONTROL_MAXPATH_LEN
   #define CONTROL_MAXPATH_LEN 255
@@ -42,37 +39,13 @@
   #define CTL_PLUGIN_EXT ".ctlso"
 #endif
 
-
-
-typedef enum {
-    CTL_TYPE_NONE=0,
-    CTL_TYPE_API,
-    CTL_TYPE_CB,
-    CTL_TYPE_LUA,
-} CtlActionTypeT;
-
-
-typedef struct {
-    CtlActionTypeT type;
-    const char* api;
-    const char* call;
-    json_object *argsJ;
-    int (*actionCB)(CtlSourceT *source, json_object *argsJ, json_object *queryJ);
-    CtlSourceT source;
-} CtlActionT;
-
-typedef struct {
-    const char* label;
-    const char *info;
-    CtlActionT *actions;
-} DispatchHandleT;
-
 typedef struct ConfigSectionS {
   const char *key;
   const char *label;
   const char *info;
-  int (*loadCB)(struct ConfigSectionS *section, json_object *sectionJ);
-  void *handle;  
+  int (*loadCB)(AFB_ApiT apihandle, struct ConfigSectionS *section, json_object *sectionJ);
+  void *handle;
+  CtlActionT *actions;  
 } CtlSectionT;
 
 typedef struct {
@@ -80,6 +53,7 @@ typedef struct {
     const char* label;
     const char *info;
     const char *version;
+    json_object *configJ;
     json_object *requireJ;
     CtlSectionT *sections;
 } CtlConfigT;
@@ -87,27 +61,54 @@ typedef struct {
 
 #ifdef CONTROL_SUPPORT_LUA
   #include "ctl-lua.h"
-#else
- typedef void* Lua2cWrapperT;
 #endif
+ 
+// This should not be global as application may want to define their own sections 
+typedef enum {
+  CTL_SECTION_PLUGIN,  
+  CTL_SECTION_ONLOAD,  
+  CTL_SECTION_CONTROL,  
+  CTL_SECTION_EVENT,
+  CTL_SECTION_HAL,
+          
+  CTL_SECTION_ENDTAG, 
+} SectionEnumT;
 
 
 // ctl-action.c
-PUBLIC CtlActionT *ActionLoad(json_object *actionsJ);
-PUBLIC int ActionExecOne(CtlActionT* action, json_object *queryJ);
-PUBLIC int ActionLoadOne(CtlActionT *action, json_object *actionJ);
+PUBLIC CtlActionT *ActionConfig(AFB_ApiT apiHandle, json_object *actionsJ,  int exportApi);
+PUBLIC void ActionExecOne( CtlSourceT *source, CtlActionT* action, json_object *queryJ);
+PUBLIC int ActionLoadOne(AFB_ApiT apiHandle, CtlActionT *action, json_object *, int exportApi);
+PUBLIC int ActionLabelToIndex(CtlActionT* actions, const char* actionLabel);
+
 
 // ctl-config.c
-PUBLIC CtlConfigT *CtlConfigLoad(const char* filepath, CtlSectionT *sections);
-PUBLIC int CtlConfigExec(CtlConfigT *ctlConfig);
+PUBLIC int CtlConfigMagicNew();
+PUBLIC json_object* CtlConfigScan(const char *dirList, const char *prefix) ;
+PUBLIC char* CtlConfigSearch(AFB_ApiT apiHandle, const char *dirList, const char *prefix) ;
+PUBLIC int CtlConfigExec(AFB_ApiT apiHandle, CtlConfigT *ctlConfig) ;
+PUBLIC CtlConfigT *CtlLoadMetaData(AFB_ApiT apiHandle,const char* filepath) ;
+PUBLIC int CtlLoadSections(AFB_ApiT apiHandle, CtlConfigT *ctlHandle, CtlSectionT *sections);
 
-// ctl-onload.c
-PUBLIC int OnloadConfig(CtlSectionT *section, json_object *actionsJ);
 
 
+// ctl-event.c
+PUBLIC int EventConfig(AFB_ApiT apihandle, CtlSectionT *section, json_object *actionsJ);
+#ifdef AFB_BINDING_PREV3
+PUBLIC void CtrlDispatchApiEvent (AFB_ApiT apiHandle, const char *evtLabel, struct json_object *eventJ);
+#else
+PUBLIC void CtrlDispatchV2Event(const char *evtLabel, json_object *eventJ);
+#endif
+
+// ctl-control.c
+PUBLIC int ControlConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *actionsJ);
+
+// ctl-onload.c
+PUBLIC int OnloadConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *actionsJ);
+
 // ctl-plugin.c
-PUBLIC int PluginConfig(CtlSectionT *section, json_object *pluginsJ);
-PUBLIC int PluginGetCB (CtlActionT *action , json_object *callbackJ);
+PUBLIC int PluginConfig(AFB_ApiT UNUSED_ARG(apiHandle), CtlSectionT *section, json_object *pluginsJ);
+PUBLIC int PluginGetCB (AFB_ApiT apiHandle, CtlActionT *action , json_object *callbackJ);
 
 
 #endif /* _CTL_CONFIG_INCLUDE_ */
\ No newline at end of file
diff --git a/ctl-lib/ctl-control.c b/ctl-lib/ctl-control.c
new file mode 100644
index 0000000..117f5b5
--- /dev/null
+++ b/ctl-lib/ctl-control.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author Fulup Ar Foll <fulup@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, something express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+
+#include "ctl-config.h"
+
+// onload section receive one action or an array of actions
+PUBLIC int ControlConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *actionsJ) {
+    
+    // Load time parse actions in config file
+    if (actionsJ != NULL) {
+        section->actions= ActionConfig(apiHandle, actionsJ, 1);
+        
+        if (!section->actions) {
+            AFB_ApiError (apiHandle, "ControlLoad config fail processing onload actions");
+            goto OnErrorExit;
+        }        
+    }
+
+    return 0;
+
+OnErrorExit:
+    return 1;
+
+}
diff --git a/ctl-lib/ctl-event.c b/ctl-lib/ctl-event.c
new file mode 100644
index 0000000..b9be1c7
--- /dev/null
+++ b/ctl-lib/ctl-event.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author Fulup Ar Foll <fulup@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, something express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+
+#include "ctl-config.h"
+
+
+// Event dynamic API-V3 mode
+#ifdef AFB_BINDING_PREV3
+PUBLIC void CtrlDispatchApiEvent (AFB_ApiT apiHandle, const char *evtLabel, struct json_object *eventJ) {
+    AFB_ApiNotice (apiHandle, "Received event=%s, query=%s", evtLabel, json_object_get_string(eventJ));
+    
+    // retrieve section config from api handle
+    CtlConfigT *ctrlConfig = (CtlConfigT*) afb_dynapi_get_userdata(apiHandle);
+    
+    CtlActionT* actions = ctrlConfig->sections[CTL_SECTION_EVENT].actions;
+            
+    int index= ActionLabelToIndex(actions, evtLabel);
+    if (index < 0) {
+        AFB_ApiWarning(apiHandle, "CtlDispatchEvent: fail to find label=%s in action event section", evtLabel);
+        return;
+    }
+
+    // create a dummy source for action    
+    CtlSourceT source;
+    source.label = actions[index].label;
+    source.api   = actions[index].api;
+    source.request = NULL;
+    
+    // Best effort ignoring error to exec corresponding action 
+    (void) ActionExecOne (&source, &actions[index], eventJ);
+    
+}
+#else
+// In API-V2 controller config is unique and static
+extern CtlConfigT *ctrlConfig;
+
+// call action attached to even name if any
+PUBLIC void CtrlDispatchV2Event(const char *evtLabel, json_object *eventJ) {
+    CtlActionT* actions = ctrlConfig->sections[CTL_SECTION_EVENT].actions;
+            
+    int index= ActionLabelToIndex(actions, evtLabel);
+    if (index < 0) {
+        AFB_WARNING ("CtlDispatchEvent: fail to find label=%s in action event section", evtLabel);
+        return;
+    }
+        
+    CtlSourceT source;
+    source.label = actions[index].label;
+    source.api   = actions[index].api;
+    source.request = AFB_ReqNone;
+
+    // Best effort ignoring error to exec corresponding action 
+    (void) ActionExecOne (&source, &actions[index], eventJ);
+}
+#endif
+
+// onload section receive one action or an array of actions
+PUBLIC int EventConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *actionsJ) {
+    
+    // Load time parse actions in config file
+    if (actionsJ != NULL) {
+        section->actions= ActionConfig(apiHandle, actionsJ, 1);
+        
+        if (!section->actions) {
+            AFB_ApiError (apiHandle, "EventLoad config fail processing onload actions");
+            goto OnErrorExit;
+        }        
+    }
+
+    return 0;
+
+OnErrorExit:
+    return 1;
+
+}
diff --git a/ctl-lib/ctl-lua.c b/ctl-lib/ctl-lua.c
index 7b68fe2..2aaaabb 100644
--- a/ctl-lib/ctl-lua.c
+++ b/ctl-lib/ctl-lua.c
@@ -27,47 +27,43 @@
 #define _GNU_SOURCE
 #include <stdio.h>
 #include <string.h>
+#include <sys/time.h>
 
 #include "ctl-config.h"
 
 #define LUA_FIST_ARG 2  // when using luaL_newlib calllback receive libtable as 1st arg
 #define LUA_MSG_MAX_LENGTH 512
 #define JSON_ERROR (json_object*)-1
-static afb_req NULL_AFBREQ = {};
 
 
 static  lua_State* luaState;
 
-#define CTX_MAGIC 123456789
-#define CTX_TOKEN "AFB_ctx"
+#ifndef CTX_MAGIC
+ static int CTX_MAGIC;
+#endif
+
+#ifndef TIMER_MAGIC
+ static int TIMER_MAGIC;
+#endif
 
 typedef struct {
     char *name;
     int  count;
-    afb_event event;
+    AFB_EventT event;
 } LuaAfbEvent;
-static LuaAfbEvent *luaDefaultEvt;
 
 typedef struct {
     int ctxMagic;
-    afb_req request;
-    void *handle;
-    char *info;
-} LuaAfbContextT;
+    CtlSourceT *source;
+} LuaAfbSourceT;
 
 typedef struct {
   const char *callback;
   json_object *context;
-  void *handle;
-} LuaCallServiceT;
+  CtlSourceT *source;
+} LuaCbHandleT;
+
 
-typedef enum {
-    AFB_MSG_INFO,
-    AFB_MSG_WARNING,
-    AFB_MSG_NOTICE,
-    AFB_MSG_DEBUG,
-    AFB_MSG_ERROR,
-} LuaAfbMessageT;
 
 /*
  * Note(Fulup): I fail to use luaL_setmetatable and replaced it with a simple opaque
@@ -75,43 +71,32 @@ typedef enum {
  *  https://stackoverflow.com/questions/45596493/lua-using-lua-newuserdata-from-lua-pcall
  */
 
-STATIC LuaAfbContextT *LuaCtxCheck (lua_State *luaState, int index) {
-  LuaAfbContextT *afbContext;
-  //luaL_checktype(luaState, index, LUA_TUSERDATA);
-  //afbContext = (LuaAfbContextT *)luaL_checkudata(luaState, index, CTX_TOKEN);
+STATIC CtlSourceT *LuaSourcePop (lua_State *luaState, int index) {
+  LuaAfbSourceT *afbSource;
   luaL_checktype(luaState, index, LUA_TLIGHTUSERDATA);
-  afbContext = (LuaAfbContextT *) lua_touserdata(luaState, index);
-  if (afbContext == NULL && afbContext->ctxMagic != CTX_MAGIC) {
-      luaL_error(luaState, "Fail to retrieve user data context=%s", CTX_TOKEN);
-      AFB_ERROR ("afbContextCheck error retrieving afbContext");
+  afbSource = (LuaAfbSourceT *) lua_touserdata(luaState, index);
+  if (afbSource == NULL || afbSource->ctxMagic != CTX_MAGIC) {
+      luaL_error(luaState, "(Hoops) Invalid source handle");
       return NULL;
   }
-  return afbContext;
+  return afbSource->source;
 }
 
-STATIC LuaAfbContextT *LuaCtxPush (lua_State *luaState, afb_req request, void *handle, const char* info) {
-  // LuaAfbContextT *afbContext = (LuaAfbContextT *)lua_newuserdata(luaState, sizeof(LuaAfbContextT));
-  // luaL_setmetatable(luaState, CTX_TOKEN);
-  LuaAfbContextT *afbContext = (LuaAfbContextT *)calloc(1, sizeof(LuaAfbContextT));
-  lua_pushlightuserdata(luaState, afbContext);
-  if (!afbContext) {
-      AFB_ERROR ("LuaCtxPush fail to allocate user data context");
+STATIC LuaAfbSourceT *LuaSourcePush (lua_State *luaState, CtlSourceT *source) {
+  LuaAfbSourceT *afbSource = (LuaAfbSourceT *)calloc(1, sizeof(LuaAfbSourceT));
+  if (!afbSource) {
+      AFB_ApiError(source->api, "LuaSourcePush fail to allocate user data context");
       return NULL;
   }
-  afbContext->ctxMagic=CTX_MAGIC;
-  afbContext->info=strdup(info);
-  afbContext->request= request;
-  afbContext->handle= handle;
-  return afbContext;
-}
-
-STATIC void LuaCtxFree (LuaAfbContextT *afbContext) {
-    free(afbContext->info);
-    free(afbContext);
+  
+  lua_pushlightuserdata(luaState, afbSource);
+  afbSource->ctxMagic=CTX_MAGIC;
+  afbSource->source= source;
+  return afbSource;
 }
 
 // Push a json structure on the stack as a LUA table
-STATIC int LuaPushArgument (json_object *argsJ) {
+STATIC int LuaPushArgument (CtlSourceT *source, json_object *argsJ) {
 
     //AFB_NOTICE("LuaPushArgument argsJ=%s", json_object_get_string(argsJ));
 
@@ -120,7 +105,7 @@ STATIC int LuaPushArgument (json_object *argsJ) {
         case json_type_object: {
             lua_newtable (luaState);
             json_object_object_foreach (argsJ, key, val) {
-                int done = LuaPushArgument (val);
+                int done = LuaPushArgument (source, val);
                 if (done) {
                     lua_setfield(luaState,-2, key);
                 }
@@ -132,7 +117,7 @@ STATIC int LuaPushArgument (json_object *argsJ) {
             lua_newtable (luaState);
             for (int idx=0; idx < length; idx ++) {
                 json_object *val=json_object_array_get_idx(argsJ, idx);
-                LuaPushArgument (val);
+                LuaPushArgument (source, val);
                 lua_seti (luaState,-2, idx);
             }
             break;
@@ -150,23 +135,23 @@ STATIC int LuaPushArgument (json_object *argsJ) {
             lua_pushnumber(luaState, json_object_get_double(argsJ));
             break;
         case json_type_null:
-            AFB_WARNING("LuaPushArgument: NULL object type %s", json_object_get_string(argsJ));
+            AFB_ApiWarning(source->api, "LuaPushArgument: NULL object type %s", json_object_get_string(argsJ));
             return 0;
             break;
 
         default:
-            AFB_ERROR("LuaPushArgument: unsupported Json object type %s", json_object_get_string(argsJ));
+            AFB_ApiError(source->api, "LuaPushArgument: unsupported Json object type %s", json_object_get_string(argsJ));
             return 0;
     }
     return 1;
 }
 
-STATIC  json_object *LuaPopOneArg (lua_State* luaState, int idx);
+STATIC  json_object *LuaPopOneArg (CtlSourceT *source, lua_State* luaState, int idx);
 
 // Move a table from Internal Lua representation to Json one
 // Numeric table are transformed in json array, string one in object
 // Mix numeric/string key are not supported
-STATIC json_object *LuaTableToJson (lua_State* luaState, int index) {
+STATIC json_object *LuaTableToJson (CtlSourceT *source, lua_State* luaState, int index) {
     #define LUA_KEY_INDEX -2
     #define LUA_VALUE_INDEX -1
 
@@ -185,12 +170,12 @@ STATIC json_object *LuaTableToJson (lua_State* luaState, int index) {
                 tableJ= json_object_new_object();
                 tableType=LUA_TSTRING;
             } else if (tableType != LUA_TSTRING){
-                AFB_ERROR("MIX Lua Table with key string/numeric not supported");
+                AFB_ApiError(source->api, "MIX Lua Table with key string/numeric not supported");
                 return NULL;
             }
 
             const char *key= lua_tostring(luaState, LUA_KEY_INDEX);
-            json_object *argJ= LuaPopOneArg(luaState, LUA_VALUE_INDEX);
+            json_object *argJ= LuaPopOneArg(source, luaState, LUA_VALUE_INDEX);
             json_object_object_add(tableJ, key, argJ);
 
         } else {
@@ -198,11 +183,11 @@ STATIC json_object *LuaTableToJson (lua_State* luaState, int index) {
                 tableJ= json_object_new_array();
                 tableType=LUA_TNUMBER;
             } else if(tableType != LUA_TNUMBER) {
-                AFB_ERROR("MIX Lua Table with key numeric/string not supported");
+                AFB_ApiError(source->api, "MIX Lua Table with key numeric/string not supported");
                 return NULL;
             }
 
-            json_object *argJ= LuaPopOneArg(luaState, LUA_VALUE_INDEX);
+            json_object *argJ= LuaPopOneArg(source, luaState, LUA_VALUE_INDEX);
             json_object_array_add(tableJ, argJ);
         }
 
@@ -218,7 +203,7 @@ STATIC json_object *LuaTableToJson (lua_State* luaState, int index) {
     return tableJ;
 }
 
-STATIC  json_object *LuaPopOneArg (lua_State* luaState, int idx) {
+STATIC  json_object *LuaPopOneArg (CtlSourceT *source, lua_State* luaState, int idx) {
     json_object *value=NULL;
 
     int luaType = lua_type(luaState, idx);
@@ -240,7 +225,7 @@ STATIC  json_object *LuaPopOneArg (lua_State* luaState, int idx) {
            value=  json_object_new_string(lua_tostring(luaState, idx));
             break;
         case LUA_TTABLE:
-            value= LuaTableToJson(luaState, idx);
+            value= LuaTableToJson(source, luaState, idx);
             break;
         case LUA_TNIL:
             value=json_object_new_string("nil") ;
@@ -250,14 +235,14 @@ STATIC  json_object *LuaPopOneArg (lua_State* luaState, int idx) {
             break;
 
         default:
-            AFB_NOTICE ("LuaPopOneArg: script returned Unknown/Unsupported idx=%d type:%d/%s", idx, luaType, lua_typename(luaState, luaType));
+            AFB_ApiNotice (source->api, "LuaPopOneArg: script returned Unknown/Unsupported idx=%d type:%d/%s", idx, luaType, lua_typename(luaState, luaType));
             value=NULL;
     }
 
     return value;
 }
 
-static json_object *LuaPopArgs (lua_State* luaState, int start) {
+static json_object *LuaPopArgs (CtlSourceT *source, lua_State* luaState, int start) {
     json_object *responseJ;
 
     int stop = lua_gettop(luaState);
@@ -265,12 +250,12 @@ static json_object *LuaPopArgs (lua_State* luaState, int start) {
 
     // start at 2 because we are using a function array lib
     if (start == stop) {
-        responseJ=LuaPopOneArg (luaState, start);
+        responseJ=LuaPopOneArg (source, luaState, start);
     } else {
         // loop on remaining return arguments
         responseJ= json_object_new_array();
         for (int idx=start; idx <= stop; idx++) {
-            json_object *argJ=LuaPopOneArg (luaState, idx);
+            json_object *argJ=LuaPopOneArg (source, luaState, idx);
             if (!argJ) goto OnErrorExit;
             json_object_array_add(responseJ, argJ);
        }
@@ -283,10 +268,41 @@ static json_object *LuaPopArgs (lua_State* luaState, int start) {
 }
 
 
-STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) {
-    char *message;
 
-    json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG);
+ /*
+  * 'level' is defined by syslog standard:
+  *      EMERGENCY         0        System is unusable
+  *      ALERT             1        Action must be taken immediately
+  *      CRITICAL          2        Critical conditions
+  *      ERROR             3        Error conditions
+  *      WARNING           4        Warning conditions
+  *      NOTICE            5        Normal but significant condition
+  *      INFO              6        Informational
+  *      DEBUG             7        Debug-level messages
+  */
+typedef enum {
+    AFB_MSG_INFO=6,
+    AFB_MSG_WARNING=4,
+    AFB_MSG_NOTICE=5,
+    AFB_MSG_DEBUG=7,
+    AFB_MSG_ERROR=3,
+} LuaAfbLevelT;
+
+STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbLevelT level) {
+    char *message;
+    
+    CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+    if (!source) goto OnErrorExit;
+\
+    
+    // if log level low then silently ignore message
+#ifdef AFB_BINDING_PREV3
+    if(source->api->verbosity < level) return 0; 
+#else
+    if(afb_get_verbosity() < level) return 0; 
+#endif
+    
+    json_object *responseJ= LuaPopArgs(source, luaState, LUA_FIST_ARG+1);
 
     if (!responseJ) {
         luaL_error(luaState,"LuaFormatMessage empty message");
@@ -329,6 +345,10 @@ STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) {
                     message[targetIdx]='%';
                     targetIdx++;
                     break;
+                    
+                case 'A':
+                    targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"level: %s", source->label);
+                    break;
 
                 case 's':
                 default:
@@ -339,7 +359,7 @@ STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) {
 
         } else {
             if (targetIdx >= LUA_MSG_MAX_LENGTH) {
-                AFB_WARNING ("LuaFormatMessage: message[%s] owerverflow LUA_MSG_MAX_LENGTH=%d", format, LUA_MSG_MAX_LENGTH);
+                AFB_ApiWarning (source->api, "LuaFormatMessage: message[%s] owerverflow LUA_MSG_MAX_LENGTH=%d", format, LUA_MSG_MAX_LENGTH);
                 targetIdx --; // move backward for EOL
                 break;
             } else {
@@ -350,36 +370,22 @@ STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) {
     message[targetIdx]='\0';
 
 PrintMessage:
-    switch (action) {
-        case  AFB_MSG_WARNING:
-            AFB_WARNING ("%s", message);
-            break;
-        case AFB_MSG_NOTICE:
-            AFB_NOTICE ("%s", message);
-            break;
-        case AFB_MSG_DEBUG:
-            AFB_DEBUG ("%s", message);
-            break;
-        case AFB_MSG_INFO:
-            AFB_INFO ("%s", message);
-            break;
-        case AFB_MSG_ERROR:
-        default:
-            AFB_ERROR ("%s", message);
-    }
+    // TBD: __file__ and __line__ should match LUA source code                
+    AFB_ApiVerbose(source->api, level,__FILE__,__LINE__,source->label, message);
     return 0;  // nothing return to lua
 
   OnErrorExit: // on argument to return (the error message)
     return 1;
 }
 
+
 STATIC int LuaPrintInfo(lua_State* luaState) {
     int err=LuaFormatMessage (luaState, AFB_MSG_INFO);
     return err;
 }
 
 STATIC int LuaPrintError(lua_State* luaState) {
-    int err=LuaFormatMessage (luaState, AFB_MSG_ERROR);
+    int err=LuaFormatMessage (luaState, AFB_MSG_DEBUG);
     return err; // no value return
 }
 
@@ -394,21 +400,20 @@ STATIC int LuaPrintNotice(lua_State* luaState) {
 }
 
 STATIC int LuaPrintDebug(lua_State* luaState) {
-    int err=LuaFormatMessage (luaState, AFB_MSG_DEBUG);
+    int err=LuaFormatMessage (luaState, AFB_MSG_ERROR);
     return err;
 }
 
 STATIC int LuaAfbSuccess(lua_State* luaState) {
-    LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG);
-    if (!afbContext) goto OnErrorExit;
+    CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+    if (!source) goto OnErrorExit;
 
     // ignore context argument
-    json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1);
+    json_object *responseJ= LuaPopArgs(source, luaState, LUA_FIST_ARG+1);
     if (responseJ == JSON_ERROR) return 1;
 
-    afb_req_success(afbContext->request, responseJ, NULL);
+    AFB_ReqSucess (source->request, responseJ, NULL);
 
-    LuaCtxFree(afbContext);
     return 0;
 
  OnErrorExit:
@@ -417,15 +422,14 @@ STATIC int LuaAfbSuccess(lua_State* luaState) {
 }
 
 STATIC int LuaAfbFail(lua_State* luaState) {
-    LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG);
-    if (!afbContext) goto OnErrorExit;
+    CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+    if (!source) goto OnErrorExit;
 
-    json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1);
+    json_object *responseJ= LuaPopArgs(source, luaState, LUA_FIST_ARG+1);
     if (responseJ == JSON_ERROR) return 1;
 
-    afb_req_fail(afbContext->request, afbContext->info, json_object_get_string(responseJ));
+    AFB_ReqFail(source->request, source->label, json_object_get_string(responseJ));
 
-    LuaCtxFree(afbContext);
     return 0;
 
  OnErrorExit:
@@ -433,46 +437,52 @@ STATIC int LuaAfbFail(lua_State* luaState) {
         return 1;
 }
 
-STATIC void LuaAfbServiceCB(void *handle, int iserror, struct json_object *responseJ) {
-    LuaCallServiceT *contextCB= (LuaCallServiceT*)handle;
+STATIC void LuaAfbServiceCB(void *handle, int iserror, struct json_object *responseJ, AFB_ApiT apiHandle) {
+    LuaCbHandleT *handleCb= (LuaCbHandleT*)handle;
     int count=1;
 
-    lua_getglobal(luaState, contextCB->callback);
+    lua_getglobal(luaState, handleCb->callback);
 
     // push error status & response
     lua_pushboolean(luaState, iserror);
-    count+= LuaPushArgument(responseJ);
-    count+= LuaPushArgument(contextCB->context);
+    count+= LuaPushArgument(handleCb->source, responseJ);
+    count+= LuaPushArgument(handleCb->source, handleCb->context);
 
     int err=lua_pcall(luaState, count, LUA_MULTRET, 0);
     if (err) {
-        AFB_ERROR ("LUA-SERICE-CB:FAIL response=%s err=%s", json_object_get_string(responseJ), lua_tostring(luaState,-1) );
+        AFB_ApiError(apiHandle, "LUA-SERICE-CB:FAIL response=%s err=%s", json_object_get_string(responseJ), lua_tostring(luaState,-1) );
     }
 
-    free (contextCB);
+    free (handleCb);
 }
 
 
 STATIC int LuaAfbService(lua_State* luaState) {
     int count = lua_gettop(luaState);
 
+    CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+    if (!source) {
+        lua_pushliteral (luaState, "LuaAfbService-Fail Invalid request handle");
+        goto OnErrorExit;
+    }
+    
     // note: argument start at 2 because of AFB: table
-    if (count <5 || !lua_isstring(luaState, 2) || !lua_isstring(luaState, 3) || !lua_istable(luaState, 4) || !lua_isstring(luaState, 5)) {
+    if (count <6 || !lua_isstring(luaState, 3) || !lua_isstring(luaState, 4) || !lua_istable(luaState, 5) || !lua_isstring(luaState, 6)) {
         lua_pushliteral (luaState, "ERROR: syntax AFB:service(api, verb, {[Lua Table]})");
         goto OnErrorExit;
     }
 
     // get api/verb+query
-    const char *api = lua_tostring(luaState,2);
-    const char *verb= lua_tostring(luaState,3);
-    json_object *queryJ= LuaTableToJson(luaState, 4);
+    const char *api = lua_tostring(luaState,3);
+    const char *verb= lua_tostring(luaState,4);
+    json_object *queryJ= LuaTableToJson(source, luaState, 5);
     if (queryJ == JSON_ERROR) return 1;
 
-    LuaCallServiceT *contextCB = calloc (1, sizeof(LuaCallServiceT));
-    contextCB->callback= lua_tostring(luaState, 5);
-    contextCB->context =  LuaPopArgs(luaState, 6);
+    LuaCbHandleT *handleCb = calloc (1, sizeof(LuaCbHandleT));
+    handleCb->callback= lua_tostring(luaState, 6);
+    handleCb->context =  LuaPopArgs(source, luaState, 7);
 
-    afb_service_call(api, verb, queryJ, LuaAfbServiceCB, contextCB);
+    AFB_ServiceCall(source->api, api, verb, queryJ, LuaAfbServiceCB, handleCb);
 
     return 0; // no value return
 
@@ -485,22 +495,29 @@ STATIC int LuaAfbServiceSync(lua_State* luaState) {
     int count = lua_gettop(luaState);
     json_object *responseJ;
 
+    CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+    if (!source) {
+        lua_pushliteral (luaState, "LuaAfbServiceSync-Fail Invalid request handle");
+        goto OnErrorExit;
+    }
+    
     // note: argument start at 2 because of AFB: table
-    if (count <3 || !lua_isstring(luaState, 2) || !lua_isstring(luaState, 3) || !lua_istable(luaState, 4)) {
+    if (count <4 || !lua_isstring(luaState, 3) || !lua_isstring(luaState, 4) || !lua_istable(luaState, 5)) {
         lua_pushliteral (luaState, "ERROR: syntax AFB:servsync(api, verb, {[Lua Table]})");
         goto OnErrorExit;
     }
 
-    // get api/verb+query
-    const char *api = lua_tostring(luaState,2);
-    const char *verb= lua_tostring(luaState,3);
-    json_object *queryJ= LuaTableToJson(luaState, 4);
+    
+    // get source/api/verb+query
+    const char *api = lua_tostring(luaState,LUA_FIST_ARG+2);
+    const char *verb= lua_tostring(luaState,LUA_FIST_ARG+3);
+    json_object *queryJ= LuaTableToJson(source, luaState, LUA_FIST_ARG+4);
 
-    int iserror=afb_service_call_sync (api, verb, queryJ, &responseJ);
+    int iserror=AFB_ServiceSync(source->api, api, verb, queryJ, &responseJ);
 
     // push error status & response
     count=1; lua_pushboolean(luaState, iserror);
-    count+= LuaPushArgument(responseJ);
+    count+= LuaPushArgument(source, responseJ);
 
     return count; // return count values
 
@@ -511,38 +528,42 @@ STATIC int LuaAfbServiceSync(lua_State* luaState) {
 
 STATIC int LuaAfbEventPush(lua_State* luaState) {
     LuaAfbEvent *afbevt;
-    int index;
 
+    CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+    if (!source) {
+        lua_pushliteral (luaState, "LuaAfbEventSubscribe-Fail Invalid request handle");
+        goto OnErrorExit;
+    }
+    
     // if no private event handle then use default binding event
-    if (lua_islightuserdata(luaState, LUA_FIST_ARG)) {
-        afbevt = (LuaAfbEvent*) lua_touserdata(luaState, LUA_FIST_ARG);
-        index=LUA_FIST_ARG+1;
-    } else {
-        index=LUA_FIST_ARG;
-        afbevt=luaDefaultEvt;
+    if (!lua_islightuserdata(luaState, LUA_FIST_ARG+1)) {
+        lua_pushliteral (luaState, "LuaAfbMakePush-Fail missing event handle");
+        goto OnErrorExit;
     }
-
-    if (!afb_event_is_valid(afbevt->event)) {
+    
+    afbevt = (LuaAfbEvent*) lua_touserdata(luaState, LUA_FIST_ARG+1);
+    
+    if (!AFB_EventIsValid(afbevt->event)) {
         lua_pushliteral (luaState, "LuaAfbMakePush-Fail invalid event");
         goto OnErrorExit;
     }
 
-    json_object *ctlEventJ= LuaTableToJson(luaState, index);
+    json_object *ctlEventJ= LuaTableToJson(source, luaState, LUA_FIST_ARG+2);
     if (!ctlEventJ) {
         lua_pushliteral (luaState, "LuaAfbEventPush-Syntax is AFB:signal ([evtHandle], {lua table})");
         goto OnErrorExit;
     }
 
-    int done = afb_event_push(afbevt->event, ctlEventJ);
+    int done = AFB_EventPush(afbevt->event, ctlEventJ);
     if (!done) {
         lua_pushliteral (luaState, "LuaAfbEventPush-Fail No Subscriber to event");
-        AFB_ERROR ("LuaAfbEventPush-Fail name subscriber event=%s count=%d", afbevt->name, afbevt->count);
+        AFB_ApiError(source->api, "LuaAfbEventPush-Fail name subscriber event=%s count=%d", afbevt->name, afbevt->count);
         goto OnErrorExit;
     }
     afbevt->count++;
     return 0;
 
-  OnErrorExit:
+OnErrorExit:
         lua_error(luaState);
         return 1;
 }
@@ -550,28 +571,29 @@ STATIC int LuaAfbEventPush(lua_State* luaState) {
 STATIC int LuaAfbEventSubscribe(lua_State* luaState) {
     LuaAfbEvent *afbevt;
 
-    LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG);
-    if (!afbContext) {
+    CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+    if (!source) {
         lua_pushliteral (luaState, "LuaAfbEventSubscribe-Fail Invalid request handle");
         goto OnErrorExit;
     }
 
     // if no private event handle then use default binding event
-    if (lua_islightuserdata(luaState, LUA_FIST_ARG+1)) {
-        afbevt = (LuaAfbEvent*) lua_touserdata(luaState, LUA_FIST_ARG+1);
-    } else {
-        afbevt=luaDefaultEvt;
+    if (!lua_islightuserdata(luaState, LUA_FIST_ARG+1)) {
+        lua_pushliteral (luaState, "LuaAfbMakePush-Fail missing event handle");
+        goto OnErrorExit;
     }
+    
+    afbevt = (LuaAfbEvent*) lua_touserdata(luaState, LUA_FIST_ARG+1);
 
-    if (!afb_event_is_valid(afbevt->event)) {
+    if (!AFB_EventIsValid(afbevt->event)) {
         lua_pushliteral (luaState, "LuaAfbMakePush-Fail invalid event handle");
         goto OnErrorExit;
     }
 
-    int err = afb_req_subscribe(afbContext->request, afbevt->event);
+    int err = AFB_ReqSubscribe(source->request, afbevt->event);
     if (err) {
         lua_pushliteral (luaState, "LuaAfbEventSubscribe-Fail No Subscriber to event");
-        AFB_ERROR ("LuaAfbEventPush-Fail name subscriber event=%s count=%d", afbevt->name, afbevt->count);
+        AFB_ApiError(source->api, "LuaAfbEventPush-Fail name subscriber event=%s count=%d", afbevt->name, afbevt->count);
         goto OnErrorExit;
     }
     afbevt->count++;
@@ -586,17 +608,24 @@ STATIC int LuaAfbEventMake(lua_State* luaState) {
     int count = lua_gettop(luaState);
     LuaAfbEvent *afbevt=calloc(1,sizeof(LuaAfbEvent));
 
-    if (count != LUA_FIST_ARG || !lua_isstring(luaState, LUA_FIST_ARG)) {
+    CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+    if (!source) {
+        lua_pushliteral (luaState, "LuaAfbEventMake-Fail Invalid request handle");
+        goto OnErrorExit;
+    }
+
+    if (count != LUA_FIST_ARG+1 || !lua_isstring(luaState, LUA_FIST_ARG+1)) {
         lua_pushliteral (luaState, "LuaAfbEventMake-Syntax is evtHandle= AFB:event ('myEventName')");
         goto OnErrorExit;
     }
 
     // event name should be the only argument
-    afbevt->name= strdup (lua_tostring(luaState,LUA_FIST_ARG));
+    afbevt->name= strdup (lua_tostring(luaState,LUA_FIST_ARG+1));
 
     // create a new binder event
-    afbevt->event = afb_daemon_make_event(afbevt->name);
-    if (!afb_event_is_valid(afbevt->event)) {
+    afbevt->event = AFB_EventMake(source->api, afbevt->name);
+    if (!AFB_EventIsValid(afbevt->event)) {
+        AFB_ApiError (source->api,"Fail to CreateEvent evtname=%s",  afbevt->name);
         lua_pushliteral (luaState, "LuaAfbEventMake-Fail to Create Binder event");
         goto OnErrorExit;
     }
@@ -610,38 +639,63 @@ STATIC int LuaAfbEventMake(lua_State* luaState) {
         return 1;
 }
 
+STATIC int LuaAfbGetLabel (lua_State* luaState) {
+
+    CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+    if (!source) {
+        lua_pushliteral (luaState, "LuaAfbEventSubscribe-Fail Invalid request handle");
+        goto OnErrorExit;
+    }
+    
+    // extract and return afbSource from timer handle
+    lua_pushstring(luaState, source->label);
+
+    return 1; // return argument
+
+OnErrorExit:
+    return 0;
+}
+
 // Function call from LUA when lua2c plugin L2C is used
-PUBLIC int Lua2cWrapper(lua_State* luaState, char *funcname, Lua2cFunctionT callback) {
+PUBLIC int Lua2cWrapper(void* luaHandle, char *funcname, Lua2cFunctionT callback) {
+    lua_State* luaState = (lua_State*)luaHandle;
+    json_object *responseJ=NULL;
+    
+    CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
 
-    json_object *argsJ= LuaPopArgs(luaState, LUA_FIST_ARG+1);
-    int response = (*callback) (funcname, argsJ);
+    json_object *argsJ= LuaPopArgs(source, luaState, LUA_FIST_ARG+1);
+    int err= (*callback) (source, argsJ, &responseJ);
 
-    // push response to LUA
-    lua_pushinteger(luaState, response);
-    return 1;
+    // push error code and eventual response to LUA
+    int count=1;
+    lua_pushinteger (luaState, err);
+    if (!responseJ) count += LuaPushArgument (source, responseJ);
+    
+    return count;
 }
 
 // Call a Lua function from a control action
-PUBLIC int LuaCallFunc (CtlActionT *action, json_object *queryJ) {
+PUBLIC int LuaCallFunc (CtlSourceT *source, CtlActionT *action, json_object *queryJ) {
 
     int err, count;
 
     json_object* argsJ  = action->argsJ;
-    const char*  func   = action->call;
+    const char*  func   = action->exec.lua.funcname;
 
     // load function (should exist in CONTROL_PATH_LUA
     lua_getglobal(luaState, func);
 
     // push source on the stack
     count=1;
-    lua_pushstring(luaState, action->source.label);
+    // Push AFB client context on the stack
+    LuaAfbSourceT *afbSource= LuaSourcePush(luaState, source);
+    if (!afbSource) goto OnErrorExit;
 
     // push argsJ on the stack
     if (!argsJ) {
-        lua_pushnil(luaState);
-        count++;
+        lua_pushnil(luaState); count++;
     } else {
-        count+= LuaPushArgument (argsJ);
+        count+= LuaPushArgument (source, argsJ);
     }
 
     // push queryJ on the stack
@@ -649,13 +703,13 @@ PUBLIC int LuaCallFunc (CtlActionT *action, json_object *queryJ) {
         lua_pushnil(luaState);
         count++;
     } else {
-        count+= LuaPushArgument (queryJ);
+        count+= LuaPushArgument (source, queryJ);
     }
 
     // effectively exec LUA script code
     err=lua_pcall(luaState, count, 1, 0);
     if (err)  {
-        AFB_ERROR("LuaCallFunc Fail calling %s error=%s", func, lua_tostring(luaState,-1));
+        AFB_ApiError(source->api, "LuaCallFunc Fail calling %s error=%s", func, lua_tostring(luaState,-1));
         goto OnErrorExit;
     }
 
@@ -669,11 +723,14 @@ PUBLIC int LuaCallFunc (CtlActionT *action, json_object *queryJ) {
 
 
 // Execute LUA code from received API request
-STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
+STATIC void LuaDoAction (LuaDoActionT action, AFB_ReqT request) {
 
     int err, count=0;
+    CtlSourceT *source = alloca(sizeof(CtlSourceT));
+    source->request = request;
 
-    json_object* queryJ = afb_req_json(request);
+    json_object* queryJ = AFB_ReqJson(request);
+    
 
     switch (action) {
 
@@ -681,12 +738,12 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
             const char *script = json_object_get_string(queryJ);
             err=luaL_loadstring(luaState, script);
             if (err) {
-                AFB_ERROR ("LUA-DO-COMPILE:FAIL String=%s err=%s", script, lua_tostring(luaState,-1) );
+                AFB_ApiError(source->api, "LUA-DO-COMPILE:FAIL String=%s err=%s", script, lua_tostring(luaState,-1) );
                 goto OnErrorExit;
             }
             // Push AFB client context on the stack
-            LuaAfbContextT *afbContext= LuaCtxPush(luaState, request,NULL,script);
-            if (!afbContext) goto OnErrorExit;
+            LuaAfbSourceT *afbSource= LuaSourcePush(luaState, source);
+            if (!afbSource) goto OnErrorExit;
 
             break;
         }
@@ -697,7 +754,7 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
 
             err= wrap_json_unpack (queryJ, "{s:s, s?o !}", "target", &func, "args", &argsJ);
             if (err) {
-                AFB_ERROR ("LUA-DOCALL-SYNTAX missing target|args query=%s", json_object_get_string(queryJ));
+                AFB_ApiError(source->api, "LUA-DOCALL-SYNTAX missing target|args query=%s", json_object_get_string(queryJ));
                 goto OnErrorExit;
             }
 
@@ -705,15 +762,15 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
             lua_getglobal(luaState, func);
 
             // Push AFB client context on the stack
-            LuaAfbContextT *afbContext= LuaCtxPush(luaState, request, NULL, func);
-            if (!afbContext) goto OnErrorExit;
+            LuaAfbSourceT *afbSource= LuaSourcePush(luaState, source);
+            if (!afbSource) goto OnErrorExit;
 
             // push query on the stack
             if (!argsJ) {
                 lua_pushnil(luaState);
                 count++;
             } else {
-                count+= LuaPushArgument (argsJ);
+                count+= LuaPushArgument (source, argsJ);
             }
 
             break;
@@ -732,7 +789,7 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
             json_object *argsJ=NULL;
             err= wrap_json_unpack (queryJ, "{s:s,s?s,s?s,s?o !}","target", &target,"path",&luaScriptPathJ,"function",&func,"args",&argsJ);
             if (err) {
-                AFB_ERROR ("LUA-DOSCRIPT-SYNTAX:missing target|[path]|[function]|[args] query=%s", json_object_get_string(queryJ));
+                AFB_ApiError(source->api, "LUA-DOSCRIPT-SYNTAX:missing target|[path]|[function]|[args] query=%s", json_object_get_string(queryJ));
                 goto OnErrorExit;
             }
 
@@ -748,11 +805,11 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
 
                 err= wrap_json_unpack (entryJ, "{s:s, s:s !}", "fullpath",  &fullpath,"filename", &filename);
                 if (err) {
-                    AFB_ERROR ("LUA-DOSCRIPT-SCAN:HOOPs invalid config file path = %s", json_object_get_string(entryJ));
+                    AFB_ApiError(source->api, "LUA-DOSCRIPT-SCAN:HOOPs invalid config file path = %s", json_object_get_string(entryJ));
                     goto OnErrorExit;
                 }
 
-                if (index > 0) AFB_WARNING("LUA-DOSCRIPT-SCAN:Ignore second script=%s path=%s", filename, fullpath);
+                if (index > 0) AFB_ApiWarning(source->api, "LUA-DOSCRIPT-SCAN:Ignore second script=%s path=%s", filename, fullpath);
                 else {
                     strncpy (luaScriptPath, fullpath, sizeof(luaScriptPath));
                     strncat (luaScriptPath, "/", sizeof(luaScriptPath));
@@ -762,14 +819,14 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
 
             err= luaL_loadfile(luaState, luaScriptPath);
             if (err) {
-                AFB_ERROR ("LUA-DOSCRIPT HOOPs Error in LUA loading scripts=%s err=%s", luaScriptPath, lua_tostring(luaState,-1));
+                AFB_ApiError(source->api, "LUA-DOSCRIPT HOOPs Error in LUA loading scripts=%s err=%s", luaScriptPath, lua_tostring(luaState,-1));
                 goto OnErrorExit;
             }
 
             // script was loaded we need to parse to make it executable
             err=lua_pcall(luaState, 0, 0, 0);
             if (err) {
-                AFB_ERROR ("LUA-DOSCRIPT:FAIL to load %s", luaScriptPath);
+                AFB_ApiError(source->api, "LUA-DOSCRIPT:FAIL to load %s", luaScriptPath);
                 goto OnErrorExit;
             }
 
@@ -780,7 +837,7 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
                 func=luaScriptPath;
             }
             if (!func) {
-                AFB_ERROR ("LUA-DOSCRIPT:FAIL to deduct funcname from %s", filename);
+                AFB_ApiError(source->api, "LUA-DOSCRIPT:FAIL to deduct funcname from %s", filename);
                 goto OnErrorExit;
             }
 
@@ -788,60 +845,73 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
             lua_getglobal(luaState, func);
 
             // Push AFB client context on the stack
-            LuaAfbContextT *afbContext= LuaCtxPush(luaState, request, NULL, func);
-            if (!afbContext) goto OnErrorExit;
+            LuaAfbSourceT *afbSource= LuaSourcePush(luaState, source);
+            if (!afbSource) goto OnErrorExit;
 
             // push function arguments
             if (!argsJ) {
                 lua_pushnil(luaState);
                 count++;
             } else {
-                count+= LuaPushArgument(argsJ);
+                count+= LuaPushArgument(source, argsJ);
             }
 
             break;
         }
 
         default:
-            AFB_ERROR ("LUA-DOSCRIPT-ACTION unknown query=%s", json_object_get_string(queryJ));
+            AFB_ApiError(source->api, "LUA-DOSCRIPT-ACTION unknown query=%s", json_object_get_string(queryJ));
             goto OnErrorExit;
     }
 
     // effectively exec LUA code (afb_reply/fail done later from callback)
     err=lua_pcall(luaState, count+1, 0, 0);
     if (err) {
-        AFB_ERROR ("LUA-DO-EXEC:FAIL query=%s err=%s", json_object_get_string(queryJ), lua_tostring(luaState,-1));
+        AFB_ApiError(source->api, "LUA-DO-EXEC:FAIL query=%s err=%s", json_object_get_string(queryJ), lua_tostring(luaState,-1));
         goto OnErrorExit;
     }
     return;
 
  OnErrorExit:
-    afb_req_fail(request,"LUA:ERROR", lua_tostring(luaState,-1));
+    AFB_ReqFail(request,"LUA:ERROR", lua_tostring(luaState,-1));
     return;
 }
 
-PUBLIC void ctlapi_execlua (afb_req request) {
+PUBLIC void ctlapi_execlua (AFB_ReqT request) {
     LuaDoAction (LUA_DOSTRING, request);
 }
 
-PUBLIC void ctlapi_request (afb_req request) {
+PUBLIC void ctlapi_request (AFB_ReqT request) {
     LuaDoAction (LUA_DOCALL, request);
 }
 
-PUBLIC void ctlapi_debuglua (afb_req request) {
+PUBLIC void ctlapi_debuglua (AFB_ReqT request) {
     LuaDoAction (LUA_DOSCRIPT, request);
 }
 
-STATIC int LuaTimerClear (lua_State* luaState) {
 
-    // Get Timer Handle
-    LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG);
-    if (!afbContext) goto OnErrorExit;
+STATIC TimerHandleT *LuaTimerPop (lua_State *luaState, int index) {
+  TimerHandleT *timerHandle;
+  
+  luaL_checktype(luaState, index, LUA_TLIGHTUSERDATA);
+  timerHandle = (TimerHandleT *) lua_touserdata(luaState, index);
+  
+  if (timerHandle == NULL && timerHandle->magic != TIMER_MAGIC) {
+      luaL_error(luaState, "Invalid source handle");
+      fprintf(stderr, "LuaSourcePop error retrieving afbSource");
+      return NULL;
+  }
+  return timerHandle;
+}
+
+STATIC int LuaTimerClear (lua_State* luaState) {
 
     // retrieve useful information opaque handle
-    TimerHandleT *timerHandle = (TimerHandleT*)afbContext->handle;
+    TimerHandleT *timerHandle = LuaTimerPop(luaState, LUA_FIST_ARG);
+    if (!timerHandle) goto OnErrorExit;
+    LuaCbHandleT *luaCbHandle = (LuaCbHandleT*) timerHandle->context;
 
-    AFB_NOTICE ("LuaTimerClear timer=%s", timerHandle->label);
+    AFB_ApiNotice (luaCbHandle->source->api,"LuaTimerClear timer=%s", timerHandle->label);
     TimerEvtStop(timerHandle);
 
     return 0; //happy end
@@ -851,13 +921,11 @@ OnErrorExit:
 }
 STATIC int LuaTimerGet (lua_State* luaState) {
 
-    // Get Timer Handle
-    LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG);
-    if (!afbContext) goto OnErrorExit;
-
     // retrieve useful information opaque handle
-    TimerHandleT *timerHandle = (TimerHandleT*)afbContext->handle;
-
+    TimerHandleT *timerHandle = LuaTimerPop(luaState, LUA_FIST_ARG);
+    if (!timerHandle) goto OnErrorExit;
+    LuaCbHandleT *luaCbHandle = (LuaCbHandleT*) timerHandle->context;
+        
     // create response as a JSON object
     json_object *responseJ= json_object_new_object();
     json_object_object_add(responseJ,"label", json_object_new_string(timerHandle->label));
@@ -865,7 +933,7 @@ STATIC int LuaTimerGet (lua_State* luaState) {
     json_object_object_add(responseJ,"count", json_object_new_int(timerHandle->count));
 
     // return JSON object as Lua table
-    int count=LuaPushArgument(responseJ);
+    int count=LuaPushArgument(luaCbHandle->source, responseJ);
 
     // free json object
     json_object_put(responseJ);
@@ -880,24 +948,24 @@ OnErrorExit:
 
 // Set timer
 STATIC int LuaTimerSetCB (void *handle) {
-    LuaCallServiceT *contextCB =(LuaCallServiceT*) handle;
-    TimerHandleT *timerHandle = (TimerHandleT*) contextCB->handle;
+    LuaCbHandleT *LuaCbHandle = (LuaCbHandleT*) handle;
     int count;
 
     // push timer handle and user context on Lua stack
-    lua_getglobal(luaState, contextCB->callback);
+    lua_getglobal(luaState, LuaCbHandle->callback);
 
-    // Push timer handle
-    LuaAfbContextT *afbContext= LuaCtxPush(luaState, NULL_AFBREQ, contextCB->handle, timerHandle->label);
-    if (!afbContext) goto OnErrorExit;
     count=1;
+    // Push AFB client context on the stack
+    LuaAfbSourceT *afbSource= LuaSourcePush(luaState, LuaCbHandle->source);
+    if (!afbSource) goto OnErrorExit;
 
     // Push user Context
-    count+= LuaPushArgument(contextCB->context);
+    count+= LuaPushArgument(LuaCbHandle->source, LuaCbHandle->context);
 
     int err=lua_pcall(luaState, count, LUA_MULTRET, 0);
     if (err) {
-        AFB_ERROR ("LUA-TIMER-CB:FAIL response=%s err=%s", json_object_get_string(contextCB->context), lua_tostring(luaState,-1));
+        printf ("LUA-TIMER-CB:FAIL response=%s err=%s\n", json_object_get_string(LuaCbHandle->context), lua_tostring(luaState,-1));
+        AFB_ApiError (LuaCbHandle->source->api,"LUA-TIMER-CB:FAIL response=%s err=%s", json_object_get_string(LuaCbHandle->context), lua_tostring(luaState,-1));
         goto OnErrorExit;
     }
 
@@ -906,26 +974,36 @@ STATIC int LuaTimerSetCB (void *handle) {
         return (lua_toboolean(luaState, -1));
     }
 
-    // timer last run free context resource
-    if (timerHandle->count == 1) {
-        LuaCtxFree(afbContext);
-    }
     return 0;  // By default we are happy
 
  OnErrorExit:
     return 1;  // stop timer
 }
 
+// Free Timer context handle
+STATIC int LuaTimerCtxFree(void *handle) {
+    LuaCbHandleT *LuaCbHandle = (LuaCbHandleT*) handle;
+    
+    free (LuaCbHandle->source);
+    free (LuaCbHandle);
+    
+    return 0;
+}
+
 STATIC int LuaTimerSet(lua_State* luaState) {
     const char *label=NULL, *info=NULL;
     int delay=0, count=0;
+    
+    // Get source handle
+    CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+    if (!source) goto OnErrorExit;
 
-    json_object *timerJ = LuaPopOneArg(luaState, LUA_FIST_ARG);
-    const char *callback = lua_tostring(luaState, LUA_FIST_ARG + 1);
-    json_object *contextJ = LuaPopOneArg(luaState, LUA_FIST_ARG + 2);
+    json_object *timerJ = LuaPopOneArg(source, luaState, LUA_FIST_ARG+1);
+    const char *callback = lua_tostring(luaState, LUA_FIST_ARG + 2);
+    json_object *contextJ = LuaPopOneArg(source, luaState, LUA_FIST_ARG + 3);
 
-    if (lua_gettop(luaState) != LUA_FIST_ARG+2 || !timerJ || !callback || !contextJ) {
-        lua_pushliteral(luaState, "LuaTimerSet-Syntax timerset (timerT, 'callback', contextT)");
+    if (lua_gettop(luaState) != LUA_FIST_ARG+3 || !timerJ || !callback || !contextJ) {
+        lua_pushliteral(luaState, "LuaTimerSet-Syntax timerset (source, timerT, 'callback', contextT)");
         goto OnErrorExit;
     }
 
@@ -935,22 +1013,30 @@ STATIC int LuaTimerSet(lua_State* luaState) {
         goto OnErrorExit;
     }
 
+    // Allocate handle to store context and callback
+    LuaCbHandleT *handleCb = calloc (1, sizeof(LuaCbHandleT));
+    handleCb->callback= callback;
+    handleCb->context = contextJ;
+    handleCb->source  = malloc(sizeof(CtlSourceT));
+    memcpy (handleCb->source, source, sizeof(CtlSourceT));  // Fulup need to be free when timer is done
+        
     // everything look fine create timer structure
     TimerHandleT *timerHandle = malloc (sizeof (TimerHandleT));
+    timerHandle->magic= TIMER_MAGIC;
     timerHandle->delay=delay;
     timerHandle->count=count;
     timerHandle->label=label;
-
-    // Allocate handle to store context and callback
-    LuaCallServiceT *contextCB = calloc (1, sizeof(LuaCallServiceT));
-    contextCB->callback= callback;
-    contextCB->context = contextJ;
-    contextCB->handle  = timerHandle;
+    timerHandle->freeCB=LuaTimerCtxFree;
 
     // fire timer
-    TimerEvtStart (timerHandle, LuaTimerSetCB, contextCB);
+    TimerEvtStart (source->api, timerHandle, LuaTimerSetCB, handleCb);
+    
+    // Fulup finir les timers avec handle
 
-    return 0;  // Happy No Return Function
+    // return empty error code plus timer handle
+    lua_pushnil(luaState);
+    lua_pushlightuserdata(luaState, timerHandle);
+    return 2;  
 
 OnErrorExit:
     lua_error(luaState);
@@ -982,18 +1068,23 @@ static const luaL_Reg afbFunction[] = {
     {"subscribe" , LuaAfbEventSubscribe},
     {"evtmake"   , LuaAfbEventMake},
     {"evtpush"   , LuaAfbEventPush},
+    {"getlabel"  , LuaAfbGetLabel},
 
     {NULL, NULL}  /* sentinel */
 };
 
 // Load Lua Interpreter
-PUBLIC int LuaConfigLoad () {
-    
+PUBLIC int LuaConfigLoad (AFB_ApiT apiHandle) {
+    static int luaLoaded=0;
 
+    // Lua loads only once
+    if (luaLoaded) return 0;
+    luaLoaded=1;
+    
     // open a new LUA interpretor
     luaState = luaL_newstate();
     if (!luaState)  {
-        AFB_ERROR ("LUA_INIT: Fail to open lua interpretor");
+        AFB_ApiError(apiHandle, "LUA_INIT: Fail to open lua interpretor");
         goto OnErrorExit;
     }
 
@@ -1004,6 +1095,15 @@ PUBLIC int LuaConfigLoad () {
     luaL_newlib(luaState, afbFunction);
     lua_setglobal(luaState, "AFB");
     
+    // initialise static magic for context
+    #ifndef CTX_MAGIC
+        CTX_MAGIC=CtlConfigMagicNew();
+    #endif
+
+    #ifndef TIMER_MAGIC
+        TIMER_MAGIC=CtlConfigMagicNew();
+    #endif
+    
     return 0;
     
  OnErrorExit:
@@ -1011,17 +1111,9 @@ PUBLIC int LuaConfigLoad () {
 }
 
 // Create Binding Event at Init Exec Time
-PUBLIC int LuaConfigExec () {
+PUBLIC int LuaConfigExec (AFB_ApiT apiHandle) {
     
     int err, index;
-    // create default lua event to send test pause/resume
-    luaDefaultEvt=calloc(1,sizeof(LuaAfbEvent));
-    luaDefaultEvt->name=CONTROL_LUA_EVENT;
-    luaDefaultEvt->event = afb_daemon_make_event(CONTROL_LUA_EVENT);
-    if (!afb_event_is_valid(luaDefaultEvt->event)) {
-        AFB_ERROR ("POLCTL_INIT: Cannot register lua-events=%s ", CONTROL_LUA_EVENT);
-        goto OnErrorExit;;
-    }
 
     // search for default policy config file
     char fullprefix[CONTROL_MAXPATH_LEN];
@@ -1046,7 +1138,7 @@ PUBLIC int LuaConfigExec () {
         char *filename; char*fullpath;
         err= wrap_json_unpack (entryJ, "{s:s, s:s !}", "fullpath",  &fullpath,"filename", &filename);
         if (err) {
-            AFB_ERROR ("LUA-INIT HOOPs invalid config file path = %s", json_object_get_string(entryJ));
+            AFB_ApiError(apiHandle, "LUA-INIT HOOPs invalid config file path = %s", json_object_get_string(entryJ));
             goto OnErrorExit;
         }
 
@@ -1056,24 +1148,26 @@ PUBLIC int LuaConfigExec () {
         strncat(filepath, filename, sizeof(filepath));
         err= luaL_loadfile(luaState, filepath);
         if (err) {
-            AFB_ERROR ("LUA-LOAD HOOPs Error in LUA loading scripts=%s err=%s", filepath, lua_tostring(luaState,-1));
+            AFB_ApiError(apiHandle, "LUA-LOAD HOOPs Error in LUA loading scripts=%s err=%s", filepath, lua_tostring(luaState,-1));
             goto OnErrorExit;
         }
 
         // exec/compil script
         err = lua_pcall(luaState, 0, 0, 0);
         if (err) {
-            AFB_ERROR ("LUA-LOAD HOOPs Error in LUA exec scripts=%s err=%s", filepath, lua_tostring(luaState,-1));
+            AFB_ApiError(apiHandle, "LUA-LOAD HOOPs Error in LUA exec scripts=%s err=%s", filepath, lua_tostring(luaState,-1));
             goto OnErrorExit;
+        } else {
+            AFB_ApiNotice(apiHandle, "LUA-LOAD '%s'", filepath);            
         }
     }
 
     // no policy config found remove control API from binder
     if (index == 0)  {
-        AFB_WARNING ("POLICY-INIT:WARNING (setenv CONTROL_LUA_PATH) No LUA '%s*.lua' in '%s'", fullprefix, dirList);
+        AFB_ApiWarning (apiHandle, "POLICY-INIT:WARNING (setenv CONTROL_LUA_PATH) No LUA '%s*.lua' in '%s'", fullprefix, dirList);
     }
 
-    AFB_DEBUG ("Audio control-LUA Init Done");
+    AFB_ApiDebug (apiHandle, "Audio control-LUA Init Done");
     return 0;
 
  OnErrorExit:
diff --git a/ctl-lib/ctl-lua.h b/ctl-lib/ctl-lua.h
index 6f2ce7d..53eb6cb 100644
--- a/ctl-lib/ctl-lua.h
+++ b/ctl-lib/ctl-lua.h
@@ -49,13 +49,6 @@
 
 PUBLIC int LuaLibInit ();
 
-typedef int (*Lua2cFunctionT)(char *funcname, json_object *argsJ);
-typedef int (*Lua2cWrapperT) (lua_State* luaState, char *funcname, Lua2cFunctionT callback);
-
-#define CTLP_LUALOAD Lua2cWrapperT Lua2cWrap;
-#define CTLP_LUA2C(FuncName, label,argsJ, context) static int FuncName(char*label,json_object*argsJ);\
-        int lua2c_ ## FuncName(lua_State* luaState){return((*Lua2cWrap)(luaState, MACRO_STR_VALUE(FuncName), FuncName, PLUGIN_NAME));};\
-        static int FuncName(char* label, json_object* argsJ, void* context)
 
 typedef enum {
     LUA_DOCALL,
@@ -64,11 +57,11 @@ typedef enum {
 } LuaDoActionT;
 
 
-PUBLIC int LuaConfigLoad();
-PUBLIC int LuaConfigExec();
+PUBLIC int LuaConfigLoad (AFB_ApiT apiHandle);
+PUBLIC int LuaConfigExec(AFB_ApiT apiHandle);
 PUBLIC void LuaL2cNewLib(const char *label, luaL_Reg *l2cFunc, int count);
-PUBLIC int Lua2cWrapper(lua_State* luaState, char *funcname, Lua2cFunctionT callback);
-PUBLIC int LuaCallFunc (CtlActionT *action, json_object *queryJ) ;
+PUBLIC int Lua2cWrapper(void* luaHandle, char *funcname, Lua2cFunctionT callback);
+PUBLIC int LuaCallFunc (CtlSourceT *source, CtlActionT *action, json_object *queryJ) ;
 PUBLIC void ctlapi_lua_docall (afb_req request);
 PUBLIC void ctlapi_lua_dostring (afb_req request);
 PUBLIC void ctlapi_lua_doscript (afb_req request);
diff --git a/ctl-lib/ctl-onload.c b/ctl-lib/ctl-onload.c
index 97bd109..1dec75a 100644
--- a/ctl-lib/ctl-onload.c
+++ b/ctl-lib/ctl-onload.c
@@ -23,29 +23,31 @@
 #include "ctl-config.h"
 
 // onload section receive one action or an array of actions
-PUBLIC int OnloadConfig(CtlSectionT *section, json_object *actionsJ) {
-    CtlActionT *actions;
-     
-    // Load time parse actions in config file
+PUBLIC int OnloadConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *actionsJ) {
+    
+    // Load time parse actions in control file
     if (actionsJ != NULL) {
-        actions= ActionLoad(actionsJ);
-        section->handle=actions;
+        section->actions= ActionConfig(apiHandle, actionsJ, 0);
         
-        if (!actions) {
-            AFB_ERROR ("OnloadLoad config fail processing onload actions");
+        if (!section->actions) {
+            AFB_ApiError (apiHandle, "OnloadConfig control fail processing onload actions");
             goto OnErrorExit;
         }
         
     } else {
         // Exec time process onload action now
-        actions=(CtlActionT*)section->handle;
-        if (!actions) {
-            AFB_ERROR ("OnloadLoad Cannot Exec Non Existing Onload Action");
+        if (!section->actions) {
+            AFB_ApiError (apiHandle, "OnloadConfig Cannot Exec Non Existing Onload Action");
             goto OnErrorExit;
         }
 
-        for (int idx=0; actions[idx].source.label != NULL; idx ++) {
-            ActionExecOne(&actions[idx], NULL);
+        for (int idx=0; section->actions[idx].label != NULL; idx ++) {
+            CtlSourceT source;
+            source.label = section->actions[idx].label;
+            source.api  = section->actions[idx].api;
+            source.request = AFB_ReqNone;
+            
+            ActionExecOne(&source, &section->actions[idx], NULL);
         }              
     }
 
diff --git a/ctl-lib/ctl-plugin.c b/ctl-lib/ctl-plugin.c
index f589035..03f4c34 100644
--- a/ctl-lib/ctl-plugin.c
+++ b/ctl-lib/ctl-plugin.c
@@ -26,20 +26,19 @@
 
 static  CtlPluginT *ctlPlugins=NULL;
 
-PUBLIC int PluginGetCB (CtlActionT *action , json_object *callbackJ) {
+PUBLIC int PluginGetCB (AFB_ApiT apiHandle, CtlActionT *action , json_object *callbackJ) {
     const char *plugin=NULL, *function=NULL;
     json_object *argsJ;
     int idx;
 
     if (!ctlPlugins) {
-        AFB_ERROR ("PluginGetCB plugin section missing cannot call '%s'", json_object_get_string(callbackJ));
+        AFB_ApiError(apiHandle, "PluginGetCB plugin section missing cannot call '%s'", json_object_get_string(callbackJ));
         goto OnErrorExit;        
     }
-    
-    
+      
     int err = wrap_json_unpack(callbackJ, "{ss,ss,s?s,s?o!}", "plugin", &plugin, "function", &function, "args", &argsJ); 
     if (err) {
-        AFB_ERROR("PluginGet missing plugin|function|[args] in %s", json_object_get_string(callbackJ));
+        AFB_ApiError(apiHandle, "PluginGet missing plugin|function|[args] in %s", json_object_get_string(callbackJ));
         goto OnErrorExit;
     }
     
@@ -48,15 +47,16 @@ PUBLIC int PluginGetCB (CtlActionT *action , json_object *callbackJ) {
     }
     
     if (!ctlPlugins[idx].label) {
-        AFB_ERROR ("PluginGetCB no plugin with label=%s", plugin);
+        AFB_ApiError(apiHandle, "PluginGetCB no plugin with label=%s", plugin);
         goto OnErrorExit;
     }
     
-    action->actionCB = dlsym(ctlPlugins[idx].dlHandle, function); 
-    action->source.context  = ctlPlugins[idx].context;
+    action->exec.cb.funcname = function; 
+    action->exec.cb.callback = dlsym(ctlPlugins[idx].dlHandle, function); 
+    action->exec.cb.plugin= &ctlPlugins[idx];
     
-    if (!action->actionCB) {
-       AFB_ERROR ("PluginGetCB no plugin=%s no function=%s", plugin, function); 
+    if (!action->exec.cb.callback) {
+       AFB_ApiError(apiHandle, "PluginGetCB no plugin=%s no function=%s", plugin, function); 
        goto OnErrorExit;
     }
     return 0; 
@@ -67,9 +67,9 @@ OnErrorExit:
 }
 
 // Wrapper to Lua2c plugin command add context and delegate to LuaWrapper
-STATIC int DispatchOneL2c(lua_State* luaState, char *funcname, Lua2cFunctionT callback) {
+STATIC int DispatchOneL2c(void* luaState, char *funcname, Lua2cFunctionT callback) {
 #ifndef CONTROL_SUPPORT_LUA
-    AFB_ERROR("CTL-ONE-L2C: LUA support not selected (cf:CONTROL_SUPPORT_LUA) in config.cmake");
+    fprintf(stderr, "CTL-ONE-L2C: LUA support not selected (cf:CONTROL_SUPPORT_LUA) in config.cmake");
     return 1;
 #else
     int err=Lua2cWrapper(luaState, funcname, callback);
@@ -77,8 +77,8 @@ STATIC int DispatchOneL2c(lua_State* luaState, char *funcname, Lua2cFunctionT ca
 #endif
 }
 
-STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* handle) {
-    json_object *lua2csJ = NULL, *actionsJ = NULL;
+STATIC int PluginLoadOne (AFB_ApiT apiHandle, CtlPluginT *ctlPlugin, json_object *pluginJ, void* handle) {
+    json_object *lua2csJ = NULL;
     const char*ldSearchPath = NULL, *basename = NULL;
     void *dlHandle;
 
@@ -86,12 +86,15 @@ STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* han
     // plugin initialises at 1st load further init actions should be place into onload section
     if (!pluginJ) return 0;
     
-    int err = wrap_json_unpack(pluginJ, "{ss,s?s,s?s,s?s,ss,s?o,s?o!}",
-            "label", &ctlPlugin->label,  "version", &ctlPlugin->version, "info", &ctlPlugin->info, "ldpath", &ldSearchPath, "basename", &basename, "lua2c", &lua2csJ, "actions", &actionsJ);
+    int err = wrap_json_unpack(pluginJ, "{ss,s?s,s?s,s?s !}",
+            "label", &ctlPlugin->label,  "info", &ctlPlugin->info, "ldpath", &ldSearchPath, "basename", &basename);
     if (err) {
-        AFB_ERROR("CTL-PLUGIN-LOADONE Plugin missing label|basename|version|[info]|[ldpath]|[lua2c]|[actions] in:\n-- %s", json_object_get_string(pluginJ));
+        AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE Plugin missing label|[info]|[basename]|[ldpath] in:\n-- %s", json_object_get_string(pluginJ));
         goto OnErrorExit;
     }
+    
+    // default basename equal label
+    if (!basename) basename=ctlPlugin->label;
 
     // if search path not in Json config file, then try default
     if (!ldSearchPath) ldSearchPath = CONTROL_PLUGIN_PATH;
@@ -99,7 +102,7 @@ STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* han
     // search for default policy config file
     json_object *pluginPathJ = ScanForConfig(ldSearchPath, CTL_SCAN_RECURSIVE, basename, CTL_PLUGIN_EXT);
     if (!pluginPathJ || json_object_array_length(pluginPathJ) == 0) {
-        AFB_ERROR("CTL-PLUGIN-LOADONE Missing plugin=%s*%s (config ldpath?) search=\n-- %s", basename, CTL_PLUGIN_EXT, ldSearchPath);
+        AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE Missing plugin=%s*%s (config ldpath?) search=\n-- %s", basename, CTL_PLUGIN_EXT, ldSearchPath);
         goto OnErrorExit;
     }
 
@@ -107,12 +110,12 @@ STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* han
     char*fullpath;
     err = wrap_json_unpack(json_object_array_get_idx(pluginPathJ, 0), "{s:s, s:s !}", "fullpath", &fullpath, "filename", &filename);
     if (err) {
-        AFB_ERROR("CTL-PLUGIN-LOADONE HOOPs invalid plugin file path=\n-- %s", json_object_get_string(pluginPathJ));
+        AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE HOOPs invalid plugin file path=\n-- %s", json_object_get_string(pluginPathJ));
         goto OnErrorExit;
     }
 
     if (json_object_array_length(pluginPathJ) > 1) {
-        AFB_WARNING("CTL-PLUGIN-LOADONE plugin multiple instances in searchpath will use %s/%s", fullpath, filename);
+        AFB_ApiWarning(apiHandle, "CTL-PLUGIN-LOADONE plugin multiple instances in searchpath will use %s/%s", fullpath, filename);
     }
 
     char pluginpath[CONTROL_MAXPATH_LEN];
@@ -121,24 +124,26 @@ STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* han
     strncat(pluginpath, filename, sizeof (pluginpath));
     dlHandle = dlopen(pluginpath, RTLD_NOW);
     if (!dlHandle) {
-        AFB_ERROR("CTL-PLUGIN-LOADONE Fail to load pluginpath=%s err= %s", pluginpath, dlerror());
+        AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE Fail to load pluginpath=%s err= %s", pluginpath, dlerror());
         goto OnErrorExit;
     }
 
     CtlPluginMagicT *ctlPluginMagic = (CtlPluginMagicT*) dlsym(dlHandle, "CtlPluginMagic");
     if (!ctlPluginMagic || ctlPluginMagic->magic != CTL_PLUGIN_MAGIC) {
-        AFB_ERROR("CTL-PLUGIN-LOADONE symbol'CtlPluginMagic' missing or !=  CTL_PLUGIN_MAGIC plugin=%s", pluginpath);
+        AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE symbol'CtlPluginMagic' missing or !=  CTL_PLUGIN_MAGIC plugin=%s", pluginpath);
         goto OnErrorExit;
     } else {
-        AFB_NOTICE("CTL-PLUGIN-LOADONE %s successfully registered", ctlPluginMagic->label);
+        AFB_ApiNotice(apiHandle, "CTL-PLUGIN-LOADONE %s successfully registered", ctlPluginMagic->label);
     }
     
     // store dlopen handle to enable onload action at exec time
     ctlPlugin->dlHandle = dlHandle;
     
-    // Jose hack to make verbosity visible from sharelib
+#ifndef AFB_BINDING_PREV3
+    // Jose hack to make verbosity visible from sharelib with API-V2
     struct afb_binding_data_v2 *afbHidenData = dlsym(dlHandle, "afbBindingV2data");
     if (afbHidenData) *afbHidenData = afbBindingV2data;
+#endif
 
     // Push lua2cWrapper @ into plugin
     Lua2cWrapperT *lua2cInPlug = dlsym(dlHandle, "Lua2cWrap");
@@ -156,7 +161,7 @@ STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* han
 
             Lua2cFunctionT l2cFunction = (Lua2cFunctionT) dlsym(dlHandle, funcName);
             if (!l2cFunction) {
-                AFB_ERROR("CTL-PLUGIN-LOADONE symbol'%s' missing err=%s", funcName, dlerror());
+                AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE symbol'%s' missing err=%s", funcName, dlerror());
                 return 1;
             }
             l2cFunc[index].func = (void*) l2cFunction;
@@ -184,13 +189,14 @@ STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* han
             errCount = Lua2cAddOne(l2cFunc, l2cName, 0);
         }
         if (errCount) {
-            AFB_ERROR("CTL-PLUGIN-LOADONE %d symbols not found in plugin='%s'", errCount, pluginpath);
+            AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE %d symbols not found in plugin='%s'", errCount, pluginpath);
             goto OnErrorExit;
         }
     }
 #endif
     DispatchPluginInstallCbT ctlPluginOnload = dlsym(dlHandle, "CtlPluginOnload");
     if (ctlPluginOnload) {
+        ctlPlugin->api = apiHandle;
         ctlPlugin->context = (*ctlPluginOnload) (ctlPlugin, handle);
     }
     return 0;
@@ -200,7 +206,7 @@ OnErrorExit:
 }
 
 
-PUBLIC int PluginConfig(CtlSectionT *section, json_object *pluginsJ) {
+PUBLIC int PluginConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *pluginsJ) {
     int err=0;
     
     if (json_object_get_type(pluginsJ) == json_type_array) {
@@ -208,11 +214,11 @@ PUBLIC int PluginConfig(CtlSectionT *section, json_object *pluginsJ) {
         ctlPlugins = calloc (length+1, sizeof(CtlPluginT));
         for (int idx=0; idx < length; idx++) {
             json_object *pluginJ = json_object_array_get_idx(pluginsJ, idx);
-            err += PluginLoadOne(&ctlPlugins[idx], pluginJ, section->handle);
+            err += PluginLoadOne(apiHandle, &ctlPlugins[idx], pluginJ, section->handle);
         }
     } else {
         ctlPlugins = calloc (2, sizeof(CtlPluginT));
-        err += PluginLoadOne(&ctlPlugins[0], pluginsJ, section->handle);       
+        err += PluginLoadOne(apiHandle, &ctlPlugins[0], pluginsJ, section->handle);       
     }
     
     return err;
diff --git a/ctl-lib/ctl-plugin.h b/ctl-lib/ctl-plugin.h
index e0ab3dd..a678af4 100644
--- a/ctl-lib/ctl-plugin.h
+++ b/ctl-lib/ctl-plugin.h
@@ -20,9 +20,112 @@
 #ifndef _CTL_PLUGIN_INCLUDE_
 #define _CTL_PLUGIN_INCLUDE_
 
+
 #define _GNU_SOURCE
 #include <json-c/json.h>
 
+// Waiting for a clean AppFW-V3 API
+#ifdef USE_API_DYN
+    #define AFB_BINDING_VERSION dyn
+    #include <afb/afb-binding.h>
+
+    #define AFB_BINDING_PREV3
+    #define AFB_ReqNone NULL
+    typedef afb_request* AFB_ReqT;
+    typedef afb_dynapi*  AFB_ApiT;
+
+    typedef afb_eventid* AFB_EventT;
+    #define AFB_EventIsValid(eventid) eventid
+    #define AFB_EventPush afb_eventid_push
+    #define AFB_ReqSubscribe  afb_request_subscribe
+    #define AFB_EventMake(api, name) afb_dynapi_make_eventid(api, name)
+
+    #define AFB_ReqJson(request) afb_request_json(request)
+
+    #define AFB_ReqSucess  afb_request_success
+    #define AFB_ReqSucessF afb_request_success_f
+    #define AFB_ReqFail    afb_request_fail
+    #define AFB_ReqFailF   afb_request_fail_f
+
+    #define AFB_ReqNotice(request, ...)   AFB_REQUEST_NOTICE (request, __VA_ARGS__)
+    #define AFB_ReqWarning(request, ...)  AFB_REQUEST_WARNING (request, __VA_ARGS__)
+    #define AFB_ReqDebug(request, ...)    AFB_REQUEST_DEBUG (request, __VA_ARGS__)
+    #define AFB_ReqError(request, ...)    AFB_REQUEST_ERROR (request, __VA_ARGS__)
+    #define AFB_ReqInfo(request, ...)     AFB_REQUEST_INFO (request, __VA_ARGS__)
+    
+    #define AFB_ApiVerbose(api, level, ...) afb_dynapi_verbose(api, level, __VA_ARGS__)
+    #define AFB_ApiNotice(api, ...)   AFB_DYNAPI_NOTICE (api, __VA_ARGS__)
+    #define AFB_ApiWarning(api, ...)  AFB_DYNAPI_WARNING (api, __VA_ARGS__)
+    #define AFB_ApiDebug(api, ...)    AFB_DYNAPI_DEBUG (api, __VA_ARGS__)
+    #define AFB_ApiError(api, ...)    AFB_DYNAPI_ERROR (api, __VA_ARGS__)
+    #define AFB_ApiInfo(api, ...)     AFB_DYNAPI_INFO (api, __VA_ARGS__)
+
+    #define AFB_ReqIsValid(request)   request
+    #define AFB_EvtIsValid(evtHandle) evtHandle
+
+    #define AFB_ServiceCall(api, ...) afb_dynapi_call(api, __VA_ARGS__) 
+    #define AFB_ServiceSync(api, ...) afb_dynapi_call_sync(api, __VA_ARGS__) 
+
+    #define AFB_RequireApi(api, ...) afb_dynapi_require_api(api, __VA_ARGS__) 
+
+    #define AFB_GetEventLoop(api) afb_dynapi_get_event_loop(api) 
+
+
+    typedef struct { 
+            const char *verb;                       /* name of the verb, NULL only at end of the array */
+            void (*callback)(AFB_ReqT req);   /* callback function implementing the verb */
+            const struct afb_auth *auth;		/* required authorisation, can be NULL */
+            const char *info;			/* some info about the verb, can be NULL */
+            uint32_t session;    
+    } AFB_ApiVerbs;
+
+#else
+    #define AFB_BINDING_VERSION 2
+    #include <afb/afb-binding.h>
+
+    typedef afb_req AFB_ReqT;
+    typedef void* AFB_ApiT;
+    #define AFB_ReqNone (struct afb_req){0,0}
+    
+    typedef afb_event AFB_EventT;    
+    #define AFB_EventPush afb_event_push
+    #define AFB_ReqSubscribe  afb_req_subscribe
+    #define AFB_EventIsValid(event) afb_event_is_valid(event)
+    #define AFB_EventMake(api, name) afb_daemon_make_event(name)
+
+    #define AFB_ReqJson(request) afb_req_json(request)
+    #define AFB_ReqSucess  afb_req_success
+    #define AFB_ReqSucessF afb_req_success_f
+    #define AFB_ReqFail    afb_req_fail
+    #define AFB_ReqFailF   afb_req_fail_f
+
+    #define AFB_ReqNotice(request, ...)   AFB_NOTICE (__VA_ARGS__)
+    #define AFB_ReqWarning(request, ...)  AFB_WARNING (__VA_ARGS__)
+    #define AFB_ReqDebug(request, ...)    AFB_DEBUG (__VA_ARGS__)
+    #define AFB_ReqError(request, ...)    AFB_ERROR (__VA_ARGS__)
+    #define AFB_ReqInfo(request, ...)     AFB_INFO (__VA_ARGS__)
+
+    #define AFB_ApiVerbose(api, level, ...) afb_daemon_verbose_v2(level,__VA_ARGS__)
+    #define AFB_ApiNotice(api, ...)   AFB_NOTICE (__VA_ARGS__)
+    #define AFB_ApiWarning(api, ...)  AFB_WARNING (__VA_ARGS__)
+    #define AFB_ApiDebug(api, ...)    AFB_DEBUG (__VA_ARGS__)
+    #define AFB_ApiError(api, ...)    AFB_ERROR (__VA_ARGS__)
+    #define AFB_ApiInfo(api, ...)     AFB_INFO (__VA_ARGS__)
+
+    #define AFB_ReqIsValid(request)   afb_req_is_valid(request)
+    #define AFB_EvtIsValid(evtHandle) afb_event_is_valid(evtHandle)
+
+    #define AFB_ServiceCall(api, ...) afb_service_call(__VA_ARGS__) 
+    #define AFB_ServiceSync(api, ...) afb_service_call_sync(__VA_ARGS__) 
+
+    #define AFB_RequireApi (api, ...) afb_daemon_require_api(__VA_ARGS__) 
+
+    #define AFB_GetEventLoop(api) afb_daemon_get_event_loop() 
+
+    #define AFB_ApiVerbs afb_verb_v2
+#endif
+
+
 #ifndef CTL_PLUGIN_MAGIC
   #define CTL_PLUGIN_MAGIC 852369147
 #endif
@@ -40,35 +143,76 @@
   #define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x
 #endif
 
-typedef struct {
-    char *label;
-    char *info;
-    afb_req request;
-    void *context;
-} CtlSourceT;
-
 
+    
 typedef struct {
-  long  magic;
-  char *label;
-  void *handle;
+  const char *label;
+  const long magic;
 } CtlPluginMagicT;
 
+typedef struct {
+    const char *label; 
+    const char *info; 
+    AFB_ApiT api;
+    void *dlHandle;
+    void *context;
+} CtlPluginT;
+
+
+typedef enum {
+    CTL_TYPE_NONE=0,
+    CTL_TYPE_API,
+    CTL_TYPE_CB,
+    CTL_TYPE_LUA,
+} CtlActionTypeT;
 
 typedef struct {
     const char *label;
-    const char *info;
-    const char *version;
+    AFB_ApiT api;
+    AFB_ReqT request;
     void *context;
-    void *dlHandle;
-} CtlPluginT;
+} CtlSourceT;
+
+typedef struct {
+    const char *label;
+    const char *info;   
+    AFB_ApiT api;
+    json_object *argsJ;
+    CtlActionTypeT type;
+    union {
+        struct {
+            const char* api;
+            const char* verb;
+        } subcall;
+        
+        struct {
+            const char* load;
+            const char* funcname;
+        } lua;
+        
+        struct {
+            const char* funcname;
+            int (*callback)(CtlSourceT *source, json_object *argsJ, json_object *queryJ);
+            CtlPluginT *plugin;
+        } cb;        
+    } exec;
+} CtlActionT;
 
-typedef void*(*DispatchPluginInstallCbT)(CtlPluginT *plugin, void* handle);
 
+typedef void*(*DispatchPluginInstallCbT)(CtlPluginT *plugin, void* handle);
 
 #define MACRO_STR_VALUE(arg) #arg
-#define CTLP_REGISTER(pluglabel) CtlPluginMagicT CtlPluginMagic={.magic=CTL_PLUGIN_MAGIC,.label=pluglabel}; struct afb_binding_data_v2;
+#define CTLP_CAPI_REGISTER(pluglabel) CtlPluginMagicT CtlPluginMagic={.magic=CTL_PLUGIN_MAGIC,.label=pluglabel}; struct afb_binding_data_v2;
 #define CTLP_ONLOAD(plugin, handle) void* CtlPluginOnload(CtlPluginT *plugin, void* handle)
 #define CTLP_CAPI(funcname, source, argsJ, queryJ) int funcname(CtlSourceT *source, json_object* argsJ, json_object* queryJ)
 
+// LUA2c Wrapper macro. Allows to call C code from Lua script
+typedef int (*Lua2cFunctionT)(CtlSourceT *source, json_object *argsJ, json_object **responseJ);
+typedef int (*Lua2cWrapperT) (void*luaHandle, char *funcname, Lua2cFunctionT callback);
+
+#define CTLP_LUA_REGISTER(pluglabel) Lua2cWrapperT Lua2cWrap; CTLP_CAPI_REGISTER(pluglabel);
+#define CTLP_LUA2C(funcname, source, argsJ, responseJ) static int funcname (CtlSourceT* source, json_object* argsJ, json_object** responseJ);\
+        int lua2c_ ## funcname (void* luaState){return((*Lua2cWrap)(luaState, MACRO_STR_VALUE(funcname), funcname));};\
+        static int funcname (CtlSourceT* source, json_object* argsJ, json_object** responseJ)
+
 #endif /* _CTL_PLUGIN_INCLUDE_ */
\ No newline at end of file
diff --git a/ctl-lib/ctl-timer.c b/ctl-lib/ctl-timer.c
index 1de6f99..81aa984 100644
--- a/ctl-lib/ctl-timer.c
+++ b/ctl-lib/ctl-timer.c
@@ -30,7 +30,6 @@ typedef struct {
     const char *label;
 } AutoTestCtxT;
 
-static afb_event afbevt;
 
 STATIC int TimerNext (sd_event_source* source, uint64_t timer, void* handle) {
     TimerHandleT *timerHandle = (TimerHandleT*) handle;
@@ -41,12 +40,13 @@ STATIC int TimerNext (sd_event_source* source, uint64_t timer, void* handle) {
     timerHandle->count --;
     if (timerHandle->count == 0) {
         sd_event_source_unref(source);
+        if (timerHandle->freeCB) timerHandle->freeCB(timerHandle->context);
         free (handle);
         return 0;
     }
     else {
         // otherwise validate timer for a new run
-        sd_event_now(afb_daemon_get_event_loop(), CLOCK_MONOTONIC, &usec);
+        sd_event_now(AFB_GetEventLoop(timerHandle->api), CLOCK_MONOTONIC, &usec);
         sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
         sd_event_source_set_time(source, usec + timerHandle->delay*1000);
     }
@@ -57,7 +57,7 @@ STATIC int TimerNext (sd_event_source* source, uint64_t timer, void* handle) {
     return 0;
 
 OnErrorExit:
-    AFB_WARNING("TimerNext Callback Fail Tag=%s", timerHandle->label);
+    AFB_ApiWarning(timerHandle->api, "TimerNext Callback Fail Tag=%s", timerHandle->label);
     return -1;
 }
 
@@ -68,34 +68,24 @@ PUBLIC void TimerEvtStop(TimerHandleT *timerHandle) {
 }
 
 
-PUBLIC void TimerEvtStart(TimerHandleT *timerHandle, timerCallbackT callback, void *context) {
+PUBLIC void TimerEvtStart(AFB_ApiT apiHandle, TimerHandleT *timerHandle, timerCallbackT callback, void *context) {
     uint64_t usec;
 
     // populate CB handle
     timerHandle->callback=callback;
     timerHandle->context=context;
+    timerHandle->api=apiHandle;
 
     // set a timer with ~250us accuracy
-    sd_event_now(afb_daemon_get_event_loop(), CLOCK_MONOTONIC, &usec);
-    sd_event_add_time(afb_daemon_get_event_loop(), &timerHandle->evtSource, CLOCK_MONOTONIC, usec+timerHandle->delay*1000, 250, TimerNext, timerHandle);
-}
-
-PUBLIC afb_event TimerEvtGet(void) {
-    return afbevt;
+    sd_event_now(AFB_GetEventLoop(apiHandle), CLOCK_MONOTONIC, &usec);
+    sd_event_add_time(AFB_GetEventLoop(apiHandle), &timerHandle->evtSource, CLOCK_MONOTONIC, usec+timerHandle->delay*1000, 250, TimerNext, timerHandle);
 }
 
 
 // Create Binding Event at Init
-PUBLIC int TimerEvtInit () {
-
-    // create binder event to send test pause/resume
-    afbevt = afb_daemon_make_event("control");
-    if (!afb_event_is_valid(afbevt)) {
-        AFB_ERROR ("POLCTL_INIT: Cannot register ctl-events");
-        return 1;
-    }
+PUBLIC int TimerEvtInit (AFB_ApiT apiHandle) {
 
-    AFB_DEBUG ("Audio Control-Events Init Done");
+    AFB_ApiDebug (apiHandle, "Timer-Init Done");
     return 0;
 }
 
diff --git a/ctl-lib/ctl-timer.h b/ctl-lib/ctl-timer.h
index b08299f..ced0417 100644
--- a/ctl-lib/ctl-timer.h
+++ b/ctl-lib/ctl-timer.h
@@ -26,17 +26,19 @@
 typedef int (*timerCallbackT)(void *context);
 
 typedef struct TimerHandleS {
+    int magic;
     int count;
     int delay;
     const char*label;
     void *context;
     timerCallbackT callback;
     sd_event_source *evtSource;
+    AFB_ApiT api;
+    timerCallbackT freeCB;
 } TimerHandleT;
 
-PUBLIC int TimerEvtInit (void);
-PUBLIC afb_event TimerEvtGet(void);
-PUBLIC void TimerEvtStart(TimerHandleT *timerHandle, timerCallbackT callback, void *context);
+PUBLIC int TimerEvtInit (AFB_ApiT apiHandle);
+PUBLIC void TimerEvtStart(AFB_ApiT apiHandle, TimerHandleT *timerHandle, timerCallbackT callback, void *context);
 PUBLIC void TimerEvtStop(TimerHandleT *timerHandle);
 
 #endif // CTL_TIMER_INCLUDE
-- 
cgit