1
0
mirror of https://github.com/lxsang/antd-lua-plugin synced 2025-04-21 13:16:44 +02:00

Compare commits

..

2 Commits

Author SHA1 Message Date
DanyLE
c7ea2af3f1 lua plugin now used a separated process to handle requests 2022-08-27 21:46:50 +02:00
DanyLE
7814611008 Use unix domain socket to process lua handlers 2022-08-27 21:46:50 +02:00
10 changed files with 1239 additions and 1488 deletions

View File

@ -1,10 +1,61 @@
package.cpath = __api__.apiroot..'/?.so'
require("antd")
std = modules.std()
local read_header =function()
local l
repeat
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 = std.antd_recv(HTTP_REQUEST.id)
if l1 ~= '\r' then
coroutine.yield(l, l1)
end
l = l1
end
end
until not l or l == '\r'
end
local read_headers = function()
local co = coroutine.create(function () read_header() end)
return function () -- iterator
local code, k, v = coroutine.resume(co)
return k,v
end
end
local parse_headers =function()
local lut = {
HTTP_REQUEST = HTTP_REQUEST
}
local curr_tbl = "HTTP_REQUEST"
for k,v in read_headers() do
if v == "LUA_TABLE" then
if not lut[k] then
lut[k] = {}
end
curr_tbl = k
else
lut[curr_tbl][k] = v
end
end
HTTP_REQUEST.request = lut.request
HTTP_REQUEST.request.COOKIE = lut.COOKIE
HTTP_REQUEST.request.REQUEST_HEADER = lut.REQUEST_HEADER
HTTP_REQUEST.request.REQUEST_DATA = lut.REQUEST_DATA
end
-- parsing the header
parse_headers()
-- root dir -- root dir
__ROOT__ = __api__.root __ROOT__ = HTTP_REQUEST.request.SERVER_WWW_ROOT
-- set require path -- set require path
package.path = __ROOT__ .. '/?.lua;'..__api__.apiroot..'/?.lua' package.path = __ROOT__ .. '/?.lua;'..__api__.apiroot..'/?.lua'
package.cpath = __api__.apiroot..'/?.so'
require("antd")
require("std") require("std")
require("utils") require("utils")
require("extra_mime") require("extra_mime")
@ -24,6 +75,14 @@ if HEADER["User-Agent"] and HEADER["User-Agent"]:match("Mobi") then
HEADER.mobile = true HEADER.mobile = true
end end
function LOG_INFO(fmt,...)
ulib.syslog(5,string.format(fmt or "LOG", table.unpack({...}) or ""))
end
function LOG_ERROR(fmt,...)
ulib.syslog(3,string.format(fmt or "ERROR", table.unpack({...}) or ""))
end
function has_module(m) function has_module(m)
if utils.file_exists(__ROOT__..'/'..m) then if utils.file_exists(__ROOT__..'/'..m) then
if m:find("%.ls$") then if m:find("%.ls$") then
@ -102,7 +161,6 @@ function loadscript(file, args)
end end
end end
pro = pro.."\""..utils.escape(tmp:gsub("%%","%%%%")).."\")\n" pro = pro.."\""..utils.escape(tmp:gsub("%%","%%%%")).."\")\n"
--print(pro)
else else
html = html..std.trim(line," "):gsub("%%","%%%%").."\n" html = html..std.trim(line," "):gsub("%%","%%%%").."\n"
end end
@ -118,12 +176,61 @@ function loadscript(file, args)
pro = pro.."echo(\""..utils.escape(html).."\")\n" pro = pro.."echo(\""..utils.escape(html).."\")\n"
end end
pro = pro.."\nend \n return fn" pro = pro.."\nend \n return fn"
--print(pro)
local r,e = load(pro) local r,e = load(pro)
if r then return r(), e else return nil,e end if r then return r(), e else return nil,e end
end end
end end
-- decode post data if any
local decode_request_data = function()
if (not REQUEST.method)
or (REQUEST.method ~= "POST"
and REQUEST.method ~= "PUT"
and REQUEST.method ~= "PATCH")
or (not REQUEST.HAS_RAW_BODY) then
return 0
end
local ctype = HEADER['Content-Type']
local clen = HEADER['Content-Length'] or -1
if clen then
clen = tonumber(clen)
end
if not ctype or clen == -1 then
LOG_ERROR("Invalid content type %s or content length %d", ctype, clen)
return 400, "Bad Request, missing content description"
end
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
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_data()
if code ~= 0 then
LOG_ERROR(error)
std.error(code, error)
return
end
-- OOP support -- OOP support
--require("OOP") --require("OOP")
-- load sqlite helper -- load sqlite helper

View File

@ -1,5 +1,5 @@
function std.extra_mime(name) function std.extra_mime(name)
local ext = std.ext(name); local ext = std.ext(name)
local mpath = __ROOT__.."/".."mimes.json" local mpath = __ROOT__.."/".."mimes.json"
local xmimes = {} local xmimes = {}
if utils.file_exists(mpath) then 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 == "cpp" or ext == "hpp" then return "text/cpp",false
elseif ext == "md" then return "text/markdown",false elseif ext == "md" then return "text/markdown",false
elseif ext == "lua" then return "text/lua",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 xmimes[ext] then return xmimes[ext].mime, xmimes[ext].binary
--elseif ext == "pgm" then return "image/x-portable-graymap", true --elseif ext == "pgm" then return "image/x-portable-graymap", true
else else

View File

@ -1,4 +1,3 @@
std = modules.std()
bytes = modules.bytes() bytes = modules.bytes()
array = modules.array() array = modules.array()
@ -62,6 +61,7 @@ function std.b(s)
end end
function std.f(v) function std.f(v)
std._f(HTTP_REQUEST.id,v) std._f(HTTP_REQUEST.id,v)
--ulib.send_file(v, HTTP_REQUEST.socket)
end end
function std.setCookie(v) function std.setCookie(v)

View File

@ -1,74 +0,0 @@
-- require the utils library to work
--require("utils")
-- require("std")
local wurl = require("wurl")
local web = {}
web.understand = function(proto)
if proto == "http" or proto == "https" then
return true
else
return false
end
end
web.get = function(url)
local obj = utils.url_parser(url)
if web.understand(obj.protocol) then
return wurl._get(obj.hostname,obj.port, obj.query)
else
return nil,"Protocol is unsupported: "..obj.protocol
end
end
web.post = function(url,data)
local obj = utils.url_parser(url)
if web.understand(obj.protocol) then
if type(data) == "string" then
return wurl._post(obj.hostname,
obj.port,
obj.query,
"application/x-www-form-urlencoded",data)
else
return wurl._post(obj.hostname,
obj.port,
obj.query,
data.contentType,data.value)
end
else
return nil,"Protocol is unsupported: "..obj.protocol
end
end
web.download = function(url,to)
local obj = utils.url_parser(url)
if web.understand(obj.protocol) then
local file
if std.is_dir(to) then
-- need to find file name here
local pattern = "^[^%?]*/([%w.]*)%??.*$"
local filename = string.gsub(obj.query,pattern,"%1")
if filename == "" then filename = "index" end
file = to.."/"..filename
else
file = to
end
local obj = utils.url_parser(url)
return wurl._download(obj.hostname,obj.port,obj.query,file)
else
return false,"Protocol is unsupported: "..obj.protocol
end
end
web.upload = function(url,name,file)
local obj = utils.url_parser(url)
if web.understand(obj.protocol) then
return wurl._upload(obj.hostname,obj.port,obj.query,name,file)
else
return nil,"Protocol is unsupported: "..obj.protocol
end
end
return web

View File

@ -19,10 +19,6 @@ json_la_LDFLAGS = -module -avoid-version -shared
json_la_SOURCES = 3rd/jsmn/jsmn.c json.c json_la_SOURCES = 3rd/jsmn/jsmn.c json.c
lib_LTLIBRARIES += wurl.la
wurl_la_LDFLAGS = -module -avoid-version -shared
wurl_la_SOURCES = wurl.c
if HAS_FFI if HAS_FFI
lib_LTLIBRARIES += ffi.la lib_LTLIBRARIES += ffi.la
ffi_la_LDFLAGS = -module -avoid-version -shared -lffi ffi_la_LDFLAGS = -module -avoid-version -shared -lffi

View File

