diff options
| -rw-r--r-- | shared/bin.c | 11 | ||||
| -rw-r--r-- | shared/bin.h | 5 | ||||
| -rwxr-xr-x | shared/main | bin | 21456 -> 28568 bytes | |||
| -rw-r--r-- | shared/makefile | 2 | ||||
| -rw-r--r-- | shared/protocol.c | 42 | ||||
| -rw-r--r-- | shared/protocol.h | 63 | 
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 Binary files differindex 7d7b7fe..10b0d3c 100755 --- a/shared/main +++ b/shared/main 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  |