mirror of
https://github.com/lxsang/antd-lua-plugin
synced 2024-12-26 17:38:21 +01:00
lua plugin now used a separated process to handle requests
This commit is contained in:
parent
7814611008
commit
c7ea2af3f1
133
APIs/api.lua
133
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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
1272
lib/asl/antd.c
1272
lib/asl/antd.c
File diff suppressed because it is too large
Load Diff
177
lib/asl/handle.c
177
lib/asl/handle.c
@ -1,6 +1,4 @@
|
||||
#include <antd/plugin.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h> /* See NOTES */
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <errno.h>
|
||||
@ -8,105 +6,100 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#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);
|
||||
}
|
||||
|
425
lua-api.c
425
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");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user