diff --git a/APIs/api.lua b/APIs/api.lua index 2c6cd1d..07f9b65 100644 --- a/APIs/api.lua +++ b/APIs/api.lua @@ -1,32 +1,23 @@ package.cpath = __api__.apiroot..'/?.so' require("antd") - -local readline = function() - local s = "" - repeat - local c = modules.std().antd_recv(HTTP_REQUEST.id,1) - if c ~= 0 and c ~= 10 then - s = s..utf8.char(c) - end - until(c == 0 or c == 10) - return s -end +std = modules.std() local read_header =function() + local l repeat - local l = readline() - if l ~= '\r' then + l = std.antd_recv(HTTP_REQUEST.id) + if l and l ~= '\r' then if l == "HTTP_REQUEST" or l == "request" or l == "COOKIE" or l == "REQUEST_HEADER" or l == "REQUEST_DATA" then coroutine.yield(l, "LUA_TABLE") else - local l1 = readline() + local l1 = std.antd_recv(HTTP_REQUEST.id) if l1 ~= '\r' then coroutine.yield(l, l1) end l = l1 end end - until l == '\r' + until not l or l == '\r' end @@ -85,11 +76,11 @@ if HEADER["User-Agent"] and HEADER["User-Agent"]:match("Mobi") then end function LOG_INFO(fmt,...) - ulib.syslog(5,string.format(fmt, table.unpack({...}))) + ulib.syslog(5,string.format(fmt or "LOG", table.unpack({...}) or "")) end function LOG_ERROR(fmt,...) - ulib.syslog(3,string.format(fmt, table.unpack({...}))) + ulib.syslog(3,string.format(fmt or "ERROR", table.unpack({...}) or "")) end function has_module(m) @@ -190,88 +181,13 @@ function loadscript(file, args) end end -local decode_post_data = function(ctype, clen, is_url) - local raw_data,size = std.antd_recv(HTTP_REQUEST.id, clen) - if not raw_data or size ~= clen then - LOG_ERROR("Unable to read request data: received %d bytes expected %d bytes", size, clen) - return 400, "Unable to read request data" - end - if is_url then - local str = tostring(raw) - local arr = explode(str, "&") - LOG_INFO("encoded POST URI: %s", str) - for i,v in ipairs(arr) do - local assoc = explode(v,"=") - if #assoc == 2 then - REQUEST[assoc[1]] = untils.decodeURI(assoc[2]) - else - REQUEST[assoc[1]] = "" - end - end - else - local key = ctype:gsub("^[^/]*", "") - REQUEST[key] = raw_data - end - return 0 -end - -local decode_multi_part = function(ctype, clen) - --[[ - local arr = explode(ctype, "=") - if #arr ~= 2 then - LOG_ERROR("Unable to parsed boundary for: %s", ctype) - return 400, "Multipart Boundary not found" - end - local boundary = std.trim(arr[2]," ") - local boundary_end = boundary.."--" - LOG_INFO("Boundary found: %s", boundary) - local line = nil - repeat - line = readline() - until not line or line:find(boundary) or line == "" - if not line or line == "" then - LOG_ERROR("Cannot find first match for boundary %s", boundary) - return 400, "Unable to decode data based on content boundary" - end - repeat - line = readline() - until not line or line:find("Content-Disposition:") or line == "" - if not line or line == "" then - LOG_ERROR("Content-Disposition meta data not fond") - return 400, "Unable to query Content-Disposition from request" - end - line = line:gsub("Content-Disposition:",""):gsub("\r\n","") - -- extract parameters from header - arr = explode(line,";") - local part_name, part_file = nil, nil - for i,v in ipairs(arr) do - LOG_INFO('Decoding: %s', v) - local assoc = explode(v, "=") - local key = std.trim(assoc[1]) - local val = assoc[1] - if val then - val = std.trim(val, " ") - if key == "name" then - LOG_INFO("Part name: %s", val) - part_name = val - end - if key == "filename" then - LOG_INFO("Part file: %s", val) - part_file = val - end - end - end - -- TODO: to be continue - ]] - return 0 -end -- decode post data if any -local decode_request = function() - LOG_INFO("Request method %s", REQUEST.method) +local decode_request_data = function() if (not REQUEST.method) or (REQUEST.method ~= "POST" and REQUEST.method ~= "PUT" - and REQUEST.method ~= "PATCH") then + and REQUEST.method ~= "PATCH") + or (not REQUEST.HAS_RAW_BODY) then return 0 end local ctype = HEADER['Content-Type'] @@ -283,16 +199,31 @@ local decode_request = function() LOG_ERROR("Invalid content type %s or content length %d", ctype, clen) return 400, "Bad Request, missing content description" end - if ctype == "application/x-www-form-urlencoded" then - return decode_post_data(ctype, clen, true) - elseif ctype == "multipart/form-data" then - return decode_multi_part(ctype, clen) + local raw_data, len = std.antd_recv(HTTP_REQUEST.id, clen) + if len ~= clen then + LOG_ERROR("Unable to read all data: read %d expected %d", len, clen) + return 400, "Bad Request, missing content data" + end + if ctype:find("application/json") then + REQUEST.json = bytes.__tostring(raw_data) else - return decode_post_data(ctype, clen, false) + REQUEST[ctype] = raw_data + end + REQUEST.HAS_RAW_BODY = nil + return 0 +end + +-- set compression level +local accept_encoding = HEADER["Accept-Encoding"] +if accept_encoding then + if accept_encoding:find("gzip") then + std.antd_set_zlevel(HTTP_REQUEST.id, "gzip") + elseif accept_encoding:find("deflate") then + std.antd_set_zlevel(HTTP_REQUEST.id, "deflate") end end -local code, error = decode_request() +local code, error = decode_request_data() if code ~= 0 then LOG_ERROR(error) diff --git a/APIs/extra_mime.lua b/APIs/extra_mime.lua index 9b4a4ee..da97300 100644 --- a/APIs/extra_mime.lua +++ b/APIs/extra_mime.lua @@ -1,5 +1,5 @@ function std.extra_mime(name) - local ext = std.ext(name); + local ext = std.ext(name) local mpath = __ROOT__.."/".."mimes.json" local xmimes = {} if utils.file_exists(mpath) then @@ -15,7 +15,7 @@ function std.extra_mime(name) elseif ext == "cpp" or ext == "hpp" then return "text/cpp",false elseif ext == "md" then return "text/markdown",false elseif ext == "lua" then return "text/lua",false - elseif ext == "yaml" then return "application/x-yaml", false + elseif ext == "yml" then return "application/x-yaml", false elseif xmimes[ext] then return xmimes[ext].mime, xmimes[ext].binary --elseif ext == "pgm" then return "image/x-portable-graymap", true else diff --git a/APIs/std.lua b/APIs/std.lua index b221a89..7635b98 100644 --- a/APIs/std.lua +++ b/APIs/std.lua @@ -1,4 +1,3 @@ -std = modules.std() bytes = modules.bytes() array = modules.array() @@ -61,7 +60,8 @@ function std.b(s) std._b(HTTP_REQUEST.id,s) end function std.f(v) - ulib.send_file(v, HTTP_REQUEST.socket) + std._f(HTTP_REQUEST.id,v) + --ulib.send_file(v, HTTP_REQUEST.socket) end function std.setCookie(v) diff --git a/lib/asl/antd.c b/lib/asl/antd.c index 71d1576..ef3bfb9 100644 --- a/lib/asl/antd.c +++ b/lib/asl/antd.c @@ -2,346 +2,395 @@ #include #include "../lualib.h" // add a length field, and -void lua_new_byte_array(lua_State*L, int n) +void lua_new_byte_array(lua_State *L, int n) { - size_t nbytes = sizeof(byte_array_t) + n*sizeof(unsigned char); - byte_array_t *a = (byte_array_t *)lua_newuserdata(L, nbytes); - a->data = &((char*)a)[sizeof(byte_array_t)]; - luaL_getmetatable(L, BYTEARRAY); - lua_setmetatable(L, -2); - a->size = n; + size_t nbytes = sizeof(byte_array_t) + n * sizeof(unsigned char); + byte_array_t *a = (byte_array_t *)lua_newuserdata(L, nbytes); + a->data = &((char *)a)[sizeof(byte_array_t)]; + luaL_getmetatable(L, BYTEARRAY); + lua_setmetatable(L, -2); + a->size = n; } -void lua_new_light_byte_array(lua_State*L, int n, char* ptr) +void lua_new_light_byte_array(lua_State *L, int n, char *ptr) { - size_t nbytes = sizeof(byte_array_t); - byte_array_t *a = (byte_array_t *)lua_newuserdata(L, nbytes); - a->size = n; - a->data = ptr; - luaL_getmetatable(L, BYTEARRAY); - lua_setmetatable(L, -2); + size_t nbytes = sizeof(byte_array_t); + byte_array_t *a = (byte_array_t *)lua_newuserdata(L, nbytes); + a->size = n; + a->data = ptr; + luaL_getmetatable(L, BYTEARRAY); + lua_setmetatable(L, -2); } -static int l_new_barray (lua_State *L) { - int n = luaL_checknumber(L, 1); - lua_new_byte_array(L,n); - return 1; /* new userdatum is already on the stack */ +static int l_new_barray(lua_State *L) +{ + int n = luaL_checknumber(L, 1); + lua_new_byte_array(L, n); + return 1; /* new userdatum is already on the stack */ } -static int l_new_lightbarray (lua_State *L) { - unsigned char * ptr = lua_touserdata(L,1); - int n = luaL_checknumber(L, 2); - lua_new_light_byte_array(L,n, ptr); - return 1; /* new userdatum is already on the stack */ +static int l_new_lightbarray(lua_State *L) +{ + unsigned char *ptr = lua_touserdata(L, 1); + int n = luaL_checknumber(L, 2); + lua_new_light_byte_array(L, n, ptr); + return 1; /* new userdatum is already on the stack */ } -byte_array_t *l_check_barray (lua_State *L,int idx) { - void *ud = luaL_checkudata(L, idx, BYTEARRAY); - luaL_argcheck(L, ud != NULL, idx, "`byte array' expected"); - return (byte_array_t *)ud; +byte_array_t *l_check_barray(lua_State *L, int idx) +{ + void *ud = luaL_checkudata(L, idx, BYTEARRAY); + luaL_argcheck(L, ud != NULL, idx, "`byte array' expected"); + return (byte_array_t *)ud; } -static unsigned char *get_bel(lua_State *L) { - byte_array_t *a = l_check_barray(L,1); - int index = luaL_checknumber(L, 2); - luaL_argcheck(L, 1 <= index && index <= a->size, 2, - "index out of range"); - - /* return element address */ - return &a->data[index - 1]; - } - -static int l_set_barray (lua_State *L) { - unsigned char value = luaL_checknumber(L, 3); - *get_bel(L) = value; +static unsigned char *get_bel(lua_State *L) +{ + byte_array_t *a = l_check_barray(L, 1); + int index = luaL_checknumber(L, 2); + luaL_argcheck(L, 1 <= index && index <= a->size, 2, + "index out of range"); + + /* return element address */ + return &a->data[index - 1]; +} + +static int l_set_barray(lua_State *L) +{ + unsigned char value = luaL_checknumber(L, 3); + *get_bel(L) = value; return 0; } -static int l_get_barray (lua_State *L) { - lua_pushnumber(L, *get_bel(L)); - return 1; -} - -static int l_get_barray_size (lua_State *L) { - byte_array_t *a = l_check_barray(L,1); - lua_pushnumber(L, a->size); - return 1; -} - -static int l_barray_to_string (lua_State *L) { - byte_array_t *a = l_check_barray(L,1); - char * d = (char*) malloc(a->size+1); - memcpy(d, a->data, a->size); - d[a->size] = '\0'; - lua_pushstring(L, d); - if(d) - free(d); - return 1; -} - -static int l_barray_write(lua_State* L) +static int l_get_barray(lua_State *L) { - byte_array_t *a = l_check_barray(L,1); - const char* f = luaL_checkstring(L,2); - FILE *fp; - fp = fopen(f,"wb"); - - if(!fp) - lua_pushboolean(L,0); - else - { - fwrite(a->data ,1, a->size ,fp); - lua_pushboolean(L,1); - fclose(fp); - } - return 1; + lua_pushnumber(L, *get_bel(L)); + return 1; +} + +static int l_get_barray_size(lua_State *L) +{ + byte_array_t *a = l_check_barray(L, 1); + lua_pushnumber(L, a->size); + return 1; +} + +static int l_barray_to_string(lua_State *L) +{ + byte_array_t *a = l_check_barray(L, 1); + char *d = (char *)malloc(a->size + 1); + memcpy(d, a->data, a->size); + d[a->size] = '\0'; + lua_pushstring(L, d); + if (d) + free(d); + return 1; +} + +static int l_barray_write(lua_State *L) +{ + byte_array_t *a = l_check_barray(L, 1); + const char *f = luaL_checkstring(L, 2); + FILE *fp; + fp = fopen(f, "wb"); + + if (!fp) + lua_pushboolean(L, 0); + else + { + fwrite(a->data, 1, a->size, fp); + lua_pushboolean(L, 1); + fclose(fp); + } + return 1; } static const struct luaL_Reg barraylib[] = { - {"unew", l_new_lightbarray}, - {"new", l_new_barray}, - {"set", l_set_barray}, - {"get", l_get_barray}, - {"size",l_get_barray_size}, - {"__tostring", l_barray_to_string}, - {"write", l_barray_write}, - {NULL, NULL} -}; + {"unew", l_new_lightbarray}, + {"new", l_new_barray}, + {"set", l_set_barray}, + {"get", l_get_barray}, + {"size", l_get_barray_size}, + {"__tostring", l_barray_to_string}, + {"write", l_barray_write}, + {NULL, NULL}}; -int luaopen_bytes (lua_State *L) { - luaL_newmetatable(L, BYTEARRAY); - luaL_newlib(L, barraylib); - lua_pushstring(L, "__index"); - lua_pushstring(L, "get"); - lua_gettable(L, 2); /* get array.get */ - lua_settable(L, 1); /* metatable.__index = array.get */ - - lua_pushstring(L, "__newindex"); - lua_pushstring(L, "set"); - lua_gettable(L, 2); /* get array.set */ - lua_settable(L, 1); - //lua_pushstring(L, "__index"); - //lua_pushvalue(L, -2); /* pushes the metatable */ - //lua_settable(L, -3); /* metatable.__index = metatable */ - //luaL_setfuncs(L, barraylib_m, 0); - //luaL_openlib(L, NULL, barraylib_m, 0); - //luaL_newlib(L, barraylib_f); +int luaopen_bytes(lua_State *L) +{ + luaL_newmetatable(L, BYTEARRAY); + luaL_newlib(L, barraylib); + lua_pushstring(L, "__index"); + lua_pushstring(L, "get"); + lua_gettable(L, 2); /* get array.get */ + lua_settable(L, 1); /* metatable.__index = array.get */ + + lua_pushstring(L, "__newindex"); + lua_pushstring(L, "set"); + lua_gettable(L, 2); /* get array.set */ + lua_settable(L, 1); + // lua_pushstring(L, "__index"); + // lua_pushvalue(L, -2); /* pushes the metatable */ + // lua_settable(L, -3); /* metatable.__index = metatable */ + // luaL_setfuncs(L, barraylib_m, 0); + // luaL_openlib(L, NULL, barraylib_m, 0); + // luaL_newlib(L, barraylib_f); return 1; } // ARRAY -void lua_new_array(lua_State*L, int n) +void lua_new_array(lua_State *L, int n) { - size_t nbytes = sizeof(array_t) + (n-1)*sizeof(double); - array_t *a = (array_t *)lua_newuserdata(L, nbytes); - luaL_getmetatable(L, ARRAY); - lua_setmetatable(L, -2); - a->size = n; + size_t nbytes = sizeof(array_t) + (n - 1) * sizeof(double); + array_t *a = (array_t *)lua_newuserdata(L, nbytes); + luaL_getmetatable(L, ARRAY); + lua_setmetatable(L, -2); + a->size = n; } -static int l_new_array (lua_State *L) { - int n = luaL_checknumber(L, 1); - lua_new_array(L,n); - return 1; /* new userdatum is already on the stack */ +static int l_new_array(lua_State *L) +{ + int n = luaL_checknumber(L, 1); + lua_new_array(L, n); + return 1; /* new userdatum is already on the stack */ } -array_t *l_check_array (lua_State *L, int idx) { - void *ud = luaL_checkudata(L, idx, ARRAY); - luaL_argcheck(L, ud != NULL, idx, "`array' expected"); - return (array_t *)ud; +array_t *l_check_array(lua_State *L, int idx) +{ + void *ud = luaL_checkudata(L, idx, ARRAY); + luaL_argcheck(L, ud != NULL, idx, "`array' expected"); + return (array_t *)ud; } -static double *get_el(lua_State *L) { - array_t *a = l_check_array(L,1); - int index = luaL_checknumber(L, 2); - luaL_argcheck(L, 1 <= index && index <= a->size, 2, - "index out of range"); - - /* return element address */ - return &a->data[index - 1]; - } - -static int l_set_array (lua_State *L) { - double value = luaL_checknumber(L, 3); - *get_el(L) = value; +static double *get_el(lua_State *L) +{ + array_t *a = l_check_array(L, 1); + int index = luaL_checknumber(L, 2); + luaL_argcheck(L, 1 <= index && index <= a->size, 2, + "index out of range"); + + /* return element address */ + return &a->data[index - 1]; +} + +static int l_set_array(lua_State *L) +{ + double value = luaL_checknumber(L, 3); + *get_el(L) = value; return 0; } -static int l_get_array (lua_State *L) { - lua_pushnumber(L, *get_el(L)); - return 1; +static int l_get_array(lua_State *L) +{ + lua_pushnumber(L, *get_el(L)); + return 1; } -static int l_get_array_size (lua_State *L) { - array_t *a = l_check_array(L,1); - lua_pushnumber(L, a->size); - return 1; +static int l_get_array_size(lua_State *L) +{ + array_t *a = l_check_array(L, 1); + lua_pushnumber(L, a->size); + return 1; } -static int l_array_to_string (lua_State *L) { - array_t *a = l_check_array(L,1); - lua_pushfstring(L, "number array(%d)", a->size); - return 1; +static int l_array_to_string(lua_State *L) +{ + array_t *a = l_check_array(L, 1); + lua_pushfstring(L, "number array(%d)", a->size); + return 1; } - -static const struct luaL_Reg arraylib [] = { - {"new", l_new_array}, - {"set", l_set_array}, - {"get", l_get_array}, - {"size",l_get_array_size}, - {"__tostring", l_array_to_string}, - {NULL, NULL} -}; -int luaopen_array (lua_State *L) { - luaL_newmetatable(L, ARRAY); - luaL_newlib(L, arraylib); - lua_pushstring(L, "__index"); - lua_pushstring(L, "get"); - lua_gettable(L, 2); /* get array.get */ - lua_settable(L, 1); /* metatable.__index = array.get */ - - lua_pushstring(L, "__newindex"); - lua_pushstring(L, "set"); - lua_gettable(L, 2); /* get array.set */ - lua_settable(L, 1); /* metatable.__newindex = array.set */ - - //lua_pushstring(L, "__index"); - //lua_pushvalue(L, -2); /* pushes the metatable */ - //lua_settable(L, -3); /* metatable.__index = metatable */ - // luaL_setfuncs(L, arraylib_m, 0); - // luaL_openlib(L, NULL, arraylib_m, 0); - // luaL_newlib(L, arraylib_f); - return 1; - } +static const struct luaL_Reg arraylib[] = { + {"new", l_new_array}, + {"set", l_set_array}, + {"get", l_get_array}, + {"size", l_get_array_size}, + {"__tostring", l_array_to_string}, + {NULL, NULL}}; +int luaopen_array(lua_State *L) +{ + luaL_newmetatable(L, ARRAY); + luaL_newlib(L, arraylib); + lua_pushstring(L, "__index"); + lua_pushstring(L, "get"); + lua_gettable(L, 2); /* get array.get */ + lua_settable(L, 1); /* metatable.__index = array.get */ + + lua_pushstring(L, "__newindex"); + lua_pushstring(L, "set"); + lua_gettable(L, 2); /* get array.set */ + lua_settable(L, 1); /* metatable.__newindex = array.set */ + + // lua_pushstring(L, "__index"); + // lua_pushvalue(L, -2); /* pushes the metatable */ + // lua_settable(L, -3); /* metatable.__index = metatable */ + // luaL_setfuncs(L, arraylib_m, 0); + // luaL_openlib(L, NULL, arraylib_m, 0); + // luaL_newlib(L, arraylib_f); + return 1; +} // int mime -static int l_mime(lua_State* L) +static int l_mime(lua_State *L) { - const char* file = luaL_checkstring(L,1); - lua_pushstring(L,mime(file)); - return 1; + const char *file = luaL_checkstring(L, 1); + lua_pushstring(L, mime(file)); + return 1; } // int mime -static int l_ext(lua_State* L) +static int l_ext(lua_State *L) { - const char* file = luaL_checkstring(L,1); - char* e = ext(file); - lua_pushstring(L,e); - if(e) - free(e); - return 1; + const char *file = luaL_checkstring(L, 1); + char *e = ext(file); + lua_pushstring(L, e); + if (e) + free(e); + return 1; } /* static int l_is_bin(lua_State* L) { - const char* file = luaL_checkstring(L,1); - lua_pushboolean(L, is_bin(file)); - return 1; + const char* file = luaL_checkstring(L,1); + lua_pushboolean(L, is_bin(file)); + return 1; }*/ -//int __ti(int,int); +// int __ti(int,int); /* static int l_ti (lua_State *L) { - void* client = lua_touserdata (L, 1); - int v = (int)luaL_checknumber(L, 2); - lua_pushnumber(L, __ti(client,v)); - return 1; + void* client = lua_touserdata (L, 1); + int v = (int)luaL_checknumber(L, 2); + lua_pushnumber(L, __ti(client,v)); + return 1; } */ -//int __t(int, const char*,...); -static int l_t (lua_State *L) { - void* client = lua_touserdata (L, 1); - const char* v = luaL_checkstring(L, 2); - lua_pushnumber(L, __t(client,v)); - return 1; /* number of results */ +// int __t(int, const char*,...); +static int l_t(lua_State *L) +{ + void *client = lua_touserdata(L, 1); + const char *v = luaL_checkstring(L, 2); + lua_pushnumber(L, __t(client, v)); + return 1; /* number of results */ } +static int l_antd_set_zlevel(lua_State* L) +{ + antd_client_t *client = (antd_client_t *)lua_touserdata(L, 1); + const char * lvl_str = luaL_checkstring(L, 2); + if(strncmp(lvl_str, "gzip", 4) == 0) + { + client->z_level = ANTD_CGZ; + return 0; + } + if(strncmp(lvl_str,"deflate", 7) == 0) + { + client->z_level = ANTD_CDEFL; + } + return 0; +} -static int l_antd_recv (lua_State *L) { - void* client = lua_touserdata (L, 1); - int len = luaL_checknumber(L,2); - if(len == 0) - { - lua_pushnil(L); - return 1; - } - if(len == 1) - { - char c = 0; - len = antd_recv(client, &c, len); - lua_pushnumber(L, c); - return 1; - } - else - { - lua_new_byte_array(L,len); - byte_array_t * arr = l_check_barray(L,-1); - len = antd_recv(client, arr->data, len); - lua_pushnumber(L,len); - return 2; /* number of results */ - } +static int l_antd_recv(lua_State *L) +{ + void *client = lua_touserdata(L, 1); + int len = 0; + if (lua_isnumber(L, 2)) + { + len = (int)luaL_checknumber(L, 2); + } + + if (len == 0) + { + char buff[BUFFLEN * 2] = {0}; + len = read_buf(client, buff, sizeof(buff)); + if (len == 0) + { + lua_pushnil(L); + } + else + { + trim(buff, '\n'); + lua_pushstring(L, buff); + } + return 1; + } + if (len == 1) + { + char c = 0; + len = antd_recv(client, &c, len); + lua_pushnumber(L, c); + return 1; + } + else + { + lua_new_byte_array(L, len); + byte_array_t *arr = l_check_barray(L, -1); + len = antd_recv(client, arr->data, len); + lua_pushnumber(L, len); + return 2; /* number of results */ + } } // TODO: add __b to LUA -//int __b(int, const unsigned char*, int); -static int l_b (lua_State *L) { - void * client = lua_touserdata(L,1); - byte_array_t * arr = l_check_barray(L,2); - lua_pushnumber(L, __b(client, arr->data,arr->size)); - return 1; +// int __b(int, const unsigned char*, int); +static int l_b(lua_State *L) +{ + void *client = lua_touserdata(L, 1); + byte_array_t *arr = l_check_barray(L, 2); + lua_pushnumber(L, __b(client, arr->data, arr->size)); + return 1; } -//int __f(int, const char*); -static int l_f (lua_State *L) { - void* client = lua_touserdata (L, 1); - const char* v = luaL_checkstring(L, 2); - lua_pushnumber(L, __f(client,v)); - return 1; +// int __f(int, const char*); +static int l_f(lua_State *L) +{ + void *client = lua_touserdata(L, 1); + const char *v = luaL_checkstring(L, 2); + lua_pushnumber(L, __f(client, v)); + return 1; } -//int __fb(int, const char*); +// int __fb(int, const char*); /*static int l_fb (lua_State *L) { - void* client = lua_touserdata (L, 1); - const char* v = luaL_checkstring(L, 2); - lua_pushnumber(L, __fb(client,v)); - return 1; + void* client = lua_touserdata (L, 1); + const char* v = luaL_checkstring(L, 2); + lua_pushnumber(L, __fb(client,v)); + return 1; }*/ -//int upload(const char*, const char*); -static int l_upload (lua_State *L) { - const char* s = luaL_checkstring(L, 1); - const char* d = luaL_checkstring(L, 2); - lua_pushnumber(L, upload(s,d)); - return 1; +// int upload(const char*, const char*); +static int l_upload(lua_State *L) +{ + const char *s = luaL_checkstring(L, 1); + const char *d = luaL_checkstring(L, 2); + lua_pushnumber(L, upload(s, d)); + return 1; } -//char* route(const char*); +// char* route(const char*); /* static int l_route (lua_State *L) { - const char* s = luaL_checkstring(L, 1); - lua_pushstring(L, route(s)); - return 1; + const char* s = luaL_checkstring(L, 1); + lua_pushstring(L, route(s)); + return 1; }*/ -//char* htdocs(const char*); +// char* htdocs(const char*); //#ifdef USE_DB -//sqldb getdb(); +// sqldb getdb(); //#endif -//void set_cookie(int,dictionary); +// void set_cookie(int,dictionary); -//void unknow(int); +// void unknow(int); /* static int l_unknow (lua_State *L) { - void* client = lua_touserdata (L, 1); - unknow(client); - return 0; + void* client = lua_touserdata (L, 1); + unknow(client); + return 0; } */ static int l_log(lua_State *L) { - const char* s = luaL_checkstring(L,1); - syslog (LOG_NOTICE, "%s", s); - return 0; + const char *s = luaL_checkstring(L, 1); + syslog(LOG_NOTICE, "%s", s); + return 0; } dictionary_t iterate_lua_table(lua_State *L, int index) @@ -349,7 +398,7 @@ dictionary_t iterate_lua_table(lua_State *L, int index) // Push another reference to the table on top of the stack (so we know // where it is, and this function can work for negative, positive and // pseudo indices - dictionary_t dic = dict(); + dictionary_t dic = dict(); lua_pushvalue(L, index); // stack now contains: -1 => table lua_pushnil(L); @@ -361,21 +410,21 @@ dictionary_t iterate_lua_table(lua_State *L, int index) lua_pushvalue(L, -2); // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table const char *key = lua_tostring(L, -1); - if(lua_istable(L,-2)) + if (lua_istable(L, -2)) { - // the element is a table - // create new dictionary - dictionary_t cdic = iterate_lua_table(L,-2); - dput(dic,key, cdic); - } - else - { - // other value is converted to string - const char *value = lua_tostring(L, -2); - //LOG("%s=%s\n", key, value); - dput(dic,key, strdup(value)); - } - + // the element is a table + // create new dictionary + dictionary_t cdic = iterate_lua_table(L, -2); + dput(dic, key, cdic); + } + else + { + // other value is converted to string + const char *value = lua_tostring(L, -2); + // LOG("%s=%s\n", key, value); + dput(dic, key, strdup(value)); + } + // pop value + copy of key, leaving original key lua_pop(L, 2); // stack now contains: -1 => key; -2 => table @@ -385,398 +434,393 @@ dictionary_t iterate_lua_table(lua_State *L, int index) // Pop table lua_pop(L, 1); // Stack is now the same as it was on entry to this function - return dic; + return dic; } /* static int l_set_cookie(lua_State* L) { - if (lua_istable(L, 3)) - { - dictionary_t d = iterate_lua_table(L,-2); - if(d) - { - void* client = lua_touserdata (L, 1); - const char* type = luaL_checkstring(L,2); - const char* path = luaL_checkstring(L,4); - set_cookie(client, type,d,path); - freedict(d); - } - } - return 0; + if (lua_istable(L, 3)) + { + dictionary_t d = iterate_lua_table(L,-2); + if(d) + { + void* client = lua_touserdata (L, 1); + const char* type = luaL_checkstring(L,2); + const char* path = luaL_checkstring(L,4); + set_cookie(client, type,d,path); + freedict(d); + } + } + return 0; }*/ -static int l_simple_hash(lua_State* L) +static int l_simple_hash(lua_State *L) { - const char* s = luaL_checkstring(L,1); - lua_pushnumber(L, simple_hash(s)); - return 1; + const char *s = luaL_checkstring(L, 1); + lua_pushnumber(L, simple_hash(s)); + return 1; } -static int l_md5(lua_State* L) +static int l_md5(lua_State *L) { - const char* s = luaL_checkstring(L,1); - int len = strlen(s); - char buff[256]; - md5((uint8_t*)s,len,buff); - lua_pushstring(L,buff); - return 1; + const char *s = luaL_checkstring(L, 1); + int len = strlen(s); + char buff[256]; + md5((uint8_t *)s, len, buff); + lua_pushstring(L, buff); + return 1; } -static int l_sha1(lua_State *L ) +static int l_sha1(lua_State *L) { - const char* s = luaL_checkstring(L,1); - char buff[80]; - sha1(s,buff); - lua_pushstring(L,buff); - return 1; + const char *s = luaL_checkstring(L, 1); + char buff[80]; + sha1(s, buff); + lua_pushstring(L, buff); + return 1; } static int l_base64_encode(lua_State *L) { - char* s; - int len; - char* dst; - byte_array_t *arr = NULL; - if(lua_isstring(L,1)) - { - s= (char*)luaL_checkstring(L,1); - len = strlen(s); - } - else - { - // this may be an bytearray - arr = l_check_barray(L,1); - s = (char*)arr->data; - len = arr->size; - } - if(len == 0) - { - lua_pushstring(L,""); - return 1; - } - dst = (char*) malloc( ((len * 4) / 3) + (len / 96) + 6 );//(((4 * len / 3) + 3) & ~3)+1 - Base64encode(dst, s,len); - lua_pushstring(L,dst); - free(dst); - return 1; + char *s; + int len; + char *dst; + byte_array_t *arr = NULL; + if (lua_isstring(L, 1)) + { + s = (char *)luaL_checkstring(L, 1); + len = strlen(s); + } + else + { + // this may be an bytearray + arr = l_check_barray(L, 1); + s = (char *)arr->data; + len = arr->size; + } + if (len == 0) + { + lua_pushstring(L, ""); + return 1; + } + dst = (char *)malloc(((len * 4) / 3) + (len / 96) + 6); //(((4 * len / 3) + 3) & ~3)+1 + Base64encode(dst, s, len); + lua_pushstring(L, dst); + free(dst); + return 1; } static int l_base64_decode(lua_State *L) { - const char* s = luaL_checkstring(L,1); - int len = Base64decode_len(s); - // decode data to a byte array - lua_new_byte_array(L,len); - byte_array_t * arr = NULL; - arr = l_check_barray(L,2); - len = Base64decode((char*)arr->data, s); - arr->size = len; - //lua_pushstring(L,dst); - //free(dst); - return 1; + const char *s = luaL_checkstring(L, 1); + int len = Base64decode_len(s); + // decode data to a byte array + lua_new_byte_array(L, len); + byte_array_t *arr = NULL; + arr = l_check_barray(L, 2); + len = Base64decode((char *)arr->data, s); + arr->size = len; + // lua_pushstring(L,dst); + // free(dst); + return 1; } /* -* web socket handle for lua -*/ + * web socket handle for lua + */ static int l_ws_read_header(lua_State *L) { - void* client = lua_touserdata (L, 1); - ws_msg_header_t * header = ws_read_header(client); - if(!header) - { - lua_pushnil(L); - return 1; - } - else - { - // create newtable - lua_newtable(L); - - lua_pushstring(L,"fin"); - lua_pushnumber(L,(int)header->fin); - lua_settable(L,-3); - - lua_pushstring(L,"opcode"); - lua_pushnumber(L,(int)header->opcode); - lua_settable(L,-3); - - lua_pushstring(L,"plen"); - lua_pushnumber(L,(int)header->plen); - lua_settable(L,-3); - - lua_pushstring(L,"mask"); - lua_pushnumber(L,(int)header->mask); - lua_settable(L,-3); - - lua_pushstring(L,"mask_key"); - lua_newtable(L); - - lua_pushnumber(L,0); - lua_pushnumber(L,(int)header->mask_key[0]); - lua_settable(L,-3); - - lua_pushnumber(L,1); - lua_pushnumber(L,(int)header->mask_key[1]); - lua_settable(L,-3); - - lua_pushnumber(L,2); - lua_pushnumber(L,(int)header->mask_key[2]); - lua_settable(L,-3); - - lua_pushnumber(L,3); - lua_pushnumber(L,(int)header->mask_key[3]); - lua_settable(L,-3); - - lua_settable(L,-3); - - free(header); - return 1; - } + void *client = lua_touserdata(L, 1); + ws_msg_header_t *header = ws_read_header(client); + if (!header) + { + lua_pushnil(L); + return 1; + } + else + { + // create newtable + lua_newtable(L); + + lua_pushstring(L, "fin"); + lua_pushnumber(L, (int)header->fin); + lua_settable(L, -3); + + lua_pushstring(L, "opcode"); + lua_pushnumber(L, (int)header->opcode); + lua_settable(L, -3); + + lua_pushstring(L, "plen"); + lua_pushnumber(L, (int)header->plen); + lua_settable(L, -3); + + lua_pushstring(L, "mask"); + lua_pushnumber(L, (int)header->mask); + lua_settable(L, -3); + + lua_pushstring(L, "mask_key"); + lua_newtable(L); + + lua_pushnumber(L, 0); + lua_pushnumber(L, (int)header->mask_key[0]); + lua_settable(L, -3); + + lua_pushnumber(L, 1); + lua_pushnumber(L, (int)header->mask_key[1]); + lua_settable(L, -3); + + lua_pushnumber(L, 2); + lua_pushnumber(L, (int)header->mask_key[2]); + lua_settable(L, -3); + + lua_pushnumber(L, 3); + lua_pushnumber(L, (int)header->mask_key[3]); + lua_settable(L, -3); + + lua_settable(L, -3); + + free(header); + return 1; + } } /* * Read socket data given the header */ - static int l_ws_read_data(lua_State *L) - { - void* client = lua_touserdata (L, 1); - if(!lua_istable(L,2)) - { - ws_close(client,1011); - lua_pushnil(L); - return 1; - } - dictionary_t dic = iterate_lua_table(L,2); - if(dic) - { - // convert dictionary to header - ws_msg_header_t * header = (ws_msg_header_t*) malloc(sizeof(*header)); - header->fin = (uint8_t)(R_INT(dic,"fin")); - header->opcode = (uint8_t)(R_INT(dic,"opcode")); - header->mask = 1; - header->plen = R_INT(dic,"plen"); - dictionary_t d1 = (dictionary_t)dvalue(dic,"mask_key"); - if(d1) - { - header->mask_key[0] = (uint8_t)(R_INT(d1,"0")); - header->mask_key[1] = (uint8_t)(R_INT(d1,"1")); - header->mask_key[2] = (uint8_t)(R_INT(d1,"2")); - header->mask_key[3] = (uint8_t)(R_INT(d1,"3")); - freedict(d1); - dput(dic,"mask_key", NULL); - } - freedict(dic); - - // read data - // This return max 1024 bytes data, - //user should handle consecutive read - // by examining the header (FIN bit and plen) - uint8_t* data = (uint8_t*) malloc(header->plen+1); - int size = ws_read_data(client, header, header->plen, data); - if(size < 0) - { - lua_pushnil(L); - free(header); - if(data) free(data); - return 1; - } - - if(header->opcode == WS_TEXT) - { - data[size] = '\0'; - lua_pushstring(L, (char*)data); - } - else - { - // binary data as byte array - // this is not an optimal way to store byte array - // TODO: we may need a dedicated byte array type - // for it - lua_new_byte_array(L,size); - byte_array_t * arr = NULL; - arr = l_check_barray(L,3); - memcpy(arr->data,data,size); - /*lua_newtable(L); - for (int i = 0; i < size; i++) - { - lua_pushnumber(L,i); - lua_pushnumber(L,(int)(data[i])); - lua_settable(L,-3); - }*/ - - } - if(data) - free(data); - free(header); - } - else - { - lua_pushnil(L); - } - return 1; - } - /* - * Send a text to web socket - */ -static int l_ws_t(lua_State*L) +static int l_ws_read_data(lua_State *L) { - void* client = lua_touserdata (L, 1); - char* str = (char*)luaL_checkstring(L,2); - ws_t(client,str); - return 1; + void *client = lua_touserdata(L, 1); + if (!lua_istable(L, 2)) + { + ws_close(client, 1011); + lua_pushnil(L); + return 1; + } + dictionary_t dic = iterate_lua_table(L, 2); + if (dic) + { + // convert dictionary to header + ws_msg_header_t *header = (ws_msg_header_t *)malloc(sizeof(*header)); + header->fin = (uint8_t)(R_INT(dic, "fin")); + header->opcode = (uint8_t)(R_INT(dic, "opcode")); + header->mask = 1; + header->plen = R_INT(dic, "plen"); + dictionary_t d1 = (dictionary_t)dvalue(dic, "mask_key"); + if (d1) + { + header->mask_key[0] = (uint8_t)(R_INT(d1, "0")); + header->mask_key[1] = (uint8_t)(R_INT(d1, "1")); + header->mask_key[2] = (uint8_t)(R_INT(d1, "2")); + header->mask_key[3] = (uint8_t)(R_INT(d1, "3")); + freedict(d1); + dput(dic, "mask_key", NULL); + } + freedict(dic); + + // read data + // This return max 1024 bytes data, + // user should handle consecutive read + // by examining the header (FIN bit and plen) + uint8_t *data = (uint8_t *)malloc(header->plen + 1); + int size = ws_read_data(client, header, header->plen, data); + if (size < 0) + { + lua_pushnil(L); + free(header); + if (data) + free(data); + return 1; + } + + if (header->opcode == WS_TEXT) + { + data[size] = '\0'; + lua_pushstring(L, (char *)data); + } + else + { + // binary data as byte array + // this is not an optimal way to store byte array + // TODO: we may need a dedicated byte array type + // for it + lua_new_byte_array(L, size); + byte_array_t *arr = NULL; + arr = l_check_barray(L, 3); + memcpy(arr->data, data, size); + /*lua_newtable(L); + for (int i = 0; i < size; i++) + { + lua_pushnumber(L,i); + lua_pushnumber(L,(int)(data[i])); + lua_settable(L,-3); + }*/ + } + if (data) + free(data); + free(header); + } + else + { + lua_pushnil(L); + } + return 1; +} +/* + * Send a text to web socket + */ +static int l_ws_t(lua_State *L) +{ + void *client = lua_touserdata(L, 1); + char *str = (char *)luaL_checkstring(L, 2); + ws_t(client, str); + return 1; } /*static int l_status(lua_State*L) { - void* client = lua_touserdata (L, 1); - int code = (int) luaL_checknumber(L,2); - const char* msg = luaL_checkstring(L,3); - set_status(client,code,msg); - return 1; + void* client = lua_touserdata (L, 1); + int code = (int) luaL_checknumber(L,2); + const char* msg = luaL_checkstring(L,3); + set_status(client,code,msg); + return 1; }*/ /* * send a file as binary data */ - static int l_ws_f(lua_State*L) - { - void* client = lua_touserdata (L, 1); - char* str = (char*)luaL_checkstring(L,2); - ws_f(client,str); - return 1; - } - static int l_ws_bin(lua_State*L) - { - byte_array_t * arr = NULL; - void* client = lua_touserdata (L, 1); - arr = l_check_barray(L,2); - ws_b(client, arr->data, arr->size); - return 1; - } - static int l_ws_close(lua_State *L) - { - void* client = lua_touserdata (L, 1); - int status = (int) luaL_checknumber(L,2); - ws_close(client,status); - return 1; - } - - static int l_trim(lua_State* L) - { - char* str = strdup((char*)luaL_checkstring(L,1)); - const char* tok = luaL_checkstring(L,2); - - trim(str,tok[0]); - lua_pushstring(L,(const char*)str); - free(str); - return 1; - } - - static int l_is_dir(lua_State* L) - { - const char* file = (char*)luaL_checkstring(L,1); - lua_pushboolean(L,is_dir(file) == 1); - return 1; - } - -static int l_std_error(lua_State* L) +static int l_ws_f(lua_State *L) { - void* client = lua_touserdata (L, 1); - int status = luaL_checknumber(L,2); - const char* msg = luaL_checkstring(L,3); - antd_error(client, status, msg); - return 1; + void *client = lua_touserdata(L, 1); + char *str = (char *)luaL_checkstring(L, 2); + ws_f(client, str); + return 1; } -static int l_send_header(lua_State* L) +static int l_ws_bin(lua_State *L) { - if (lua_istable(L, 3)) - { - dictionary_t d = iterate_lua_table(L,-2); - if(d) - { - void* client = lua_touserdata (L, 1); - int status = luaL_checknumber(L,2); - antd_response_header_t h; - h.status = status; - h.header = d; - dictionary_t c = iterate_lua_table(L,-1); - h.cookie = NULL; - if(c) - { - h.cookie = list_init(); - if(h.cookie) - { - chain_t it; - for_each_assoc(it,c) - { - list_put_ptr(&h.cookie,strdup(it->value)); - } - } - freedict(c); - } - antd_send_header(client, &h); - } - } - return 1; + byte_array_t *arr = NULL; + void *client = lua_touserdata(L, 1); + arr = l_check_barray(L, 2); + ws_b(client, arr->data, arr->size); + return 1; +} +static int l_ws_close(lua_State *L) +{ + void *client = lua_touserdata(L, 1); + int status = (int)luaL_checknumber(L, 2); + ws_close(client, status); + return 1; } -static const struct luaL_Reg standard [] = { - //{"_header", l_header}, - //{"_redirect", l_redirect}, - //{"_html", l_html}, - //{"_text", l_text}, - //{"_json", l_json}, - //{"_jpeg", l_jpeg}, - {"antd_recv", l_antd_recv}, - {"_error", l_std_error}, - {"_send_header", l_send_header}, - {"b64encode", l_base64_encode}, - {"b64decode", l_base64_decode}, - //{"_octstream", l_octstream} , - //{"_textstream", l_textstream} , - //{"_ti", l_ti} , - {"_t", l_t} , - {"_f", l_f} , - {"_b", l_b} , - {"trim", l_trim}, - {"upload", l_upload} , - //{"route", l_route} , - {"mime", l_mime} , - //{"is_bin", l_is_bin} , - //{"_unknow", l_unknow} , - //{"_status", l_status}, - {"console", l_log} , - //{"_setCookie", l_set_cookie}, - {"hash",l_simple_hash}, - {"md5",l_md5}, - {"sha1",l_sha1}, - {"ext",l_ext}, - {"ws_header",l_ws_read_header}, - {"ws_read",l_ws_read_data}, - {"ws_f",l_ws_f}, - {"ws_t", l_ws_t}, - {"ws_b", l_ws_bin}, - {"ws_close", l_ws_close}, - {"is_dir", l_is_dir}, - {NULL,NULL} -}; +static int l_trim(lua_State *L) +{ + char *str = strdup((char *)luaL_checkstring(L, 1)); + const char *tok = luaL_checkstring(L, 2); + trim(str, tok[0]); + lua_pushstring(L, (const char *)str); + free(str); + return 1; +} +static int l_is_dir(lua_State *L) +{ + const char *file = (char *)luaL_checkstring(L, 1); + lua_pushboolean(L, is_dir(file) == 1); + return 1; +} + +static int l_std_error(lua_State *L) +{ + void *client = lua_touserdata(L, 1); + int status = luaL_checknumber(L, 2); + const char *msg = luaL_checkstring(L, 3); + antd_error(client, status, msg); + return 1; +} +static int l_send_header(lua_State *L) +{ + if (lua_istable(L, 3)) + { + dictionary_t d = iterate_lua_table(L, -2); + if (d) + { + void *client = lua_touserdata(L, 1); + int status = luaL_checknumber(L, 2); + antd_response_header_t h; + h.status = status; + h.header = d; + dictionary_t c = iterate_lua_table(L, -1); + h.cookie = NULL; + if (c) + { + h.cookie = list_init(); + if (h.cookie) + { + chain_t it; + for_each_assoc(it, c) + { + list_put_ptr(&h.cookie, strdup(it->value)); + } + } + freedict(c); + } + antd_send_header(client, &h); + } + } + return 1; +} + +static const struct luaL_Reg standard[] = { + //{"_header", l_header}, + //{"_redirect", l_redirect}, + //{"_html", l_html}, + //{"_text", l_text}, + //{"_json", l_json}, + //{"_jpeg", l_jpeg}, + {"antd_set_zlevel", l_antd_set_zlevel}, + {"antd_recv", l_antd_recv}, + {"_error", l_std_error}, + {"_send_header", l_send_header}, + {"b64encode", l_base64_encode}, + {"b64decode", l_base64_decode}, + //{"_octstream", l_octstream} , + //{"_textstream", l_textstream} , + //{"_ti", l_ti} , + {"_t", l_t}, + {"_f", l_f}, + {"_b", l_b}, + {"trim", l_trim}, + {"upload", l_upload}, + //{"route", l_route} , + {"mime", l_mime}, + //{"is_bin", l_is_bin} , + //{"_unknow", l_unknow} , + //{"_status", l_status}, + {"console", l_log}, + //{"_setCookie", l_set_cookie}, + {"hash", l_simple_hash}, + {"md5", l_md5}, + {"sha1", l_sha1}, + {"ext", l_ext}, + {"ws_header", l_ws_read_header}, + {"ws_read", l_ws_read_data}, + {"ws_f", l_ws_f}, + {"ws_t", l_ws_t}, + {"ws_b", l_ws_bin}, + {"ws_close", l_ws_close}, + {"is_dir", l_is_dir}, + {NULL, NULL}}; int luaopen_std(lua_State *L) { - luaL_newlib(L, standard); - return 1; + luaL_newlib(L, standard); + return 1; } -static const struct luaL_Reg modules [] = { - {"bytes",luaopen_bytes}, - {"array",luaopen_array}, - {"std", luaopen_std}, - {NULL,NULL} -}; - - +static const struct luaL_Reg modules[] = { + {"bytes", luaopen_bytes}, + {"array", luaopen_array}, + {"std", luaopen_std}, + {NULL, NULL}}; int luaopen_antd(lua_State *L) { - luaL_newlib(L, modules); - lua_setglobal(L, "modules"); + luaL_newlib(L, modules); + lua_setglobal(L, "modules"); return 1; } diff --git a/lib/asl/handle.c b/lib/asl/handle.c index e0bfdd9..dcdfcd2 100644 --- a/lib/asl/handle.c +++ b/lib/asl/handle.c @@ -1,6 +1,4 @@ #include -#include -#include /* See NOTES */ #include #include #include @@ -8,105 +6,100 @@ #include #include #include +#include +#include #include "../lualib.h" typedef struct { - plugin_header_t* __plugin__; - int fd; + plugin_header_t* __plugin__; + int fd; } lua_thread_data_t; void* lua_handle(void* ptr) { - lua_thread_data_t* data = (lua_thread_data_t**)ptr; - lua_State* L = NULL; - antd_client_t cl = {0}; - cl.sock = data->fd; - time(&cl.last_io); - cl.ssl = NULL; - cl.state = ANTD_CLIENT_PLUGIN_EXEC; - cl.z_status = 0; - cl.z_level = ANTD_CNONE; - cl.zstream = NULL; - //char * index = __s("%s/%s",__plugin__->htdocs,"router.lua"); - char* cnf = __s("%s%s%s", data->__plugin__->pdir,DIR_SEP, data->__plugin__->name); - char * apis = __s("%s/%s",cnf,"api.lua"); - L = luaL_newstate(); - luaL_openlibs(L); - //module loader - //luaL_newlib(L, modules); - //lua_setglobal(L, "modules"); - // set up global variable - // API header - lua_newtable(L); - lua_pushstring(L,"name"); - lua_pushstring(L, data->__plugin__->name); - lua_settable(L,-3); - - //lua_pushstring(L,"root"); - //htdocs(rq, buf); - //lua_pushstring(L, data->__plugin__->htdocs); - //lua_settable(L,-3); - - lua_pushstring(L,"apiroot"); - lua_pushstring(L, cnf); - lua_settable(L,-3); + lua_thread_data_t* data = (lua_thread_data_t*)ptr; + lua_State* L = NULL; + antd_client_t* cl = (antd_client_t*) malloc(sizeof(antd_client_t)); + cl->sock = data->fd; + time(&cl->last_io); + cl->ssl = NULL; + cl->state = ANTD_CLIENT_PLUGIN_EXEC; + cl->z_status = 0; + cl->z_level = ANTD_CNONE; + cl->zstream = NULL; + //char * index = __s("%s/%s",__plugin__->htdocs,"router.lua"); + char* cnf = __s("%s%s%s", data->__plugin__->pdir,DIR_SEP, data->__plugin__->name); + char * apis = __s("%s/%s",cnf,"api.lua"); + L = luaL_newstate(); + luaL_openlibs(L); + //module loader + //luaL_newlib(L, modules); + //lua_setglobal(L, "modules"); + // set up global variable + // API header + lua_newtable(L); + lua_pushstring(L,"name"); + lua_pushstring(L, data->__plugin__->name); + lua_settable(L,-3); + + //lua_pushstring(L,"root"); + //htdocs(rq, buf); + //lua_pushstring(L, data->__plugin__->htdocs); + //lua_settable(L,-3); + + lua_pushstring(L,"apiroot"); + lua_pushstring(L, cnf); + lua_settable(L,-3); - lua_pushstring(L,"tmpdir"); - lua_pushstring(L, data->__plugin__->tmpdir); - lua_settable(L,-3); + lua_pushstring(L,"tmpdir"); + lua_pushstring(L, data->__plugin__->tmpdir); + lua_settable(L,-3); - lua_pushstring(L,"dbpath"); - lua_pushstring(L, data->__plugin__->dbpath); - lua_settable(L,-3); - - lua_setglobal(L, "__api__"); - - // Request - lua_newtable(L); - lua_pushstring(L,"id"); - lua_pushlightuserdata(L, &cl); - //lua_pushnumber(L,client); - lua_settable(L, -3); + lua_pushstring(L,"dbpath"); + lua_pushstring(L, data->__plugin__->dbpath); + lua_settable(L,-3); + + lua_setglobal(L, "__api__"); + + // Request + lua_newtable(L); + lua_pushstring(L,"id"); + lua_pushlightuserdata(L, cl); + //lua_pushnumber(L,client); + lua_settable(L, -3); - lua_pushstring(L,"socket"); - lua_pushnumber(L, cl.sock); - //lua_pushnumber(L,client); - lua_settable(L, -3); + lua_pushstring(L,"socket"); + lua_pushnumber(L, cl->sock); + //lua_pushnumber(L,client); + lua_settable(L, -3); - int flag = 1; - - if (setsockopt(cl.sock, IPPROTO_TCP, TCP_NODELAY, &(int){1}, sizeof(int)) == -1) - { - ERROR("Unable to set TCP_NODELAY on %d - setsockopt: %s", cl.sock, strerror(errno)); - } - //lua_pushstring(L,"request"); - //push_dict_to_lua(L,rq->request); - //lua_settable(L, -3); - lua_setglobal(L, "HTTP_REQUEST"); - free(ptr); - // load major apis - if(is_file(apis)) - if (luaL_loadfile(L, apis) || lua_pcall(L, 0, 0, 0)) - { - ERROR( "cannot start API file: [%s] %s\n", apis, lua_tostring(L, -1)); - antd_error(&cl, 503, "Internal server error"); - } - - /*if (luaL_loadfile(L, index) || lua_pcall(L, 0, 0, 0)) - { - text(client); - __t(client, "Cannot run router: %s", lua_tostring(L, -1)); - } - free(index);*/ - LOG("LUA handle exit on %d", cl.sock); - // clear request - if(L) - lua_close(L); - if(cnf) - free(cnf); - if(apis) - free(apis); - (void) close(cl.sock); - return 0; - //lua_close(L); + //lua_pushstring(L,"request"); + //push_dict_to_lua(L,rq->request); + //lua_settable(L, -3); + lua_setglobal(L, "HTTP_REQUEST"); + free(ptr); + // load major apis + if(is_file(apis)) + if (luaL_loadfile(L, apis) || lua_pcall(L, 0, 0, 0)) + { + ERROR("cannot start API file: [%s] %s\n", apis, lua_tostring(L, -1)); + } + + /*if (luaL_loadfile(L, index) || lua_pcall(L, 0, 0, 0)) + { + text(client); + __t(client, "Cannot run router: %s", lua_tostring(L, -1)); + } + free(index);*/ + LOG("LUA handle exit on %d", cl->sock); + // clear request + if(L) + lua_close(L); + if(cnf) + free(cnf); + if(apis) + free(apis); + (void) antd_close(cl); + return 0; + //lua_close(L); } diff --git a/lua-api.c b/lua-api.c index c11c085..48f5851 100644 --- a/lua-api.c +++ b/lua-api.c @@ -30,19 +30,18 @@ #define PROCESS_TIMEOUT 200u //100ms typedef struct { - plugin_header_t* __plugin__; - int fd; + plugin_header_t* __plugin__; + int fd; } lua_thread_data_t; static pid_t pid = 0; +static char sock_path[108]; static int open_unix_socket() { struct sockaddr_un address; address.sun_family = AF_UNIX; - char path[sizeof(address.sun_path)]; - (void)snprintf(path, sizeof(address.sun_path), "%s/%s", __plugin__.tmpdir, SOCKET_NAME); - (void) strncpy(address.sun_path, path, sizeof(address.sun_path)); + (void) strncpy(address.sun_path, sock_path, sizeof(address.sun_path)); int fd = socket(AF_UNIX, SOCK_STREAM, 0); if(fd == -1) { @@ -54,20 +53,16 @@ static int open_unix_socket() ERROR( "Unable to connect to socket '%s': %s", address.sun_path, strerror(errno)); return -1; } - LOG( "Socket %s is created successfully", path); + LOG( "Socket %s is created successfully", sock_path); return fd; } static int mk_socket() { struct sockaddr_un address; - char path[sizeof(address.sun_path)]; - (void)snprintf(path, sizeof(address.sun_path), "%s/%s", __plugin__.tmpdir, SOCKET_NAME); address.sun_family = AF_UNIX; // create the socket - (void)snprintf(path, sizeof(address.sun_path), "%s/%s", __plugin__.tmpdir, SOCKET_NAME); - - (void)strncpy(address.sun_path, path, sizeof(address.sun_path)); + (void)strncpy(address.sun_path, sock_path, sizeof(address.sun_path)); int fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd == -1) { @@ -82,231 +77,247 @@ static int mk_socket() // mark the socket as passive mode if (listen(fd, 500) == -1) { - ERROR("Unable to listen to socket: %d (%s): %s", fd, path, strerror(errno)); + ERROR("Unable to listen to socket: %d (%s): %s", fd, sock_path, strerror(errno)); return -1; } - LOG("Socket %s is created successfully: %d", path, fd); + LOG("Socket %s is created successfully: %d", sock_path, fd); return fd; } static void lua_serve() { - void* core = NULL; - void* lua_handle = NULL; - void *(*handle_fn)(void*); - char path[BUFFLEN]; - char* error; - (void)snprintf(path, BUFFLEN, "%s/lua/core.so", __plugin__.pdir); - core = dlopen(path, RTLD_NOW| RTLD_GLOBAL); - if(!core) - { - ERROR("Cannot load Lua core: %s", dlerror()); - return; - } - LOG("Lua core loaded"); - // now load the handle - (void)snprintf(path, BUFFLEN, "%s/lua/handle.so", __plugin__.pdir); - lua_handle = dlopen(path, RTLD_LAZY); - if(!lua_handle) - { - ERROR("Cannot load lua_handle: %s", dlerror()); - return; - } - // find the fn - handle_fn = (void *(*)(void*))dlsym(lua_handle, LUA_HDL_FN); - if ((error = dlerror()) != NULL) - { - ERROR("Problem when finding %s method from handle : %s", LUA_HDL_FN, error); - handle_fn = NULL; - return; - } - int socket = mk_socket(); - if(socket != -1) - { - int fd; - if (setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) == -1) + void* core = NULL; + void* lua_handle = NULL; + void *(*handle_fn)(void*); + char path[BUFFLEN]; + char* error; + (void)snprintf(path, BUFFLEN, "%s/lua/core.so", __plugin__.pdir); + core = dlopen(path, RTLD_NOW| RTLD_GLOBAL); + if(!core) + { + ERROR("Cannot load Lua core: %s", dlerror()); + return; + } + // now load the handle + (void)snprintf(path, BUFFLEN, "%s/lua/handle.so", __plugin__.pdir); + lua_handle = dlopen(path, RTLD_LAZY); + if(!lua_handle) + { + ERROR("Cannot load lua_handle: %s", dlerror()); + return; + } + // find the fn + handle_fn = (void *(*)(void*))dlsym(lua_handle, LUA_HDL_FN); + if ((error = dlerror()) != NULL) + { + ERROR("Problem when finding %s method from handle : %s", LUA_HDL_FN, error); + handle_fn = NULL; + return; + } + int socket = mk_socket(); + if(socket != -1) + { + int fd; + if (setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) == -1) + { + ERROR("Unable to set reuse address on %d - setsockopt: %s", socket, strerror(errno)); + } + LOG("LUA server online"); + /*set log level*/ + const char * enable_debug = getenv("ANTD_DEBUG"); + int log_level = LOG_ERR; + if(enable_debug) { - ERROR("Unable to set reuse address on %d - setsockopt: %s", socket, strerror(errno)); + if(atoi(enable_debug)) + { + LOG("LUA Debug is enabled"); + log_level = LOG_NOTICE; + } } - while((fd = accept(socket, NULL, NULL)) > 0) - { - pthread_t thread; - lua_thread_data_t* data = (lua_thread_data_t*)malloc(sizeof(lua_thread_data_t)); - data->__plugin__ = &__plugin__; - data->fd = fd; - set_nonblock(fd); - if (pthread_create(&thread, NULL, (void *(*)(void*))handle_fn, (void *)data) != 0) - { - ERROR("pthread_create: cannot create lua thread: %s", strerror(errno)); - (void)close(fd); - } - else - { - LOG("Serve thread created for %d", fd); - pthread_detach(thread); - } + setlogmask(LOG_UPTO(log_level)); + while((fd = accept(socket, NULL, NULL)) > 0) + { + pthread_t thread; + lua_thread_data_t* data = (lua_thread_data_t*)malloc(sizeof(lua_thread_data_t)); + data->__plugin__ = &__plugin__; + data->fd = fd; + set_nonblock(fd); + if (pthread_create(&thread, NULL, (void *(*)(void*))handle_fn, (void *)data) != 0) + { + ERROR("pthread_create: cannot create lua thread: %s", strerror(errno)); + (void)close(fd); + } + else + { + LOG("Serve thread created for %d", fd); + pthread_detach(thread); + } - } - if (fd < 0) - { - ERROR("Unable to accept the new connection: %s", strerror(errno)); - } - } - if(core) - (void)dlclose(core); - if(lua_handle) - (void)dlclose(lua_handle); - LOG("lua_serve: stop serve due to error"); + } + if (fd < 0) + { + ERROR("Unable to accept the new connection: %s", strerror(errno)); + } + } + if(core) + (void)dlclose(core); + if(lua_handle) + (void)dlclose(lua_handle); + LOG("lua_serve: stop serve due to error"); } void init() { - use_raw_body(); - pid = fork(); - if (pid == 0) + (void)snprintf(sock_path, sizeof(sock_path), "%s/%s", __plugin__.tmpdir, SOCKET_NAME); + LOG("Lua socket will be stored in %s", sock_path); + pid = fork(); + if (pid == 0) { - // child - lua_serve(); - } - // parent - LOG("Lua module initialized"); + // child + lua_serve(); + } + LOG("Lua module initialized"); } static void push_dict_to_socket(antd_client_t* cl, char* name, char* parent_name, dictionary_t d) { - antd_send(cl,name, strlen(name)); - antd_send(cl,"\n", 1); - chain_t as; - if(d) - for_each_assoc(as, d) - { - if(EQU(as->key,"COOKIE") || EQU(as->key,"REQUEST_HEADER") || EQU(as->key,"REQUEST_DATA") ) - push_dict_to_socket(cl, as->key, name, (dictionary_t)as->value); - else if(as->value) - { - antd_send(cl,as->key, strlen(as->key)); - antd_send(cl,"\n", 1); - antd_send(cl,as->value, strlen(as->value)); - antd_send(cl,"\n", 1); - } - } - antd_send(cl,parent_name, strlen(parent_name)); - antd_send(cl,"\n", 1); + antd_send(cl,name, strlen(name)); + antd_send(cl,"\n", 1); + chain_t as; + if(d) + for_each_assoc(as, d) + { + if(EQU(as->key,"COOKIE") || EQU(as->key,"REQUEST_HEADER") || EQU(as->key,"REQUEST_DATA") ) + push_dict_to_socket(cl, as->key, name, (dictionary_t)as->value); + else if(as->value) + { + antd_send(cl,as->key, strlen(as->key)); + antd_send(cl,"\n", 1); + antd_send(cl,as->value, strlen(as->value)); + antd_send(cl,"\n", 1); + } + } + antd_send(cl,parent_name, strlen(parent_name)); + antd_send(cl,"\n", 1); } static void *process(void *data) { - fd_set fd_in; - antd_request_t *rq = (antd_request_t *)data; - antd_client_t* cl = (antd_client_t* ) dvalue(rq->request, "LUA_CL_DATA"); - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = PROCESS_TIMEOUT; - FD_ZERO(&fd_in); - FD_SET(rq->client->sock, &fd_in); - FD_SET(cl->sock, &fd_in); - int max_fdm = rq->client->sock > cl->sock ? rq->client->sock : cl->sock; - int rc = select(max_fdm + 1, &fd_in, NULL, NULL, &timeout); - antd_task_t* task; - uint8_t buff[BUFFLEN]; - int ret; - switch (rc) - { - case -1: - ERROR("Error on select(): %s", strerror(errno)); - close(cl->sock); - return antd_create_task(NULL, data, NULL, rq->client->last_io); - case 0: - // time out - task = antd_create_task(process, (void *)rq, NULL, time(NULL)); - //antd_task_bind_event(task, rq->client->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE); - //antd_task_bind_event(task, cl->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE); - return task; - // we have data - default: - // If data is on webserver - if (FD_ISSET(rq->client->sock, &fd_in)) - { - while((ret = antd_recv_upto(rq->client,buff, BUFFLEN)) > 0) - { - LOG("Receive %d bytes from antd ", ret); - // write data to the other side - if(antd_send(cl,buff, ret) != ret) - { - ERROR("Error atnd_send(): %s", strerror(errno)); - close(cl->sock); - return antd_create_task(NULL, data, NULL, rq->client->last_io); - } - } - if(ret <= 0) - { - ERROR("Error antd_recv_upto() on %d: %s",rq->client->sock, strerror(errno)); - close(cl->sock); - return antd_create_task(NULL, data, NULL, rq->client->last_io); - } - } - else if(FD_ISSET(cl->sock, &fd_in)) - { - while((ret = antd_recv_upto(cl,buff, BUFFLEN)) > 0) - { - LOG("Receive %d bytes from LUA %d", ret, cl->sock); - // write data to the other side - if(antd_send(rq->client,buff, ret) != ret) - { - ERROR("Error atnd_send(): %s", strerror(errno)); - close(cl->sock); - return antd_create_task(NULL, data, NULL, rq->client->last_io); - } - } - if(ret < 0) - { - ERROR("Error antd_recv_upto() on %d: %s", cl->sock, strerror(errno)); - close(cl->sock); - return antd_create_task(NULL, data, NULL, rq->client->last_io); - } - } - task = antd_create_task(process, (void *)rq, NULL, time(NULL)); - antd_task_bind_event(task, rq->client->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE); - antd_task_bind_event(task, cl->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE); - return task; - } + fd_set fd_in; + antd_request_t *rq = (antd_request_t *)data; + antd_client_t* cl = (antd_client_t* ) dvalue(rq->request, "LUA_CL_DATA"); + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = PROCESS_TIMEOUT; + FD_ZERO(&fd_in); + FD_SET(rq->client->sock, &fd_in); + FD_SET(cl->sock, &fd_in); + int max_fdm = rq->client->sock > cl->sock ? rq->client->sock : cl->sock; + int rc = select(max_fdm + 1, &fd_in, NULL, NULL, &timeout); + antd_task_t* task; + uint8_t buff[BUFFLEN]; + int ret; + switch (rc) + { + case -1: + ERROR("Error on select(): %s", strerror(errno)); + antd_close(cl); + dput(rq->request, "LUA_CL_DATA", NULL); + return antd_create_task(NULL, data, NULL, rq->client->last_io); + case 0: + // time out + task = antd_create_task(process, (void *)rq, NULL, time(NULL)); + //antd_task_bind_event(task, rq->client->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE); + //antd_task_bind_event(task, cl->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE); + return task; + // we have data + default: + // If data is on webserver + if (FD_ISSET(rq->client->sock, &fd_in)) + { + while((ret = antd_recv_upto(rq->client,buff, BUFFLEN)) > 0) + { + // write data to the other side + if(antd_send(cl,buff, ret) != ret) + { + ERROR("Error on atnd_send(): %s", strerror(errno)); + antd_close(cl); + dput(rq->request, "LUA_CL_DATA", NULL); + return antd_create_task(NULL, data, NULL, rq->client->last_io); + } + } + if(ret < 0) + { + LOG("antd_recv_upto() on %d: %s",rq->client->sock, strerror(errno)); + antd_close(cl); + dput(rq->request, "LUA_CL_DATA", NULL); + return antd_create_task(NULL, data, NULL, rq->client->last_io); + } + } + else if(FD_ISSET(cl->sock, &fd_in)) + { + while((ret = antd_recv_upto(cl,buff, BUFFLEN)) > 0) + { + // write data to the other side + if(antd_send(rq->client,buff, ret) != ret) + { + ERROR("Error atnd_send(): %s", strerror(errno)); + antd_close(cl); + dput(rq->request, "LUA_CL_DATA", NULL); + return antd_create_task(NULL, data, NULL, rq->client->last_io); + } + } + if(ret < 0) + { + LOG("antd_recv_upto() on %d: %s", cl->sock, strerror(errno)); + antd_close(cl); + dput(rq->request, "LUA_CL_DATA", NULL); + return antd_create_task(NULL, data, NULL, rq->client->last_io); + } + } + task = antd_create_task(process, (void *)rq, NULL, time(NULL)); + antd_task_bind_event(task, rq->client->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE); + antd_task_bind_event(task, cl->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE); + return task; + } } void* handle(void* data) { - antd_request_t *rq = (antd_request_t *)data; - // connect to socket - int fd = open_unix_socket(); - if(fd < 0) - { - antd_error(rq->client, 503, "Service unavailable"); + antd_request_t *rq = (antd_request_t *)data; + // connect to socket + int fd = open_unix_socket(); + if(fd < 0) + { + antd_error(rq->client, 503, "Service unavailable"); return antd_create_task(NULL, data, NULL, rq->client->last_io); - } - LOG("Connected to lua server at %d", fd); - set_nonblock(fd); - // write all header to lua - antd_client_t* cl = (antd_client_t*) malloc(sizeof(antd_client_t)); - (void)memset(cl, 0, sizeof(antd_client_t)); - cl->sock = fd; - time(&cl->last_io); - cl->ssl = NULL; - cl->state = ANTD_CLIENT_PLUGIN_EXEC; - cl->z_status = 0; - cl->z_level = ANTD_CNONE; - cl->zstream = NULL; - push_dict_to_socket(cl, "request","HTTP_REQUEST", rq->request); - antd_send(cl,"\r\n", 2); - dput(rq->request, "LUA_CL_DATA", cl); - antd_task_t* task = antd_create_task(process, (void *)rq, NULL, time(NULL)); - antd_task_bind_event(task, rq->client->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE); - antd_task_bind_event(task, fd, 0, TASK_EVT_ON_READABLE); - return task; + } + LOG("Connected to lua server at %d", fd); + set_nonblock(fd); + // write all header to lua + antd_client_t* cl = (antd_client_t*) malloc(sizeof(antd_client_t)); + (void)memset(cl, 0, sizeof(antd_client_t)); + cl->sock = fd; + time(&cl->last_io); + cl->ssl = NULL; + cl->state = ANTD_CLIENT_PLUGIN_EXEC; + cl->z_status = 0; + cl->z_level = ANTD_CNONE; + cl->zstream = NULL; + rq->client->z_level = ANTD_CNONE; + push_dict_to_socket(cl, "request","HTTP_REQUEST", rq->request); + antd_send(cl,"\r\n", 2); + dput(rq->request, "LUA_CL_DATA", cl); + antd_task_t* task = antd_create_task(process, (void *)rq, NULL, time(NULL)); + antd_task_bind_event(task, rq->client->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE); + antd_task_bind_event(task, fd, 0, TASK_EVT_ON_READABLE); + return task; } void destroy() { - if(pid > 0) - { - kill(pid, SIGKILL); - } - LOG("Exit LUA Handle"); + if(pid > 0) + { + kill(pid, SIGHUP); + } + LOG("Exit LUA Handle"); }