diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4af0fca --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +build/ +*.tar.gz +*.zip +*.rar +*.gz +*.bz2 +*.vgcore diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8d08d59 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "sdk"] + path = sdk + url = git@lowenware.com:lowenware/aisl-sdk.git +[submodule "cStuff"] + path = cStuff + url = git@lowenware.com:lowenware/cStuff.git diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0aba51d --- /dev/null +++ b/Makefile @@ -0,0 +1,77 @@ +# +# Makefile +# Ilja Kartašov, 2019-03-02 17:32 +# +.POSIX: + +# Project directories +SRC_DIR ?= src +SDK_DIR ?= sdk +CSTUFF_DIR ?= cStuff +OUT_DIR ?= ./build + +# Project definition +include project.mk + +# CFLAGS + +CFLAGS := \ + $(PROJECT_INCLUDES) \ + -std=c99 \ + -pedantic \ + -Wall \ + -Wmissing-prototypes \ + -Wstrict-prototypes \ + -Wold-style-definition \ + -O2 \ + -s \ + -fvisibility=hidden \ + -DVERSION_MAJOR=$(PROJECT_VERSION_MAJOR) \ + -DVERSION_MINOR=$(PROJECT_VERSION_MINOR) \ + -DVERSION_TWEAK=$(PROJECT_VERSION_TWEAK) \ + -DVERSION_LABEL=$(PROJECT_VERSION_LABEL) \ + $(PROJECT_CFLAGS) \ + $(CFLAGS) \ + + +LDFLAGS := \ + $(PROJECT_LIBRARIES) \ + $(LDFLAGS) \ + $(PROJECT_LDFLAGS) \ + + +SOURCE_LIST := $(wildcard $(PROJECT_SOURCES)) +OBJECT_FILES := $(addprefix $(OUT_DIR)/o_, ${SOURCE_LIST:.c=.o}) + + +project: dirs $(OBJECT_FILES) + $(info linking target: $@) + @$(CC) -o $(OUT_DIR)/$(PROJECT_NAME) $(OBJECT_FILES) $(LDFLAGS) + $(info done: $@) + + +build/o_%.o: %.c + $(info compiling file: $<) + @$(CC) $(CFLAGS) -c $< -o $@ + +dirs: + $(info preparing: build folders) + @mkdir -p $(OUT_DIR)/o_$(SRC_DIR) + @mkdir -p $(OUT_DIR)/o_$(CSTUFF_DIR) + @mkdir -p $(OUT_DIR)/o_$(SDK_DIR)/components + @mkdir -p $(OUT_DIR)/o_$(SDK_DIR)/mods + + +clean: + $(info cleaning: build files) + @rm -Rf $(OUT_DIR) + @rm -Rf ./vgcore.* + + +all: project + +default: project +.PHONY: all dirs clean + +# vim:ft=make +# diff --git a/cStuff b/cStuff new file mode 160000 index 0000000..4ba00ca --- /dev/null +++ b/cStuff @@ -0,0 +1 @@ +Subproject commit 4ba00ca17a6a86a9309fe8426220cc378d8f4579 diff --git a/data/arcd.config b/data/arcd.config new file mode 100644 index 0000000..72f257d --- /dev/null +++ b/data/arcd.config @@ -0,0 +1,3 @@ +agent: + surgard-1 = surgard-serial:///dev/ttyUSB0/?speed=9600 + osm-1 = osm://127.0.0.1/ diff --git a/project.mk b/project.mk new file mode 100644 index 0000000..7f01ee9 --- /dev/null +++ b/project.mk @@ -0,0 +1,77 @@ +# +# config.mk +# Löwenware Makefile Config, 2019-03-02 17:35 +# + +PREFIX = /usr/ +PKG_CONFIG = pkg-config + +PROJECT_NAME = arcd + +# Version + +PROJECT_VERSION_MAJOR = 1 +PROJECT_VERSION_MINOR = 0 +PROJECT_VERSION_TWEAK = 0 +PROJECT_VERSION_LABEL = 0 + +# Override default paths +#SRC_DIR = src +#SDK_DIR = sdk +#OUT_DIR = ./build + + +# Source files + +PROJECT_SOURCES := \ + $(SRC_DIR)/main.c \ + $(SRC_DIR)/observer.c \ + $(SRC_DIR)/agent.c \ + \ + $(CSTUFF_DIR)/log.c \ + $(CSTUFF_DIR)/string.c \ + $(CSTUFF_DIR)/list.c \ + $(CSTUFF_DIR)/file.c \ + \ + $(SDK_DIR)/components/query.c \ + $(SDK_DIR)/components/quick.c \ + $(SDK_DIR)/components/validate.c \ + $(SDK_DIR)/components/mail.c \ + $(SDK_DIR)/components/log.c \ + $(SDK_DIR)/components/todo.c \ + \ + $(SDK_DIR)/mods/context.c \ + $(SDK_DIR)/mods/module.c \ + + + +# includes +PROJECT_INCLUDES = \ + -I./ \ + -I./$(SDK_DIR) \ + `$(PKG_CONFIG) --cflags libaisl` \ + `$(PKG_CONFIG) --cflags libcurl` \ + `$(PKG_CONFIG) --cflags uuid` \ + +# libraries +PROJECT_LIBRARIES = \ + `$(PKG_CONFIG) --libs libaisl` \ + `$(PKG_CONFIG) --libs libcurl` \ + `$(PKG_CONFIG) --libs uuid` \ + -lpthread \ + +# compilation macro options: + +# flags +PROJECT_CFLAGS = -D_POSIX_C_SOURCE=200809L +PROJECT_CFLAGS += -D_ISOC99_SOURCE +PROJECT_CFLAGS += -D_XOPEN_SOURCE=500 +PROJECT_CFLAGS += -D_GNU_SOURCE +# PROJECT_CFLAGS += -DDEBUG + + +# PROJECT_LDFLAGS = -L + + +# vim:ft=make +# diff --git a/sdk b/sdk new file mode 160000 index 0000000..e00ffe6 --- /dev/null +++ b/sdk @@ -0,0 +1 @@ +Subproject commit e00ffe6f708f1460ca1d2b00d94c739ebb2cb184 diff --git a/src/agent.c b/src/agent.c new file mode 100644 index 0000000..f324b1c --- /dev/null +++ b/src/agent.c @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file agent.c + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#include "agent.h" + + +int +agent_init(void) +{ + return 0; +} + + +void +agent_release(void) +{ + +} + + +int +agent_run_cycle(void) +{ + return 1; +} diff --git a/src/agent.h b/src/agent.h new file mode 100644 index 0000000..232455f --- /dev/null +++ b/src/agent.h @@ -0,0 +1,31 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file agent.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#ifndef AGENT_H_D0CDB429_AC49_4BC6_83FA_9163404D387E +#define AGENT_H_D0CDB429_AC49_4BC6_83FA_9163404D387E + + +int +agent_init(void); + + +void +agent_release(void); + + +int +agent_run_cycle(void); + +#endif /* !AGENT_H */ diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..a4f1b83 --- /dev/null +++ b/src/config.h @@ -0,0 +1,58 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file config.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#ifndef CONFIG_H_18E4DCB3_B446_424F_9E5E_06DC15FA40BA +#define CONFIG_H_18E4DCB3_B446_424F_9E5E_06DC15FA40BA + +/** Default HTTP server port */ +#ifndef CONFIG_HTTP_PORT +#define CONFIG_HTTP_PORT 8080 +#endif + +#ifndef CONFIG_LOG_TARGET +#define CONFIG_LOG_TARGET "output.log" +#endif + +#ifndef CONFIG_SMTP_SERVER +#define CONFIG_SMTP_SERVER "mx.lowenware.com" +#endif + +#ifndef CONFIG_SMTP_PORT +#define CONFIG_SMTP_PORT 465 +#endif + +#ifndef CONFIG_SMTP_USER +#define CONFIG_SMTP_USER "robot@lowenware.com" +#endif + +#ifndef CONFIG_SMTP_PASS +#define CONFIG_SMTP_PASS "3HFzxiQYY9QJ6LN3" /* +){xA8}(mNF43B(~" */ +#endif + +#ifndef CONFIG_MAIL_FROM +#define CONFIG_MAIL_FROM CONFIG_SMTP_USER +#endif + +#ifndef CONFIG_MAIL_TO +#define CONFIG_MAIL_TO "ik@lowenware.com" +#endif + +#ifndef CONFIG_MAIL_SUBJECT +#define CONFIG_MAIL_SUBJECT "Feedback from website" +#endif + + + +#endif /* !CONFIG_H */ diff --git a/src/end-points.h b/src/end-points.h new file mode 100644 index 0000000..8ee6670 --- /dev/null +++ b/src/end-points.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file end-points.h + * @author Ilja Kartašov + * @brief Header-file only module with end-points URI macroses + * + * @see https://lowenware.com/ + */ + +#ifndef END_POINTS_H_406472C7_FC75_41D5_8988_AA12455597EC +#define END_POINTS_H_406472C7_FC75_41D5_8988_AA12455597EC + + +#define ROOT_URI "/" +#define HOOK_URI "/hook/" +#define BLOG_URI "/blog/" +#define TODO_URI "/todo/" + +/* Pages */ + +/* Blog */ + +/* Static */ + +/* ToDo */ +#define TODO_END_POINT TODO_URI + +/* Hooks */ +#define FEEDBACK_END_POINT HOOK_URI "feedback/" + +#endif /* !END_POINTS_H */ diff --git a/src/html.c b/src/html.c new file mode 100644 index 0000000..99a657c --- /dev/null +++ b/src/html.c @@ -0,0 +1,33 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file html.c + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#include "html.h" + +typedef enum { + + HTML_HEADER = 0, + HTML_MENU = 20, + HTML_FOOTER = 100 + +} HtmlSequence; + + +const struct html html[] = { + {7, 0, 0, "\n"} + , {7, 1, 0, "\n"} + , {7, 2, 0, ""}, + , {9, 2, 0, "\n"}, + , {8, 1, 0, "\n"}, +}; diff --git a/src/html.h b/src/html.h new file mode 100644 index 0000000..6942480 --- /dev/null +++ b/src/html.h @@ -0,0 +1,26 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file html.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#ifndef HTML_H_43FF7C60_6224_40DF_B3C6_6E4E18350871 +#define HTML_H_43FF7C60_6224_40DF_B3C6_6E4E18350871 + +struct html { + uint32_t size; + uint16_t offset; + uint16_t reserve; + const char *data; +}; + +#endif /* !HTML_H */ diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000..e10a29b --- /dev/null +++ b/src/log.h @@ -0,0 +1,26 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file log.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#ifndef LOG_H_33B3B660_C0F7_455F_A17D_AB4FD0C0FD2C +#define LOG_H_33B3B660_C0F7_455F_A17D_AB4FD0C0FD2C + +#include + +#define LOG_DEBUG(...) AX_LOG_DEBUG(__VA_ARGS__) +#define LOG_STATE(...) AX_LOG_STATE(__VA_ARGS__) +#define LOG_ALERT(...) AX_LOG_ALERT(__VA_ARGS__) +#define LOG_ERROR(...) AX_LOG_ERROR(__VA_ARGS__) + +#endif /* !LOG_H */ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..5e0d11d --- /dev/null +++ b/src/main.c @@ -0,0 +1,142 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file main.c + * @author Ilja Kartašov + * @brief Lowenware.com backend main source code file + * + * @see https://lowenware.com/ + */ + +#include +#include +#include +#include +#include +#include + +/* Include library meta header */ +#include +#include "log.h" +#include "config.h" +#include "observer.h" +#include "agent.h" + + +static const struct aisl_cfg_srv m_srv[] = {{ + .host = "0.0.0.0", + .port = CONFIG_HTTP_PORT, + .secure = false +}}; + + +static const struct aisl_cfg m_cfg = { + AISL_CFG_DEFAULTS + , .srv = m_srv + , .srv_cnt = sizeof (m_srv) / sizeof (m_srv[0]) + , .ssl = NULL + , .ssl_cnt = 0 + , .callback = observer_on_aisl_event +}; + + +static int +process_args(int argc, char **argv) +{ + int i; + char c = 0; + + for (i = 1; i < argc; i++) { + switch (c) { + case 'd': + if (chdir(argv[i]) != 0) { + LOG_ERROR("Failed to set working directory `%s`: %s", argv[i], + strerror(errno)); + return -1; + } + break; + + default: + if (strcmp(argv[i], "-d") == 0) { + c = 'd'; + } else if (strcmp(argv[i], "-h") == 0) { + printf("arcd %d.%d.%d\n\n", VERSION_MAJOR, VERSION_MINOR, VERSION_TWEAK); + printf("USAGE: arcd [ARGUMENTS]\n"); + printf("ARGUMENTS:\n"); + printf("\t-h - show this information\n"); + printf("\t-d :dir - set custom working directory\n"); + printf("\n"); + exit(0); + } + continue; + } + c = 0; + } + + if (c) { + LOG_ERROR("No value for -%c argument", c); + return -1; + } + + return 0; +} + + +int +main(int argc, char **argv) +{ + AislInstance aisl; /**< AISL instance pointer */ + char cwd[64]; + + AX_LOG_INIT(CSTUFF_LOG_ALL); + + if (!setlocale(LC_ALL, "C")) { + LOG_ERROR("Failed to set C locale"); + return -1; + } + + if (process_args(argc, argv)) { + return -1; + } + + LOG_STATE("working directory: `%s`", getcwd(cwd, sizeof(cwd))); + + /* Initialize instance */ + if ((aisl = aisl_new(&m_cfg)) != NULL) { + if (observer_init() == 0) { + if (agent_init() == 0) { + /* launch application loop */ + fprintf(stdout, "Entering main loop"); + for(;;) { + int rc, do_sleep = 1; + + if ((rc = aisl_run_cycle(aisl)) == AISL_SUCCESS) + do_sleep = 0; + + if ((rc = agent_run_cycle()) == 0) + do_sleep = 0; + + if (!do_sleep) + continue; + + aisl_sleep(aisl, 500); + } + agent_release(); + } + observer_release(); + } + aisl_free(aisl); + } else { + fprintf(stderr, "Failed to initialize AISL"); + } + + AX_LOG_RELEASE(); + + return 0; +} + diff --git a/src/observer.c b/src/observer.c new file mode 100644 index 0000000..ebf2aec --- /dev/null +++ b/src/observer.c @@ -0,0 +1,155 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file observer.c + * @author Ilja Kartašov + * @brief AISL event observer source code file + * + * @see https://lowenware.com/ + */ +#include +/* modules */ +#include +/* commons */ +#include "config.h" +#include "end-points.h" +#include "log.h" +#include "observer.h" + + +/* static struct ax_feedback m_feedback = {0}; */ + +AislStatus +observer_init(void) +{ + AislStatus result = AISL_SUCCESS; + + /* struct ax_feedback_cfg feedback_cfg; */ + + /* + memset(&feedback_cfg, 0, sizeof(struct ax_feedback_cfg)); + feedback_cfg.end_point = FEEDBACK_END_POINT; + feedback_cfg.smtp.host = CONFIG_SMTP_SERVER; + feedback_cfg.smtp.user = CONFIG_SMTP_USER; + feedback_cfg.smtp.pass = CONFIG_SMTP_PASS; + feedback_cfg.smtp.port = CONFIG_SMTP_PORT; + feedback_cfg.mail_from = CONFIG_MAIL_FROM; + feedback_cfg.mail_to = CONFIG_MAIL_TO; + feedback_cfg.mail_subject = CONFIG_MAIL_SUBJECT; + feedback_cfg.name_email = "email"; + feedback_cfg.name_msg = "msg"; + + if ((result = ax_feedback_init(&m_feedback, &feedback_cfg)) != 0) + return result; + */ + + return result; +} + + +void +observer_release(void) +{ + /* ax_feedback_release(&m_feedback); */ +} + + +static void +observer_on_stream_event(const struct aisl_evt *evt) +{ + AxModule mods[] = { /* AX_MODULE(&m_feedback) */ NULL }; + + int i, c = sizeof (mods) / sizeof (mods[0]); + + for (i = 0; i < c; i++) { + + /* TODO: remove !!!! */ + if (!mods[i]) + continue; + + AislStatus status = ax_module_on_event(mods[i], evt); + + switch(status) { + case AISL_IDLE: + continue; + + case AISL_SUCCESS: + return; + + default: + LOG_ALERT("Module error: %s", aisl_status_to_string(status)); + return; + } + } +} + + +static void +observer_on_server_event(const struct aisl_evt *evt) +{ + struct sockaddr_in srv_addr; + AislServer srv = (AislServer) evt->source; + AislStatus status = evt->status; + + aisl_server_get_address(srv, &srv_addr); + + LOG_STATE("HTTP%s server %s:%d: %s", (aisl_server_get_ssl(srv) ? "s" : ""), + inet_ntoa(srv_addr.sin_addr), ntohs(srv_addr.sin_port), + (status ? aisl_status_to_string(status) : "ready")); +} + + +static void +observer_on_client_event(const struct aisl_evt *evt, const char *msg) +{ + struct sockaddr_in cli_addr; + AislClient cli = (AislClient) evt->source; + + aisl_client_get_address(cli, &cli_addr); + if (evt->status == AISL_IDLE) + msg = "timeout"; + + LOG_STATE( "HTTP%s client %s:%d: %s", + (aisl_client_is_secure(cli) ? "s" : ""), + inet_ntoa(cli_addr.sin_addr), + ntohs(cli_addr.sin_port), + msg + ); +} + + +void +observer_on_aisl_event(const struct aisl_evt *evt, void *p_ctx) +{ + switch(evt->code) { + case AISL_EVENT_SERVER_READY: + case AISL_EVENT_SERVER_ERROR: + observer_on_server_event(evt); + break; + + case AISL_EVENT_CLIENT_CONNECT: + observer_on_client_event(evt, "connected"); + break; + + + case AISL_EVENT_CLIENT_DISCONNECT: + observer_on_client_event(evt, "disconnected"); + break; + + case AISL_EVENT_STREAM_OPEN: + case AISL_EVENT_STREAM_HEADER: + case AISL_EVENT_STREAM_INPUT: + case AISL_EVENT_STREAM_REQUEST: + case AISL_EVENT_STREAM_OUTPUT: + case AISL_EVENT_STREAM_CLOSE: + case AISL_EVENT_STREAM_ERROR: + observer_on_stream_event(evt); + break; + } +} + diff --git a/src/observer.h b/src/observer.h new file mode 100644 index 0000000..356f65b --- /dev/null +++ b/src/observer.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file observer.h + * @author Ilja Kartašov + * @brief AISL event observer header file + * + * @see https://lowenware.com/ + */ + +#ifndef OBSERVER_H_C0DE24F7_EC8D_4C89_B253_15F0BB5BF7B5 +#define OBSERVER_H_C0DE24F7_EC8D_4C89_B253_15F0BB5BF7B5 + +#include + + +AislStatus +observer_init(void); + + +void +observer_release(void); + + +void +observer_on_aisl_event(const struct aisl_evt *evt, void *p_ctx); + + +#endif /* !OBSERVER_H */ diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..126499c --- /dev/null +++ b/todo.txt @@ -0,0 +1,12 @@ +Port templight to SDK +Implement authentication UI +Implement authentication modules in SDK +Implement serial surgard receiver +Implement EBS OSM receiver +Define device file format +Implement device logs +Implement ARC journal +Implement device cards +Implement routes +x Create project repository +