aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shared/protocol.c35
-rw-r--r--shared/protocol.h42
-rw-r--r--shared/test.c17
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) {