mirror of
https://github.com/lxsang/antd-lua-plugin
synced 2025-04-21 13:16:44 +02:00
Compare commits
No commits in common. "c7ea2af3f1cadd20834928feee852c514b84a26d" and "4259ec7eef754cae78054d42aa6c7844321edb02" have entirely different histories.
c7ea2af3f1
...
4259ec7eef
119
APIs/api.lua
119
APIs/api.lua
@ -1,61 +1,10 @@
|
|||||||
|
|
||||||
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__ = HTTP_REQUEST.request.SERVER_WWW_ROOT
|
__ROOT__ = __api__.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")
|
||||||
@ -75,14 +24,6 @@ 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
|
||||||
@ -161,6 +102,7 @@ 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
|
||||||
@ -176,61 +118,12 @@ 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
|
||||||
|
@ -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 == "yml" then return "application/x-yaml", false
|
elseif ext == "yaml" 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
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
std = modules.std()
|
||||||
bytes = modules.bytes()
|
bytes = modules.bytes()
|
||||||
array = modules.array()
|
array = modules.array()
|
||||||
|
|
||||||
@ -61,7 +62,6 @@ 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)
|
||||||
|
74
APIs/web.lua
Normal file
74
APIs/web.lua
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
-- 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
|
@ -19,6 +19,10 @@ 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
|
||||||
|
143
lib/asl/antd.c
143
lib/asl/antd.c
@ -22,30 +22,26 @@ 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,
|
||||||
@ -55,28 +51,24 @@ static unsigned char *get_bel(lua_State *L)
|
|||||||
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);
|
byte_array_t *a = l_check_barray(L,1);
|
||||||
char * d = (char*) malloc(a->size+1);
|
char * d = (char*) malloc(a->size+1);
|
||||||
memcpy(d, a->data, a->size);
|
memcpy(d, a->data, a->size);
|
||||||
@ -113,10 +105,10 @@ static const struct luaL_Reg barraylib[] = {
|
|||||||
{"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");
|
||||||
@ -146,22 +138,19 @@ void lua_new_array(lua_State *L, int n)
|
|||||||
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,
|
||||||
@ -171,27 +160,23 @@ static double *get_el(lua_State *L)
|
|||||||
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;
|
||||||
@ -203,9 +188,9 @@ static const struct luaL_Reg arraylib[] = {
|
|||||||
{"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");
|
||||||
@ -227,6 +212,7 @@ int luaopen_array(lua_State *L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// int mime
|
// int mime
|
||||||
static int l_mime(lua_State* L)
|
static int l_mime(lua_State* L)
|
||||||
{
|
{
|
||||||
@ -262,75 +248,16 @@ 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);
|
void* client = lua_touserdata (L, 1);
|
||||||
const char* v = luaL_checkstring(L, 2);
|
const char* v = luaL_checkstring(L, 2);
|
||||||
lua_pushnumber(L, __t(client,v));
|
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);
|
void * client = lua_touserdata(L,1);
|
||||||
byte_array_t * arr = l_check_barray(L,2);
|
byte_array_t * arr = l_check_barray(L,2);
|
||||||
lua_pushnumber(L, __b(client, arr->data,arr->size));
|
lua_pushnumber(L, __b(client, arr->data,arr->size));
|
||||||
@ -338,8 +265,7 @@ static int l_b(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//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);
|
void* client = lua_touserdata (L, 1);
|
||||||
const char* v = luaL_checkstring(L, 2);
|
const char* v = luaL_checkstring(L, 2);
|
||||||
lua_pushnumber(L, __f(client,v));
|
lua_pushnumber(L, __f(client,v));
|
||||||
@ -355,8 +281,7 @@ static int l_f(lua_State *L)
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
//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* s = luaL_checkstring(L, 1);
|
||||||
const char* d = luaL_checkstring(L, 2);
|
const char* d = luaL_checkstring(L, 2);
|
||||||
lua_pushnumber(L, upload(s,d));
|
lua_pushnumber(L, upload(s,d));
|
||||||
@ -623,8 +548,7 @@ static int l_ws_read_data(lua_State *L)
|
|||||||
{
|
{
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
free(header);
|
free(header);
|
||||||
if (data)
|
if(data) free(data);
|
||||||
free(data);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,6 +574,7 @@ static int l_ws_read_data(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);
|
||||||
@ -772,8 +697,6 @@ static const struct luaL_Reg standard[] = {
|
|||||||
//{"_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},
|
||||||
@ -804,7 +727,10 @@ static const struct luaL_Reg standard[] = {
|
|||||||
{"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)
|
||||||
{
|
{
|
||||||
@ -816,7 +742,10 @@ 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)
|
||||||
{
|
{
|
||||||
|
@ -1,34 +1,49 @@
|
|||||||
#include <antd/plugin.h>
|
#include <antd/plugin.h>
|
||||||
#include <sys/socket.h>
|
#include <antd/scheduler.h>
|
||||||
#include <netinet/tcp.h>
|
#include <antd/dbhelper.h>
|
||||||
#include <errno.h>
|
#include <sys/stat.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;
|
|
||||||
|
|
||||||
void* lua_handle(void* ptr)
|
* convert antd dictionary to lua table
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void push_dict_to_lua(lua_State* L, dictionary_t d)
|
||||||
{
|
{
|
||||||
lua_thread_data_t* data = (lua_thread_data_t*)ptr;
|
lua_newtable(L);
|
||||||
|
|
||||||
|
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;
|
||||||
antd_client_t* cl = (antd_client_t*) malloc(sizeof(antd_client_t));
|
//char * index = __s("%s/%s",__plugin__.htdocs,"router.lua");
|
||||||
cl->sock = data->fd;
|
char* cnf = __s("%s%s%s", __plugin__->pdir,DIR_SEP, __plugin__->name);
|
||||||
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);
|
||||||
@ -39,24 +54,25 @@ void* lua_handle(void* ptr)
|
|||||||
// API header
|
// API header
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
lua_pushstring(L,"name");
|
lua_pushstring(L,"name");
|
||||||
lua_pushstring(L, data->__plugin__->name);
|
lua_pushstring(L, __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, data->__plugin__->htdocs);
|
lua_pushstring(L, buf);
|
||||||
//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");
|
||||||
lua_pushstring(L, data->__plugin__->tmpdir);
|
tmpdir(buf);
|
||||||
|
lua_pushstring(L, buf);
|
||||||
lua_settable(L,-3);
|
lua_settable(L,-3);
|
||||||
|
|
||||||
lua_pushstring(L,"dbpath");
|
lua_pushstring(L,"dbpath");
|
||||||
lua_pushstring(L, data->__plugin__->dbpath);
|
lua_pushstring(L, __plugin__->dbpath);
|
||||||
lua_settable(L,-3);
|
lua_settable(L,-3);
|
||||||
|
|
||||||
lua_setglobal(L, "__api__");
|
lua_setglobal(L, "__api__");
|
||||||
@ -64,20 +80,15 @@ void* lua_handle(void* ptr)
|
|||||||
// Request
|
// Request
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
lua_pushstring(L,"id");
|
lua_pushstring(L,"id");
|
||||||
lua_pushlightuserdata(L, cl);
|
lua_pushlightuserdata(L, rq->client);
|
||||||
//lua_pushnumber(L,client);
|
//lua_pushnumber(L,client);
|
||||||
lua_settable(L, -3);
|
lua_settable(L, -3);
|
||||||
|
|
||||||
lua_pushstring(L,"socket");
|
lua_pushstring(L,"request");
|
||||||
lua_pushnumber(L, cl->sock);
|
push_dict_to_lua(L,rq->request);
|
||||||
//lua_pushnumber(L,client);
|
|
||||||
lua_settable(L, -3);
|
lua_settable(L, -3);
|
||||||
|
|
||||||
//lua_pushstring(L,"request");
|
|
||||||
//push_dict_to_lua(L,rq->request);
|
|
||||||
//lua_settable(L, -3);
|
|
||||||
lua_setglobal(L, "HTTP_REQUEST");
|
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))
|
||||||
@ -91,7 +102,7 @@ void* lua_handle(void* ptr)
|
|||||||
__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", cl->sock);
|
LOG("LUA handle exit on %d", rq->client->sock);
|
||||||
// clear request
|
// clear request
|
||||||
if(L)
|
if(L)
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
@ -99,7 +110,6 @@ void* lua_handle(void* ptr)
|
|||||||
free(cnf);
|
free(cnf);
|
||||||
if(apis)
|
if(apis)
|
||||||
free(apis);
|
free(apis);
|
||||||
(void) antd_close(cl);
|
return antd_create_task(NULL, (void*)rq, NULL,rq->client->last_io);
|
||||||
return 0;
|
|
||||||
//lua_close(L);
|
//lua_close(L);
|
||||||
}
|
}
|
||||||
|
@ -381,19 +381,16 @@ 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;
|
||||||
size_t sz = 0;
|
off_t off = 0;
|
||||||
char* old = NULL;
|
if (unlink(new) < 0 && errno != ENOENT) {
|
||||||
char* new = NULL;
|
lua_pushboolean(L,0);
|
||||||
if(lua_isnumber(L,1))
|
goto end_send_file;
|
||||||
{
|
|
||||||
fromfd = (int)luaL_checknumber(L,1);
|
|
||||||
}
|
}
|
||||||
else
|
if ((fromfd = open(old, O_RDONLY)) < 0 ||
|
||||||
{
|
(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;
|
||||||
}
|
}
|
||||||
@ -403,57 +400,24 @@ static int l_send_file(lua_State* L)
|
|||||||
lua_pushboolean(L,0);
|
lua_pushboolean(L,0);
|
||||||
goto end_send_file;
|
goto end_send_file;
|
||||||
}
|
}
|
||||||
sz = st.st_size;
|
size_t sz = st.st_size;
|
||||||
}
|
|
||||||
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;
|
int read = 0;
|
||||||
while (
|
while (read != sz && (ret = sendfile(tofd, fromfd, &off, sz - read)) == 0)
|
||||||
sz > 0 &&
|
|
||||||
read != sz &&
|
|
||||||
(
|
|
||||||
((ret = sendfile(tofd, fromfd, &off, sz - read)) >= 0) ||
|
|
||||||
(errno == EAGAIN)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if(ret < 0) ret = 0;
|
|
||||||
read += ret;
|
read += ret;
|
||||||
}
|
}
|
||||||
if(read != sz)
|
if(ret != 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 && old)
|
if(fromfd >= 0)
|
||||||
{
|
{
|
||||||
(void) close(fromfd);
|
(void) close(fromfd);
|
||||||
}
|
}
|
||||||
if(tofd >= 0 && new)
|
if(tofd >= 0)
|
||||||
{
|
{
|
||||||
(void) close(tofd);
|
(void) close(tofd);
|
||||||
}
|
}
|
||||||
|
633
lib/asl/wurl.c
Normal file
633
lib/asl/wurl.c
Normal file
@ -0,0 +1,633 @@
|
|||||||
|
#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;
|
||||||
|
}
|
300
lua-api.c
300
lua-api.c
@ -2,105 +2,31 @@
|
|||||||
#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"
|
||||||
#define MAX_SOCK_NAME 64
|
static void* core = NULL;
|
||||||
#define SOCKET_NAME "lua.sock"
|
static void* lua_handle = NULL;
|
||||||
|
static void *(*handle_fn)(void *, void*);
|
||||||
|
|
||||||
#define MAX_SESSION_TIMEOUT (15u * 60u) //15 min
|
void init()
|
||||||
#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;
|
||||||
(void)snprintf(path, BUFFLEN, "%s/lua/core.so", __plugin__.pdir);
|
char* path = __s("%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
|
||||||
(void)snprintf(path, BUFFLEN, "%s/lua/handle.so", __plugin__.pdir);
|
path = __s("%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());
|
||||||
@ -114,210 +40,26 @@ static void lua_serve()
|
|||||||
handle_fn = NULL;
|
handle_fn = NULL;
|
||||||
return;
|
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)
|
|
||||||
{
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(core)
|
|
||||||
(void)dlclose(core);
|
|
||||||
if(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");
|
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)
|
void* handle(void* data)
|
||||||
{
|
{
|
||||||
|
plugin_header_t* meta_ptr = (void*)meta();
|
||||||
antd_request_t *rq = (antd_request_t *)data;
|
antd_request_t *rq = (antd_request_t *)data;
|
||||||
// connect to socket
|
// find the handle function and execute it
|
||||||
int fd = open_unix_socket();
|
if(!handle_fn)
|
||||||
if(fd < 0)
|
|
||||||
{
|
{
|
||||||
antd_error(rq->client, 503, "Service unavailable");
|
antd_error(rq->client, 503, "Requested service not found");
|
||||||
return antd_create_task(NULL, data, NULL, rq->client->last_io);
|
return antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io);
|
||||||
}
|
}
|
||||||
LOG("Connected to lua server at %d", fd);
|
return handle_fn(data, meta_ptr);
|
||||||
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()
|
void destroy()
|
||||||
{
|
{
|
||||||
if(pid > 0)
|
if(core)
|
||||||
{
|
(void)dlclose(core);
|
||||||
kill(pid, SIGHUP);
|
if(lua_handle)
|
||||||
}
|
(void)dlclose(lua_handle);
|
||||||
LOG("Exit LUA Handle");
|
LOG("Exit LUA Handle");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user