aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2022-10-13 20:37:23 +0200
committerlonkaars <loek@pipeframe.xyz>2022-10-13 20:37:23 +0200
commit78f8f18e48d25547e837630d8317ef029bba6d72 (patch)
tree8e6055aeec0b27733ff53804d13c98ed4e61dafd
parent385b47211ea8674f97f014537d694bb2efbd6ab9 (diff)
more protocol parsing done
-rw-r--r--shared/bin.c11
-rw-r--r--shared/bin.h5
-rwxr-xr-xshared/mainbin21456 -> 28568 bytes
-rw-r--r--shared/makefile2
-rw-r--r--shared/protocol.c42
-rw-r--r--shared/protocol.h63
6 files changed, 107 insertions, 16 deletions
diff --git a/shared/bin.c b/shared/bin.c
new file mode 100644
index 0000000..def2aa8
--- /dev/null
+++ b/shared/bin.c
@@ -0,0 +1,11 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <memory.h>
+
+#include "bin.h"
+
+ws_s_bin *ws_bin_s_alloc(uint16_t bytes) {
+ ws_s_bin *temp = malloc(sizeof(ws_s_bin) + sizeof(uint8_t) * bytes);
+ temp->bytes = bytes;
+ return temp;
+}
diff --git a/shared/bin.h b/shared/bin.h
index c7405be..bfcda0c 100644
--- a/shared/bin.h
+++ b/shared/bin.h
@@ -2,11 +2,12 @@
#include <stdint.h>
+/** @brief binary data container with length */
typedef struct {
uint16_t bytes;
uint8_t data[];
} ws_s_bin;
-/** allocate new ws_s_bin struct and fill with `*data` for `bytes` bytes */
-ws_s_bin *ws_bin_s_alloc(uint16_t bytes, uint8_t *data);
+/** @brief allocate new ws_s_bin struct */
+ws_s_bin *ws_bin_s_alloc(uint16_t bytes);
diff --git a/shared/main b/shared/main
index 7d7b7fe..10b0d3c 100755
--- a/shared/main
+++ b/shared/main
Binary files differ
diff --git a/shared/makefile b/shared/makefile
index 4d538da..2ca254c 100644
--- a/shared/makefile
+++ b/shared/makefile
@@ -1,7 +1,7 @@
CC = gcc
LD = gcc
RM = rm -f
-CFLAGS =
+CFLAGS = -g
LFLAGS =
TARGET = main
diff --git a/shared/protocol.c b/shared/protocol.c
index 85b320f..49d1795 100644
--- a/shared/protocol.c
+++ b/shared/protocol.c
@@ -1,5 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "protocol.h"
@@ -12,7 +13,7 @@ void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input) {
case WS_PROTOCOL_C_SPACE: {
if (!state->valid) return;
- printf("argument delimiter\n");
+ state->arg_len++;
return;
}
@@ -23,15 +24,39 @@ void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input) {
default: {
if (!state->valid) return;
- printf("recv byte 0x%02x, (\"%c\")\n", input, input);
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++;
- printf("command done!\n");
+ // parse cmd into argc and argv
+ ws_protocol_cmd_init(state);
+ // create response
+ ws_s_protocol_response* response = ws_protocol_parse_finished(state->target);
+
+ //TODO: send response
+
+ free(response->msg);
+ free(response);
+
+ return;
+}
+
+ws_s_protocol_response* ws_protocol_parse_finished(ws_s_protocol_parsed_cmd* parsed_cmd) {
+ ws_s_protocol_response* response = malloc(sizeof(ws_s_protocol_response));
+
+ if (strncmp("last-records", parsed_cmd->argv[0], 12) == 0) {
+ printf("last-records found!\n");
+ }
+
+ response->msg = ws_bin_s_alloc(50);
+ strncpy((char*) response->msg->data, "hello world!\n\0", 14);
+
+ return response;
}
void ws_protocol_parse_bytes(ws_s_protocol_parser_state* state, char* input, unsigned int length) {
@@ -51,8 +76,16 @@ ws_s_protocol_parser_state* ws_protocol_parser_alloc() {
void ws_protocol_cmd_init(ws_s_protocol_parser_state* state) {
state->target = malloc(sizeof(ws_s_protocol_parsed_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]);
+ state->target->argv[i] = malloc(sizeof(char) * (state->args_len[i] + 1));
+
state->target->argc = state->arg_len;
+
+ unsigned int head = 0;
+ for (unsigned int i = 0; i < state->arg_len; i++) {
+ strncpy(state->target->argv[i], &state->cmd[head], state->args_len[i]);
+ state->target->argv[i][state->args_len[i]] = 0x00; // terminate argument with null byte
+ head += state->args_len[i];
+ }
}
void ws_protocol_parser_free(ws_s_protocol_parser_state* state) {
@@ -63,6 +96,7 @@ void ws_protocol_parser_free(ws_s_protocol_parser_state* state) {
state = NULL;
return;
}
+
void ws_protocol_cmd_free(ws_s_protocol_parsed_cmd* cmd) {
for (unsigned int i = 0; i < cmd->argc; i++)
free(cmd->argv[i]);
diff --git a/shared/protocol.h b/shared/protocol.h
index 5cf7ac6..3082af4 100644
--- a/shared/protocol.h
+++ b/shared/protocol.h
@@ -14,24 +14,54 @@
#define WS_PROTOCOL_C_SPACE (0x20)
#define WS_PROTOCOL_C_NULL (0x00)
+/**
+ * @brief parsed cmd struct, holds arguments similar to argc and argv provided
+ * to `int main()`
+ */
typedef struct {
- int argc;
- char* argv[];
+ int argc; /** argument count */
+ char* argv[]; /** argument array, null terminated strings */
} ws_s_protocol_parsed_cmd;
+/**
+ * @brief holds parser state variables for `ws_protocol_parse_byte` function.
+ * each incoming tcp request should get it's own parser 'instance'
+ */
typedef struct {
- ws_s_protocol_parsed_cmd* target;
- bool valid;
- char* cmd;
- uint16_t cmd_len;
- uint16_t arg_len;
- uint16_t args_len[];
+ ws_s_protocol_parsed_cmd* target; /** parsed cmd reference */
+ bool valid; /** command still valid flag */
+ char* cmd; /** raw cmd */
+ uint16_t cmd_len; /** raw cmd string length */
+ uint16_t arg_len; /** amount of arguments */
+ uint16_t args_len[]; /** array of argument lengths */
} ws_s_protocol_parser_state;
-//TODO: document
+/** @brief return values for command handlers */
+typedef enum {
+ WS_PROTOCOL_CMD_RETURN_OK = 0,
+ WS_PROTOCOL_CMD_RETURN_ERROR = 1,
+} ws_e_protocol_cmd_return_value;
+
+/** @brief request response data struct */
+typedef struct {
+ ws_e_protocol_cmd_return_value success;
+ ws_s_bin* msg;
+} ws_s_protocol_response;
+
+/**
+ * @brief allocate parser struct
+ *
+ * @return pointer to newly allocated struct
+ */
ws_s_protocol_parser_state* ws_protocol_parser_alloc();
+/** @brief deallocate parser struct, automatically frees all child pointers */
void ws_protocol_parser_free(ws_s_protocol_parser_state* state);
+/**
+ * @brief initialize ws_s_protocol_parsed_cmd struct pointer of
+ * ws_s_protocol_parser_state (internal only)
+ */
void ws_protocol_cmd_init(ws_s_protocol_parser_state* state);
+/** @brief deallocate ws_s_protocol_parsed_cmd struct pointer (internal only) */
void ws_protocol_cmd_free(ws_s_protocol_parsed_cmd* cmd);
/**
@@ -53,6 +83,21 @@ void ws_protocol_parse_byte(ws_s_protocol_parser_state* state, char input);
* @param length input byte array length
*/
void ws_protocol_parse_bytes(ws_s_protocol_parser_state* state, char* input, unsigned int length);
+/**
+ * @brief handle complete command
+ *
+ * this function gets called when ws_protocol_parse_byte has detected a
+ * finished command. this function decides which command handler gets called,
+ * given that argv[0] contains a valid command. command argument parsing is
+ * handled by the command handler function.
+ *
+ * @remark [server]
+ *
+ * @return response
+ *
+ * @param parsed_cmd cmd parsed into ws_s_protocol_parsed_cmd struct
+ */
+ws_s_protocol_response* ws_protocol_parse_finished(ws_s_protocol_parsed_cmd* parsed_cmd);
/**
* @brief create a `last-records` request command