#include "cmd_lua.h"
void fatal_error(lua_State *L, char *msg)
{
fprintf(stderr, "\n FATAL ERROR:\n %s %s\n\n", msg, lua_tostring(L,-1));
}
int check_table_key_string(lua_State *L, const char *key, const char **value, size_t *size)
{
const char *result;
size_t result_sz;
int t;
lua_pushstring(L, key);
lua_gettable(L,1);
t = lua_type(L,-1);
if (t == LUA_TSTRING)
{
result = luaL_checklstring(L,-1,&result_sz);
*value = result;
*size = result_sz;
return 0;
} else
{
*value = NULL;
*size = 0;
return -1;
}
}
int check_table_key_integer(lua_State *L, const char *key, int *value)
{
int result;
int t;
lua_pushstring(L, key);
lua_gettable(L,1);
if ((t = lua_type(L, -1)) == LUA_TNUMBER)
{
result = luaL_checkinteger(L,-1);
*value = result;
return 0;
}
return -1;
}
int verify_name(const char *lua_name)
{
int i;
//check if all symbols are alphanumeric
for (i=0;i<strlen(lua_name);i++)
{
if (!isdigit(lua_name[i]) && !isalpha(lua_name[i]))
{
return -1;
}
}
return 0;
}
int lua_excute(const char *fname, rpc_call_request *req, rpc_call_response **resp)
{
lua_State *L;
sds lua_full_path = sdsempty();
L = luaL_newstate();
luaL_openlibs(L);
if (verify_name(fname) != 0)
{
return -1;
}
lua_full_path = sdscat(lua_full_path, "lua/");
lua_full_path = sdscat(lua_full_path, fname);
lua_full_path = sdscat(lua_full_path, ".lua");
if (luaL_loadfile(L,lua_full_path))
{
fatal_error(L, "load file failed");
sdsfree(lua_full_path);
return -1;
}
sdsfree(lua_full_path);
if (lua_pcall(L,0,0,0))
{
fatal_error(L, "lua_pcall failed");
return -1;
}
lua_getglobal(L, "callback");
lua_newtable(L);
lua_pushstring(L,"method");
lua_pushstring(L, req->method);
lua_settable(L,-3);
lua_pushstring(L,"params");
lua_pushstring(L, req->params);
lua_settable(L,-3);
lua_pushstring(L,"id");
lua_pushinteger(L, req->id);
lua_settable(L,-3);
lua_pushstring(L,"user");
lua_pushstring(L, req->user);
lua_settable(L,-3);
lua_pushstring(L,"mask");
lua_pushstring(L, req->mask);
lua_settable(L,-3);
lua_pushstring(L,"server");
lua_pushstring(L, req->server);
lua_settable(L,-3);
if (lua_pcall(L,1,1,0))
{
fatal_error(L, "cant call callback function from file");
return -1;
}
{
int t;
int top = lua_gettop(L);
//int len = lua_rawlen(L,1);
if (top == 1)
{
t = lua_type(L,1);
if (t == LUA_TTABLE)
{
char *r_result; //this care unchangable stupid C dont know what is const
char *r_error; //this unchangable stupid C dont know what is const
int r_id;
size_t sz;
check_table_key_string(L, "result", (const char **)&r_result, &sz);
check_table_key_integer(L, "id", &r_id);
check_table_key_string(L, "error", (const char **)&r_error, &sz);
if (r_result == NULL) r_result = "!";
if (r_error == NULL) r_error = "!";
*resp = rpc_call_resp_new(alloc_new_str(r_result), alloc_new_str(r_error), r_id);
(*resp)->user = alloc_new_str(" ");
(*resp)->server = alloc_new_str(" ");
(*resp)->mask = alloc_new_str(" ");
}
} else
{
fatal_error(L,"Some unexpected argumetns");
return -1;
}
}
lua_close(L);
return 0;
}
void *cmd_lua(void *data)
{
char *ret = NULL;
char *req_data = NULL;
int fret;
int count;
sds params = sdsempty();
sds out_result = sdsempty();
sds *tokens;
rpc_call_request *req = NULL;
rpc_call_response *resp = NULL;
netbyte_store *nb_req = NULL, *nb_resp=NULL;
char *nb_buf = NULL;
PRINT("LUA\n");
req_data = (char *)data;
if (!req_data)
{
PERM();
return NULL;
}
//----------------------------------------------------------------------------
//prepare request
nb_req = malloc(sizeof(netbyte_store));
nb_init(nb_req);
nb_load(nb_req, (unsigned char *)req_data);
if (nb_req == NULL)
{
ERROR("implement response\n");
return NULL;
}
fret = rpc_call_req_unmarsh(nb_req, &req);
if (fret != 0)
{
ERROR("Invalid request format\n");
return NULL;
}
//----------------------------------------------------------------------------
//main code
params = sdsnew(req->params);
tokens = sdssplitargs(params, &count);
if (-1 == lua_excute(tokens[1], req, &resp))
{
resp = rpc_call_resp_new(out_result,"None",1);
resp->user = alloc_new_str(" ");
resp->server = alloc_new_str(" ");
resp->mask = alloc_new_str(" ");
}
sdsfree(params);
sdsfreesplitres(tokens, count);
//----------------------------------------------------------------------------
//prepare response
nb_resp = malloc(sizeof(netbyte_store));
nb_init(nb_resp);
rpc_call_resp_marsh(resp, &nb_resp);
nb_buf = (char *)nb_create(nb_resp);
if (nb_buf)
{
ret = nb_buf;
}
nb_free(nb_resp);
rpc_call_resp_free(resp);
return ret;
}