mirror of
https://github.com/jorisvink/kore
synced 2025-03-09 04:29:02 -04:00
Initial lua runtime.
Works enough so one can do basic configuration and handle HTTP.
This commit is contained in:
parent
2f5d274059
commit
4718bae098
10
Makefile
10
Makefile
@ -117,6 +117,16 @@ ifneq ("$(PYTHON)", "")
|
||||
FEATURES_INC+=$(KORE_PYTHON_INC)
|
||||
endif
|
||||
|
||||
ifneq ("$(LUA)", "")
|
||||
S_SRC+=src/lua.c
|
||||
KORE_LUA_LIB?=$(shell pkg-config --libs lua)
|
||||
KORE_LUA_INC?=$(shell pkg-config --cflags lua)
|
||||
LDFLAGS+=$(KORE_LUA_LIB)
|
||||
CFLAGS+=$(KORE_LUA_INC) -DKORE_USE_LUA
|
||||
FEATURES+=-DKORE_USE_LUA
|
||||
FEATURES_INC+=$(KORE_LUA_INC)
|
||||
endif
|
||||
|
||||
OSNAME=$(shell uname -s | sed -e 's/[-_].*//g' | tr A-Z a-z)
|
||||
ifeq ("$(OSNAME)", "freebsd")
|
||||
KORE_CURL_LIB=-L/usr/local/lib -lcurl
|
||||
|
@ -274,6 +274,7 @@ extern struct connection_list disconnected;
|
||||
|
||||
#define KORE_RUNTIME_NATIVE 0
|
||||
#define KORE_RUNTIME_PYTHON 1
|
||||
#define KORE_RUNTIME_LUA 2
|
||||
|
||||
struct kore_runtime {
|
||||
int type;
|
||||
@ -413,8 +414,9 @@ struct kore_auth {
|
||||
#define KORE_MODULE_LOAD 1
|
||||
#define KORE_MODULE_UNLOAD 2
|
||||
|
||||
#define KORE_MODULE_NATIVE 0
|
||||
#define KORE_MODULE_PYTHON 1
|
||||
#define KORE_MODULE_NATIVE KORE_RUNTIME_NATIVE
|
||||
#define KORE_MODULE_PYTHON KORE_RUNTIME_PYTHON
|
||||
#define KORE_MODULE_LUA KORE_RUNTIME_LUA
|
||||
|
||||
struct kore_module;
|
||||
|
||||
@ -894,13 +896,10 @@ const char *kore_connection_ip(struct connection *);
|
||||
void kore_log_init(void);
|
||||
void kore_log_file(const char *);
|
||||
|
||||
#if defined(KORE_USE_PYTHON)
|
||||
int kore_configure_setting(const char *, char *);
|
||||
#endif
|
||||
|
||||
/* config.c */
|
||||
void kore_parse_config(void);
|
||||
void kore_parse_config_file(FILE *);
|
||||
int kore_configure_setting(const char *, char *);
|
||||
|
||||
/* mem.c */
|
||||
void *kore_malloc(size_t);
|
||||
|
30
include/kore/lua_api.h
Normal file
30
include/kore/lua_api.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Joris Vink <joris@coders.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __H_LUA_API_H
|
||||
#define __H_LUA_API_H
|
||||
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
void kore_lua_init(void);
|
||||
void kore_lua_cleanup(void);
|
||||
|
||||
extern struct kore_module_functions kore_lua_module;
|
||||
extern struct kore_runtime kore_lua_runtime;
|
||||
|
||||
#endif
|
49
include/kore/lua_methods.h
Normal file
49
include/kore/lua_methods.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Joris Vink <joris@coders.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __H_LUA_METHODS_H
|
||||
#define __H_LUA_METHODS_H
|
||||
|
||||
static int lua_http_request_gc(lua_State *);
|
||||
static int lua_http_request_index(lua_State *);
|
||||
|
||||
static int lua_http_response(lua_State *);
|
||||
static int lua_http_request_header(lua_State *);
|
||||
static int lua_http_response_header(lua_State *);
|
||||
|
||||
static const luaL_Reg lua_http_request_meta[] = {
|
||||
{ "__gc", lua_http_request_gc },
|
||||
{ "__index", lua_http_request_index },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
static const luaL_Reg lua_http_request_methods[] = {
|
||||
{ "response", lua_http_response },
|
||||
{ "request_header", lua_http_request_header },
|
||||
{ "response_header", lua_http_response_header },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
static int lua_kore_config(lua_State *);
|
||||
static int lua_kore_server(lua_State *);
|
||||
|
||||
static const luaL_Reg lua_kore_functions[] = {
|
||||
{ "config", lua_kore_config },
|
||||
{ "server", lua_kore_server },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
#endif
|
10
src/config.c
10
src/config.c
@ -93,6 +93,7 @@ static int configure_socket_backlog(char *);
|
||||
static int configure_privsep_skip(char *);
|
||||
static int configure_privsep_root(char *);
|
||||
static int configure_privsep_runas(char *);
|
||||
static int configure_deployment(char *);
|
||||
|
||||
#if defined(KORE_USE_PLATFORM_PLEDGE)
|
||||
static int configure_add_pledge(char *);
|
||||
@ -157,7 +158,6 @@ static int configure_task_threads(char *);
|
||||
#endif
|
||||
|
||||
#if defined(KORE_USE_PYTHON)
|
||||
static int configure_deployment(char *);
|
||||
static int configure_python_path(char *);
|
||||
static int configure_python_import(char *);
|
||||
#endif
|
||||
@ -240,6 +240,7 @@ static struct {
|
||||
{ "tls_cipher", configure_tls_cipher },
|
||||
{ "tls_dhparam", configure_tls_dhparam },
|
||||
{ "rand_file", configure_rand_file },
|
||||
{ "deployment", configure_deployment },
|
||||
#if defined(KORE_USE_ACME)
|
||||
{ "acme_email", configure_acme_email },
|
||||
{ "acme_provider", configure_acme_provider },
|
||||
@ -269,9 +270,6 @@ static struct {
|
||||
{ "websocket_maxframe", configure_websocket_maxframe },
|
||||
{ "websocket_timeout", configure_websocket_timeout },
|
||||
#endif
|
||||
#if defined(KORE_USE_PYTHON)
|
||||
{ "deployment", configure_deployment },
|
||||
#endif
|
||||
#if defined(KORE_USE_PGSQL)
|
||||
{ "pgsql_conn_max", configure_pgsql_conn_max },
|
||||
{ "pgsql_queue_limit", configure_pgsql_queue_limit },
|
||||
@ -524,7 +522,6 @@ kore_parse_config_file(FILE *fp)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(KORE_USE_PYTHON)
|
||||
int
|
||||
kore_configure_setting(const char *name, char *value)
|
||||
{
|
||||
@ -544,7 +541,6 @@ kore_configure_setting(const char *name, char *value)
|
||||
kore_log(LOG_NOTICE, "ignoring unknown kore.config.%s setting", name);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
configure_check_var(char **var, const char *other, const char *logmsg)
|
||||
@ -2015,7 +2011,6 @@ configure_task_threads(char *option)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(KORE_USE_PYTHON)
|
||||
static int
|
||||
configure_deployment(char *value)
|
||||
{
|
||||
@ -2040,6 +2035,7 @@ configure_deployment(char *value)
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
#if defined(KORE_USE_PYTHON)
|
||||
static int
|
||||
configure_python_path(char *path)
|
||||
{
|
||||
|
30
src/kore.c
30
src/kore.c
@ -46,6 +46,10 @@
|
||||
#include "python_api.h"
|
||||
#endif
|
||||
|
||||
#if defined(KORE_USE_LUA)
|
||||
#include "lua_api.h"
|
||||
#endif
|
||||
|
||||
#if defined(KORE_USE_ACME)
|
||||
#include "acme.h"
|
||||
#endif
|
||||
@ -97,11 +101,11 @@ static const char *parent_daemonized_hook = KORE_DAEMONIZED_HOOK;
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
#if defined(KORE_USE_PYTHON)
|
||||
printf("Usage: %s [options] [app | app.py]\n", __progname);
|
||||
#else
|
||||
printf("Usage: %s [options]\n", __progname);
|
||||
#endif
|
||||
if (kore_runtime_count() > 0) {
|
||||
printf("Usage: %s [options] [app | script]\n", __progname);
|
||||
} else {
|
||||
printf("Usage: %s [options]\n", __progname);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf("Command-line options:\n");
|
||||
@ -151,6 +155,10 @@ version(void)
|
||||
#if defined(KORE_USE_PYTHON)
|
||||
printf("python-%s ", PY_VERSION);
|
||||
#endif
|
||||
#if defined(KORE_USE_LUA)
|
||||
printf("lua-%s.%s.%s ",
|
||||
LUA_VERSION_MAJOR, LUA_VERSION_MINOR, LUA_VERSION_RELEASE);
|
||||
#endif
|
||||
#if defined(KORE_USE_ACME)
|
||||
printf("acme ");
|
||||
#endif
|
||||
@ -234,8 +242,8 @@ main(int argc, char *argv[])
|
||||
kore_domain_init();
|
||||
kore_module_init();
|
||||
|
||||
#if !defined(KORE_SINGLE_BINARY) && !defined(KORE_USE_PYTHON)
|
||||
if (config_file == NULL)
|
||||
#if !defined(KORE_SINGLE_BINARY)
|
||||
if (kore_runtime_count() == 0 && config_file == NULL)
|
||||
usage();
|
||||
#endif
|
||||
kore_module_load(NULL, NULL, KORE_MODULE_NATIVE);
|
||||
@ -244,6 +252,10 @@ main(int argc, char *argv[])
|
||||
kore_python_init();
|
||||
#endif
|
||||
|
||||
#if defined(KORE_USE_LUA)
|
||||
kore_lua_init();
|
||||
#endif
|
||||
|
||||
#if !defined(KORE_SINGLE_BINARY)
|
||||
if (kore_runtime_count() > 0 && rarg0 != NULL)
|
||||
kore_runtime_resolve(rarg0, &st);
|
||||
@ -294,6 +306,10 @@ main(int argc, char *argv[])
|
||||
kore_python_cleanup();
|
||||
#endif
|
||||
|
||||
#if defined(KORE_USE_LUA)
|
||||
kore_lua_cleanup();
|
||||
#endif
|
||||
|
||||
kore_mem_cleanup();
|
||||
|
||||
return (kore_quit);
|
||||
|
626
src/lua.c
Normal file
626
src/lua.c
Normal file
@ -0,0 +1,626 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Joris Vink <joris@coders.se>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "kore.h"
|
||||
|
||||
#if !defined(KORE_NO_HTTP)
|
||||
#include "http.h"
|
||||
#endif
|
||||
|
||||
#include "lua_api.h"
|
||||
#include "lua_methods.h"
|
||||
|
||||
struct lua_http_request {
|
||||
struct http_request *req;
|
||||
};
|
||||
|
||||
struct lua_symbol {
|
||||
lua_State *L;
|
||||
int ref;
|
||||
LIST_ENTRY(lua_symbol) list;
|
||||
};
|
||||
|
||||
struct lua_module {
|
||||
lua_State *L;
|
||||
LIST_HEAD(, lua_symbol) symbols;
|
||||
};
|
||||
|
||||
static int lua_runtime_resolve(const char *, const struct stat *);
|
||||
static int lua_runtime_http_request(void *, struct http_request *);
|
||||
static void lua_runtime_http_request_free(void *, struct http_request *);
|
||||
static void lua_runtime_http_body_chunk(void *, struct http_request *,
|
||||
const void *, size_t);
|
||||
static int lua_runtime_validator(void *, struct http_request *,
|
||||
const void *);
|
||||
static void lua_runtime_wsmessage(void *, struct connection *,
|
||||
u_int8_t, const void *, size_t);
|
||||
static void lua_runtime_execute(void *);
|
||||
static int lua_runtime_onload(void *, int);
|
||||
static void lua_runtime_signal(void *, int);
|
||||
static void lua_runtime_configure(void *, int, char **);
|
||||
static void lua_runtime_connect(void *, struct connection *);
|
||||
|
||||
static void lua_module_load(struct kore_module *);
|
||||
static void lua_module_free(struct kore_module *);
|
||||
static void lua_module_reload(struct kore_module *);
|
||||
static void *lua_module_getsym(struct kore_module *, const char *);
|
||||
|
||||
static void *lua_mem_alloc(void *, void *, size_t, size_t);
|
||||
|
||||
static int lua_kore_module_init(lua_State *);
|
||||
static void lua_symbol_resolve(struct lua_symbol *, lua_State **);
|
||||
|
||||
static int lua_argument_get_bool(lua_State *, const char *);
|
||||
static const char *lua_argument_get_string(lua_State *, const char *);
|
||||
//static int lua_argument_get_integer(lua_State *, const char *,
|
||||
// lua_Integer *);
|
||||
|
||||
struct kore_module_functions kore_lua_module = {
|
||||
.free = lua_module_free,
|
||||
.load = lua_module_load,
|
||||
.getsym = lua_module_getsym,
|
||||
.reload = lua_module_reload
|
||||
};
|
||||
|
||||
struct kore_runtime kore_lua_runtime = {
|
||||
KORE_RUNTIME_LUA,
|
||||
.resolve = lua_runtime_resolve,
|
||||
.http_request = lua_runtime_http_request,
|
||||
.http_body_chunk = lua_runtime_http_body_chunk,
|
||||
.http_request_free = lua_runtime_http_request_free,
|
||||
.validator = lua_runtime_validator,
|
||||
.wsconnect = lua_runtime_connect,
|
||||
.wsmessage = lua_runtime_wsmessage,
|
||||
.wsdisconnect = lua_runtime_connect,
|
||||
.onload = lua_runtime_onload,
|
||||
.signal = lua_runtime_signal,
|
||||
.connect = lua_runtime_connect,
|
||||
.execute = lua_runtime_execute,
|
||||
.configure = lua_runtime_configure,
|
||||
};
|
||||
|
||||
#define LUA_CONSTANT(x) { #x, x }
|
||||
|
||||
static struct {
|
||||
const char *symbol;
|
||||
int value;
|
||||
} lua_integers[] = {
|
||||
LUA_CONSTANT(LOG_ERR),
|
||||
LUA_CONSTANT(LOG_INFO),
|
||||
LUA_CONSTANT(LOG_NOTICE),
|
||||
LUA_CONSTANT(HTTP_METHOD_GET),
|
||||
LUA_CONSTANT(HTTP_METHOD_PUT),
|
||||
LUA_CONSTANT(HTTP_METHOD_POST),
|
||||
LUA_CONSTANT(HTTP_METHOD_HEAD),
|
||||
LUA_CONSTANT(HTTP_METHOD_PATCH),
|
||||
LUA_CONSTANT(HTTP_METHOD_DELETE),
|
||||
LUA_CONSTANT(HTTP_METHOD_OPTIONS),
|
||||
{ NULL, -1 },
|
||||
};
|
||||
|
||||
void
|
||||
kore_lua_init(void)
|
||||
{
|
||||
if (!kore_configure_setting("deployment", "dev"))
|
||||
fatal("failed to set initial deployment to dev");
|
||||
}
|
||||
|
||||
void
|
||||
kore_lua_cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void *
|
||||
lua_mem_alloc(void *uptr, void *ptr, size_t osize, size_t nsize)
|
||||
{
|
||||
if (nsize == 0) {
|
||||
kore_free(ptr);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (kore_realloc(ptr, nsize));
|
||||
}
|
||||
|
||||
static void
|
||||
lua_symbol_resolve(struct lua_symbol *sym, lua_State **L)
|
||||
{
|
||||
lua_rawgeti(sym->L, LUA_REGISTRYINDEX, sym->ref);
|
||||
*L = sym->L;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int
|
||||
lua_argument_get_integer(lua_State *L, const char *field, lua_Integer *ret)
|
||||
{
|
||||
int type;
|
||||
|
||||
lua_pushstring(L, field);
|
||||
type = lua_gettable(L, -2);
|
||||
|
||||
if (type == LUA_TNIL) {
|
||||
lua_pop(L, 1);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
luaL_argcheck(L, type == LUA_TNUMBER, 0, field);
|
||||
|
||||
*ret = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
lua_argument_get_bool(lua_State *L, const char *field)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lua_pushstring(L, field);
|
||||
ret = lua_gettable(L, -2);
|
||||
|
||||
if (ret == LUA_TNIL) {
|
||||
lua_pop(L, 1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
luaL_argcheck(L, ret == LUA_TBOOLEAN, 0, field);
|
||||
|
||||
ret = lua_toboolean(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static const char *
|
||||
lua_argument_get_string(lua_State *L, const char *field)
|
||||
{
|
||||
const char *v;
|
||||
int type;
|
||||
|
||||
lua_pushstring(L, field);
|
||||
type = lua_gettable(L, -2);
|
||||
|
||||
if (type == LUA_TNIL) {
|
||||
lua_pop(L, 1);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
luaL_argcheck(L, type == LUA_TSTRING, 0, field);
|
||||
|
||||
v = lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return (v);
|
||||
}
|
||||
|
||||
static int
|
||||
lua_kore_module_init(lua_State *L)
|
||||
{
|
||||
int i;
|
||||
|
||||
luaL_newlib(L, lua_kore_functions);
|
||||
|
||||
for (i = 0; lua_integers[i].symbol != NULL; i++) {
|
||||
lua_pushstring(L, lua_integers[i].symbol);
|
||||
lua_pushnumber(L, lua_integers[i].value);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
lua_module_free(struct kore_module *module)
|
||||
{
|
||||
struct lua_symbol *sym;
|
||||
struct lua_module *lua;
|
||||
|
||||
lua = module->handle;
|
||||
|
||||
while ((sym = LIST_FIRST(&lua->symbols)) != NULL) {
|
||||
LIST_REMOVE(sym, list);
|
||||
kore_free(sym);
|
||||
}
|
||||
|
||||
kore_free(lua);
|
||||
}
|
||||
|
||||
static void
|
||||
lua_module_reload(struct kore_module *module)
|
||||
{
|
||||
lua_module_free(module);
|
||||
lua_module_load(module);
|
||||
}
|
||||
|
||||
static void
|
||||
lua_module_load(struct kore_module *module)
|
||||
{
|
||||
struct lua_module *lua;
|
||||
|
||||
lua = kore_calloc(1, sizeof(*lua));
|
||||
LIST_INIT(&lua->symbols);
|
||||
|
||||
if ((lua->L = lua_newstate(lua_mem_alloc, NULL)) == NULL)
|
||||
fatal("luaL_newstate");
|
||||
|
||||
luaL_openlibs(lua->L);
|
||||
|
||||
luaL_requiref(lua->L, "kore", lua_kore_module_init, 1);
|
||||
lua_pop(lua->L, 1);
|
||||
|
||||
luaL_newmetatable(lua->L, "http_request");
|
||||
luaL_setfuncs(lua->L, lua_http_request_meta, 0);
|
||||
lua_pop(lua->L, 1);
|
||||
|
||||
lua_pushliteral(lua->L, "http_request_methods");
|
||||
luaL_newlib(lua->L, lua_http_request_methods);
|
||||
lua_settable(lua->L, LUA_REGISTRYINDEX);
|
||||
|
||||
luaL_newlib(lua->L, lua_http_request_methods);
|
||||
lua_pop(lua->L, 1);
|
||||
|
||||
if (luaL_loadfile(lua->L, module->path) != LUA_OK) {
|
||||
fatal("%s: failed to import module (%s)", module->path,
|
||||
lua_tostring(lua->L, -1));
|
||||
}
|
||||
|
||||
if (lua_pcall(lua->L, 0, 0, 0) != LUA_OK) {
|
||||
fatal("%s: failed to import module (%s)", module->path,
|
||||
lua_tostring(lua->L, -1));
|
||||
}
|
||||
|
||||
module->handle = lua;
|
||||
}
|
||||
|
||||
static void *
|
||||
lua_module_getsym(struct kore_module *module, const char *symbol)
|
||||
{
|
||||
int ref;
|
||||
struct lua_module *lua;
|
||||
struct lua_symbol *sym;
|
||||
|
||||
lua = module->handle;
|
||||
|
||||
if (lua_getglobal(lua->L, symbol) != LUA_TFUNCTION)
|
||||
return (NULL);
|
||||
|
||||
if ((ref = luaL_ref(lua->L, LUA_REGISTRYINDEX)) == LUA_REFNIL)
|
||||
return (NULL);
|
||||
|
||||
sym = kore_calloc(1, sizeof(*sym));
|
||||
|
||||
sym->ref = ref;
|
||||
sym->L = lua->L;
|
||||
|
||||
LIST_INSERT_HEAD(&lua->symbols, sym, list);
|
||||
|
||||
return (sym);
|
||||
}
|
||||
|
||||
static int
|
||||
lua_runtime_resolve(const char *module, const struct stat *st)
|
||||
{
|
||||
const char *ext;
|
||||
|
||||
if (!S_ISREG(st->st_mode))
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
ext = strrchr(module, '.');
|
||||
|
||||
if (ext == NULL || strcasecmp(ext, ".lua"))
|
||||
return (KORE_RESULT_ERROR);
|
||||
|
||||
kore_module_load(module, NULL, KORE_MODULE_LUA);
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
lua_runtime_http_request(void *addr, struct http_request *req)
|
||||
{
|
||||
lua_State *L;
|
||||
struct lua_http_request *lreq;
|
||||
|
||||
lua_symbol_resolve(addr, &L);
|
||||
|
||||
lreq = lua_newuserdata(L, sizeof(*lreq));
|
||||
luaL_setmetatable(L, "http_request");
|
||||
|
||||
lreq->req = req;
|
||||
|
||||
if (lua_pcall(L, 1, 0, 0)) {
|
||||
kore_log(LOG_NOTICE, "%s: failed to call handler: %s", __func__,
|
||||
lua_tostring(L, -1));
|
||||
http_response(req, 500, NULL, 0);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
static void
|
||||
lua_runtime_http_request_free(void *addr, struct http_request *req)
|
||||
{
|
||||
fatal("%s: not yet implemented", __func__);
|
||||
}
|
||||
|
||||
static void
|
||||
lua_runtime_http_body_chunk(void *addr, struct http_request *req,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
fatal("%s: not yet implemented", __func__);
|
||||
}
|
||||
|
||||
static int
|
||||
lua_runtime_validator(void *addr, struct http_request *req, const void *data)
|
||||
{
|
||||
fatal("%s: not yet implemented", __func__);
|
||||
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
static void
|
||||
lua_runtime_wsmessage(void *addr, struct connection *c, u_int8_t op,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
fatal("%s: not yet implemented", __func__);
|
||||
}
|
||||
|
||||
static void
|
||||
lua_runtime_execute(void *addr)
|
||||
{
|
||||
lua_State *L;
|
||||
|
||||
lua_symbol_resolve(addr, &L);
|
||||
|
||||
if (lua_pcall(L, 0, 0, 0)) {
|
||||
fatal("failed to execute function: %s",
|
||||
lua_tostring(L, -1));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lua_runtime_configure(void *addr, int argc, char **argv)
|
||||
{
|
||||
lua_State *L;
|
||||
int idx;
|
||||
|
||||
lua_symbol_resolve(addr, &L);
|
||||
|
||||
lua_pushinteger(L, argc);
|
||||
lua_newtable(L);
|
||||
|
||||
for (idx = 0; idx < argc; idx++) {
|
||||
lua_pushstring(L, argv[idx]);
|
||||
lua_rawseti(L, -2, idx);
|
||||
}
|
||||
|
||||
if (lua_pcall(L, 2, 0, 0)) {
|
||||
fatal("failed to configure your application (%s)",
|
||||
lua_tostring(L, -1));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
lua_runtime_onload(void *addr, int action)
|
||||
{
|
||||
fatal("%s: not yet implemented", __func__);
|
||||
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
static void
|
||||
lua_runtime_connect(void *addr, struct connection *c)
|
||||
{
|
||||
fatal("%s: not yet implemented", __func__);
|
||||
}
|
||||
|
||||
static void
|
||||
lua_runtime_signal(void *addr, int sig)
|
||||
{
|
||||
fatal("%s: not yet implemented", __func__);
|
||||
}
|
||||
|
||||
static int
|
||||
lua_kore_config(lua_State *L)
|
||||
{
|
||||
char *v;
|
||||
const char *opt, *val;
|
||||
|
||||
lua_pushnil(L);
|
||||
|
||||
while (lua_next(L, -2) != 0) {
|
||||
if (!lua_isstring(L, -2))
|
||||
fatal("kore.config: keyword not a string");
|
||||
|
||||
opt = lua_tostring(L, -2);
|
||||
|
||||
if (lua_isinteger(L, -1)) {
|
||||
lua_pushvalue(L, -1);
|
||||
val = lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
} else if (lua_isstring(L, -1)) {
|
||||
val = lua_tostring(L, -1);
|
||||
} else {
|
||||
fatal("kore.config: value not a string or integer");
|
||||
}
|
||||
|
||||
v = kore_strdup(val);
|
||||
|
||||
if (!kore_configure_setting(opt, v)) {
|
||||
kore_free(v);
|
||||
luaL_error(L, "kore.config: cannot be set at runtime");
|
||||
lua_pop(L, 1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
kore_free(v);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
lua_kore_server(lua_State *L)
|
||||
{
|
||||
struct kore_server *srv;
|
||||
const char *name, *ip, *port;
|
||||
|
||||
if ((name = lua_argument_get_string(L, "name")) == NULL)
|
||||
name = "default";
|
||||
|
||||
if ((ip = lua_argument_get_string(L, "ip")) == NULL) {
|
||||
luaL_error(L, "kore.server: missing ip keyword");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if ((port = lua_argument_get_string(L, "port")) == NULL) {
|
||||
luaL_error(L, "kore.server: missing port keyword");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if ((srv = kore_server_lookup(name)) != NULL) {
|
||||
luaL_error(L, "kore.server: server '%s' exists", name);
|
||||
return (0);
|
||||
}
|
||||
|
||||
srv = kore_server_create(name);
|
||||
srv->tls = lua_argument_get_bool(L, "tls");
|
||||
|
||||
if (srv->tls && !kore_tls_supported()) {
|
||||
kore_server_free(srv);
|
||||
luaL_error(L, "kore.server: TLS not supported");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (!kore_server_bind(srv, ip, port, NULL)) {
|
||||
kore_server_free(srv);
|
||||
luaL_error(L, "kore.server: failed to bind %s:%s", ip, port);
|
||||
return (0);
|
||||
}
|
||||
|
||||
kore_server_finalize(srv);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
lua_http_request_gc(lua_State *L)
|
||||
{
|
||||
struct lua_http_request *lreq;
|
||||
|
||||
lreq = luaL_checkudata(L, 1, "http_request");
|
||||
kore_free(lreq);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
lua_http_request_index(lua_State *L)
|
||||
{
|
||||
struct lua_http_request *lreq;
|
||||
const char *field;
|
||||
|
||||
lreq = luaL_checkudata(L, 1, "http_request");
|
||||
field = luaL_checkstring(L, 2);
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "http_request_methods");
|
||||
lua_getfield(L, -1, field);
|
||||
|
||||
if (!lua_isnil(L, -1))
|
||||
return (1);
|
||||
|
||||
lua_pop(L, 2);
|
||||
|
||||
if (!strcmp(field, "path")) {
|
||||
lua_pushstring(L, lreq->req->path);
|
||||
return (1);
|
||||
} else if (!strcmp(field, "host")) {
|
||||
lua_pushstring(L, lreq->req->host);
|
||||
return (1);
|
||||
} else if (!strcmp(field, "agent")) {
|
||||
lua_pushstring(L, lreq->req->agent);
|
||||
return (1);
|
||||
} else if (!strcmp(field, "referer")) {
|
||||
lua_pushstring(L, lreq->req->referer);
|
||||
return (1);
|
||||
} else if (!strcmp(field, "method")) {
|
||||
lua_pushinteger(L, lreq->req->method);
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
lua_http_response_header(lua_State *L)
|
||||
{
|
||||
struct lua_http_request *lreq;
|
||||
const char *header, *value;
|
||||
|
||||
lreq = luaL_checkudata(L, 1, "http_request");
|
||||
header = luaL_checkstring(L, 2);
|
||||
value = luaL_checkstring(L, 3);
|
||||
|
||||
http_response_header(lreq->req, header, value);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
lua_http_request_header(lua_State *L)
|
||||
{
|
||||
struct lua_http_request *lreq;
|
||||
const char *header, *value;
|
||||
|
||||
lreq = luaL_checkudata(L, 1, "http_request");
|
||||
header = luaL_checkstring(L, 2);
|
||||
|
||||
if (!http_request_header(lreq->req, header, &value)) {
|
||||
lua_pushnil(L);
|
||||
} else {
|
||||
lua_pushstring(L, value);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
lua_http_response(lua_State *L)
|
||||
{
|
||||
size_t len;
|
||||
struct lua_http_request *lreq;
|
||||
const void *data;
|
||||
int status;
|
||||
|
||||
lreq = luaL_checkudata(L, 1, "http_request");
|
||||
status = luaL_checkinteger(L, 2);
|
||||
|
||||
if (lua_isnil(L, 3)) {
|
||||
len = 0;
|
||||
data = NULL;
|
||||
} else {
|
||||
data = luaL_checklstring(L, 3, &len);
|
||||
}
|
||||
|
||||
http_response(lreq->req, status, data, len);
|
||||
|
||||
return (0);
|
||||
}
|
10
src/module.c
10
src/module.c
@ -29,6 +29,10 @@
|
||||
#include "python_api.h"
|
||||
#endif
|
||||
|
||||
#if defined(KORE_USE_LUA)
|
||||
#include "lua_api.h"
|
||||
#endif
|
||||
|
||||
static TAILQ_HEAD(, kore_module) modules;
|
||||
|
||||
static void native_free(struct kore_module *);
|
||||
@ -92,6 +96,12 @@ kore_module_load(const char *path, const char *onload, int type)
|
||||
module->fun = &kore_python_module;
|
||||
module->runtime = &kore_python_runtime;
|
||||
break;
|
||||
#endif
|
||||
#if defined(KORE_USE_LUA)
|
||||
case KORE_MODULE_LUA:
|
||||
module->fun = &kore_lua_module;
|
||||
module->runtime = &kore_lua_runtime;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fatal("kore_module_load: unknown type %d", type);
|
||||
|
@ -206,7 +206,6 @@ kore_pool_put(struct kore_pool *pool, void *ptr)
|
||||
pool_mark_entry_none(pool, entry);
|
||||
|
||||
pool->freelist = entry;
|
||||
|
||||
#if defined(KORE_USE_TASKS)
|
||||
pool_unlock(pool);
|
||||
#endif
|
||||
|
@ -27,6 +27,10 @@
|
||||
#include "python_api.h"
|
||||
#endif
|
||||
|
||||
#if defined(KORE_USE_LUA)
|
||||
#include "lua_api.h"
|
||||
#endif
|
||||
|
||||
static void native_runtime_execute(void *);
|
||||
static int native_runtime_onload(void *, int);
|
||||
static void native_runtime_signal(void *, int);
|
||||
@ -65,6 +69,9 @@ struct kore_runtime kore_native_runtime = {
|
||||
static struct kore_runtime *runtimes[] = {
|
||||
#if defined(KORE_USE_PYTHON)
|
||||
&kore_python_runtime,
|
||||
#endif
|
||||
#if defined(KORE_USE_LUA)
|
||||
&kore_lua_runtime,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user