/* BSD-2-Clause license * * Copyright (c) 2018-2023 NST , sss . * */ #include #include #include #include #include #include #include #include #include #include "cmdline.h" #include "config_file.h" #include "ev_loop.h" #include "exports.h" #include "globals.h" #include "thread_impl.h" #include "utilities.h" #include "wrdp_thpool.h" #include "ws_session.h" #include "remote_control.h" #include "curl_helpers.h" #include "thread_sync.h" globals g_globals; static void custom_thread_init(void *user_pool_data, wrdp_thpool_thread *t) { per_thread_curl_init(user_pool_data, t); } static void init_internals() { if (g_globals.settings.thread_count <= 0) { g_globals.settings.thread_count = sysconf(_SC_NPROCESSORS_ONLN); } if (g_globals.settings.thread_count <= 0) { g_globals.settings.thread_count = 2; } if (!init_exports()) { printf("error: failed to initialize core exports\n"); exit(EXIT_FAILURE); } /* random seed */ srand(time(0) + 13); LIST_INIT(&(g_globals.backends_head)); void *c = init_curl_global(); g_globals.thpool = wrdp_thpool_create(g_globals.settings.thread_count, g_globals.settings.tasks_per_thread, custom_thread_init, 0, 0, 0, pool_message_handler, thread_message_handler, EV_DEFAULT, c); } static void settings_load_default() { memset(&g_globals, 0, sizeof(globals)); memset(&g_globals.settings, 0, sizeof(global_settings)); g_globals.settings.secret_key_verify[0] = 0; g_globals.settings.secret_key_sign[0] = 0; g_globals.settings.thread_count = -1; } static void settings_validate() { bool failure = false; if (!g_globals.settings.ws_port) g_globals.settings.ws_port = 8080; if (!g_globals.settings.ctl_port) g_globals.settings.ctl_port = 13666; if (!g_globals.settings.tasks_per_thread) g_globals.settings.tasks_per_thread = 1024; if (!g_globals.settings.secret_key_verify[0]) { printf("\"secret_key_verify\" must be set\n"); failure = true; } if (!g_globals.settings.secret_key_sign[0]) { strcpy(g_globals.settings.secret_key_sign, g_globals.settings.secret_key_verify); } if (!g_globals.settings.ctl_ssl_cert) { printf("\"ctl_ssl_cert\" must be set\n"); failure = true; } if (!g_globals.settings.ctl_ssl_key) { printf("\"ctl_ssl_key\" must be set\n"); failure = true; } if (failure) { exit(EXIT_FAILURE); } } void shutdown_core() { free(g_globals.exports); } static void daemonize() { pid_t p = fork(); if (p) { printf("child process forked, exiting parent\n"); exit(EXIT_SUCCESS); } /* TODO: */ } /* https://stackoverflow.com/questions/77005/how-to-automatically * -generate-a-stacktrace-when-my-program-crashes */ /*static void sigsegv_handler(int sig) { void *array[100]; size_t size; // get void*'s for all entries on the stack size = backtrace (array, 100); // print out all the frames to stderr fprintf(stderr, "Error: signal %d:\n", sig); backtrace_symbols_fd (array, size, STDERR_FILENO); exit (EXIT_FAILURE); } */ #ifdef DEBUG /* https://github.com/cslarsen/libunwind-examples/blob/master/backtrace.cpp */ static void sigsegv_handler(int sig) { unw_cursor_t cursor; unw_context_t context; unw_getcontext(&context); unw_init_local(&cursor, &context); int n = 0; while (unw_step(&cursor) > 0) { unw_word_t ip, sp, off; unw_get_reg(&cursor, UNW_REG_IP, &ip); unw_get_reg(&cursor, UNW_REG_SP, &sp); char symbol[256] = {""}; char *name = symbol; unw_get_proc_name(&cursor, symbol, sizeof(symbol), &off); printf("#%-2d 0x%016" PRIxPTR " sp=0x%016" PRIxPTR " %s + 0x%" PRIxPTR "\n", ++n, ip, sp, name, off); if (name != symbol) free(name); } exit(EXIT_FAILURE); } /* this is required to generate gprof profile */ static void sigusr2_handler(int sif) { exit(EXIT_SUCCESS); } #endif int main(int argc, char **argv) { #ifdef DEBUG signal(SIGSEGV, sigsegv_handler); signal(SIGUSR2, sigusr2_handler); #endif settings_load_default(); handle_cmdline_args(argc, argv); if (g_globals.settings.daemon) { daemonize(); } settings_validate(); init_internals(); { int ws_tcp_sock = ws_server_init(); int ws_unix_sock = ws_server_init_unix(); int ctl_server_tcp_sock = ctl_server_init_tcp(); int ctl_server_unix_sock = ctl_server_init_unix(); //init_remote_control(); run_ev_loop_main(ws_tcp_sock, ws_unix_sock, ctl_server_tcp_sock, ctl_server_unix_sock); } shutdown_core(); return 0; }