aboutsummaryrefslogtreecommitdiffstats
path: root/Controller-afb
diff options
context:
space:
mode:
authorRomain Forlot <romain.forlot@iot.bzh>2017-08-22 19:13:47 +0200
committerRomain Forlot <romain.forlot@iot.bzh>2017-08-22 19:13:47 +0200
commit450ae7e324165efa84e398b224d01c7ef1710579 (patch)
treefb330116fe333b8976169b3e46214837787066c2 /Controller-afb
parent461f9d7db948612e8ceabcb006409a328c568db6 (diff)
Fixed Lua Table to Json parsing
Change-Id: I423ca987d0647b8985172aa03510927d75af4e0d Signed-off-by: Sebastien Douheret <sebastien.douheret@iot.bzh> Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
Diffstat (limited to 'Controller-afb')
-rw-r--r--Controller-afb/ctl-lua.c475
1 files changed, 249 insertions, 226 deletions
diff --git a/Controller-afb/ctl-lua.c b/Controller-afb/ctl-lua.c
index 2aaa3a5..8d5a87e 100644
--- a/Controller-afb/ctl-lua.c
+++ b/Controller-afb/ctl-lua.c
@@ -13,15 +13,15 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- * ref:
- * (manual) https://www.lua.org/manual/5.3/manual.html
+ * ref:
+ * (manual) https://www.lua.org/manual/5.3/manual.html
* (lua->C) http://www.troubleshooters.com/codecorn/lua/lua_c_calls_lua.htm#_Anatomy_of_a_Lua_Call
* (lua/C Var) http://acamara.es/blog/2012/08/passing-variables-from-lua-5-2-to-c-and-vice-versa/
* (Lua/C Lib)https://john.nachtimwald.com/2014/07/12/wrapping-a-c-library-in-lua/
* (Lua/C Table) https://gist.github.com/SONIC3D/10388137
* (Lua/C Nested table) https://stackoverflow.com/questions/45699144/lua-nested-table-from-lua-to-c
* (Lua/C Wrapper) https://stackoverflow.com/questions/45699950/lua-passing-handle-to-function-created-with-newlib
- *
+ *
*/
#define _GNU_SOURCE
@@ -58,17 +58,17 @@ typedef struct {
} LuaAfbContextT;
typedef struct {
- const char *callback;
- json_object *context;
- void *handle;
+ const char *callback;
+ json_object *context;
+ void *handle;
} LuaCallServiceT;
typedef enum {
AFB_MSG_INFO,
AFB_MSG_WARNING,
- AFB_MSG_NOTICE,
- AFB_MSG_DEBUG,
- AFB_MSG_ERROR,
+ AFB_MSG_NOTICE,
+ AFB_MSG_DEBUG,
+ AFB_MSG_ERROR,
} LuaAfbMessageT;
/*
@@ -107,16 +107,16 @@ STATIC LuaAfbContextT *LuaCtxPush (lua_State *luaState, afb_req request, void *h
return afbContext;
}
-STATIC void LuaCtxFree (LuaAfbContextT *afbContext) {
+STATIC void LuaCtxFree (LuaAfbContextT *afbContext) {
free(afbContext->info);
free(afbContext);
}
// Push a json structure on the stack as a LUA table
STATIC int LuaPushArgument (json_object *argsJ) {
-
+
//AFB_NOTICE("LuaPushArgument argsJ=%s", json_object_get_string(argsJ));
-
+
json_type jtype= json_object_get_type(argsJ);
switch (jtype) {
case json_type_object: {
@@ -124,7 +124,7 @@ STATIC int LuaPushArgument (json_object *argsJ) {
json_object_object_foreach (argsJ, key, val) {
int done = LuaPushArgument (val);
if (done) {
- lua_setfield(luaState,-2, key);
+ lua_setfield(luaState,-2, key);
}
}
break;
@@ -155,39 +155,63 @@ STATIC int LuaPushArgument (json_object *argsJ) {
AFB_WARNING("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));
return 0;
- }
+ }
return 1;
}
STATIC json_object *LuaPopOneArg (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) {
- int idx;
#define LUA_KEY_INDEX -2
#define LUA_VALUE_INDEX -1
-
- json_object *tableJ= json_object_new_object();
- const char *key;
- char number[3];
+
+ int idx;
+ int tableType;
+ json_object *tableJ= NULL;
+
lua_pushnil(luaState); // 1st key
- if (index < 0) index--;
+ if (index < 0) index--;
for (idx=1; lua_next(luaState, index) != 0; idx++) {
// uses 'key' (at index -2) and 'value' (at index -1)
- if (lua_type(luaState,LUA_KEY_INDEX) == LUA_TSTRING) key= lua_tostring(luaState, LUA_KEY_INDEX);
- else {
- snprintf(number, sizeof(number),"%d", idx);
- key=number;
- }
- json_object *argJ= LuaPopOneArg(luaState, LUA_VALUE_INDEX);
- json_object_object_add(tableJ, key, argJ);
- lua_pop(luaState, 1); // removes 'value'; keeps 'key' for next iteration
- }
-
+ if (lua_type(luaState,LUA_KEY_INDEX) == LUA_TSTRING) {
+
+ if (!tableJ) {
+ tableJ= json_object_new_object();
+ tableType=LUA_TSTRING;
+ } else if (tableType != LUA_TSTRING){
+ AFB_ERROR("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_object_add(tableJ, key, argJ);
+
+ } else {
+ if (!tableJ) {
+ tableJ= json_object_new_array();
+ tableType=LUA_TNUMBER;
+ } else if(tableType != LUA_TNUMBER) {
+ AFB_ERROR("MIX Lua Table with key numeric/string not supported");
+ return NULL;
+ }
+
+ json_object *argJ= LuaPopOneArg(luaState, LUA_VALUE_INDEX);
+ json_object_array_add(tableJ, argJ);
+ }
+
+
+ lua_pop(luaState, 1); // removes 'value'; keeps 'key' for next iteration
+ }
+
// Query is empty free empty json object
if (idx == 1) {
json_object_put(tableJ);
@@ -215,32 +239,32 @@ STATIC json_object *LuaPopOneArg (lua_State* luaState, int idx) {
value= json_object_new_boolean(lua_toboolean(luaState, idx));
break;
case LUA_TSTRING:
- value= json_object_new_string(lua_tostring(luaState, idx));
+ value= json_object_new_string(lua_tostring(luaState, idx));
break;
- case LUA_TTABLE:
+ case LUA_TTABLE:
value= LuaTableToJson(luaState, idx);
- break;
+ break;
case LUA_TNIL:
value=json_object_new_string("nil") ;
break;
case LUA_TUSERDATA:
value=json_object_new_int64((int64_t)lua_touserdata(luaState, idx)); // store userdata as int !!!
break;
-
+
default:
AFB_NOTICE ("LuaPopOneArg: script returned Unknown/Unsupported idx=%d type:%d/%s", idx, luaType, lua_typename(luaState, luaType));
value=NULL;
}
- return value;
+ return value;
}
-
-static json_object *LuaPopArgs (lua_State* luaState, int start) {
+
+static json_object *LuaPopArgs (lua_State* luaState, int start) {
json_object *responseJ;
-
+
int stop = lua_gettop(luaState);
if(stop-start <0) return NULL;
-
+
// start at 2 because we are using a function array lib
if (start == stop) {
responseJ=LuaPopOneArg (luaState, start);
@@ -250,71 +274,71 @@ static json_object *LuaPopArgs (lua_State* luaState, int start) {
for (int idx=start; idx <= stop; idx++) {
json_object *argJ=LuaPopOneArg (luaState, idx);
if (!argJ) goto OnErrorExit;
- json_object_array_add(responseJ, argJ);
+ json_object_array_add(responseJ, argJ);
}
}
-
+
return responseJ;
-
+
OnErrorExit:
return NULL;
-}
+}
STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) {
char *message;
json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG);
-
+
if (!responseJ) {
luaL_error(luaState,"LuaFormatMessage empty message");
goto OnErrorExit;
}
-
+
// if we have only on argument just return the value.
if (json_object_get_type(responseJ)!=json_type_array || json_object_array_length(responseJ) <2) {
message= (char*)json_object_get_string(responseJ);
goto PrintMessage;
}
-
+
// extract format and push all other parameter on the stack
message = alloca (LUA_MSG_MAX_LENGTH);
const char *format = json_object_get_string(json_object_array_get_idx(responseJ, 0));
-
+
int arrayIdx=1;
int targetIdx=0;
-
+
for (int idx=0; format[idx] !='\0'; idx++) {
-
+
if (format[idx]=='%' && format[idx] !='\0') {
json_object *slotJ= json_object_array_get_idx(responseJ, arrayIdx);
//if (slotJ) AFB_NOTICE("**** idx=%d slotJ=%s", arrayIdx, json_object_get_string(slotJ));
-
+
switch (format[++idx]) {
case 'd':
- if (slotJ) targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%d", json_object_get_int(slotJ));
+ if (slotJ) targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%d", json_object_get_int(slotJ));
else targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"nil");
arrayIdx++;
break;
case 'f':
- if (slotJ) targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%f", json_object_get_double(slotJ));
+ if (slotJ) targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%f", json_object_get_double(slotJ));
else targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"nil");
arrayIdx++;
break;
-
+
case'%':
message[targetIdx]='%';
targetIdx++;
break;
-
+
case 's':
default:
- if (slotJ) targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%s", json_object_get_string(slotJ));
+ if (slotJ) targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%s", json_object_get_string(slotJ));
else targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"nil");
arrayIdx++;
}
-
+
} else {
if (targetIdx >= LUA_MSG_MAX_LENGTH) {
AFB_WARNING ("LuaFormatMessage: message[%s] owerverflow LUA_MSG_MAX_LENGTH=%d", format, LUA_MSG_MAX_LENGTH);
@@ -327,46 +351,46 @@ STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) {
}
message[targetIdx]='\0';
-PrintMessage:
+PrintMessage:
switch (action) {
case AFB_MSG_WARNING:
- AFB_WARNING (message);
+ AFB_WARNING ("%s", message);
break;
case AFB_MSG_NOTICE:
- AFB_NOTICE (message);
+ AFB_NOTICE ("%s", message);
break;
case AFB_MSG_DEBUG:
- AFB_DEBUG (message);
+ AFB_DEBUG ("%s", message);
break;
case AFB_MSG_INFO:
- AFB_INFO (message);
+ AFB_INFO ("%s", message);
break;
- case AFB_MSG_ERROR:
+ case AFB_MSG_ERROR:
default:
- AFB_ERROR (message);
+ AFB_ERROR ("%s", message);
}
return 0; // nothing return to lua
-
+
OnErrorExit: // on argument to return (the error message)
return 1;
}
-STATIC int LuaPrintInfo(lua_State* luaState) {
+STATIC int LuaPrintInfo(lua_State* luaState) {
int err=LuaFormatMessage (luaState, AFB_MSG_INFO);
- return err;
+ return err;
}
-STATIC int LuaPrintError(lua_State* luaState) {
+STATIC int LuaPrintError(lua_State* luaState) {
int err=LuaFormatMessage (luaState, AFB_MSG_ERROR);
return err; // no value return
}
-STATIC int LuaPrintWarning(lua_State* luaState) {
+STATIC int LuaPrintWarning(lua_State* luaState) {
int err=LuaFormatMessage (luaState, AFB_MSG_WARNING);
return err;
}
-STATIC int LuaPrintNotice(lua_State* luaState) {
+STATIC int LuaPrintNotice(lua_State* luaState) {
int err=LuaFormatMessage (luaState, AFB_MSG_NOTICE);
return err;
}
@@ -379,17 +403,17 @@ STATIC int LuaPrintDebug(lua_State* luaState) {
STATIC int LuaAfbSuccess(lua_State* luaState) {
LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG);
if (!afbContext) goto OnErrorExit;
-
+
// ignore context argument
json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1);
if (responseJ == JSON_ERROR) return 1;
-
+
afb_req_success(afbContext->request, responseJ, NULL);
LuaCtxFree(afbContext);
return 0;
-
- OnErrorExit:
+
+ OnErrorExit:
lua_error(luaState);
return 1;
}
@@ -397,26 +421,26 @@ STATIC int LuaAfbSuccess(lua_State* luaState) {
STATIC int LuaAfbFail(lua_State* luaState) {
LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG);
if (!afbContext) goto OnErrorExit;
-
+
json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1);
if (responseJ == JSON_ERROR) return 1;
afb_req_fail(afbContext->request, afbContext->info, json_object_get_string(responseJ));
-
- LuaCtxFree(afbContext);
- return 0;
- OnErrorExit:
+ LuaCtxFree(afbContext);
+ return 0;
+
+ OnErrorExit:
lua_error(luaState);
return 1;
}
-STATIC void LuaAfbServiceCB(void *handle, int iserror, struct json_object *responseJ) {
+STATIC void LuaAfbServiceCB(void *handle, int iserror, struct json_object *responseJ) {
LuaCallServiceT *contextCB= (LuaCallServiceT*)handle;
int count=1;
-
+
lua_getglobal(luaState, contextCB->callback);
-
+
// push error status & response
lua_pushboolean(luaState, iserror);
count+= LuaPushArgument(responseJ);
@@ -426,35 +450,35 @@ STATIC void LuaAfbServiceCB(void *handle, int iserror, struct json_object *respo
if (err) {
AFB_ERROR ("LUA-SERICE-CB:FAIL response=%s err=%s", json_object_get_string(responseJ), lua_tostring(luaState,-1) );
}
-
+
free (contextCB);
}
STATIC int LuaAfbService(lua_State* luaState) {
int count = lua_gettop(luaState);
-
+
// 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)) {
lua_pushliteral (luaState, "LuaAfbServiceCall-Syntax is AFB:service_call (api, verb, query, callback, handle ....");
- goto OnErrorExit;
+ 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);
if (queryJ == JSON_ERROR) return 1;
-
- LuaCallServiceT *contextCB = calloc (1, sizeof(LuaCallServiceT));
+
+ LuaCallServiceT *contextCB = calloc (1, sizeof(LuaCallServiceT));
contextCB->callback= lua_tostring(luaState, 5);
contextCB->context = LuaPopArgs(luaState, 6);
-
+
afb_service_call(api, verb, queryJ, LuaAfbServiceCB, contextCB);
-
+
return 0; // no value return
-
- OnErrorExit:
+
+ OnErrorExit:
lua_error(luaState);
return 1;
}
@@ -462,27 +486,27 @@ STATIC int LuaAfbService(lua_State* luaState) {
STATIC int LuaAfbServiceSync(lua_State* luaState) {
int count = lua_gettop(luaState);
json_object *responseJ;
-
+
// note: argument start at 2 because of AFB: table
if (count <3 || !lua_isstring(luaState, 2) || !lua_isstring(luaState, 3) || !lua_istable(luaState, 4)) {
lua_pushliteral (luaState, "LuaAfbServiceSync-Syntax is error,data=AFB:service_call (api, verb, query)");
- goto OnErrorExit;
+ 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);
-
+
int iserror=afb_service_call_sync (api, verb, queryJ, &responseJ);
-
+
// push error status & response
count=1; lua_pushboolean(luaState, iserror);
count+= LuaPushArgument(responseJ);
return count; // return count values
-
- OnErrorExit:
+
+ OnErrorExit:
lua_error(luaState);
return 1;
}
@@ -490,7 +514,7 @@ STATIC int LuaAfbServiceSync(lua_State* luaState) {
STATIC int LuaAfbEventPush(lua_State* luaState) {
LuaAfbEvent *afbevt;
int index;
-
+
// 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);
@@ -504,13 +528,13 @@ STATIC int LuaAfbEventPush(lua_State* luaState) {
lua_pushliteral (luaState, "LuaAfbMakePush-Fail invalid event");
goto OnErrorExit;
}
-
+
json_object *ctlEventJ= LuaTableToJson(luaState, index);
if (!ctlEventJ) {
lua_pushliteral (luaState, "LuaAfbEventPush-Syntax is AFB:signal ([evtHandle], {lua table})");
- goto OnErrorExit;
+ goto OnErrorExit;
}
-
+
int done = afb_event_push(afbevt->event, ctlEventJ);
if (!done) {
lua_pushliteral (luaState, "LuaAfbEventPush-Fail No Subscriber to event");
@@ -518,22 +542,22 @@ STATIC int LuaAfbEventPush(lua_State* luaState) {
goto OnErrorExit;
}
afbevt->count++;
- return 0;
-
- OnErrorExit:
+ return 0;
+
+ OnErrorExit:
lua_error(luaState);
return 1;
}
STATIC int LuaAfbEventSubscribe(lua_State* luaState) {
LuaAfbEvent *afbevt;
-
+
LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG);
if (!afbContext) {
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);
@@ -545,7 +569,7 @@ STATIC int LuaAfbEventSubscribe(lua_State* luaState) {
lua_pushliteral (luaState, "LuaAfbMakePush-Fail invalid event handle");
goto OnErrorExit;
}
-
+
int err = afb_req_subscribe(afbContext->request, afbevt->event);
if (err) {
lua_pushliteral (luaState, "LuaAfbEventSubscribe-Fail No Subscriber to event");
@@ -553,9 +577,9 @@ STATIC int LuaAfbEventSubscribe(lua_State* luaState) {
goto OnErrorExit;
}
afbevt->count++;
- return 0;
-
- OnErrorExit:
+ return 0;
+
+ OnErrorExit:
lua_error(luaState);
return 1;
}
@@ -563,12 +587,12 @@ STATIC int LuaAfbEventSubscribe(lua_State* luaState) {
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)) {
lua_pushliteral (luaState, "LuaAfbEventMake-Syntax is evtHandle= AFB:event ('myEventName')");
- goto OnErrorExit;
+ goto OnErrorExit;
}
-
+
// event name should be the only argument
afbevt->name= strdup (lua_tostring(luaState,LUA_FIST_ARG));
@@ -581,64 +605,64 @@ STATIC int LuaAfbEventMake(lua_State* luaState) {
// push event handler as a LUA opaque handle
lua_pushlightuserdata(luaState, afbevt);
- return 1;
-
- OnErrorExit:
+ return 1;
+
+ OnErrorExit:
lua_error(luaState);
return 1;
}
-// Function call from LUA when lua2c plugin L2C is used
+// Function call from LUA when lua2c plugin L2C is used
PUBLIC int Lua2cWrapper(lua_State* luaState, char *funcname, Lua2cFunctionT callback, void *context) {
-
+
json_object *argsJ= LuaPopArgs(luaState, LUA_FIST_ARG+1);
int response = (*callback) (funcname, argsJ, context);
-
+
// push response to LUA
lua_pushinteger(luaState, response);
- return 1;
+ return 1;
}
// Generated some fake event based on watchdog/counter
PUBLIC int LuaCallFunc (DispatchSourceT source, DispatchActionT *action, json_object *queryJ) {
-
+
int err, count;
json_object* argsJ = action->argsJ;
const char* func = action->call;
-
+
// load function (should exist in CONTROL_PATH_LUA
lua_getglobal(luaState, func);
// push source on the stack
count=1;
- lua_pushinteger(luaState, source);
-
+ lua_pushinteger(luaState, source);
+
// push argsJ on the stack
if (!argsJ) {
lua_pushnil(luaState);
count++;
- } else {
+ } else {
count+= LuaPushArgument (argsJ);
}
-
+
// push queryJ on the stack
if (!queryJ) {
lua_pushnil(luaState);
count++;
- } else {
+ } else {
count+= LuaPushArgument (queryJ);
- }
+ }
- // effectively exec LUA script code
+ // 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));
goto OnErrorExit;
}
-
+
// return LUA script value
- int rc= (int)lua_tointeger(luaState, -1);
+ int rc= (int)lua_tointeger(luaState, -1);
return rc;
OnErrorExit:
@@ -646,15 +670,15 @@ PUBLIC int LuaCallFunc (DispatchSourceT source, DispatchActionT *action, json_ob
}
-// Execute LUA code from received API request
+// Execute LUA code from received API request
STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
-
+
int err, count=0;
-
- json_object* queryJ = afb_req_json(request);
-
+
+ json_object* queryJ = afb_req_json(request);
+
switch (action) {
-
+
case LUA_DOSTRING: {
const char *script = json_object_get_string(queryJ);
err=luaL_loadstring(luaState, script);
@@ -665,14 +689,14 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
// Push AFB client context on the stack
LuaAfbContextT *afbContext= LuaCtxPush(luaState, request,NULL,script);
if (!afbContext) goto OnErrorExit;
-
+
break;
}
-
+
case LUA_DOCALL: {
const char *func;
json_object *argsJ=NULL;
-
+
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));
@@ -681,7 +705,7 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
// load function (should exist in CONTROL_PATH_LUA
lua_getglobal(luaState, func);
-
+
// Push AFB client context on the stack
LuaAfbContextT *afbContext= LuaCtxPush(luaState, request, NULL, func);
if (!afbContext) goto OnErrorExit;
@@ -690,18 +714,18 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
if (!argsJ) {
lua_pushnil(luaState);
count++;
- } else {
+ } else {
count+= LuaPushArgument (argsJ);
}
-
+
break;
}
-
+
case LUA_DOSCRIPT: { // Fulup need to fix argument passing
char *filename; char*fullpath;
char luaScriptPath[CONTROL_MAXPATH_LEN];
int index;
-
+
// scan luascript search path once
static json_object *luaScriptPathJ =NULL;
@@ -716,89 +740,89 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
// search for filename=script in CONTROL_LUA_PATH
if (!luaScriptPathJ) {
- strncpy(luaScriptPath,CONTROL_DOSCRIPT_PRE, sizeof(luaScriptPath));
- strncat(luaScriptPath,"-", sizeof(luaScriptPath));
- strncat(luaScriptPath,target, sizeof(luaScriptPath));
+ strncpy(luaScriptPath,CONTROL_DOSCRIPT_PRE, sizeof(luaScriptPath));
+ strncat(luaScriptPath,"-", sizeof(luaScriptPath));
+ strncat(luaScriptPath,target, sizeof(luaScriptPath));
luaScriptPathJ= ScanForConfig(CONTROL_LUA_PATH , CTL_SCAN_RECURSIVE,luaScriptPath,".lua");
- }
+ }
for (index=0; index < json_object_array_length(luaScriptPathJ); index++) {
- json_object *entryJ=json_object_array_get_idx(luaScriptPathJ, index);
-
+ json_object *entryJ=json_object_array_get_idx(luaScriptPathJ, index);
+
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));
goto OnErrorExit;
}
-
+
if (index > 0) AFB_WARNING("LUA-DOSCRIPT-SCAN:Ignore second script=%s path=%s", filename, fullpath);
else {
strncpy (luaScriptPath, fullpath, sizeof(luaScriptPath));
strncat (luaScriptPath, "/", sizeof(luaScriptPath));
- strncat (luaScriptPath, filename, sizeof(luaScriptPath));
- }
+ strncat (luaScriptPath, filename, sizeof(luaScriptPath));
+ }
}
-
- err= luaL_loadfile(luaState, luaScriptPath);
+
+ 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));
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);
goto OnErrorExit;
}
-
+
// if no func name given try to deduct from filename
- if (!func && (func=(char*)GetMidleName(filename))!=NULL) {
+ if (!func && (func=(char*)GetMidleName(filename))!=NULL) {
strncpy(luaScriptPath,"_", sizeof(luaScriptPath));
strncat(luaScriptPath,func, sizeof(luaScriptPath));
func=luaScriptPath;
}
if (!func) {
AFB_ERROR ("LUA-DOSCRIPT:FAIL to deduct funcname from %s", filename);
- goto OnErrorExit;
+ goto OnErrorExit;
}
-
+
// load function (should exist in CONTROL_PATH_LUA
lua_getglobal(luaState, func);
-
+
// Push AFB client context on the stack
LuaAfbContextT *afbContext= LuaCtxPush(luaState, request, NULL, func);
if (!afbContext) goto OnErrorExit;
-
+
// push function arguments
if (!argsJ) {
lua_pushnil(luaState);
count++;
- } else {
+ } else {
count+= LuaPushArgument(argsJ);
}
-
+
break;
}
-
- default:
+
+ default:
AFB_ERROR ("LUA-DOSCRIPT-ACTION unknown query=%s", json_object_get_string(queryJ));
goto OnErrorExit;
}
-
- // effectively exec LUA code (afb_reply/fail done later from callback)
+
+ // 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));
goto OnErrorExit;
}
return;
-
+
OnErrorExit:
afb_req_fail(request,"LUA:ERROR", lua_tostring(luaState,-1));
return;
}
-PUBLIC void ctlapi_execlua (afb_req request) {
+PUBLIC void ctlapi_execlua (afb_req request) {
LuaDoAction (LUA_DOSTRING, request);
}
@@ -811,77 +835,77 @@ PUBLIC void ctlapi_debuglua (afb_req request) {
}
STATIC int LuaTimerClear (lua_State* luaState) {
-
+
// Get Timer Handle
LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG);
if (!afbContext) goto OnErrorExit;
-
- // retrieve useful information opaque handle
+
+ // retrieve useful information opaque handle
TimerHandleT *timerHandle = (TimerHandleT*)afbContext->handle;
-
+
AFB_NOTICE ("LuaTimerClear timer=%s", timerHandle->label);
TimerEvtStop(timerHandle);
-
+
return 0; //happy end
-
+
OnErrorExit:
return 1;
}
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
+
+ // retrieve useful information opaque handle
TimerHandleT *timerHandle = (TimerHandleT*)afbContext->handle;
-
+
// 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));
- json_object_object_add(responseJ,"delay", json_object_new_int(timerHandle->delay));
- json_object_object_add(responseJ,"count", json_object_new_int(timerHandle->count));
-
+ json_object_object_add(responseJ,"label", json_object_new_string(timerHandle->label));
+ json_object_object_add(responseJ,"delay", json_object_new_int(timerHandle->delay));
+ json_object_object_add(responseJ,"count", json_object_new_int(timerHandle->count));
+
// return JSON object as Lua table
int count=LuaPushArgument(responseJ);
-
+
// free json object
json_object_put(responseJ);
-
+
return count; // return argument
-
+
OnErrorExit:
return 0;
}
// Timer Callback
-// Set timer
+// Set timer
STATIC int LuaTimerSetCB (void *handle) {
LuaCallServiceT *contextCB =(LuaCallServiceT*) handle;
TimerHandleT *timerHandle = (TimerHandleT*) contextCB->handle;
int count;
-
+
// push timer handle and user context on Lua stack
lua_getglobal(luaState, contextCB->callback);
-
+
// Push timer handle
LuaAfbContextT *afbContext= LuaCtxPush(luaState, NULL_AFBREQ, contextCB->handle, timerHandle->label);
if (!afbContext) goto OnErrorExit;
count=1;
-
+
// Push user Context
- count+= LuaPushArgument(contextCB->context);
-
- int err=lua_pcall(luaState, count, LUA_MULTRET, 0);
+ count+= LuaPushArgument(contextCB->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));
goto OnErrorExit;
}
-
+
// get return parameter
if (!lua_isboolean(luaState, -1)) {
- return (lua_toboolean(luaState, -1));
+ return (lua_toboolean(luaState, -1));
}
// timer last run free context resource
@@ -889,7 +913,7 @@ STATIC int LuaTimerSetCB (void *handle) {
LuaCtxFree(afbContext);
}
return 0; // By default we are happy
-
+
OnErrorExit:
return 1; // stop timer
}
@@ -906,13 +930,13 @@ STATIC int LuaTimerSet(lua_State* luaState) {
lua_pushliteral(luaState, "LuaTimerSet-Syntax timerset (timerT, 'callback', contextT)");
goto OnErrorExit;
}
-
+
int err = wrap_json_unpack(timerJ, "{ss, s?s si, si !}", "label", &label, "info", &info, "delay", &delay, "count", &count);
if (err) {
lua_pushliteral(luaState, "LuaTimerSet-Syntax timerT={label:xxx delay:ms, count:xx}");
goto OnErrorExit;
}
-
+
// everything look fine create timer structure
TimerHandleT *timerHandle = malloc (sizeof (TimerHandleT));
timerHandle->delay=delay;
@@ -920,14 +944,14 @@ STATIC int LuaTimerSet(lua_State* luaState) {
timerHandle->label=label;
// Allocate handle to store context and callback
- LuaCallServiceT *contextCB = calloc (1, sizeof(LuaCallServiceT));
+ LuaCallServiceT *contextCB = calloc (1, sizeof(LuaCallServiceT));
contextCB->callback= callback;
contextCB->context = contextJ;
contextCB->handle = timerHandle;
// fire timer
TimerEvtStart (timerHandle, LuaTimerSetCB, contextCB);
-
+
return 0; // Happy No Return Function
OnErrorExit:
@@ -960,39 +984,39 @@ static const luaL_Reg afbFunction[] = {
{"subscribe" , LuaAfbEventSubscribe},
{"evtmake" , LuaAfbEventMake},
{"evtpush" , LuaAfbEventPush},
-
+
{NULL, NULL} /* sentinel */
};
// Create Binding Event at Init
PUBLIC int LuaLibInit () {
int err, index;
-
+
// search for default policy config file
char fullprefix[CONTROL_MAXPATH_LEN];
strncpy (fullprefix, CONTROL_CONFIG_PRE "-", sizeof(fullprefix));
strncat (fullprefix, GetBinderName(), sizeof(fullprefix));
strncat (fullprefix, "-", sizeof(fullprefix));
-
+
const char *dirList= getenv("CONTROL_LUA_PATH");
if (!dirList) dirList=CONTROL_LUA_PATH;
-
+
json_object *luaScriptPathJ = ScanForConfig(dirList , CTL_SCAN_RECURSIVE, fullprefix, "lua");
-
+
// open a new LUA interpretor
luaState = luaL_newstate();
if (!luaState) {
AFB_ERROR ("LUA_INIT: Fail to open lua interpretor");
goto OnErrorExit;
}
-
+
// load auxiliary libraries
luaL_openlibs(luaState);
- // redirect print to AFB_NOTICE
+ // redirect print to AFB_NOTICE
luaL_newlib(luaState, afbFunction);
lua_setglobal(luaState, "AFB");
-
+
// create default lua event to send test pause/resume
luaDefaultEvt=calloc(1,sizeof(LuaAfbEvent));
luaDefaultEvt->name=CONTROL_LUA_EVENT;
@@ -1001,45 +1025,44 @@ PUBLIC int LuaLibInit () {
AFB_ERROR ("POLCTL_INIT: Cannot register lua-events=%s ", CONTROL_LUA_EVENT);
goto OnErrorExit;;
}
-
+
// load+exec any file found in LUA search path
for (index=0; index < json_object_array_length(luaScriptPathJ); index++) {
json_object *entryJ=json_object_array_get_idx(luaScriptPathJ, index);
-
+
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));
goto OnErrorExit;
}
-
+
char filepath[CONTROL_MAXPATH_LEN];
- strncpy(filepath, fullpath, sizeof(filepath));
- strncat(filepath, "/", sizeof(filepath));
- strncat(filepath, filename, sizeof(filepath));
- err= luaL_loadfile(luaState, filepath);
+ strncpy(filepath, fullpath, sizeof(filepath));
+ strncat(filepath, "/", sizeof(filepath));
+ 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));
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));
goto OnErrorExit;
- }
+ }
}
-
+
// 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_DEBUG ("Audio control-LUA Init Done");
return 0;
-
- OnErrorExit:
+
+ OnErrorExit:
return 1;
}
- \ No newline at end of file