kore

Kore is a web application platform for writing scalable, concurrent web based processes in C or Python.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit 2f5d274059dcb6a55b4c5b7014b7064ffe31f716
parent d21c0aab5fcf1ae6db061cda8d02ba114986f694
Author: Joris Vink <joris@coders.se>
Date:   Mon, 16 Jan 2023 21:00:01 +0100

Rework runtime init a little bit.

It was hardcoded that if KORE_USE_PYTHON was defined we would
look at the passed argument on the command-line as the python
script or module to be run.

This won't work when adding more runtimes.

So instead call a kore_runtime_resolve() function that in
turn calls each available runtime its resolve function.

That resolve function will check if its a script / module
that it can load, and if so will load it.

This way we can remove all those KORE_USE_PYTHON blocks in the
Kore startup path and we pave the way for lua.

Diffstat:
include/kore/kore.h | 6++++++
include/kore/python_api.h | 4----
src/kore.c | 96+++++++++++++++++++++++++++++++++++++++++--------------------------------------
src/python.c | 34+++++++++++++++++++++++++++++++++-
src/runtime.c | 32++++++++++++++++++++++++++++++++
src/tls_none.c | 5+++++
src/tls_openssl.c | 12++++++++++--
7 files changed, 136 insertions(+), 53 deletions(-)

