diff --git a/.gitignore b/.gitignore index f1881e8..3527f78 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ tests/testing/ include/sql/*.h emgauwa-core.sqlite +vgcore.* diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ffe4ed..a83fd30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ add_custom_target(sql ) add_custom_target(run - COMMAND ${CMAKE_BINARY_DIR}/core start + COMMAND ${CMAKE_BINARY_DIR}/core DEPENDS core WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) @@ -56,24 +56,24 @@ add_custom_target(docs ) IF(CMAKE_BUILD_TYPE MATCHES Debug) - message("debug mode") + message(STATUS "loading debug targets") add_custom_target(debug COMMAND gdb ${CMAKE_BINARY_DIR}/core DEPENDS core WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) add_custom_target(valgrind - COMMAND valgrind -s ${CMAKE_BINARY_DIR}/core start + COMMAND valgrind -s ${CMAKE_BINARY_DIR}/core DEPENDS core WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) add_custom_target(valgrind-leak - COMMAND valgrind --leak-check=full --show-leak-kinds=all ${CMAKE_BINARY_DIR}/core start + COMMAND valgrind --leak-check=full --show-leak-kinds=all ${CMAKE_BINARY_DIR}/core DEPENDS core WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) add_custom_target(valgrind-callgrind - COMMAND valgrind --tool=callgrind ${CMAKE_BINARY_DIR}/core start + COMMAND valgrind --tool=callgrind ${CMAKE_BINARY_DIR}/core DEPENDS core WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) diff --git a/emgauwa-core.ini b/emgauwa-core.ini index cd40564..0d2ab88 100644 --- a/emgauwa-core.ini +++ b/emgauwa-core.ini @@ -1,6 +1,6 @@ [core] server-port = 5000 -database = core.sqlite +database = emgauwa-core.sqlite content-dir = /usr/share/webapps/emgauwa not-found-file = 404.html not-found-file-mime = text/html diff --git a/include/cli.h b/include/cli.h new file mode 100644 index 0000000..54e48ad --- /dev/null +++ b/include/cli.h @@ -0,0 +1,13 @@ +#ifndef CORE_CLI_H +#define CORE_CLI_H + +typedef struct cli +{ + char *config_path; +} cli_t; + + +void +cli_parse(int argc, const char **argv, config_t *config); + +#endif /* CORE_CLI_H */ diff --git a/include/config.h b/include/config.h index e7e7adb..09f2b31 100644 --- a/include/config.h +++ b/include/config.h @@ -6,12 +6,6 @@ #include #include -typedef enum -{ - RUN_TYPE_START, - RUN_TYPE_INVALID, -} run_type_t; - typedef struct { char *file; @@ -21,7 +15,6 @@ typedef struct char *group; int log_level; FILE *log_file; - run_type_t run_type; uint16_t server_port; uint16_t discovery_port; uint16_t mqtt_port; @@ -33,7 +26,7 @@ typedef struct struct mg_serve_http_opts http_server_opts; } config_t; -extern config_t global_config; +extern config_t *global_config; void config_init(); @@ -42,7 +35,7 @@ void config_free(); void -config_try_ini_files(config_t *config); +config_load_string(char **holder, const char *value); int config_load(IniDispatch *disp, void *config_void); diff --git a/include/constants.h b/include/constants.h index 329868c..358e0a4 100644 --- a/include/constants.h +++ b/include/constants.h @@ -14,13 +14,6 @@ */ #define MAX_NAME_LENGTH 128 -/** - * @brief Maximum number of dbs for the databases for the MDB_env - * - * Used when calling mdb_env_set_maxdbs() in database_setup() - */ -#define MDB_MAXDBS 8 - /** * @brief How many milli seconds to wait until poll timeout in main loop */ @@ -28,4 +21,6 @@ #define PIFACE_GPIO_BASE 200 +#define DEFAULT_CONFIG_PATH "emgauwa-core.ini" + #endif /* CORE_CONTANTS_H */ diff --git a/include/helpers.h b/include/helpers.h index e2ead83..fa2cb30 100644 --- a/include/helpers.h +++ b/include/helpers.h @@ -3,14 +3,10 @@ #include #include -#include int helper_connect_tcp_server(char* host, uint16_t port); -void -helper_parse_cli(int argc, const char **argv, config_t *config); - int helper_get_weekday(const struct tm *time_struct); diff --git a/src/helpers/parse_cli.c b/src/cli.c similarity index 63% rename from src/helpers/parse_cli.c rename to src/cli.c index f205541..afdfccd 100644 --- a/src/helpers/parse_cli.c +++ b/src/cli.c @@ -10,20 +10,20 @@ #include static const char *const usage[] = { - "core [options] [[--] args]", "core [options]", NULL, }; void -helper_parse_cli(int argc, const char **argv, config_t *config) +cli_parse(int argc, const char **argv, config_t *config) { + const char *config_file = NULL; int version = 0; struct argparse_option options[] = { OPT_HELP(), OPT_GROUP("Basic options"), - OPT_STRING('c', "config", &config->file, "path to config file", NULL, 0, OPT_NONEG), + OPT_STRING('c', "config", &config_file, "path to config file", NULL, 0, OPT_NONEG), OPT_BOOLEAN('v', "version", &version, "print version", NULL, 0, OPT_NONEG), OPT_END(), }; @@ -37,27 +37,15 @@ helper_parse_cli(int argc, const char **argv, config_t *config) ); argc = argparse_parse(&argparse, argc, argv); + if(config_file) + { + config_load_string(&config->file, config_file); + } + if(version) { printf("%s\n", EMGAUWA_CORE_VERSION); exit(0); } - - if(argc == 1) - { - config->run_type = RUN_TYPE_INVALID; - if(strcmp(argv[0], "start") == 0) - { - config->run_type = RUN_TYPE_START; - return; - } - LOGGER_CRIT("bad action '%s' given ('start')\n", argv[0]); - exit(1); - } - else - { - LOGGER_CRIT("no action given ('start')\n"); - exit(1); - } return; } diff --git a/src/config.c b/src/config.c index db45711..e4c507c 100644 --- a/src/config.c +++ b/src/config.c @@ -1,10 +1,11 @@ #include #include -#include #include +#include +#include -config_t global_config; +config_t *global_config; #define CONFINI_IS_KEY(SECTION, KEY) \ @@ -57,6 +58,7 @@ config_load_log_level(IniDispatch *disp, config_t *config) return 0; } LOGGER_WARNING("invalid log-level '%s'\n", disp->value); + return 0; } @@ -77,8 +79,49 @@ config_load_log_file(IniDispatch *disp, config_t *config) return 0; } -static void -config_load_string(char **holder, char *value) +void +config_init() +{ + global_config = calloc(1, sizeof(config_t)); + + config_load_string(&global_config->file, DEFAULT_CONFIG_PATH); + + global_config->discovery_port = 4421; + global_config->mqtt_port = 1885; + global_config->server_port = 5000; + + global_config->log_level = LOG_DEBUG; + global_config->log_file = stdout; + + global_config->user = NULL; + global_config->group = NULL; + + config_load_string(&global_config->content_dir, "."); + config_load_string(&global_config->not_found_file, "404.html"); + config_load_string(&global_config->not_found_file_type, "text/html"); + config_load_string(&global_config->not_found_content, "404 - NOT FOUND"); + config_load_string(&global_config->not_found_content_type, "text/plain"); +} + +void +config_free() +{ + free(global_config->file); + free(global_config->include); + free(global_config->database); + free(global_config->user); + free(global_config->group); + free(global_config->content_dir); + free(global_config->not_found_file); + free(global_config->not_found_file_type); + free(global_config->not_found_content); + free(global_config->not_found_content_type); + + free(global_config); +} + +void +config_load_string(char **holder, const char *value) { if(*holder) { @@ -93,50 +136,6 @@ config_load_string(char **holder, char *value) *holder = new_holder; } - -void -config_init() -{ - memset(&global_config, 0, sizeof(config_t)); - - global_config.discovery_port = 4421; - global_config.mqtt_port = 1885; - global_config.server_port = 5000; - - global_config.log_level = LOG_INFO; - global_config.log_file = stdout; - - global_config.user = NULL; - global_config.group = NULL; - - config_load_string(&global_config.content_dir, "."); - config_load_string(&global_config.not_found_file, "404.html"); - config_load_string(&global_config.not_found_file_type, "text/html"); - config_load_string(&global_config.not_found_content, "404 - NOT FOUND"); - config_load_string(&global_config.not_found_content_type, "text/plain"); -} - -void -config_free() -{ - free(global_config.file); - free(global_config.include); - free(global_config.database); - free(global_config.user); - free(global_config.group); - free(global_config.content_dir); - free(global_config.not_found_file); - free(global_config.not_found_file_type); - free(global_config.not_found_content); - free(global_config.not_found_content_type); -} - -void -config_try_ini_files(config_t *config) -{ - (void)config; -} - int config_load(IniDispatch *disp, void *config_void) { diff --git a/src/database.c b/src/database.c index 7a46488..272ef4c 100644 --- a/src/database.c +++ b/src/database.c @@ -13,7 +13,7 @@ static database_transaction_lock *transaction_lock; void database_init() { - int rc = sqlite3_open(global_config.database, &global_database); + int rc = sqlite3_open(global_config->database, &global_database); if(rc) { @@ -21,6 +21,8 @@ database_init() exit(1); } + LOGGER_DEBUG("Opened database %s\n", global_config->database); + database_migrate(); sqlite3_exec(global_database, "PRAGMA foreign_keys = ON", 0, 0, 0); diff --git a/src/endpoint.c b/src/endpoint.c index 5173538..3902e33 100644 --- a/src/endpoint.c +++ b/src/endpoint.c @@ -14,7 +14,7 @@ endpoint_func_index(struct mg_connection *nc, struct http_message *hm, endpoint_ response->status_code = 0; - mg_serve_http(nc, hm, global_config.http_server_opts); + mg_serve_http(nc, hm, global_config->http_server_opts); } void @@ -24,19 +24,19 @@ endpoint_func_not_found(struct mg_connection *nc, struct http_message *hm, endpo (void)hm; (void)nc; - if(access(global_config.not_found_file, R_OK) != -1) + if(access(global_config->not_found_file, R_OK) != -1) { - struct mg_str mime_type = mg_mk_str(global_config.not_found_file_type); + struct mg_str mime_type = mg_mk_str(global_config->not_found_file_type); response->status_code = 0; - mg_http_serve_file(nc, hm, global_config.not_found_file, mime_type, mg_mk_str("")); + mg_http_serve_file(nc, hm, global_config->not_found_file, mime_type, mg_mk_str("")); } else { LOGGER_DEBUG("404 file not found\n"); response->status_code = 404; - response->content_type = global_config.not_found_content_type; - response->content_length = strlen(global_config.not_found_content); - response->content = global_config.not_found_content; + response->content_type = global_config->not_found_content_type; + response->content_length = strlen(global_config->not_found_content); + response->content = global_config->not_found_content; response->alloced_content = false; } diff --git a/src/endpoints/api_v1_controllers_discover.c b/src/endpoints/api_v1_controllers_discover.c index 189e5b6..6ba374e 100644 --- a/src/endpoints/api_v1_controllers_discover.c +++ b/src/endpoints/api_v1_controllers_discover.c @@ -122,7 +122,7 @@ api_v1_controllers_discover_PUT(struct mg_connection *nc, struct http_message *h payload[0] = discover_server_port; LOGGER_DEBUG("sending udp broadcast\n"); - if(send_udp_broadcast("255.255.255.255", global_config.discovery_port, payload, sizeof(payload)) < 0) + if(send_udp_broadcast("255.255.255.255", global_config->discovery_port, payload, sizeof(payload)) < 0) { M_RESPONSE_TEXT_STATIC(LOGGER_ERR, response, 500, "the server failed to send discovery broadcast"); return; diff --git a/src/endpoints/api_v1_schedules.c b/src/endpoints/api_v1_schedules.c index 7a9ad6e..d72b34b 100644 --- a/src/endpoints/api_v1_schedules.c +++ b/src/endpoints/api_v1_schedules.c @@ -23,6 +23,8 @@ api_v1_schedules_POST(struct mg_connection *nc, struct http_message *hm, endpoin cJSON *json_name = cJSON_GetObjectItemCaseSensitive(json, "name"); if(!cJSON_IsString(json_name) || (json_name->valuestring == NULL)) { + cJSON_Delete(json); + M_RESPONSE_400_NO_NAME(response); return; } diff --git a/src/handlers/http.c b/src/handlers/http.c index 84c4a36..324db67 100644 --- a/src/handlers/http.c +++ b/src/handlers/http.c @@ -17,16 +17,16 @@ static char* add_extra_headers(char *extra_headers) { char *result; - size_t std_headers_len = strlen(global_config.http_server_opts.extra_headers); + size_t std_headers_len = strlen(global_config->http_server_opts.extra_headers); if(extra_headers == NULL) { result = malloc(sizeof(char) * (std_headers_len + 1)); - strcpy(result, global_config.http_server_opts.extra_headers); + strcpy(result, global_config->http_server_opts.extra_headers); return result; } result = malloc(sizeof(char) * (std_headers_len + strlen(extra_headers) + 3)); - sprintf(result, "%s\r\n%s", global_config.http_server_opts.extra_headers, extra_headers); + sprintf(result, "%s\r\n%s", global_config->http_server_opts.extra_headers, extra_headers); return result; } @@ -89,7 +89,7 @@ handle_http_request(struct mg_connection *nc, struct http_message *hm) { /* Normalize path - resolve "." and ".." (in-place). */ if (!mg_normalize_uri_path(&hm->uri, &hm->uri)) { - mg_http_send_error(nc, 400, global_config.http_server_opts.extra_headers); + mg_http_send_error(nc, 400, global_config->http_server_opts.extra_headers); LOGGER_DEBUG("failed to normalize uri %.*s\n", hm->uri.len, hm->uri.p); return; } @@ -105,15 +105,15 @@ handle_http_request(struct mg_connection *nc, struct http_message *hm) ++request_file; } - char *request_file_path = malloc(sizeof(char) * (strlen(request_file) + strlen(global_config.content_dir) + 2)); - sprintf(request_file_path, "%s/%s", global_config.content_dir, request_file); + char *request_file_path = malloc(sizeof(char) * (strlen(request_file) + strlen(global_config->content_dir) + 2)); + sprintf(request_file_path, "%s/%s", global_config->content_dir, request_file); int access_result = access(request_file_path, R_OK); free(request_file_path); free(request_file_org); if(access_result != -1) { response.status_code = 0; - mg_serve_http(nc, hm, global_config.http_server_opts); + mg_serve_http(nc, hm, global_config->http_server_opts); LOGGER_DEBUG("serving %.*s\n", hm->uri.len, hm->uri.p); return; } diff --git a/src/helpers/drop_privileges.c b/src/helpers/drop_privileges.c index e2dde8a..df0ba7f 100644 --- a/src/helpers/drop_privileges.c +++ b/src/helpers/drop_privileges.c @@ -59,8 +59,8 @@ get_gid_for_group(char *group) int helper_drop_privileges() { - uid_t uid = get_uid_for_user(global_config.user); - gid_t gid = get_gid_for_group(global_config.group); + uid_t uid = get_uid_for_user(global_config->user); + gid_t gid = get_gid_for_group(global_config->group); LOGGER_DEBUG("drop privileges to %lu:%lu\n", uid, gid); diff --git a/src/logger.c b/src/logger.c index 1839d38..a467a7d 100644 --- a/src/logger.c +++ b/src/logger.c @@ -17,7 +17,7 @@ const char *COLOR_EMERG = COLOR_MAGENTA; void logger_log(int level, const char *filename, int line, const char *func, const char *msg, ...) { - if(global_config.log_level < level || level == LOG_NONE ) + if(global_config->log_level < level || level == LOG_NONE ) { return; } @@ -76,8 +76,8 @@ logger_log(int level, const char *filename, int line, const char *func, const ch char *buffer_timed = malloc(sizeof(char) * (strlen(timestamp_str) + strlen(buffer) + 2)); sprintf(buffer_timed, "%s %s", timestamp_str, buffer); va_start(args, msg); - vfprintf(global_config.log_file, buffer_timed, args); - fflush(global_config.log_file); + vfprintf(global_config->log_file, buffer_timed, args); + fflush(global_config->log_file); va_end(args); free(buffer); diff --git a/src/main.c b/src/main.c index 43ad767..06031ea 100644 --- a/src/main.c +++ b/src/main.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -52,22 +53,22 @@ main(int argc, const char** argv) signal(SIGABRT, terminate); signal(SIGTERM, terminate); - setlogmask(LOG_UPTO(LOG_INFO)); - + openlog("emgauwa-core", 0, LOG_USER); + setlogmask(LOG_UPTO(LOG_DEBUG)); /******************** LOAD CONFIG ********************/ config_init(); - helper_parse_cli(argc, argv, &global_config); + cli_parse(argc, argv, global_config); - FILE * const ini_file = fopen(global_config.file, "rb"); + FILE * const ini_file = fopen(global_config->file, "rb"); if(ini_file == NULL) { - LOGGER_CRIT("config file '%s' was not found\n", global_config.file); + LOGGER_CRIT("config file '%s' was not found\n", global_config->file); exit(1); } - if(load_ini_file(ini_file, INI_DEFAULT_FORMAT, NULL, config_load, &global_config)) + if(load_ini_file(ini_file, INI_DEFAULT_FORMAT, NULL, config_load, global_config)) { LOGGER_CRIT("unable to parse ini file\n"); exit(1); @@ -75,16 +76,12 @@ main(int argc, const char** argv) fclose(ini_file); - memset(&global_config.http_server_opts, 0, sizeof(global_config.http_server_opts)); - global_config.http_server_opts.document_root = global_config.content_dir; - global_config.http_server_opts.enable_directory_listing = "no"; - global_config.http_server_opts.extra_headers = "Access-Control-Allow-Origin: *\r\nAccess-Control-Allow-Headers: *\r\nAccess-Control-Allow-Methods: *"; - - if(global_config.log_file == NULL) + if(global_config->log_file == NULL) { - global_config.log_file = stdout; + global_config->log_file = stdout; } - openlog("emgauwa-core", 0, LOG_USER); + + LOGGER_DEBUG("Loaded config from %s\n", global_config->file); /******************** SETUP CONNECTION ********************/ @@ -94,20 +91,20 @@ main(int argc, const char** argv) mg_mgr_init(&mgr, NULL); char address[100]; - sprintf(address, "tcp://0.0.0.0:%u", global_config.server_port); + sprintf(address, "tcp://0.0.0.0:%u", global_config->server_port); struct mg_connection *c_http = mg_bind(&mgr, address, handler_http); if(c_http == NULL) { - LOGGER_CRIT("failed to bind http server to port %u\n", global_config.server_port); + LOGGER_CRIT("failed to bind http server to port %u\n", global_config->server_port); exit(1); } mg_set_protocol_http_websocket(c_http); - sprintf(address, "tcp://0.0.0.0:%u", global_config.mqtt_port); + sprintf(address, "tcp://0.0.0.0:%u", global_config->mqtt_port); struct mg_connection *c_mqtt = mg_bind(&mgr, address, handler_mqtt); if(c_mqtt == NULL) { - LOGGER_CRIT("failed to bind mqtt server to port %u\n", global_config.mqtt_port); + LOGGER_CRIT("failed to bind mqtt server to port %u\n", global_config->mqtt_port); exit(1); } mg_mqtt_broker_init(&brk, NULL); @@ -116,6 +113,11 @@ main(int argc, const char** argv) helper_drop_privileges(); + memset(&global_config->http_server_opts, 0, sizeof(global_config->http_server_opts)); + global_config->http_server_opts.document_root = global_config->content_dir; + global_config->http_server_opts.enable_directory_listing = "no"; + global_config->http_server_opts.extra_headers = "Access-Control-Allow-Origin: *\r\nAccess-Control-Allow-Headers: *\r\nAccess-Control-Allow-Methods: *"; + /******************** INIT COMPONENTS ********************/ diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 1b158b6..ab5740d 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -41,12 +41,7 @@ touch $working_dir/index.html cp $1 $working_dir/core -echo "=== invalids start (must exit) ===" >$working_dir/core.log -$working_dir/core -c $source_dir/emgauwa-core-testing-ini >>$working_dir/core.log 2>&1 -$working_dir/core -c $source_dir/emgauwa-core-testing-ini INVALID_ACTION >>$working_dir/core.log 2>&1 - -echo "=== valid start ===" >>$working_dir/core.log -valgrind_emgauwa $working_dir/core -c $source_dir/emgauwa-core-testing.ini start >>$working_dir/core.log 2>&1 & +valgrind_emgauwa $working_dir/core -c $source_dir/emgauwa-core-testing.ini >>$working_dir/core.log 2>&1 & core_id=$!