@ -2,17 +2,17 @@
#include <antd/base64.h> #include <antd/base64.h>
#include "../lualib.h" #include "../lualib.h"
// add a length field, and // 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); size_t nbytes = sizeof(byte_array_t) + n * sizeof(unsigned char);
byte_array_t *a = (byte_array_t *)lua_newuserdata(L, nbytes); byte_array_t *a = (byte_array_t *)lua_newuserdata(L, nbytes);
a->data = &((char*)a)[sizeof(byte_array_t)]; a->data = &((char *)a)[sizeof(byte_array_t)];
luaL_getmetatable(L, BYTEARRAY); luaL_getmetatable(L, BYTEARRAY);
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
a->size = n; 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); size_t nbytes = sizeof(byte_array_t);
byte_array_t *a = (byte_array_t *)lua_newuserdata(L, nbytes); byte_array_t *a = (byte_array_t *)lua_newuserdata(L, nbytes);
@ -22,76 +22,84 @@ void lua_new_light_byte_array(lua_State*L, int n, char* ptr)
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
} }
static int l_new_barray (lua_State *L) { static int l_new_barray(lua_State *L)
{
int n = luaL_checknumber(L, 1); int n = luaL_checknumber(L, 1);
lua_new_byte_array(L,n); lua_new_byte_array(L, n);
return 1; /* new userdatum is already on the stack */ return 1; /* new userdatum is already on the stack */
} }
static int l_new_lightbarray (lua_State *L) { static int l_new_lightbarray(lua_State *L)
unsigned char * ptr = lua_touserdata(L,1); {
unsigned char *ptr = lua_touserdata(L, 1);
int n = luaL_checknumber(L, 2); int n = luaL_checknumber(L, 2);
lua_new_light_byte_array(L,n, ptr); lua_new_light_byte_array(L, n, ptr);
return 1; /* new userdatum is already on the stack */ return 1; /* new userdatum is already on the stack */
} }
byte_array_t *l_check_barray (lua_State *L,int idx) { byte_array_t *l_check_barray(lua_State *L, int idx)
{
void *ud = luaL_checkudata(L, idx, BYTEARRAY); void *ud = luaL_checkudata(L, idx, BYTEARRAY);
luaL_argcheck(L, ud != NULL, idx, "`byte array' expected"); luaL_argcheck(L, ud != NULL, idx, "`byte array' expected");
return (byte_array_t *)ud; return (byte_array_t *)ud;
} }
static unsigned char *get_bel(lua_State *L) { static unsigned char *get_bel(lua_State *L)
byte_array_t *a = l_check_barray(L,1); {
byte_array_t *a = l_check_barray(L, 1);
int index = luaL_checknumber(L, 2); int index = luaL_checknumber(L, 2);
luaL_argcheck(L, 1 <= index && index <= a->size, 2, luaL_argcheck(L, 1 <= index && index <= a->size, 2,
"index out of range"); "index out of range");
/* return element address */ /* return element address */
return &a->data[index - 1]; return &a->data[index - 1];
} }
static int l_set_barray (lua_State *L) { static int l_set_barray(lua_State *L)
{
unsigned char value = luaL_checknumber(L, 3); unsigned char value = luaL_checknumber(L, 3);
*get_bel(L) = value; *get_bel(L) = value;
return 0; return 0;
} }
static int l_get_barray (lua_State *L) { static int l_get_barray(lua_State *L)
{
lua_pushnumber(L, *get_bel(L)); lua_pushnumber(L, *get_bel(L));
return 1; return 1;
} }
static int l_get_barray_size (lua_State *L) { static int l_get_barray_size(lua_State *L)
byte_array_t *a = l_check_barray(L,1); {
byte_array_t *a = l_check_barray(L, 1);
lua_pushnumber(L, a->size); lua_pushnumber(L, a->size);
return 1; return 1;
} }
static int l_barray_to_string (lua_State *L) { 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); byte_array_t *a = l_check_barray(L, 1);
char *d = (char *)malloc(a->size + 1);
memcpy(d, a->data, a->size); memcpy(d, a->data, a->size);
d[a->size] = '\0'; d[a->size] = '\0';
lua_pushstring(L, d); lua_pushstring(L, d);
if(d) if (d)
free(d); free(d);
return 1; return 1;
} }
static int l_barray_write(lua_State* L) static int l_barray_write(lua_State *L)
{ {
byte_array_t *a = l_check_barray(L,1); byte_array_t *a = l_check_barray(L, 1);
const char* f = luaL_checkstring(L,2); const char *f = luaL_checkstring(L, 2);
FILE *fp; FILE *fp;
fp = fopen(f,"wb"); fp = fopen(f, "wb");
if(!fp) if (!fp)
lua_pushboolean(L,0); lua_pushboolean(L, 0);
else else
{ {
fwrite(a->data ,1, a->size ,fp); fwrite(a->data, 1, a->size, fp);
lua_pushboolean(L,1); lua_pushboolean(L, 1);
fclose(fp); fclose(fp);
} }
return 1; return 1;
@ -102,13 +110,13 @@ static const struct luaL_Reg barraylib[] = {
{"new", l_new_barray}, {"new", l_new_barray},
{"set", l_set_barray}, {"set", l_set_barray},
{"get", l_get_barray}, {"get", l_get_barray},
{"size",l_get_barray_size}, {"size", l_get_barray_size},
{"__tostring", l_barray_to_string}, {"__tostring", l_barray_to_string},
{"write", l_barray_write}, {"write", l_barray_write},
{NULL, NULL} {NULL, NULL}};
};
int luaopen_bytes (lua_State *L) { int luaopen_bytes(lua_State *L)
{
luaL_newmetatable(L, BYTEARRAY); luaL_newmetatable(L, BYTEARRAY);
luaL_newlib(L, barraylib); luaL_newlib(L, barraylib);
lua_pushstring(L, "__index"); lua_pushstring(L, "__index");
@ -120,77 +128,84 @@ int luaopen_bytes (lua_State *L) {
lua_pushstring(L, "set"); lua_pushstring(L, "set");
lua_gettable(L, 2); /* get array.set */ lua_gettable(L, 2); /* get array.set */
lua_settable(L, 1); lua_settable(L, 1);
//lua_pushstring(L, "__index"); // lua_pushstring(L, "__index");
//lua_pushvalue(L, -2); /* pushes the metatable */ // lua_pushvalue(L, -2); /* pushes the metatable */
//lua_settable(L, -3); /* metatable.__index = metatable */ // lua_settable(L, -3); /* metatable.__index = metatable */
//luaL_setfuncs(L, barraylib_m, 0); // luaL_setfuncs(L, barraylib_m, 0);
//luaL_openlib(L, NULL, barraylib_m, 0); // luaL_openlib(L, NULL, barraylib_m, 0);
//luaL_newlib(L, barraylib_f); // luaL_newlib(L, barraylib_f);
return 1; return 1;
} }
// ARRAY // 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); size_t nbytes = sizeof(array_t) + (n - 1) * sizeof(double);
array_t *a = (array_t *)lua_newuserdata(L, nbytes); array_t *a = (array_t *)lua_newuserdata(L, nbytes);
luaL_getmetatable(L, ARRAY); luaL_getmetatable(L, ARRAY);
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
a->size = n; a->size = n;
} }
static int l_new_array (lua_State *L) { static int l_new_array(lua_State *L)
{
int n = luaL_checknumber(L, 1); int n = luaL_checknumber(L, 1);
lua_new_array(L,n); lua_new_array(L, n);
return 1; /* new userdatum is already on the stack */ return 1; /* new userdatum is already on the stack */
} }
array_t *l_check_array (lua_State *L, int idx) { array_t *l_check_array(lua_State *L, int idx)
{
void *ud = luaL_checkudata(L, idx, ARRAY); void *ud = luaL_checkudata(L, idx, ARRAY);
luaL_argcheck(L, ud != NULL, idx, "`array' expected"); luaL_argcheck(L, ud != NULL, idx, "`array' expected");
return (array_t *)ud; return (array_t *)ud;
} }
static double *get_el(lua_State *L) { static double *get_el(lua_State *L)
array_t *a = l_check_array(L,1); {
array_t *a = l_check_array(L, 1);
int index = luaL_checknumber(L, 2); int index = luaL_checknumber(L, 2);
luaL_argcheck(L, 1 <= index && index <= a->size, 2, luaL_argcheck(L, 1 <= index && index <= a->size, 2,
"index out of range"); "index out of range");
/* return element address */ /* return element address */
return &a->data[index - 1]; return &a->data[index - 1];
} }
static int l_set_array (lua_State *L) { static int l_set_array(lua_State *L)
{
double value = luaL_checknumber(L, 3); double value = luaL_checknumber(L, 3);
*get_el(L) = value; *get_el(L) = value;
return 0; return 0;
} }
static int l_get_array (lua_State *L) { static int l_get_array(lua_State *L)
{
lua_pushnumber(L, *get_el(L)); lua_pushnumber(L, *get_el(L));
return 1; return 1;
} }
static int l_get_array_size (lua_State *L) { static int l_get_array_size(lua_State *L)
array_t *a = l_check_array(L,1); {
array_t *a = l_check_array(L, 1);
lua_pushnumber(L, a->size); lua_pushnumber(L, a->size);
return 1; return 1;
} }
static int l_array_to_string (lua_State *L) { static int l_array_to_string(lua_State *L)
array_t *a = l_check_array(L,1); {
array_t *a = l_check_array(L, 1);
lua_pushfstring(L, "number array(%d)", a->size); lua_pushfstring(L, "number array(%d)", a->size);
return 1; return 1;
} }
static const struct luaL_Reg arraylib [] = { static const struct luaL_Reg arraylib[] = {
{"new", l_new_array}, {"new", l_new_array},
{"set", l_set_array}, {"set", l_set_array},
{"get", l_get_array}, {"get", l_get_array},
{"size",l_get_array_size}, {"size", l_get_array_size},
{"__tostring", l_array_to_string}, {"__tostring", l_array_to_string},
{NULL, NULL} {NULL, NULL}};
}; int luaopen_array(lua_State *L)
int luaopen_array (lua_State *L) { {
luaL_newmetatable(L, ARRAY); luaL_newmetatable(L, ARRAY);
luaL_newlib(L, arraylib); luaL_newlib(L, arraylib);
lua_pushstring(L, "__index"); lua_pushstring(L, "__index");
@ -203,30 +218,29 @@ int luaopen_array (lua_State *L) {
lua_gettable(L, 2); /* get array.set */ lua_gettable(L, 2); /* get array.set */
lua_settable(L, 1); /* metatable.__newindex = array.set */ lua_settable(L, 1); /* metatable.__newindex = array.set */
//lua_pushstring(L, "__index"); // lua_pushstring(L, "__index");
//lua_pushvalue(L, -2); /* pushes the metatable */ // lua_pushvalue(L, -2); /* pushes the metatable */
//lua_settable(L, -3); /* metatable.__index = metatable */ // lua_settable(L, -3); /* metatable.__index = metatable */
// luaL_setfuncs(L, arraylib_m, 0); // luaL_setfuncs(L, arraylib_m, 0);
// luaL_openlib(L, NULL, arraylib_m, 0); // luaL_openlib(L, NULL, arraylib_m, 0);
// luaL_newlib(L, arraylib_f); // luaL_newlib(L, arraylib_f);
return 1; return 1;
} }
// int mime // int mime
static int l_mime(lua_State* L) static int l_mime(lua_State *L)
{ {
const char* file = luaL_checkstring(L,1); const char *file = luaL_checkstring(L, 1);
lua_pushstring(L,mime(file)); lua_pushstring(L, mime(file));
return 1; return 1;
} }
// int mime // int mime
static int l_ext(lua_State* L) static int l_ext(lua_State *L)
{ {
const char* file = luaL_checkstring(L,1); const char *file = luaL_checkstring(L, 1);
char* e = ext(file); char *e = ext(file);
lua_pushstring(L,e); lua_pushstring(L, e);
if(e) if (e)
free(e); free(e);
return 1; return 1;
} }
@ -237,7 +251,7 @@ static int l_is_bin(lua_State* L)
lua_pushboolean(L, is_bin(file)); lua_pushboolean(L, is_bin(file));
return 1; return 1;
}*/ }*/
//int __ti(int,int); // int __ti(int,int);
/* /*
static int l_ti (lua_State *L) { static int l_ti (lua_State *L) {
void* client = lua_touserdata (L, 1); void* client = lua_touserdata (L, 1);
@ -247,32 +261,92 @@ static int l_ti (lua_State *L) {
} }
*/ */
//int __t(int, const char*,...); // int __t(int, const char*,...);
static int l_t (lua_State *L) { static int l_t(lua_State *L)
void* client = lua_touserdata (L, 1); {
const char* v = luaL_checkstring(L, 2); void *client = lua_touserdata(L, 1);
lua_pushnumber(L, __t(client,v)); const char *v = luaL_checkstring(L, 2);
lua_pushnumber(L, __t(client, v));
return 1; /* number of results */ 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 = 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 // TODO: add __b to LUA
//int __b(int, const unsigned char*, int); // int __b(int, const unsigned char*, int);
static int l_b (lua_State *L) { static int l_b(lua_State *L)
void * client = lua_touserdata(L,1); {
byte_array_t * arr = l_check_barray(L,2); void *client = lua_touserdata(L, 1);
lua_pushnumber(L, __b(client, arr->data,arr->size)); byte_array_t *arr = l_check_barray(L, 2);
lua_pushnumber(L, __b(client, arr->data, arr->size));
return 1; return 1;
} }
//int __f(int, const char*); // int __f(int, const char*);
static int l_f (lua_State *L) { static int l_f(lua_State *L)
void* client = lua_touserdata (L, 1); {
const char* v = luaL_checkstring(L, 2); void *client = lua_touserdata(L, 1);
lua_pushnumber(L, __f(client,v)); const char *v = luaL_checkstring(L, 2);
lua_pushnumber(L, __f(client, v));
return 1; return 1;
} }
//int __fb(int, const char*); // int __fb(int, const char*);
/*static int l_fb (lua_State *L) { /*static int l_fb (lua_State *L) {
void* client = lua_touserdata (L, 1); void* client = lua_touserdata (L, 1);
const char* v = luaL_checkstring(L, 2); const char* v = luaL_checkstring(L, 2);
@ -280,15 +354,16 @@ static int l_f (lua_State *L) {
return 1; return 1;
}*/ }*/
//int upload(const char*, const char*); // int upload(const char*, const char*);
static int l_upload (lua_State *L) { static int l_upload(lua_State *L)
const char* s = luaL_checkstring(L, 1); {
const char* d = luaL_checkstring(L, 2); const char *s = luaL_checkstring(L, 1);
lua_pushnumber(L, upload(s,d)); const char *d = luaL_checkstring(L, 2);
lua_pushnumber(L, upload(s, d));
return 1; return 1;
} }
//char* route(const char*); // char* route(const char*);
/* /*
static int l_route (lua_State *L) { static int l_route (lua_State *L) {
const char* s = luaL_checkstring(L, 1); const char* s = luaL_checkstring(L, 1);
@ -296,13 +371,13 @@ static int l_route (lua_State *L) {
return 1; return 1;
}*/ }*/
//char* htdocs(const char*); // char* htdocs(const char*);
//#ifdef USE_DB //#ifdef USE_DB
//sqldb getdb(); // sqldb getdb();
//#endif //#endif
//void set_cookie(int,dictionary); // void set_cookie(int,dictionary);
//void unknow(int); // void unknow(int);
/* /*
static int l_unknow (lua_State *L) { static int l_unknow (lua_State *L) {
void* client = lua_touserdata (L, 1); void* client = lua_touserdata (L, 1);
@ -313,8 +388,8 @@ static int l_unknow (lua_State *L) {
static int l_log(lua_State *L) static int l_log(lua_State *L)
{ {
const char* s = luaL_checkstring(L,1); const char *s = luaL_checkstring(L, 1);
syslog (LOG_NOTICE, "%s", s); syslog(LOG_NOTICE, "%s", s);
return 0; return 0;
} }
@ -335,19 +410,19 @@ dictionary_t iterate_lua_table(lua_State *L, int index)
lua_pushvalue(L, -2); lua_pushvalue(L, -2);
// stack now contains: -1 => key; -2 => value; -3 => key; -4 => table // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table
const char *key = lua_tostring(L, -1); const char *key = lua_tostring(L, -1);
if(lua_istable(L,-2)) if (lua_istable(L, -2))
{ {
// the element is a table // the element is a table
// create new dictionary // create new dictionary
dictionary_t cdic = iterate_lua_table(L,-2); dictionary_t cdic = iterate_lua_table(L, -2);
dput(dic,key, cdic); dput(dic, key, cdic);
} }
else else
{ {
// other value is converted to string // other value is converted to string
const char *value = lua_tostring(L, -2); const char *value = lua_tostring(L, -2);
//LOG("%s=%s\n", key, value); // LOG("%s=%s\n", key, value);
dput(dic,key, strdup(value)); dput(dic, key, strdup(value));
} }
// pop value + copy of key, leaving original key // pop value + copy of key, leaving original key
@ -380,80 +455,80 @@ static int l_set_cookie(lua_State* L)
return 0; 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); const char *s = luaL_checkstring(L, 1);
lua_pushnumber(L, simple_hash(s)); lua_pushnumber(L, simple_hash(s));
return 1; return 1;
} }
static int l_md5(lua_State* L) static int l_md5(lua_State *L)
{ {
const char* s = luaL_checkstring(L,1); const char *s = luaL_checkstring(L, 1);
int len = strlen(s); int len = strlen(s);
char buff[256]; char buff[256];
md5((uint8_t*)s,len,buff); md5((uint8_t *)s, len, buff);
lua_pushstring(L,buff); lua_pushstring(L, buff);
return 1; return 1;
} }
static int l_sha1(lua_State *L ) static int l_sha1(lua_State *L)
{ {
const char* s = luaL_checkstring(L,1); const char *s = luaL_checkstring(L, 1);
char buff[80]; char buff[80];
sha1(s,buff); sha1(s, buff);
lua_pushstring(L,buff); lua_pushstring(L, buff);
return 1; return 1;
} }
static int l_base64_encode(lua_State *L) static int l_base64_encode(lua_State *L)
{ {
char* s; char *s;
int len; int len;
char* dst; char *dst;
byte_array_t *arr = NULL; byte_array_t *arr = NULL;
if(lua_isstring(L,1)) if (lua_isstring(L, 1))
{ {
s= (char*)luaL_checkstring(L,1); s = (char *)luaL_checkstring(L, 1);
len = strlen(s); len = strlen(s);
} }
else else
{ {
// this may be an bytearray // this may be an bytearray
arr = l_check_barray(L,1); arr = l_check_barray(L, 1);
s = (char*)arr->data; s = (char *)arr->data;
len = arr->size; len = arr->size;
} }
if(len == 0) if (len == 0)
{ {
lua_pushstring(L,""); lua_pushstring(L, "");
return 1; return 1;
} }
dst = (char*) malloc( ((len * 4) / 3) + (len / 96) + 6 );//(((4 * len / 3) + 3) & ~3)+1 dst = (char *)malloc(((len * 4) / 3) + (len / 96) + 6); //(((4 * len / 3) + 3) & ~3)+1
Base64encode(dst, s,len); Base64encode(dst, s, len);
lua_pushstring(L,dst); lua_pushstring(L, dst);
free(dst); free(dst);
return 1; return 1;
} }
static int l_base64_decode(lua_State *L) static int l_base64_decode(lua_State *L)
{ {
const char* s = luaL_checkstring(L,1); const char *s = luaL_checkstring(L, 1);
int len = Base64decode_len(s); int len = Base64decode_len(s);
// decode data to a byte array // decode data to a byte array
lua_new_byte_array(L,len); lua_new_byte_array(L, len);
byte_array_t * arr = NULL; byte_array_t *arr = NULL;
arr = l_check_barray(L,2); arr = l_check_barray(L, 2);
len = Base64decode((char*)arr->data, s); len = Base64decode((char *)arr->data, s);
arr->size = len; arr->size = len;
//lua_pushstring(L,dst); // lua_pushstring(L,dst);
//free(dst); // free(dst);
return 1; return 1;
} }
/* /*
* web socket handle for lua * web socket handle for lua
*/ */
static int l_ws_read_header(lua_State *L) static int l_ws_read_header(lua_State *L)
{ {
void* client = lua_touserdata (L, 1); void *client = lua_touserdata(L, 1);
ws_msg_header_t * header = ws_read_header(client); ws_msg_header_t *header = ws_read_header(client);
if(!header) if (!header)
{ {
lua_pushnil(L); lua_pushnil(L);
return 1; return 1;
@ -463,42 +538,42 @@ static int l_ws_read_header(lua_State *L)
// create newtable // create newtable
lua_newtable(L); lua_newtable(L);
lua_pushstring(L,"fin"); lua_pushstring(L, "fin");
lua_pushnumber(L,(int)header->fin); lua_pushnumber(L, (int)header->fin);
lua_settable(L,-3); lua_settable(L, -3);
lua_pushstring(L,"opcode"); lua_pushstring(L, "opcode");
lua_pushnumber(L,(int)header->opcode); lua_pushnumber(L, (int)header->opcode);
lua_settable(L,-3); lua_settable(L, -3);
lua_pushstring(L,"plen"); lua_pushstring(L, "plen");
lua_pushnumber(L,(int)header->plen); lua_pushnumber(L, (int)header->plen);
lua_settable(L,-3); lua_settable(L, -3);
lua_pushstring(L,"mask"); lua_pushstring(L, "mask");
lua_pushnumber(L,(int)header->mask); lua_pushnumber(L, (int)header->mask);
lua_settable(L,-3); lua_settable(L, -3);
lua_pushstring(L,"mask_key"); lua_pushstring(L, "mask_key");
lua_newtable(L); lua_newtable(L);
lua_pushnumber(L,0); lua_pushnumber(L, 0);
lua_pushnumber(L,(int)header->mask_key[0]); lua_pushnumber(L, (int)header->mask_key[0]);
lua_settable(L,-3); lua_settable(L, -3);
lua_pushnumber(L,1); lua_pushnumber(L, 1);
lua_pushnumber(L,(int)header->mask_key[1]); lua_pushnumber(L, (int)header->mask_key[1]);
lua_settable(L,-3); lua_settable(L, -3);
lua_pushnumber(L,2); lua_pushnumber(L, 2);
lua_pushnumber(L,(int)header->mask_key[2]); lua_pushnumber(L, (int)header->mask_key[2]);
lua_settable(L,-3); lua_settable(L, -3);
lua_pushnumber(L,3); lua_pushnumber(L, 3);
lua_pushnumber(L,(int)header->mask_key[3]); lua_pushnumber(L, (int)header->mask_key[3]);
lua_settable(L,-3); lua_settable(L, -3);
lua_settable(L,-3); lua_settable(L, -3);
free(header); free(header);
return 1; return 1;
@ -508,54 +583,55 @@ static int l_ws_read_header(lua_State *L)
/* /*
* Read socket data given the header * Read socket data given the header
*/ */
static int l_ws_read_data(lua_State *L) static int l_ws_read_data(lua_State *L)
{
void *client = lua_touserdata(L, 1);
if (!lua_istable(L, 2))
{ {
void* client = lua_touserdata (L, 1); ws_close(client, 1011);
if(!lua_istable(L,2))
{
ws_close(client,1011);
lua_pushnil(L); lua_pushnil(L);
return 1; return 1;
} }
dictionary_t dic = iterate_lua_table(L,2); dictionary_t dic = iterate_lua_table(L, 2);
if(dic) if (dic)
{ {
// convert dictionary to header // convert dictionary to header
ws_msg_header_t * header = (ws_msg_header_t*) malloc(sizeof(*header)); ws_msg_header_t *header = (ws_msg_header_t *)malloc(sizeof(*header));
header->fin = (uint8_t)(R_INT(dic,"fin")); header->fin = (uint8_t)(R_INT(dic, "fin"));
header->opcode = (uint8_t)(R_INT(dic,"opcode")); header->opcode = (uint8_t)(R_INT(dic, "opcode"));
header->mask = 1; header->mask = 1;
header->plen = R_INT(dic,"plen"); header->plen = R_INT(dic, "plen");
dictionary_t d1 = (dictionary_t)dvalue(dic,"mask_key"); dictionary_t d1 = (dictionary_t)dvalue(dic, "mask_key");
if(d1) if (d1)
{ {
header->mask_key[0] = (uint8_t)(R_INT(d1,"0")); header->mask_key[0] = (uint8_t)(R_INT(d1, "0"));
header->mask_key[1] = (uint8_t)(R_INT(d1,"1")); header->mask_key[1] = (uint8_t)(R_INT(d1, "1"));
header->mask_key[2] = (uint8_t)(R_INT(d1,"2")); header->mask_key[2] = (uint8_t)(R_INT(d1, "2"));
header->mask_key[3] = (uint8_t)(R_INT(d1,"3")); header->mask_key[3] = (uint8_t)(R_INT(d1, "3"));
freedict(d1); freedict(d1);
dput(dic,"mask_key", NULL); dput(dic, "mask_key", NULL);
} }
freedict(dic); freedict(dic);
// read data // read data
// This return max 1024 bytes data, // This return max 1024 bytes data,
//user should handle consecutive read // user should handle consecutive read
// by examining the header (FIN bit and plen) // by examining the header (FIN bit and plen)
uint8_t* data = (uint8_t*) malloc(header->plen+1); uint8_t *data = (uint8_t *)malloc(header->plen + 1);
int size = ws_read_data(client, header, header->plen, data); int size = ws_read_data(client, header, header->plen, data);
if(size < 0) if (size < 0)
{ {
lua_pushnil(L); lua_pushnil(L);
free(header); free(header);
if(data) free(data); if (data)
free(data);
return 1; return 1;
} }
if(header->opcode == WS_TEXT) if (header->opcode == WS_TEXT)
{ {
data[size] = '\0'; data[size] = '\0';
lua_pushstring(L, (char*)data); lua_pushstring(L, (char *)data);
} }
else else
{ {
@ -563,10 +639,10 @@ static int l_ws_read_header(lua_State *L)
// this is not an optimal way to store byte array // this is not an optimal way to store byte array
// TODO: we may need a dedicated byte array type // TODO: we may need a dedicated byte array type
// for it // for it
lua_new_byte_array(L,size); lua_new_byte_array(L, size);
byte_array_t * arr = NULL; byte_array_t *arr = NULL;
arr = l_check_barray(L,3); arr = l_check_barray(L, 3);
memcpy(arr->data,data,size); memcpy(arr->data, data, size);
/*lua_newtable(L); /*lua_newtable(L);
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
{ {
@ -574,9 +650,8 @@ static int l_ws_read_header(lua_State *L)
lua_pushnumber(L,(int)(data[i])); lua_pushnumber(L,(int)(data[i]));
lua_settable(L,-3); lua_settable(L,-3);
}*/ }*/
} }
if(data) if (data)
free(data); free(data);
free(header); free(header);
} }
@ -585,15 +660,15 @@ static int l_ws_read_header(lua_State *L)
lua_pushnil(L); lua_pushnil(L);
} }
return 1; return 1;
} }
/* /*
* Send a text to web socket * Send a text to web socket
*/ */
static int l_ws_t(lua_State*L) static int l_ws_t(lua_State *L)
{ {
void* client = lua_touserdata (L, 1); void *client = lua_touserdata(L, 1);
char* str = (char*)luaL_checkstring(L,2); char *str = (char *)luaL_checkstring(L, 2);
ws_t(client,str); ws_t(client, str);
return 1; return 1;
} }
/*static int l_status(lua_State*L) /*static int l_status(lua_State*L)
@ -608,78 +683,78 @@ static int l_ws_t(lua_State*L)
/* /*
* send a file as binary data * send a file as binary data
*/ */
static int l_ws_f(lua_State*L) static int l_ws_f(lua_State *L)
{ {
void* client = lua_touserdata (L, 1); void *client = lua_touserdata(L, 1);
char* str = (char*)luaL_checkstring(L,2); char *str = (char *)luaL_checkstring(L, 2);
ws_f(client,str); ws_f(client, str);
return 1; return 1;
} }
static int l_ws_bin(lua_State*L) static int l_ws_bin(lua_State *L)
{ {
byte_array_t * arr = NULL; byte_array_t *arr = NULL;
void* client = lua_touserdata (L, 1); void *client = lua_touserdata(L, 1);
arr = l_check_barray(L,2); arr = l_check_barray(L, 2);
ws_b(client, arr->data, arr->size); ws_b(client, arr->data, arr->size);
return 1; return 1;
} }
static int l_ws_close(lua_State *L) static int l_ws_close(lua_State *L)
{ {
void* client = lua_touserdata (L, 1); void *client = lua_touserdata(L, 1);
int status = (int) luaL_checknumber(L,2); int status = (int)luaL_checknumber(L, 2);
ws_close(client,status); ws_close(client, status);
return 1; return 1;
} }
static int l_trim(lua_State* L) static int l_trim(lua_State *L)
{ {
char* str = strdup((char*)luaL_checkstring(L,1)); char *str = strdup((char *)luaL_checkstring(L, 1));
const char* tok = luaL_checkstring(L,2); const char *tok = luaL_checkstring(L, 2);
trim(str,tok[0]); trim(str, tok[0]);
lua_pushstring(L,(const char*)str); lua_pushstring(L, (const char *)str);
free(str); free(str);
return 1; return 1;
} }
static int l_is_dir(lua_State* L) 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); const char *file = (char *)luaL_checkstring(L, 1);
int status = luaL_checknumber(L,2); lua_pushboolean(L, is_dir(file) == 1);
const char* msg = luaL_checkstring(L,3); 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); antd_error(client, status, msg);
return 1; return 1;
} }
static int l_send_header(lua_State* L) static int l_send_header(lua_State *L)
{ {
if (lua_istable(L, 3)) if (lua_istable(L, 3))
{ {
dictionary_t d = iterate_lua_table(L,-2); dictionary_t d = iterate_lua_table(L, -2);
if(d) if (d)
{ {
void* client = lua_touserdata (L, 1); void *client = lua_touserdata(L, 1);
int status = luaL_checknumber(L,2); int status = luaL_checknumber(L, 2);
antd_response_header_t h; antd_response_header_t h;
h.status = status; h.status = status;
h.header = d; h.header = d;
dictionary_t c = iterate_lua_table(L,-1); dictionary_t c = iterate_lua_table(L, -1);
h.cookie = NULL; h.cookie = NULL;
if(c) if (c)
{ {
h.cookie = list_init(); h.cookie = list_init();
if(h.cookie) if (h.cookie)
{ {
chain_t it; chain_t it;
for_each_assoc(it,c) for_each_assoc(it, c)
{ {
list_put_ptr(&h.cookie,strdup(it->value)); list_put_ptr(&h.cookie, strdup(it->value));
} }
} }
freedict(c); freedict(c);
@ -690,13 +765,15 @@ static int l_send_header(lua_State* L)
return 1; return 1;
} }
static const struct luaL_Reg standard [] = { static const struct luaL_Reg standard[] = {
//{"_header", l_header}, //{"_header", l_header},
//{"_redirect", l_redirect}, //{"_redirect", l_redirect},
//{"_html", l_html}, //{"_html", l_html},
//{"_text", l_text}, //{"_text", l_text},
//{"_json", l_json}, //{"_json", l_json},
//{"_jpeg", l_jpeg}, //{"_jpeg", l_jpeg},
{"antd_set_zlevel", l_antd_set_zlevel},
{"antd_recv", l_antd_recv},
{"_error", l_std_error}, {"_error", l_std_error},
{"_send_header", l_send_header}, {"_send_header", l_send_header},
{"b64encode", l_base64_encode}, {"b64encode", l_base64_encode},
@ -704,33 +781,30 @@ static const struct luaL_Reg standard [] = {
//{"_octstream", l_octstream} , //{"_octstream", l_octstream} ,
//{"_textstream", l_textstream} , //{"_textstream", l_textstream} ,
//{"_ti", l_ti} , //{"_ti", l_ti} ,
{"_t", l_t} , {"_t", l_t},
{"_f", l_f} , {"_f", l_f},
{"_b", l_b} , {"_b", l_b},
{"trim", l_trim}, {"trim", l_trim},
{"upload", l_upload} , {"upload", l_upload},
//{"route", l_route} , //{"route", l_route} ,
{"mime", l_mime} , {"mime", l_mime},
//{"is_bin", l_is_bin} , //{"is_bin", l_is_bin} ,
//{"_unknow", l_unknow} , //{"_unknow", l_unknow} ,
//{"_status", l_status}, //{"_status", l_status},
{"console", l_log} , {"console", l_log},
//{"_setCookie", l_set_cookie}, //{"_setCookie", l_set_cookie},
{"hash",l_simple_hash}, {"hash", l_simple_hash},
{"md5",l_md5}, {"md5", l_md5},
{"sha1",l_sha1}, {"sha1", l_sha1},
{"ext",l_ext}, {"ext", l_ext},
{"ws_header",l_ws_read_header}, {"ws_header", l_ws_read_header},
{"ws_read",l_ws_read_data}, {"ws_read", l_ws_read_data},
{"ws_f",l_ws_f}, {"ws_f", l_ws_f},
{"ws_t", l_ws_t}, {"ws_t", l_ws_t},
{"ws_b", l_ws_bin}, {"ws_b", l_ws_bin},
{"ws_close", l_ws_close}, {"ws_close", l_ws_close},
{"is_dir", l_is_dir}, {"is_dir", l_is_dir},
{NULL,NULL} {NULL, NULL}};
};
int luaopen_std(lua_State *L) int luaopen_std(lua_State *L)
{ {
@ -738,14 +812,11 @@ int luaopen_std(lua_State *L)
return 1; return 1;
} }
static const struct luaL_Reg modules [] = { static const struct luaL_Reg modules[] = {
{"bytes",luaopen_bytes}, {"bytes", luaopen_bytes},
{"array",luaopen_array}, {"array", luaopen_array},
{"std", luaopen_std}, {"std", luaopen_std},
{NULL,NULL} {NULL, NULL}};
};
int luaopen_antd(lua_State *L) int luaopen_antd(lua_State *L)
{ {

View File

@ -1,49 +1,34 @@
#include <antd/plugin.h> #include <antd/plugin.h>
#include <antd/scheduler.h> #include <sys/socket.h>
#include <antd/dbhelper.h> #include <netinet/tcp.h>
#include <sys/stat.h> #include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "../lualib.h" #include "../lualib.h"
/** typedef struct {
plugin_header_t* __plugin__;
int fd;
} lua_thread_data_t;
* convert antd dictionary to lua table void* lua_handle(void* ptr)
*
*/
static void push_dict_to_lua(lua_State* L, dictionary_t d)
{ {
lua_newtable(L); lua_thread_data_t* data = (lua_thread_data_t*)ptr;
chain_t as;
if(d)
for_each_assoc(as, d)
{
lua_pushstring(L,as->key);
//printf("KEY %s\n", as->key);
if(EQU(as->key,"COOKIE") || EQU(as->key,"REQUEST_HEADER") || EQU(as->key,"REQUEST_DATA") )
push_dict_to_lua(L, (dictionary_t)as->value);
else
{
if(strncmp(as->key,"octet-stream",12) == 0)
{
lua_pushlightuserdata(L, as->value);
}
else
{
lua_pushstring(L,as->value);
}
//printf("VALUE : %s\n",as->value );
}
lua_settable(L, -3);
}
}
void* lua_handle(void* data, void* meta)
{
antd_request_t* rq = (antd_request_t*) data;
char buf[BUFFLEN];
plugin_header_t* __plugin__ = meta;
lua_State* L = NULL; lua_State* L = NULL;
//char * index = __s("%s/%s",__plugin__.htdocs,"router.lua"); antd_client_t* cl = (antd_client_t*) malloc(sizeof(antd_client_t));
char* cnf = __s("%s%s%s", __plugin__->pdir,DIR_SEP, __plugin__->name); 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"); char * apis = __s("%s/%s",cnf,"api.lua");
L = luaL_newstate(); L = luaL_newstate();
luaL_openlibs(L); luaL_openlibs(L);
@ -54,25 +39,24 @@ void* lua_handle(void* data, void* meta)
// API header // API header
lua_newtable(L); lua_newtable(L);
lua_pushstring(L,"name"); lua_pushstring(L,"name");
lua_pushstring(L, __plugin__->name); lua_pushstring(L, data->__plugin__->name);
lua_settable(L,-3); lua_settable(L,-3);
lua_pushstring(L,"root"); //lua_pushstring(L,"root");
htdocs(rq, buf); //htdocs(rq, buf);
lua_pushstring(L, buf); //lua_pushstring(L, data->__plugin__->htdocs);
lua_settable(L,-3); //lua_settable(L,-3);
lua_pushstring(L,"apiroot"); lua_pushstring(L,"apiroot");
lua_pushstring(L, cnf); lua_pushstring(L, cnf);
lua_settable(L,-3); lua_settable(L,-3);
lua_pushstring(L,"tmpdir"); lua_pushstring(L,"tmpdir");
tmpdir(buf); lua_pushstring(L, data->__plugin__->tmpdir);
lua_pushstring(L, buf);
lua_settable(L,-3); lua_settable(L,-3);
lua_pushstring(L,"dbpath"); lua_pushstring(L,"dbpath");
lua_pushstring(L, __plugin__->dbpath); lua_pushstring(L, data->__plugin__->dbpath);
lua_settable(L,-3); lua_settable(L,-3);
lua_setglobal(L, "__api__"); lua_setglobal(L, "__api__");
@ -80,20 +64,25 @@ void* lua_handle(void* data, void* meta)
// Request // Request
lua_newtable(L); lua_newtable(L);
lua_pushstring(L,"id"); lua_pushstring(L,"id");
lua_pushlightuserdata(L, rq->client); lua_pushlightuserdata(L, cl);
//lua_pushnumber(L,client); //lua_pushnumber(L,client);
lua_settable(L, -3); lua_settable(L, -3);
lua_pushstring(L,"request"); lua_pushstring(L,"socket");
push_dict_to_lua(L,rq->request); lua_pushnumber(L, cl->sock);
//lua_pushnumber(L,client);
lua_settable(L, -3); lua_settable(L, -3);
lua_setglobal(L, "HTTP_REQUEST");
//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 // load major apis
if(is_file(apis)) if(is_file(apis))
if (luaL_loadfile(L, apis) || lua_pcall(L, 0, 0, 0)) if (luaL_loadfile(L, apis) || lua_pcall(L, 0, 0, 0))
{ {
ERROR( "cannot start API file: [%s] %s\n", apis, lua_tostring(L, -1)); ERROR("cannot start API file: [%s] %s\n", apis, lua_tostring(L, -1));
} }
/*if (luaL_loadfile(L, index) || lua_pcall(L, 0, 0, 0)) /*if (luaL_loadfile(L, index) || lua_pcall(L, 0, 0, 0))
@ -102,7 +91,7 @@ void* lua_handle(void* data, void* meta)
__t(client, "Cannot run router: %s", lua_tostring(L, -1)); __t(client, "Cannot run router: %s", lua_tostring(L, -1));
} }
free(index);*/ free(index);*/
LOG("LUA handle exit on %d", rq->client->sock); LOG("LUA handle exit on %d", cl->sock);
// clear request // clear request
if(L) if(L)
lua_close(L); lua_close(L);
@ -110,6 +99,7 @@ void* lua_handle(void* data, void* meta)
free(cnf); free(cnf);
if(apis) if(apis)
free(apis); free(apis);
return antd_create_task(NULL, (void*)rq, NULL,rq->client->last_io); (void) antd_close(cl);
return 0;
//lua_close(L); //lua_close(L);
} }

View File

@ -381,16 +381,19 @@ static int l_file_move(lua_State* L)
static int l_send_file(lua_State* L) static int l_send_file(lua_State* L)
{ {
const char* old = luaL_checkstring(L,1);
const char* new = luaL_checkstring(L,2);
int fromfd, tofd, ret; int fromfd, tofd, ret;
off_t off = 0; size_t sz = 0;
if (unlink(new) < 0 && errno != ENOENT) { char* old = NULL;
lua_pushboolean(L,0); char* new = NULL;
goto end_send_file; if(lua_isnumber(L,1))
{
fromfd = (int)luaL_checknumber(L,1);
} }
if ((fromfd = open(old, O_RDONLY)) < 0 || else
(tofd = open(new, O_WRONLY | O_CREAT, 0600)) < 0) { {
old = (char*)luaL_checkstring(L,1);
if((fromfd = open(old, O_RDONLY)) < 0)
{
lua_pushboolean(L,0); lua_pushboolean(L,0);
goto end_send_file; goto end_send_file;
} }
@ -400,24 +403,57 @@ static int l_send_file(lua_State* L)
lua_pushboolean(L,0); lua_pushboolean(L,0);
goto end_send_file; goto end_send_file;
} }
size_t sz = st.st_size; sz = st.st_size;
int read = 0; }
while (read != sz && (ret = sendfile(tofd, fromfd, &off, sz - read)) == 0) if(lua_isnumber(L,2))
{ {
tofd = (int) luaL_checknumber(L,2);
}
else
{
new = (char*)luaL_checkstring(L,2);
if (unlink(new) < 0 && errno != ENOENT) {
lua_pushboolean(L,0);
goto end_send_file;
}
if((tofd = open(new, O_WRONLY | O_CREAT, 0600)) < 0)
{
lua_pushboolean(L,0);
goto end_send_file;
}
}
if(lua_isnumber(L,3))
{
sz = (size_t) luaL_checknumber(L,3);
}
off_t off = 0;
int read = 0;
while (
sz > 0 &&
read != sz &&
(
((ret = sendfile(tofd, fromfd, &off, sz - read)) >= 0) ||
(errno == EAGAIN)
)
)
{
if(ret < 0) ret = 0;
read += ret; read += ret;
} }
if(ret != sz) if(read != sz)
{ {
lua_pushboolean(L,0); lua_pushboolean(L,0);
goto end_send_file; goto end_send_file;
} }
lua_pushboolean(L,1); lua_pushboolean(L,1);
end_send_file: end_send_file:
if(fromfd >= 0) if(fromfd >= 0 && old)
{ {
(void) close(fromfd); (void) close(fromfd);
} }
if(tofd >= 0) if(tofd >= 0 && new)
{ {
(void) close(tofd); (void) close(tofd);
} }

View File

@ -1,633 +0,0 @@
#include<stdio.h> //printf
#include<string.h> //memset
#include<stdlib.h> //for exit(0);
#include<errno.h> //For errno - the error number
#include<netdb.h> //hostent
#include <netinet/in.h>
#include <arpa/inet.h>
//#include <signal.h>
#include <dirent.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <errno.h>
#include <ifaddrs.h>
#include <sys/stat.h>
#include <libgen.h>
#include "../lualib.h"
//#include "../../lua-api.h"
#include <antd/utils.h>
#include <sys/time.h>
#define CLIENT_NAME "wurl"
#define CLIENT_HOST "192.168.9.249"
#define CONN_TIME_OUT_S 3
#define MAX_BUFF 1024
#define REQUEST_BOUNDARY "------wURLFormBoundaryVo4QYVaSVseFNpeK"
#define GET 0
#define POST 1
typedef struct{
int type; // POST(1) or GET(0)
char* resource; // path
char* ctype; // content type, used by POST
int clen; // content length, used by POST
unsigned char* data ;
} wurl_header_t;
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;
}
void lua_new_byte_array(lua_State*L, int n)
{
size_t nbytes = sizeof(byte_array_t) + (n-1)*sizeof(unsigned char);
byte_array_t *a = (byte_array_t *)lua_newuserdata(L, nbytes);
luaL_getmetatable(L, BYTEARRAY);
lua_setmetatable(L, -2);
a->size = n;
}
/*get the ip by hostname*/
int wurl_ip_from_hostname(const char * hostname , char* ip)
{
struct hostent *he;
struct in_addr **addr_list;
int i;
if ( (he = gethostbyname( hostname ) ) == NULL)
{
// get the host info
herror("gethostbyname");
return -1;
}
addr_list = (struct in_addr **) he->h_addr_list;
for(i = 0; addr_list[i] != NULL; i++)
{
//Return the first one;
strcpy(ip , inet_ntoa(*addr_list[i]) );
return 0;
}
return -1;
}
/*
send a request
*/
int wurl_request_socket(const char* ip, int port)
{
int sockfd;
struct sockaddr_in dest;
// time out setting
struct timeval timeout;
timeout.tv_sec = CONN_TIME_OUT_S;
timeout.tv_usec = 0;
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
{
perror("Socket");
return -1;
}
if (setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,sizeof(timeout)) < 0)
perror("setsockopt failed\n");
if (setsockopt (sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout,sizeof(timeout)) < 0)
perror("setsockopt failed\n");
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(port);
if ( inet_aton(ip, &dest.sin_addr) == 0 )
{
perror(ip);
close(sockfd);
return -1;
}
if ( connect(sockfd, (struct sockaddr*)&dest, sizeof(dest)) != 0 )
{
close(sockfd);
perror("Connect");
return -1;
}
return sockfd;
}
/*
POST %s HTTP/1.0\r\n
Host: %s\r\n
User-Agent: %s\r\n
Content-Type: %s\r\n
Content-Length: %d\r\n\r\n"
maybe cookie support? this can cause security problem
GET %s HTTP/1.0\r\n
Host: %s\r\n
User-Agent: %s\r\n\r\n"
multipart
POST %s HTTP/1.1
Host: %s
User-Agent: %s
Content-Type: multipart/form-data; boundary=----------287032381131322
Content-Length: %d
------------287032381131322
Content-Disposition: form-data; name="datafile1"; filename="r.gif"
Content-Type: image/gif
GIF87a.............,...........D..;
------------287032381131322
Content-Disposition: form-data; name="datafile2"; filename="g.gif"
Content-Type: image/gif
GIF87a.............,...........D..;
------------287032381131322
Content-Disposition: form-data; name="datafile3"; filename="b.gif"
Content-Type: image/gif
GIF87a.............,...........D..;
------------287032381131322--
*/
int wurl_header(int sockfd, wurl_header_t rq)
{
char buff[MAX_BUFF];
if(sockfd < 0) return -1;
if(rq.type == GET) // GET
{
send(sockfd,"GET ",4,0);
send(sockfd,rq.resource, strlen(rq.resource),0);
send(sockfd," HTTP/1.0\r\n",11,0);
}
else
{
send(sockfd,"POST ",5, 0);
send(sockfd,rq.resource, strlen(rq.resource),0);
send(sockfd," HTTP/1.0\r\n",11,0);
sprintf(buff,"Content-Type: %s\r\n", rq.ctype);
send(sockfd,buff,strlen(buff),0);
sprintf(buff,"Content-Length: %d\r\n", rq.clen);
send(sockfd,buff,strlen(buff),0);
}
// host dont need to send the host
//sprintf(buff,"Host: %s\r\n",CLIENT_HOST);
//send(sockfd,buff,strlen(buff),0);
// user agent
sprintf(buff,"User-Agent: %s\r\n",CLIENT_NAME);
send(sockfd,buff,strlen(buff),0);
// terminate request
send(sockfd,"\r\n",2,0);
// if there is data, send out
if(rq.type == POST && rq.data)
{
send(sockfd,rq.data,rq.clen,0);
}
return 0;
}
/*
send multiple files to server
using multipart/form-data
*/
void wurl_send_files(int sockfd,char* resource, int n, char* name [], char* files[])
{
char buff[MAX_BUFF];
wurl_header_t rq;
rq.type = POST;
rq.resource = resource;
// get the total size of data
int totalsize = 0;
FILE* fd;
struct stat st;
for(int i = 0; i < n; ++i)
{
if(stat(files[i], &st) != 0) continue;
totalsize += st.st_size;
}
rq.clen = totalsize;
sprintf(buff,"%s; boundary=%s","multipart/form-data",REQUEST_BOUNDARY);
rq.ctype = buff;
// now send the header
wurl_header(sockfd,rq);
// now send the files
size_t size;
for(int i = 0; i < n; ++i)
{
fd = fopen(files[i],"rb");
if(!fd) continue;
// first send the boundary
//printf("sending file %s name:%s\n", files[i],name[i]);
sprintf(buff,"%s\r\n",REQUEST_BOUNDARY);
send(sockfd, buff, strlen(buff),0);
// content disposition
sprintf(buff,"Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n",
name[i],basename(files[i]));
send(sockfd,buff, strlen(buff),0);
// content type
sprintf(buff,"Content-Type: %s\r\n\r\n",mime(files[i]));
send(sockfd,buff, strlen(buff),0);
// now send the file
while(!feof(fd))
{
size = fread(buff,1,MAX_BUFF,fd);
send(sockfd,buff,size,0);
//if(!__b(client,buffer,size)) return;
}
fclose(fd);
send(sockfd,"\r\n",2,0);
}
//end the boudary
sprintf(buff,"%s--\r\n",REQUEST_BOUNDARY);
send(sockfd,buff,strlen(buff),0);
}
/**
* Read the socket request in to a buffer or size
* The data is read until the buffer is full or
* there are a carrier return character
* @param sock socket
* @param buf buffer
* @param size size of buffer
* @return number of bytes read
*/
int wurl_read_buf(int sock, char*buf,int size)
{
int i = 0;
char c = '\0';
int n;
while ((i < size - 1) && (c != '\n'))
{
n = recv(sock, &c, 1, 0);
if (n > 0)
{
buf[i] = c;
i++;
}
else
c = '\n';
}
buf[i] = '\0';
return i;
}
/*
POST example
wurl_header_t rq;
rq.resource = path;
rq.type = POST;
rq.data = "s=a&q=b#test";//"{\"name\":\"sang\"}";
rq.clen = strlen(rq.data);
rq.ctype = "application/x-www-form-urlencoded";//"application/json";
if(wurl_request(hostname,port,&rq,1) == 0)
{
printf(rq.data);
}
else
{
printf("Cannot connect to host\n");
}
DOWNLOAD
wurl_header_t rq;
rq.resource = path;
rq.type = GET;
if(wurl_download(hostname,port,&rq,file) == 0)
{
printf("Download sucess ful\n");
}
else
{
printf("Cannot connect to host\n");
}
upload example
// send files
char * names[2];
names[0] = "zip";
names[1] = "text";
char* files[2];
files[0] = "/Users/mrsang/tmp/Archive.zip";
files[1] = "/Users/mrsang/tmp/test.py";
wurl_send_files(sock,path,2,names, files);
printf("RETURN:\n");
size = wurl_read_buf(sock,buff, MAX_BUFF);
while(size > 0)
{
printf("%s", buff);
size = wurl_read_buf(sock,buff, MAX_BUFF);
}
close(sock);
*/
void wurl_response_header(int sock, wurl_header_t* header)
{
char buff[MAX_BUFF];
int size = wurl_read_buf(sock,buff,MAX_BUFF);
char* token;
while (size > 0 && strcmp("\r\n",buff))
{
char* line = strdup(buff);
//printf("LINE %s\n", line);
token = strsep(&line,":");
trim(token,' ');
if(token != NULL &&strcasecmp(token,"Content-Type") == 0)
{
header->ctype = strsep(&line,":");
trim(header->ctype,' ');
trim(header->ctype,'\n');
trim(header->ctype,'\r');
} else if(token != NULL &&strcasecmp(token,"Content-Length") == 0)
{
token = strsep(&line,":");
trim(token,' ');
header->clen = atoi(token);
}
//if(line) free(line);
size = wurl_read_buf(sock,buff,MAX_BUFF);
}
}
int wurl_read_data(int sock,char** din)
{
// read line by line, ignore content length
int total_length = 0;
char* tmp = NULL;
int CHUNK = 512;
char buff[MAX_BUFF];
char * data = ( char*) malloc(CHUNK);
int cursize = CHUNK;
int size = wurl_read_buf(sock,buff,MAX_BUFF);
while(size > 0)
{
if(total_length+size > cursize)
{
tmp = (char*) realloc(data,total_length + size+ CHUNK );
if(!tmp)
{
if(data) free(data);
break;
}
cursize = total_length + size+ CHUNK;
data = tmp;
}
memcpy(data+total_length,buff,size);
total_length += size;
size = wurl_read_buf(sock,buff,MAX_BUFF);
}
data[total_length] = '\0';
close(sock);
*din = data;
return total_length;
}
/*
hostname
port
header for request and respond
lazy : if 1, all data is read to the header
if 0, user has the responsibility to handler it
*/
int wurl_request(const char* hostname, int port, wurl_header_t* header, int lazy)
{
char ip[100];
wurl_ip_from_hostname(hostname ,ip);
int sock = wurl_request_socket(ip, port);
if(sock <= 0) return -1;
// send header
wurl_header(sock,*header);
// read respond header
wurl_response_header(sock,header);
if(header->ctype == NULL || header->clen == -1)
{
LOG("Bad data\n");
return -1;
}
// read data if lazy
if(lazy)
{
// read line by line, ignore content length
header->clen = wurl_read_data(sock,(char**)&header->data);
return 0;
}
return sock;
}
int wurl_download(const char* hostname, int port, wurl_header_t* h, const char* to)
{
// we will handler the data reading
int sock = wurl_request(hostname, port,h,0);
char buff[MAX_BUFF];
if(sock < 0) return -1;
FILE* fp = fopen(to,"wb");
int size;
if(fp)
{
while((size = wurl_read_buf(sock,buff, MAX_BUFF)) > 0)
{
fwrite(buff, size, 1, fp);
}
fclose(fp);
}
else
{
close(sock);
return -1;
}
close(sock);
return 0;
}
/*
int main (int argc, char const *argv[])
{
if(argc < 4)
{
printf("wurl [host] [port] [path]\n");
exit(1);
}
char *hostname = argv[1];
char* path = argv[3];
int port = atoi(argv[2]);
char*file = argv[4];
wurl_header_t rq;
rq.resource = path;
rq.type = POST;
rq.data = "s=a&q=b#test";//"{\"name\":\"sang\"}";
rq.clen = strlen(rq.data);
rq.ctype = "application/x-www-form-urlencoded";//"application/json";
if(wurl_download(hostname,port,&rq,file) == 0)
{
printf("Download sucess ful\n");
}
else
{
printf("Cannot connect to host\n");
}
return 0;
}*/
static int l_get(lua_State *L)
{
const char* host = luaL_checkstring(L,1);
int port = luaL_checknumber(L,2);
const char* resource = luaL_checkstring(L,3);
wurl_header_t rq;
rq.resource = (char*)resource;
rq.type = GET;
if(wurl_request(host,port,&rq,1) == 0)
{
//printf("Content type is %s\n", rq.ctype);
//mime_t m = mime_from_type(rq.ctype);
lua_newtable(L);
lua_pushstring(L,"contentType");
lua_pushstring(L,rq.ctype);
lua_settable(L,-3);
/*
lua_pushstring(L,"binary");
lua_pushboolean(L,m.bin);
lua_settable(L,-3);*/
lua_pushstring(L,"data");
// byte array, that can be convert to string later
lua_new_byte_array(L,rq.clen);
byte_array_t* arr = l_check_barray(L,-1);
memcpy(arr->data,rq.data,rq.clen);
free(rq.data); // be careful
lua_settable(L,-3);
return 1;
}
else
{
lua_pushnil(L);
return 1;
}
}
static int l_post(lua_State *L)
{
const char* host = luaL_checkstring(L,1); // host
int port = luaL_checknumber(L,2); // port
const char* res = luaL_checkstring(L,3); // resource
const char* ctype = luaL_checkstring(L,4); // content type
const char* data = luaL_checkstring(L,5); // post data
wurl_header_t rq;
rq.resource = (char*)res;
rq.type = POST;
rq.ctype = (char*)ctype;
rq.clen = strlen(data);
rq.data = (unsigned char*)data;
if(wurl_request(host,port,&rq,1) == 0)
{
//printf("Content type is %s\n", rq.ctype);
mime_t m = mime_from_type(rq.ctype);
lua_newtable(L);
lua_pushstring(L,"contentType");
lua_pushstring(L,rq.ctype);
lua_settable(L,-3);
/*lua_pushstring(L,"binary");
lua_pushboolean(L,m.bin);
lua_settable(L,-3);
*/
lua_pushstring(L,"data");
lua_new_byte_array(L,rq.clen);
byte_array_t* arr = l_check_barray(L,-1);
memcpy(arr->data,rq.data,rq.clen);
free(rq.data); // be careful
lua_settable(L,-3);
return 1;
}
else
{
lua_pushnil(L);
return 1;
}
}
static int l_download(lua_State* L)
{
// we user only GET for down load and POST for upload
const char* host = luaL_checkstring(L,1); // host
int port = luaL_checknumber(L,2); // port
const char* res = luaL_checkstring(L,3); // resource
const char* file = luaL_checkstring(L,4); // file
wurl_header_t rq;
rq.resource = (char*)res;
rq.type = GET;
if(wurl_download(host,port,&rq,file) == 0)
lua_pushboolean(L, true);
else
lua_pushboolean(L,false);
return 1;
}
static int l_upload(lua_State* L)
{
const char* host = luaL_checkstring(L,1);
int port = luaL_checknumber(L,2);
const char* resource = luaL_checkstring(L,3);
const char* name = luaL_checkstring(L,4);
const char* file = luaL_checkstring(L,5);
if(!_exist(file)) goto fail;
// request socket
char ip[100];
wurl_ip_from_hostname(host ,ip);
int sock = wurl_request_socket(ip, port);
if(sock <= 0) goto fail;
char * names[2];
names[0] = (char*)name;
char* files[2];
//files[0] = "/Users/mrsang/tmp/Archive.zip";
files[0] = (char*)file;
//printf("SENDIND DILE\n");
wurl_send_files(sock, (char*)resource,1,names,files);
wurl_header_t header;
//printf("READ HEADER\n");
wurl_response_header(sock, &header);
//printf("read data\n");
wurl_read_data(sock,(char**)&header.data);
if(header.ctype != NULL && header.data)
{
lua_pushstring(L,(const char*)header.data);
free(header.data);
return 1;
}
fail:
lua_pushnil(L);
return 1;
}
static const struct luaL_Reg _lib [] = {
{"_get",l_get},
{"_post",l_post},
{"_download",l_download},
{"_upload",l_upload},
{NULL,NULL}
};
int luaopen_wurl(lua_State *L)
{
luaL_newlib(L, _lib);
return 1;
}

312
lua-api.c
View File

@ -2,64 +2,322 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <antd/plugin.h> #include <antd/plugin.h>
#include <antd/scheduler.h> #include <antd/scheduler.h>
#include <antd/dbhelper.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <time.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "lib/lualib.h"
#define LUA_HDL_FN "lua_handle" #define LUA_HDL_FN "lua_handle"
static void* core = NULL; #define MAX_SOCK_NAME 64
static void* lua_handle = NULL; #define SOCKET_NAME "lua.sock"
static void *(*handle_fn)(void *, void*);
void init() #define MAX_SESSION_TIMEOUT (15u * 60u) //15 min
#define PING_INTERVAL 10u // 10s
#define PROCESS_TIMEOUT 200u //100ms
typedef struct {
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;
(void) strncpy(address.sun_path, sock_path, sizeof(address.sun_path));
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if(fd == -1)
{
ERROR( "Unable to create Unix domain socket: %s", strerror(errno));
return -1;
}
if(connect(fd, (struct sockaddr*)(&address), sizeof(address)) == -1)
{
ERROR( "Unable to connect to socket '%s': %s", address.sun_path, strerror(errno));
return -1;
}
LOG( "Socket %s is created successfully", sock_path);
return fd;
}
static int mk_socket()
{
struct sockaddr_un address;
address.sun_family = AF_UNIX;
// create the socket
(void)strncpy(address.sun_path, sock_path, sizeof(address.sun_path));
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1)
{
ERROR("Unable to create Unix domain socket: %s", strerror(errno));
return -1;
}
if (bind(fd, (struct sockaddr *)(&address), sizeof(address)) == -1)
{
ERROR("Unable to bind name: %s to a socket: %s", address.sun_path, strerror(errno));
return -1;
}
// mark the socket as passive mode
if (listen(fd, 500) == -1)
{
ERROR("Unable to listen to socket: %d (%s): %s", fd, sock_path, strerror(errno));
return -1;
}
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; char* error;
char* path = __s("%s/lua/core.so", __plugin__.pdir); (void)snprintf(path, BUFFLEN, "%s/lua/core.so", __plugin__.pdir);
core = dlopen(path, RTLD_NOW| RTLD_GLOBAL); core = dlopen(path, RTLD_NOW| RTLD_GLOBAL);
free(path);
if(!core) if(!core)
{ {
ERROR("Cannot load Lua core: %s", dlerror()); ERROR("Cannot load Lua core: %s", dlerror());
return; return;
} }
LOG("Lua core loaded");
// now load the handle // now load the handle
path = __s("%s/lua/handle.so", __plugin__.pdir); (void)snprintf(path, BUFFLEN, "%s/lua/handle.so", __plugin__.pdir);
lua_handle = dlopen(path, RTLD_LAZY); lua_handle = dlopen(path, RTLD_LAZY);
free(path);
if(!lua_handle) if(!lua_handle)
{ {
ERROR("Cannot load lua_handle: %s", dlerror()); ERROR("Cannot load lua_handle: %s", dlerror());
return; return;
} }
// find the fn // find the fn
handle_fn = (void *(*)(void *))dlsym(lua_handle, LUA_HDL_FN); handle_fn = (void *(*)(void*))dlsym(lua_handle, LUA_HDL_FN);
if ((error = dlerror()) != NULL) if ((error = dlerror()) != NULL)
{ {
ERROR("Problem when finding %s method from handle : %s", LUA_HDL_FN, error); ERROR("Problem when finding %s method from handle : %s", LUA_HDL_FN, error);
handle_fn = NULL; handle_fn = NULL;
return; return;
} }
LOG("Lua module initialized"); int socket = mk_socket();
} if(socket != -1)
void* handle(void* data)
{
plugin_header_t* meta_ptr = (void*)meta();
antd_request_t *rq = (antd_request_t *)data;
// find the handle function and execute it
if(!handle_fn)
{ {
antd_error(rq->client, 503, "Requested service not found"); int fd;
return antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io); 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)
{
if(atoi(enable_debug))
{
LOG("LUA Debug is enabled");
log_level = LOG_NOTICE;
}
}
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));
}
} }
return handle_fn(data, meta_ptr);
}
void destroy()
{
if(core) if(core)
(void)dlclose(core); (void)dlclose(core);
if(lua_handle) if(lua_handle)
(void)dlclose(lua_handle); (void)dlclose(lua_handle);
LOG("lua_serve: stop serve due to error");
}
void init()
{
(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();
}
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);
}
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));
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");
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;
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, SIGHUP);
}
LOG("Exit LUA Handle"); LOG("Exit LUA Handle");
} }