diff --git a/include/kore/kore.h b/include/kore/kore.h @@ -25,6 +25,7 @@ #include <sys/types.h> #include <sys/time.h> #include <sys/queue.h> +#include <sys/stat.h> #include <sys/un.h> #include <netinet/in.h> @@ -276,6 +277,7 @@ extern struct connection_list disconnected; struct kore_runtime { int type; + int (*resolve)(const char *, const struct stat *); #if !defined(KORE_NO_HTTP) int (*http_request)(void *, struct http_request *); void (*http_request_free)(void *, struct http_request *); @@ -749,6 +751,7 @@ void kore_server_closeall(void); void kore_server_cleanup(void); void kore_server_free(struct kore_server *); void kore_server_finalize(struct kore_server *); +void kore_hooks_set(const char *, const char *, const char *); struct kore_server *kore_server_create(const char *); struct kore_server *kore_server_lookup(const char *); @@ -819,6 +822,7 @@ void kore_tls_dh_check(void); int kore_tls_supported(void); void kore_tls_version_set(int); void kore_tls_keymgr_init(void); +void kore_tls_log_version(void); int kore_tls_dh_load(const char *); void kore_tls_seed(const void *, size_t); int kore_tls_ciphersuite_set(const char *); @@ -1024,6 +1028,7 @@ int kore_route_lookup(struct http_request *, #endif /* runtime.c */ +const size_t kore_runtime_count(void); struct kore_runtime_call *kore_runtime_getcall(const char *); struct kore_module *kore_module_load(const char *, const char *, int); @@ -1031,6 +1036,7 @@ struct kore_module *kore_module_load(const char *, void kore_runtime_execute(struct kore_runtime_call *); int kore_runtime_onload(struct kore_runtime_call *, int); void kore_runtime_signal(struct kore_runtime_call *, int); +void kore_runtime_resolve(const char *, const struct stat *); void kore_runtime_configure(struct kore_runtime_call *, int, char **); void kore_runtime_connect(struct kore_runtime_call *, struct connection *); #if !defined(KORE_NO_HTTP) diff --git a/include/kore/python_api.h b/include/kore/python_api.h @@ -44,10 +44,6 @@ void kore_python_seccomp_cleanup(void); void kore_python_seccomp_hook(const char *); #endif -#if !defined(KORE_SINGLE_BINARY) -extern const char *kore_pymodule; -#endif - extern struct kore_module_functions kore_python_module; extern struct kore_runtime kore_python_runtime; diff --git a/src/kore.c b/src/kore.c @@ -62,7 +62,7 @@ int skip_chroot = 0; u_int8_t worker_count = 0; char **kore_argv = NULL; int kore_mem_guard = 0; -int kore_foreground = 0; +int kore_foreground = 1; char *kore_progname = NULL; u_int32_t kore_socket_backlog = 5000; int kore_quit = KORE_QUIT_NONE; @@ -83,16 +83,16 @@ static void kore_server_shutdown(void); static void kore_server_start(int, char *[]); static void kore_call_parent_configure(int, char **); -#if !defined(KORE_SINGLE_BINARY) && defined(KORE_USE_PYTHON) -static const char *parent_config_hook = KORE_PYTHON_CONFIG_HOOK; -static const char *parent_teardown_hook = KORE_PYTHON_TEARDOWN_HOOK; -#else +#if !defined(KORE_SINGLE_BINARY) +static const char *rarg0 = NULL; +#endif + static const char *parent_config_hook = KORE_CONFIG_HOOK; static const char *parent_teardown_hook = KORE_TEARDOWN_HOOK; + #if defined(KORE_SINGLE_BINARY) static const char *parent_daemonized_hook = KORE_DAEMONIZED_HOOK; #endif -#endif static void usage(void) @@ -167,10 +167,10 @@ version(void) int main(int argc, char *argv[]) { - struct kore_runtime_call *rcall; -#if !defined(KORE_SINGLE_BINARY) && defined(KORE_USE_PYTHON) +#if !defined(KORE_SINGLE_BINARY) struct stat st; #endif + struct kore_runtime_call *rcall; kore_argc = argc; kore_argv = argv; @@ -192,23 +192,22 @@ main(int argc, char *argv[]) argv += optind; #endif -#if !defined(KORE_SINGLE_BINARY) && defined(KORE_USE_PYTHON) - if (argc > 0) { - kore_pymodule = argv[0]; - argc--; - argv++; - } else { - kore_pymodule = NULL; - } - - if (kore_pymodule) { - if (lstat(kore_pymodule, &st) == -1) { - fatal("failed to stat '%s': %s", - kore_pymodule, errno_s); +#if !defined(KORE_SINGLE_BINARY) + if (kore_runtime_count() > 0) { + if (argc > 0) { + rarg0 = argv[0]; + argc--; + argv++; } - if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) - fatal("%s: not a directory or file", kore_pymodule); + if (rarg0) { + if (lstat(rarg0, &st) == -1) { + if (errno == ENOENT) + rarg0 = NULL; + else + fatal("stat(%s): %s", rarg0, errno_s); + } + } } #endif @@ -243,25 +242,17 @@ main(int argc, char *argv[]) #if defined(KORE_USE_PYTHON) kore_python_init(); -#if !defined(KORE_SINGLE_BINARY) - if (kore_pymodule) { - kore_module_load(kore_pymodule, NULL, KORE_MODULE_PYTHON); - if (S_ISDIR(st.st_mode) && chdir(kore_pymodule) == -1) - fatal("chdir(%s): %s", kore_pymodule, errno_s); - } else { - /* swap back to non-python hooks. */ - parent_config_hook = KORE_CONFIG_HOOK; - parent_teardown_hook = KORE_TEARDOWN_HOOK; - } #endif + +#if !defined(KORE_SINGLE_BINARY) + if (kore_runtime_count() > 0 && rarg0 != NULL) + kore_runtime_resolve(rarg0, &st); #endif #if defined(KORE_SINGLE_BINARY) kore_call_parent_configure(argc, argv); -#endif - -#if defined(KORE_USE_PYTHON) && !defined(KORE_SINGLE_BINARY) - if (kore_pymodule) +#else + if (kore_runtime_count() > 0 && rarg0 != NULL) kore_call_parent_configure(argc, argv); #endif @@ -314,9 +305,9 @@ kore_default_getopt(int argc, char **argv) int ch; #if !defined(KORE_SINGLE_BINARY) - while ((ch = getopt(argc, argv, "c:fhnqrv")) != -1) { + while ((ch = getopt(argc, argv, "c:dfhnqrv")) != -1) { #else - while ((ch = getopt(argc, argv, "fhnqrv")) != -1) { + while ((ch = getopt(argc, argv, "dfhnqrv")) != -1) { #endif switch (ch) { #if !defined(KORE_SINGLE_BINARY) @@ -326,8 +317,12 @@ kore_default_getopt(int argc, char **argv) fatal("strdup"); break; #endif + case 'd': + kore_foreground = 0; + break; case 'f': - kore_foreground = 1; + printf("note: -f is the default now, " + "use -d to daemonize\n"); break; case 'h': usage(); @@ -763,6 +758,17 @@ kore_proctitle(const char *title) memset(kore_argv[0] + len, 0, proctitle_maxlen - len); } +void +kore_hooks_set(const char *config, const char *teardown, const char *daemonized) +{ + parent_config_hook = config; + parent_teardown_hook = teardown; + +#if defined(KORE_SINGLE_BINARY) + parent_daemonized_hook = daemonized; +#endif +} + static void kore_proctitle_setup(void) { @@ -827,6 +833,8 @@ kore_server_start(int argc, char *argv[]) ); } + kore_tls_log_version(); + if (kore_foreground == 0) { if (daemon(1, 0) == -1) fatal("cannot daemon(): %s", errno_s); @@ -842,12 +850,8 @@ kore_server_start(int argc, char *argv[]) kore_pid = getpid(); kore_write_kore_pid(); -#if !defined(KORE_SINGLE_BINARY) && !defined(KORE_USE_PYTHON) - kore_call_parent_configure(argc, argv); -#endif - -#if defined(KORE_USE_PYTHON) && !defined(KORE_SINGLE_BINARY) - if (kore_pymodule == NULL) +#if !defined(KORE_SINGLE_BINARY) + if (kore_runtime_count() == 0 || rarg0 == NULL) kore_call_parent_configure(argc, argv); #endif diff --git a/src/python.c b/src/python.c @@ -167,6 +167,7 @@ static void python_push_integer(PyObject *, const char *, long); static void python_push_type(const char *, PyObject *, PyTypeObject *); static int python_validator_check(PyObject *); +static int python_runtime_resolve(const char *, const struct stat *); static int python_runtime_http_request(void *, struct http_request *); static void python_runtime_http_request_free(void *, struct http_request *); static void python_runtime_http_body_chunk(void *, struct http_request *, @@ -200,6 +201,7 @@ struct kore_module_functions kore_python_module = { struct kore_runtime kore_python_runtime = { KORE_RUNTIME_PYTHON, + .resolve = python_runtime_resolve, .http_request = python_runtime_http_request, .http_body_chunk = python_runtime_http_body_chunk, .http_request_free = python_runtime_http_request_free, @@ -330,7 +332,7 @@ static PyObject *python_tracer = NULL; static struct python_coro *coro_running = NULL; #if !defined(KORE_SINGLE_BINARY) -const char *kore_pymodule = NULL; +static const char *kore_pymodule = NULL; #endif void @@ -1279,6 +1281,36 @@ pyhttp_file_dealloc(struct pyhttp_file *pyfile) } static int +python_runtime_resolve(const char *module, const struct stat *st) +{ + const char *ext; + + if (!S_ISDIR(st->st_mode) && !S_ISREG(st->st_mode)) + return (KORE_RESULT_ERROR); + + if (S_ISDIR(st->st_mode)) { + kore_module_load(module, NULL, KORE_MODULE_PYTHON); + if (chdir(module) == -1) + fatal("chdir(%s): %s", module, errno_s); + } else { + if ((ext = strrchr(module, '.')) == NULL) + return (KORE_RESULT_ERROR); + + if (strcasecmp(ext, ".py")) + return (KORE_RESULT_ERROR); + + kore_module_load(module, NULL, KORE_MODULE_PYTHON); + } + + kore_pymodule = module; + + kore_hooks_set(KORE_PYTHON_CONFIG_HOOK, + KORE_PYTHON_TEARDOWN_HOOK, KORE_PYTHON_DAEMONIZED_HOOK); + + return (KORE_RESULT_OK); +} + +static int python_runtime_http_request(void *addr, struct http_request *req) { int ret, idx, cnt; diff --git a/src/runtime.c b/src/runtime.c @@ -62,6 +62,38 @@ struct kore_runtime kore_native_runtime = { .configure = native_runtime_configure }; +static struct kore_runtime *runtimes[] = { +#if defined(KORE_USE_PYTHON) + &kore_python_runtime, +#endif + NULL +}; + +const size_t +kore_runtime_count(void) +{ + return ((sizeof(runtimes) / sizeof(runtimes[0])) - 1); +} + +void +kore_runtime_resolve(const char *module, const struct stat *st) +{ + int i; + + if (runtimes[0] == NULL) + return; + + for (i = 0; runtimes[i] != NULL; i++) { + if (runtimes[i]->resolve == NULL) + continue; + if (runtimes[i]->resolve(module, st)) + break; + } + + if (runtimes[i] == NULL) + fatal("No runtime available to run '%s'", module); +} + struct kore_runtime_call * kore_runtime_getcall(const char *symbol) { diff --git a/src/tls_none.c b/src/tls_none.c @@ -41,6 +41,11 @@ kore_keymgr_cleanup(int final) void kore_tls_init(void) { +} + +void +kore_tls_log_version(void) +{ kore_log(LOG_NOTICE, "No compiled in TLS backend"); } diff --git a/src/tls_openssl.c b/src/tls_openssl.c @@ -111,15 +111,23 @@ kore_tls_init(void) #if !defined(LIBRESSL_VERSION_NUMBER) if (!CRYPTO_set_mem_functions(tls_malloc, tls_realloc, tls_free)) fatalx("CRYPTO_set_mem_functions failed"); -#else - kore_log(LOG_NOTICE, "libressl does not support malloc-wrappers"); #endif SSL_library_init(); SSL_load_error_strings(); ERR_load_crypto_strings(); +} + +void +kore_tls_log_version(void) +{ kore_log(LOG_NOTICE, "TLS backend %s", OPENSSL_VERSION_TEXT); + +#if defined(LIBRESSL_VERSION_NUMBER) + kore_log(LOG_NOTICE, "libressl does not support malloc-wrappers"); +#endif + #if !defined(TLS1_3_VERSION) if (!kore_quiet) { kore_log(LOG_NOTICE,