diff options
Diffstat (limited to 'shared')
-rw-r--r-- | shared/backlog.c | 47 | ||||
-rw-r--r-- | shared/backlog.h | 59 | ||||
-rw-r--r-- | shared/makefile | 24 | ||||
-rw-r--r-- | shared/protocol.c | 87 | ||||
-rw-r--r-- | shared/protocol.md | 7 | ||||
-rw-r--r-- | shared/shared.mk | 1 | ||||
-rw-r--r-- | shared/test.c | 82 | ||||
-rw-r--r-- | shared/testcmd | 1 |
8 files changed, 49 insertions, 259 deletions
diff --git a/shared/backlog.c b/shared/backlog.c deleted file mode 100644 index 926ccad..0000000 --- a/shared/backlog.c +++ /dev/null @@ -1,47 +0,0 @@ -#include <stdlib.h> - -#include "backlog.h" - -ws_s_backlog_database* g_ws_backlog_database = NULL; - -void ws_backlog_alloc(uint16_t record_amt) { - g_ws_backlog_database = malloc(sizeof(ws_s_backlog_database) + sizeof(ws_s_backlog_record) * record_amt); - g_ws_backlog_database->buffer_size = record_amt; - g_ws_backlog_database->buffer_start = 0; - g_ws_backlog_database->buffer_end = 0; -} - -void ws_backlog_add_record(ws_s_backlog_record record) { - static uint16_t id = 0; - - g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].id = id++; - g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].sens_atm_pressure = record.sens_atm_pressure; - g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].sens_humidity = record.sens_humidity; - g_ws_backlog_database->records[g_ws_backlog_database->buffer_end].sens_temperature = record.sens_temperature; - - // shift buffer start/end - g_ws_backlog_database->buffer_end = (g_ws_backlog_database->buffer_end + 1) % g_ws_backlog_database->buffer_size; - if (g_ws_backlog_database->buffer_end == g_ws_backlog_database->buffer_start) - g_ws_backlog_database->buffer_start = (g_ws_backlog_database->buffer_start + 1) % g_ws_backlog_database->buffer_size; -} - -ws_s_backlog_record* ws_backlog_get_record(uint16_t record_index) { - return &g_ws_backlog_database->records[record_index]; -} - -ws_s_backlog_record* ws_backlog_get_last_record(uint16_t record_offset) { - return ws_backlog_get_record((g_ws_backlog_database->buffer_end - record_offset - 1) % g_ws_backlog_database->buffer_size); -} - -static uint16_t mod(uint16_t a, uint16_t b) { - uint16_t m = a % b; - return m < 0 ? (b < 0) ? m - b : m + b : m; -} - -uint16_t ws_backlog_get_record_count() { - // add buffer_size to the result of the modulo operation if it's result is negative - // (only works when buffer_size is less than 2^15) - // this is a consequence of the way in which c handles negative numbers in modulo operations - int16_t mod = (g_ws_backlog_database->buffer_end - g_ws_backlog_database->buffer_start) % g_ws_backlog_database->buffer_size; - return mod < 0 ? mod + g_ws_backlog_database->buffer_size : mod; -} diff --git a/shared/backlog.h b/shared/backlog.h deleted file mode 100644 index c8ea019..0000000 --- a/shared/backlog.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include <stdint.h> - -/** - * @brief allocate backlog buffer and set global backlog pointer - * @param record_amt amount of records to keep before overwriting oldest record - */ -void ws_backlog_alloc(uint16_t record_amt); - -// enable struct packing -#pragma pack(push, 1) - -/** @brief backlog record */ -typedef struct { - uint16_t id; /**< unique record identifier, numbered sequentially */ - uint8_t sens_temperature; /**< temperature reading */ - uint8_t sens_humidity; /**< humidity reading */ - uint8_t sens_atm_pressure; /**< atmospheric pressure reading */ -} ws_s_backlog_record; - -typedef struct { - uint16_t buffer_size; /**< buffer size (amount of records) */ - uint16_t buffer_start; /** first record index */ - uint16_t buffer_end; /** last record index */ - ws_s_backlog_record records[]; /** record array */ -} ws_s_backlog_database; - -// disable struct packing -#pragma pack(pop) - -/** @brief global record backlog database pointer */ -extern ws_s_backlog_database* g_ws_backlog_database; - -/** - * @brief add record to database - * - * automatically sets record.id, pushes buffer_end forwards and overwrites the - * last record if the buffer is full - */ -void ws_backlog_add_record(ws_s_backlog_record record); - -/** - * there's intentionally no function to retrieve multiple records as an array, - * as this would either require - * (a) copying the selection which is not possible with the current memory - * constraints, or - * (b) giving a direct pointer, but this would cause undefined behavior at the - * ring buffer seam - */ - -/** @brief get pointer to record with index `record_index` from the database */ -ws_s_backlog_record* ws_backlog_get_record(uint16_t record_index); - -/** @brief get pointer to last record with offset `record_offset` from the database */ -ws_s_backlog_record* ws_backlog_get_last_record(uint16_t record_offset); - -/** @brief return amount of valid records in database */ -uint16_t ws_backlog_get_record_count(); diff --git a/shared/makefile b/shared/makefile deleted file mode 100644 index 2093f00..0000000 --- a/shared/makefile +++ /dev/null @@ -1,24 +0,0 @@ -CC = gcc -LD = gcc -RM = rm -f -CFLAGS = -g -std=c11 -LFLAGS = -TARGET = main - -SRCS := $(wildcard *.c) -OBJS := $(patsubst %.c,%.o, $(SRCS)) - -all: main - -%.o: %.c - $(CC) -c $(CFLAGS) $< -o $@ - -$(TARGET): $(OBJS) - $(LD) $^ $(LFLAGS) -o $@ - -clean: - $(RM) $(TARGET) $(OBJS) - -compile_commands: clean - compiledb make - diff --git a/shared/protocol.c b/shared/protocol.c index 55e6759..c6e5ddd 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -15,30 +15,30 @@ static ws_e_protocol_cmd ws_protocol_get_req_cmd_code(ws_s_protocol_parsed_req_c } void ws_protocol_parse_req_byte(ws_s_protocol_req_parser_state* state, char input) { - switch(input) { - case WS_PROTOCOL_C_EOL: { - break; - } + switch(input) { + case WS_PROTOCOL_C_EOL: { + break; + } - case WS_PROTOCOL_C_SPACE: { - if (!state->valid) return; + case WS_PROTOCOL_C_SPACE: { + if (!state->valid) return; state->arg_len++; - return; - } - - case WS_PROTOCOL_C_NULL: { - state->valid = false; - return; - } - - default: { - if (!state->valid) return; - state->cmd[state->cmd_len++] = input; - state->args_len[state->arg_len] += 1; - if (state->cmd_len == WS_PROTOCOL_CMD_BUFFER_LEN) state->valid = false; - return; - } - } + return; + } + + case WS_PROTOCOL_C_NULL: { + state->valid = false; + return; + } + + default: { + if (!state->valid) return; + state->cmd[state->cmd_len++] = input; + state->args_len[state->arg_len] += 1; + if (state->cmd_len == WS_PROTOCOL_CMD_BUFFER_LEN) state->valid = false; + return; + } + } // arg_len is used as an index while parsing, so add 1 to get length state->arg_len++; @@ -85,22 +85,23 @@ ws_protocol_parse_exit: } void ws_protocol_parse_req_bytes(ws_s_protocol_req_parser_state* state, char* input, unsigned int length) { - for (unsigned int i = 0; i < length; i++) ws_protocol_parse_req_byte(state, input[i]); + for (unsigned int i = 0; i < length; i++) ws_protocol_parse_req_byte(state, input[i]); } ws_s_protocol_req_parser_state* ws_protocol_req_parser_alloc() { - ws_s_protocol_req_parser_state* parser_state = malloc(sizeof(ws_s_protocol_req_parser_state) + sizeof(uint16_t) * WS_PROTOCOL_CMD_MAX_ARGUMENTS); - parser_state->cmd = malloc(sizeof(char) * WS_PROTOCOL_CMD_BUFFER_LEN); + ws_s_protocol_req_parser_state* parser_state = malloc(sizeof(ws_s_protocol_req_parser_state) + sizeof(uint16_t) * WS_PROTOCOL_CMD_MAX_ARGUMENTS); + parser_state->cmd = malloc(sizeof(char) * WS_PROTOCOL_CMD_BUFFER_LEN); + parser_state->target = NULL; ws_protocol_req_parser_reset(parser_state); - return parser_state; + return parser_state; } void ws_protocol_req_cmd_init(ws_s_protocol_req_parser_state* state) { - state->target = malloc(sizeof(ws_s_protocol_parsed_req_cmd) + sizeof(char*) * state->arg_len); - for (unsigned int i = 0; i < state->arg_len; i++) - state->target->argv[i] = malloc(sizeof(char) * (state->args_len[i] + 1)); + state->target = malloc(sizeof(ws_s_protocol_parsed_req_cmd) + sizeof(char*) * state->arg_len); + for (unsigned int i = 0; i < state->arg_len; i++) + state->target->argv[i] = malloc(sizeof(char) * (state->args_len[i] + 1)); - state->target->argc = state->arg_len; + state->target->argc = state->arg_len; unsigned int head = 0; for (unsigned int i = 0; i < state->arg_len; i++) { @@ -111,26 +112,26 @@ void ws_protocol_req_cmd_init(ws_s_protocol_req_parser_state* state) { } void ws_protocol_req_parser_free(ws_s_protocol_req_parser_state* state) { - if (state == NULL) return; - if (state->target != NULL) ws_protocol_req_cmd_free(state->target); + if (state == NULL) return; + if (state->target != NULL) ws_protocol_req_cmd_free(state->target); state->target = NULL; - free(state->cmd); - free(state); - return; + free(state->cmd); + free(state); + return; } void ws_protocol_req_parser_reset(ws_s_protocol_req_parser_state* state) { if (state->target != NULL) ws_protocol_req_cmd_free(state->target); - state->target = NULL; - state->valid = true; - state->cmd_len = 0; - state->arg_len = 0; + state->target = NULL; + state->valid = true; + state->cmd_len = 0; + state->arg_len = 0; memset(state->args_len, 0, sizeof(uint16_t) * WS_PROTOCOL_CMD_MAX_ARGUMENTS); } void ws_protocol_req_cmd_free(ws_s_protocol_parsed_req_cmd* cmd) { - for (unsigned int i = 0; i < cmd->argc; i++) - free(cmd->argv[i]); - free(cmd); - return; + for (int i = 0; i < cmd->argc; i++) + free(cmd->argv[i]); + free(cmd); + return; } diff --git a/shared/protocol.md b/shared/protocol.md index bafec4d..b6e955c 100644 --- a/shared/protocol.md +++ b/shared/protocol.md @@ -29,8 +29,9 @@ conventions. Returns the last `n` records in csv format. The first line has the csv table header, with the fields `id`, `temperature`, `humidity`, and `atmospheric_pressure`. The rest of the response consists of 1 record per line. -When `n` is 0, or no records exist yet, the csv header is still returned, but -without any records. +The amount of records is limited to the amount of valid records in the backlog +buffer. When the amount of returned records is 0, the response consists of the +csv header, but without any following records. ## Example transaction @@ -39,7 +40,7 @@ starting with `<`, and response by lines starting with `>`. ``` < last-records 5<0a> -> ok,115<0a> +> ok,73<0a> > id,temperature,humidity,atmospheric_pressure<0a> > 10dc,2f,c5,7f<0a> > 10dd,30,c6,7f<0a> diff --git a/shared/shared.mk b/shared/shared.mk new file mode 100644 index 0000000..f9586ff --- /dev/null +++ b/shared/shared.mk @@ -0,0 +1 @@ +OBJS += $(patsubst %.c,%-stm.o, $(wildcard ../shared/*.c)) diff --git a/shared/test.c b/shared/test.c deleted file mode 100644 index 287332a..0000000 --- a/shared/test.c +++ /dev/null @@ -1,82 +0,0 @@ -#include <stdio.h> -#include <stdint.h> -#include <unistd.h> -#include <termios.h> -#include <fcntl.h> -#include <string.h> - -#include "protocol.h" -#include "backlog.h" -#include "util.h" - -void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response, bool send) { - static unsigned int record_amount = 0; - const char* response_header = "id,temperature,humidity,atmospheric_pressure\n"; - const size_t response_line_size = sizeof("xxxx,xx,xx,xx\n"); - - if (!send) { - response->success = WS_PROTOCOL_CMD_RETURN_OK; - if (sscanf(parsed_cmd->argv[1], "%u", &record_amount) < 1) response->success = WS_PROTOCOL_CMD_RETURN_ERROR; - record_amount = WS_MIN(record_amount, ws_backlog_get_record_count()); - response->csh = true; - response->msg = ws_bin_s_alloc(0); - response->msg->bytes = strlen(response_header) + response_line_size * record_amount; - } else { - // example send routine - ws_protocol_send_data(response_header, strlen(response_header)); - char line[response_line_size + 1]; // +1 for null terminator -> sprintf - for (unsigned int i = 0; i < record_amount; i++) { - ws_s_backlog_record* record = ws_backlog_get_last_record(i); - sprintf(line, "%04x,%02x,%02x,%02x\n", record->id, record->sens_temperature, record->sens_humidity, record->sens_atm_pressure); - ws_protocol_send_data(line, response_line_size); - } - } -} - -void ws_protocol_send_data(const char* data, unsigned int length) { - printf("%.*s", length, data); -} - -int main() { - ws_backlog_alloc(10); - - // disable echo and enable raw mode - fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); - struct termios term; - tcgetattr(STDIN_FILENO, &term); - term.c_lflag &= ~(ECHO | ICANON); - term.c_cc[VTIME] = 0; - term.c_cc[VMIN] = 1; - tcsetattr(STDIN_FILENO, 0, &term); - - ws_s_protocol_req_parser_state* parser1 = ws_protocol_req_parser_alloc(); - - ws_backlog_add_record((ws_s_backlog_record) { - .sens_temperature = 0x29, - .sens_humidity = 0x34, - .sens_atm_pressure = 0x69, - }); - - ws_backlog_add_record((ws_s_backlog_record) { - .sens_temperature = 0x00, - .sens_humidity = 0x00, - .sens_atm_pressure = 0x00, - }); - - ws_backlog_add_record((ws_s_backlog_record) { - .sens_temperature = 0x01, - .sens_humidity = 0x01, - .sens_atm_pressure = 0x01, - }); - - fflush(stdout); - - char byte; - while(read(STDIN_FILENO, &byte, 1) > 0) - ws_protocol_parse_req_byte(parser1, byte); - - ws_protocol_req_parser_free(parser1); - parser1 = NULL; - - return 0; -} diff --git a/shared/testcmd b/shared/testcmd deleted file mode 100644 index 17f8842..0000000 --- a/shared/testcmd +++ /dev/null @@ -1 +0,0 @@ -last-records 5 |