diff options
-rw-r--r-- | shared/protocol.c | 35 | ||||
-rw-r--r-- | shared/protocol.h | 42 | ||||
-rw-r--r-- | shared/test.c | 17 |
3 files changed, 58 insertions, 36 deletions
diff --git a/shared/protocol.c b/shared/protocol.c index 6795197..225b46f 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -4,6 +4,16 @@ #include "protocol.h" +#define WS_CMD_MAP(parsed_cmd, name, code) \ + if (strlen(parsed_cmd->argv[0]) == strlen(name) && strncmp(parsed_cmd->argv[0], name, strlen(name)) == 0) return code; + +static ws_e_protocol_cmd ws_protocol_get_req_cmd_code(ws_s_protocol_parsed_req_cmd* parsed_cmd) { + if (parsed_cmd == NULL) return WS_PROTOCOL_CMD_UNKNOWN; // invalid command + WS_CMD_MAP(parsed_cmd, "last-records", WS_PROTOCOL_CMD_LAST_RECORDS); + + return WS_PROTOCOL_CMD_UNKNOWN; +} + void ws_protocol_parse_req_byte(ws_s_protocol_req_parser_state* state, char input) { switch(input) { case WS_PROTOCOL_C_EOL: { @@ -43,7 +53,8 @@ void ws_protocol_parse_req_byte(ws_s_protocol_req_parser_state* state, char inpu ws_s_bin* response_first_line_bin = ws_bin_s_alloc(strlen(response_first_line)); strncpy((char*) response_first_line_bin->data, response_first_line, strlen(response_first_line)); ws_protocol_send_data(response_first_line_bin); - ws_protocol_send_data(response->msg); + if (!response->csh) ws_protocol_send_data(response->msg); + else (*g_ws_protocol_res_handlers[response->cmd_code])(state->target, response, true); // free response data containers free(response_first_line_bin); @@ -56,29 +67,19 @@ void ws_protocol_parse_req_byte(ws_s_protocol_req_parser_state* state, char inpu return; } -#define WS_CMD_MAP(parsed_cmd, name, code) \ - if (strlen(parsed_cmd->argv[0]) == strlen(name) && strncmp(parsed_cmd->argv[0], name, strlen(name)) == 0) return code; - -static ws_e_protocol_cmd ws_protocol_get_req_cmd_code(ws_s_protocol_parsed_req_cmd* parsed_cmd) { - if (parsed_cmd == NULL) return WS_PROTOCOL_CMD_UNKNOWN; // invalid command - WS_CMD_MAP(parsed_cmd, "last-records", WS_PROTOCOL_CMD_LAST_RECORDS); - - return WS_PROTOCOL_CMD_UNKNOWN; -} - ws_s_protocol_res* ws_protocol_parse_req_finished(ws_s_protocol_parsed_req_cmd* parsed_cmd) { ws_s_protocol_res* response = malloc(sizeof(ws_s_protocol_res)); response->success = WS_PROTOCOL_CMD_RETURN_ERROR; + response->csh = false; response->msg = NULL; + response->cmd_code = ws_protocol_get_req_cmd_code(parsed_cmd); - ws_e_protocol_cmd cmd_code = ws_protocol_get_req_cmd_code(parsed_cmd); - if (cmd_code == WS_PROTOCOL_CMD_UNKNOWN) goto ws_protocol_parse_exit; - if (cmd_code >= WS_PROTOCOL_CMD_AMOUNT) goto ws_protocol_parse_exit; + if (response->cmd_code == WS_PROTOCOL_CMD_UNKNOWN) goto ws_protocol_parse_exit; + if (response->cmd_code >= WS_PROTOCOL_CMD_AMOUNT) goto ws_protocol_parse_exit; - void (*ws_protocol_res_handler)(ws_s_protocol_parsed_req_cmd*, ws_s_protocol_res*) = - g_ws_protocol_res_handlers[cmd_code]; + ws_protocol_res_handler_t* ws_protocol_res_handler = g_ws_protocol_res_handlers[response->cmd_code]; if (ws_protocol_res_handler == NULL) goto ws_protocol_parse_exit; - (*ws_protocol_res_handler)(parsed_cmd, response); + (*ws_protocol_res_handler)(parsed_cmd, response, false); ws_protocol_parse_exit: diff --git a/shared/protocol.h b/shared/protocol.h index 9f17e8d..c31ebc6 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -42,10 +42,22 @@ typedef enum { WS_PROTOCOL_CMD_RETURN_ERROR = 1, } ws_e_protocol_cmd_return_value; +/** @brief cmd codes (used to call handlers) */ +typedef enum { + WS_PROTOCOL_CMD_UNKNOWN = -1, + + WS_PROTOCOL_CMD_LAST_RECORDS = 0, +} ws_e_protocol_cmd; + /** @brief request response data struct */ typedef struct { - ws_e_protocol_cmd_return_value success; - ws_s_bin* msg; + ws_e_protocol_cmd_return_value success; /** status code for response + validity, defaults to + WS_PROTOCOL_CMD_RETURN_ERROR */ + bool csh; /** whether the response handler has logic for a custom send + handler, false by default */ + ws_s_bin* msg; /** pointer to response data, uninitialized by default */ + ws_e_protocol_cmd cmd_code; /** cmd code */ } ws_s_protocol_res; /** @@ -102,15 +114,22 @@ ws_s_protocol_res* ws_protocol_parse_req_finished(ws_s_protocol_parsed_req_cmd* ws_s_bin* ws_protocol_req_last_records(unsigned int record_amount); /** - * @brief `last-records` response handler + * @brief response handler * - * gets fired when the weather station receives a complete `last-records` - * command, and returns the response string + * gets fired when the weather station receives a complete command, and returns + * a response struct with a success code and an optional message. if + * response->csh is set to `true` within the handler, it gets fired a second + * time after the response header is sent, but with the `send` parameter set to + * `true`. this is so response handlers can send large amounts of data without + * allocating large areas of memory. * * @param parsed_cmd complete parsed command from ws_protocol_parse_req_* * @param response response struct with uninitialized pointer to msg + * @param send `false` on first run, `true` on second run if `response->csh` was set to true */ -void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response); +typedef void ws_protocol_res_handler_t(ws_s_protocol_parsed_req_cmd*, ws_s_protocol_res*, bool); + +ws_protocol_res_handler_t ws_protocol_res_last_records; /** * @brief data sender wrapper @@ -121,15 +140,8 @@ void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s */ void ws_protocol_send_data(ws_s_bin* data); -/** @brief cmd codes (used to call handlers) */ -typedef enum { - WS_PROTOCOL_CMD_UNKNOWN = -1, - - WS_PROTOCOL_CMD_LAST_RECORDS = 0, -} ws_e_protocol_cmd; - /** @brief response handlers, called when a command is parsed */ -static void (*g_ws_protocol_res_handlers[WS_PROTOCOL_CMD_AMOUNT])(ws_s_protocol_parsed_req_cmd*, ws_s_protocol_res*) = { - [WS_PROTOCOL_CMD_LAST_RECORDS] = &ws_protocol_res_last_records +static ws_protocol_res_handler_t* g_ws_protocol_res_handlers[WS_PROTOCOL_CMD_AMOUNT] = { + [WS_PROTOCOL_CMD_LAST_RECORDS] = &ws_protocol_res_last_records, }; diff --git a/shared/test.c b/shared/test.c index f9d4bbc..0968252 100644 --- a/shared/test.c +++ b/shared/test.c @@ -7,7 +7,7 @@ #include "protocol.h" -void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response) { +void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s_protocol_res* response, bool send) { const char* response_text = "" "id,temperature,humidity,atmospheric_pressure\n" "10dc,2f,c5,7f\n" @@ -15,9 +15,18 @@ void ws_protocol_res_last_records(ws_s_protocol_parsed_req_cmd* parsed_cmd, ws_s "10de,31,c7,7f\n" "10df,35,ca,7e\n" "10e0,34,c9,7e\n"; - response->success = WS_PROTOCOL_CMD_RETURN_OK; - response->msg = ws_bin_s_alloc(strlen(response_text)); - strncpy((char*) response->msg->data, response_text, strlen(response_text)); + + if (!send) { + response->success = WS_PROTOCOL_CMD_RETURN_OK; + response->csh = true; + response->msg = ws_bin_s_alloc(0); + response->msg->bytes = strlen(response_text); + } else { + // example send routine + ws_s_bin* response_test = ws_bin_s_alloc(strlen(response_text)); + strncpy((char*) response_test->data, response_text, strlen(response_text)); + ws_protocol_send_data(response_test); + } } void ws_protocol_send_data(ws_s_bin* data) { |