diff options
| -rw-r--r-- | library/lullaby/net.lua | 8 | ||||
| -rw-r--r-- | src/lua.c | 27 | ||||
| -rw-r--r-- | src/lua.h | 7 | ||||
| -rw-r--r-- | src/net.c | 27 | ||||
| -rw-r--r-- | src/net.h | 5 | ||||
| -rw-r--r-- | src/net/common.h | 5 | ||||
| -rw-r--r-- | src/table.c | 1 | ||||
| -rw-r--r-- | src/thread.c | 56 | ||||
| -rw-r--r-- | tests/tests.lua | 44 | ||||
| -rw-r--r-- | tests/units/thread-buffer.lua | 21 | ||||
| -rw-r--r-- | tests/units/thread-local-return.lua | 13 | ||||
| -rw-r--r-- | tests/units/thread-locals.lua | 12 | ||||
| -rw-r--r-- | tests/units/thread-nested.lua | 22 |
13 files changed, 206 insertions, 42 deletions
diff --git a/library/lullaby/net.lua b/library/lullaby/net.lua index 416851f..7ff24aa 100644 --- a/library/lullaby/net.lua +++ b/library/lullaby/net.lua @@ -146,6 +146,14 @@ function net.listen(callback, port) end ---@return request-return | error function net.srequest(url, content, header, request) end +---creates an http request +---@param url string +---@param content string | nil +---@param header table<string, string> | nil +---@param request string | nil +---@return request-return | error +function net.request(url, content, header, request) end + ---@class wss-table local wss = {} @@ -179,7 +179,7 @@ void luaI_deepcopy(lua_State* src, lua_State* dest, enum deep_copy_flags flags){ switch(type = lua_type(src, -1)){
case LUA_TNUMBER:
n = lua_tonumber(src, -1);
- if(n == (uint64_t)n) lua_pushinteger(dest, lua_tonumber(src, -1));
+ if(n == (uint64_t)n) lua_pushinteger(dest, (uint64_t)lua_tonumber(src, -1));
else lua_pushnumber(dest, n);
break;
case LUA_TBOOLEAN:
@@ -254,6 +254,7 @@ void luaI_deepcopy(lua_State* src, lua_State* dest, enum deep_copy_flags flags){ lua_dump(src, writer, (void*)awa, 0);
luaL_loadbuffer(dest, awa->c, awa->len, "fun");
+ if(!(flags & SKIP_LOCALS)) lua_assign_upvalues(dest, lua_gettop(dest));
//lua_remove(dest, -2);
str_free(awa);
break;
@@ -394,19 +395,29 @@ void luaI_jointable(lua_State* L, int main, int merge){ //copys all variables from state A to B, including locals (stored in _locals)
//populates _ENV the same as _G
void luaI_copyvars(lua_State* from, lua_State* to){
- lua_getglobal(from, "_G");
- luaI_deepcopy(from, to, SKIP_GC | SKIP__G);
- lua_set_global_table(to);
+ lua_getglobal(from, "_locals");
+ int x = lua_gettop(from);
- env_table(from, 0);
- luaI_deepcopy(from, to, SKIP_GC);
+ if(lua_isnil(from, x)){
+ lua_pop(from, 1);
+ x = 0;
+ }
+
+ env_table(from, x != 0);
+ luaI_deepcopy(from, to, SKIP_GC | SKIP_LOCALS);
int idx = lua_gettop(to);
lua_pushglobaltable(to);
int tidx = lua_gettop(to);
luaI_tsetv(to, idx, "_ENV", tidx);
-
luaI_tsetv(to, tidx, "_locals", idx);
+
+ lua_getglobal(from, "_G");
+ luaI_deepcopy(from, to, SKIP_GC | SKIP__G);
+ lua_set_global_table(to);
+
+ lua_pushvalue(to, idx);
+ lua_setglobal(to, "_locals");
}
/**
@@ -459,7 +470,7 @@ int lua_assign_upvalues(lua_State* L, int fidx){ lua_setupvalue(L, fidx, lua_tointeger(L, -2));
}
- lua_pushvalue(L, fidx);
+ lua_settop(L, fidx);
return 0;
}
@@ -12,6 +12,7 @@ enum deep_copy_flags { SKIP_GC = (1 << 1),
IS_META = (1 << 2),
SKIP__G = (1 << 3),
+ SKIP_LOCALS = (1 << 4),
};
#endif
@@ -38,9 +39,9 @@ typedef int (*stream_free_function)(void**); void luaI_newstream(lua_State* L, stream_read_function, stream_free_function, void*);
int luaI_nothing(lua_State*);
+int env_table(lua_State* L, int provide_table);
void luaI_jointable(lua_State* L, int main, int merge);
-
//generic macro that takes other macros (see below)
#define _tset_b(L, Tidx, K, V, F)\
lua_pushstring(L, K);\
@@ -65,6 +66,10 @@ void luaI_jointable(lua_State* L, int main, int merge); _tset_b(L, Tidx, K, V, lua_pushcfunction)
#define luaI_tsetlud(L, Tidx, K, V)\
_tset_b(L, Tidx, K, V, lua_pushlightuserdata)
+#define luaI_tsetnil(L, Tidx, K)\
+ lua_pushstring(L, K);\
+ lua_pushnil(L);\
+ lua_settable(L, Tidx);
#define luaI_treplk(L, Tidx, K, nK){\
lua_pushstring(L, K);\
@@ -740,19 +740,19 @@ void* handle_client(void *_arg){ str* aa = str_init(portc);
struct net_path_t parsed_path;
path_parse(&parsed_path, path);
-
+
str* decoded_path;
int decoded_err = percent_decode(parsed_path.path, &decoded_path);
larray_t* params = NULL;
parray_t* v = NULL;
- if(decoded_err == 1 || paths == NULL){
+ if(decoded_err == 1 || args->paths == NULL){
net_error(client_fd, 400);
} else {
str_push(aa, decoded_path->c);
params = larray_init();
- v = route_match(paths, aa->c, ¶ms);
+ v = route_match(args->paths, aa->c, ¶ms);
if(sT != NULL)
rolling_file_parse(L, &files_idx, &body_idx, header + 4, sT, bite - header_eof - 4, file_cont);
@@ -929,7 +929,7 @@ int clean_lullaby_net(lua_State* L){ return 0;
}
-int start_serv(lua_State* L, int port){
+int start_serv(lua_State* L, int port, parray_t* paths){
parse_mimetypes();
//need these on windows for sockets (stupid)
#ifdef _WIN32
@@ -982,6 +982,7 @@ int start_serv(lua_State* L, int port){ args->port = port;
args->cli = client_addr;
args->L = luaL_newstate();
+ args->paths = paths;
int old_top = lua_gettop(L);
lua_getglobal(L, "_G");
@@ -1004,6 +1005,10 @@ int start_serv(lua_State* L, int port){ }
int l_req_com(lua_State* L, char* req){
+ lua_pushstring(L, "paths");
+ lua_gettable(L, 1);
+ parray_t* paths = lua_touserdata(L, -1);
+
lua_pushstring(L, "port");
lua_gettable(L, 1);
int port = luaL_checkinteger(L, -1);
@@ -1024,9 +1029,6 @@ int l_req_com(lua_State* L, char* req){ strcpy(awa->req, req);
free(uwu); //yes this *should* be str_free but awa kinda owns it now:p
- if(paths == NULL)
- paths = parray_init();
-
//please free this
void* v_old_paths = parray_get(paths, portss->c);
struct sarray_t* old_paths;
@@ -1085,15 +1087,16 @@ int l_listen(lua_State* L){ luaI_tsetcf(L, mt, "PATCH", l_PATCHq);
luaI_tsetcf(L, mt, "all", l_allq);
- lua_pushstring(L, "port");
- lua_pushvalue(L, 2);
- lua_settable(L, -3);
+ luaI_tsetv(L, mt, "port", 2);
+
+ parray_t* paths = parray_init();
+ luaI_tsetlud(L, mt, "paths", paths);
lua_pushvalue(L, 1); //the function
- lua_pushvalue(L, -2); //the server table
+ lua_pushvalue(L, mt); //the server table
lua_pcall(L, 1, 0, 0);
- start_serv(L, port);
+ start_serv(L, port, paths);
return 0;
}
@@ -36,10 +36,7 @@ int content_disposition(str* src, parray_t** _dest); void* handle_client(void *_arg);
-int start_serv(lua_State* L, int port);
-
-//
-static char* http_codes[600] = {0};
+int start_serv(lua_State* L, int port, parray_t* paths);
int clean_lullaby_net(lua_State* L);
diff --git a/src/net/common.h b/src/net/common.h index 947eee7..dfac2e5 100644 --- a/src/net/common.h +++ b/src/net/common.h @@ -5,7 +5,6 @@ #include <stdio.h> #include <stdlib.h> #include <pthread.h> -#define _GNU_SOURCE #include <string.h> #include <unistd.h> #include <sys/stat.h> @@ -26,9 +25,6 @@ #define HTTP_BUFFER_SIZE 4098 #define max_content_length 200000 -static int ports[65535] = { 0 }; -static parray_t* paths = NULL; - enum file_status { _ignore, BARRIER_READ, FILE_HEADER, FILE_BODY, NORMAL }; @@ -44,6 +40,7 @@ typedef struct { int port; lua_State* L; struct sockaddr_in cli; + parray_t* paths; } thread_arg_struct; struct lchar { diff --git a/src/table.c b/src/table.c index 9caca0b..418da3a 100644 --- a/src/table.c +++ b/src/table.c @@ -1,6 +1,5 @@ #include "table.h" #include <stdlib.h> -#define _GNU_SOURCE #include <string.h> #include <stdint.h> diff --git a/src/thread.c b/src/thread.c index 5aed694..bb412ba 100644 --- a/src/thread.c +++ b/src/thread.c @@ -207,12 +207,28 @@ int _thread_await(lua_State* L){ if(!info->done) pthread_mutex_lock(&*info->lock);
info->done = 1;
+ env_table(info->L, 0);
+ luaI_deepcopy(info->L, L, SKIP_LOCALS);
+ lua_pop(info->L, 1);
+ env_table(L, 0);
+ luaI_jointable(L);
+
+ lua_setglobal(L, "_locals");
+
for(int i = 0; i != info->return_count; i++){
int ot = lua_gettop(info->L);
lua_pushvalue(info->L, ot - info->return_count + i);
+
luaI_deepcopy(info->L, L, 0);
-
+
+ int type = lua_type(info->L, ot - info->return_count + i);
+ if(type == LUA_TTABLE || type == LUA_TUSERDATA){
+ lua_getmetatable(info->L, ot - info->return_count + i);
+ int idx = lua_gettop(info->L);
+ luaI_tsetnil(info->L, idx, "__gc");
+ }
+
lua_settop(info->L, ot);
}
@@ -224,18 +240,19 @@ int _thread_clean(lua_State* L){ lua_gettable(L, 1);
struct thread_info* info = lua_touserdata(L, -1);
if(info != NULL && info->L != NULL){
-
+ luaI_tsetnil(L, 1, "_");
+
//lua_gc(info->L, LUA_GCRESTART);
lua_gc(info->L, LUA_GCCOLLECT);
+
lua_close(info->L);
+
info->L = NULL;
pthread_mutex_destroy(&*info->lock);
free(info->lock);
pthread_cancel(info->tid);
free(info);
-
- luaI_tsetlud(L, 1, "_", NULL);
}
return 0;
}
@@ -295,7 +312,7 @@ struct thread_buffer { int _buffer_get(lua_State* L){
struct thread_buffer *buffer = lua_touserdata(L, 1);
pthread_mutex_lock(&*buffer->lock);
- luaI_deepcopy(buffer->L, L, SKIP_GC);
+ luaI_deepcopy(buffer->L, L, SKIP_GC | SKIP_LOCALS);
pthread_mutex_unlock(&*buffer->lock);
return 1;
}
@@ -304,8 +321,13 @@ int _buffer_set(lua_State* L){ struct thread_buffer *buffer = lua_touserdata(L, 1);
pthread_mutex_lock(&*buffer->lock);
lua_settop(buffer->L, 0);
- luaI_deepcopy(L, buffer->L, SKIP_GC);
+ luaI_deepcopy(L, buffer->L, SKIP_LOCALS);
pthread_mutex_unlock(&*buffer->lock);
+
+ lua_getmetatable(L, 2);
+ int idx = lua_gettop(L);
+ luaI_tsetnil(L, idx, "__gc");
+
return 1;
}
@@ -319,15 +341,20 @@ int _buffer_mod(lua_State* L){ assert(used == 0);
used = 1;
- luaI_deepcopy(buffer->L, L, SKIP_GC);
+ luaI_deepcopy(buffer->L, L, SKIP_GC | SKIP_LOCALS);
int item = lua_gettop(L);
lua_pushvalue(L, 2);
lua_pushvalue(L, item);
lua_call(L, 1, 1);
if(lua_type(L, -1) != LUA_TNIL){
+ int idx = lua_gettop(L);
lua_settop(buffer->L, 0);
- luaI_deepcopy(L, buffer->L, SKIP_GC);
+ luaI_deepcopy(L, buffer->L, SKIP_LOCALS);
+
+ lua_getmetatable(L, idx);
+ idx = lua_gettop(L);
+ luaI_tsetnil(L, idx, "__gc");
}
used = 0;
@@ -362,7 +389,7 @@ int l_buffer_index(lua_State* L){ return 1;
}
- luaI_deepcopy(buffer->L, L, SKIP_GC);
+ luaI_deepcopy(buffer->L, L, SKIP_GC | SKIP_LOCALS);
lua_pop(buffer->L, 1);
break;
}
@@ -389,12 +416,12 @@ int meta_proxy(lua_State* L){ for(int i = 4; i <= argc; i++){
count++;
lua_pushvalue(L, i);
- luaI_deepcopy(L, buffer->L, SKIP_GC);
+ luaI_deepcopy(L, buffer->L, SKIP_GC | SKIP_LOCALS);
}
//printf("%i\n",count);
lua_call(buffer->L, count + 1, 1);
- luaI_deepcopy(buffer->L, L, 0);
+ luaI_deepcopy(buffer->L, L, SKIP_LOCALS);
lua_pushnil(buffer->L);
lua_setmetatable(buffer->L, -2);
@@ -453,10 +480,11 @@ int l_buffer(lua_State* L){ int buffer_idx = lua_gettop(L);
buffer->L = luaL_newstate();
+ lua_gc(buffer->L, LUA_GCSTOP);
buffer->lock = malloc(sizeof * buffer->lock);
if(pthread_mutex_init(&*buffer->lock, NULL) != 0) p_fatal("pthread_mutex_init failed");
lua_pushvalue(L, 1);
- luaI_deepcopy(L, buffer->L, SKIP_GC);
+ luaI_deepcopy(L, buffer->L, SKIP_LOCALS);
lua_newtable(L);
int meta_idx = lua_gettop(L);
@@ -464,6 +492,10 @@ int l_buffer(lua_State* L){ luaI_tsetcf(L, meta_idx, "__index", l_buffer_index);
luaI_tsetcf(L, meta_idx, "__gc", l_buffer_gc);
+ lua_getmetatable(L, 1);
+ int idx = lua_gettop(L);
+ luaI_tsetnil(L, idx, "__gc");
+
lua_pushvalue(L, meta_idx);
lua_setmetatable(L, buffer_idx);
lua_pushvalue(L, buffer_idx);
diff --git a/tests/tests.lua b/tests/tests.lua new file mode 100644 index 0000000..b4110d4 --- /dev/null +++ b/tests/tests.lua @@ -0,0 +1,44 @@ +llby = require("lullaby") + +local failed = {} +local total = 0 + +function yay(M) + print(string.format("\27[32m%s\27[0m passed", M)) +end + +function nay(M) + print(string.format("\27[31m%s\27[0m failed", M)) +end + +local search = "" +if arg[1] ~= nil then + search = "*" .. arg[1] .. "*" +end + +local handle = assert(io.popen("find tests/units/".. search .." -type f")) + +for file in handle:lines() do + total = total + 1 + local f = loadfile(file)() + + if f == true then + yay(file) + else + nay(file) + table.insert(failed, file) + end +end + +if #failed > 0 then + print("\n--- failed units (".. #failed .."/".. total ..") ---") + for _,fail in ipairs(failed) do + nay(fail) + end + print("--- failed units (".. #failed .."/".. total ..") ---") +else + print("passed all (".. total ..")") +end + +handle:close() + diff --git a/tests/units/thread-buffer.lua b/tests/units/thread-buffer.lua new file mode 100644 index 0000000..e83ad4a --- /dev/null +++ b/tests/units/thread-buffer.lua @@ -0,0 +1,21 @@ +local h1 = llby.thread.buffer(llby.crypto.md5()) +local h2 = llby.thread.buffer(llby.crypto.sha256()) +local h3 = llby.thread.buffer(llby.crypto.sha1()) + +local tthread = llby.thread.async(function(res) + h1:set(h1:get():update("mrrp")) + h2:set(h2:get():update("mrrp")) + + h3:mod(function(M) + return M:update("mrrp") + end) + + res(h1:get(), h2:get(), h3:get()) +end) + +local h4, h5, h6 = tthread:await() + +return h1:get():final() == h4:final() and h2:get():final() == h5:final() and h3:get():final() == h6:final() + and h4:final() == "be40416e1491ae73fee43a0cf01132fa" + and h5:final() == "a4ba2864e6dcc988c6df73cdfbee6d308e39174dd86dddc4e328c4f2df1c48e9" + and h6:final() == "7bf0ffbd68005c35faa12f5ba6df54288969220c" diff --git a/tests/units/thread-local-return.lua b/tests/units/thread-local-return.lua new file mode 100644 index 0000000..cc6c417 --- /dev/null +++ b/tests/units/thread-local-return.lua @@ -0,0 +1,13 @@ +local a = 224 + +local thread = llby.thread.async(function(res) + local b = 948 + + res(function(c) + return a * b * c + end) +end) + +local fun = thread:await() + +return fun(448) == 224 * 948 * 448 diff --git a/tests/units/thread-locals.lua b/tests/units/thread-locals.lua new file mode 100644 index 0000000..6f328f2 --- /dev/null +++ b/tests/units/thread-locals.lua @@ -0,0 +1,12 @@ +local lvar = 224400 +_G.gvar = 33220 + +function lfun(a, b) + return (a + lvar) * (b + gvar) +end + +local thread = llby.thread.async(function(res) + res(lfun(lvar, gvar)) +end) + +return thread:await() == lfun(lvar, gvar) diff --git a/tests/units/thread-nested.lua b/tests/units/thread-nested.lua new file mode 100644 index 0000000..e0227c6 --- /dev/null +++ b/tests/units/thread-nested.lua @@ -0,0 +1,22 @@ +local mutex = llby.thread.mutex() +mutex:lock() + +local t1 = llby.thread.async(function(res) + + local t2 = llby.thread.async(function(res) + + local t3 = llby.thread.async(function(res) + mutex:lock() + + res(254) + end) + + + res(t3) + end) + + res(t2) +end) + +mutex:unlock() +return t1:await():await():await() == 254 |
