diff options
-rw-r--r-- | include/protocol.h | 80 | ||||
-rw-r--r-- | include/utils.h | 11 | ||||
-rw-r--r-- | project.vim | 3 | ||||
-rw-r--r-- | src/common/protocol.c | 169 | ||||
-rw-r--r-- | src/common/protocol_private.h | 66 | ||||
-rw-r--r-- | src/common/utils.c | 22 |
6 files changed, 351 insertions, 0 deletions
diff --git a/include/protocol.h b/include/protocol.h new file mode 100644 index 0000000..c1b786c --- /dev/null +++ b/include/protocol.h @@ -0,0 +1,80 @@ +/* + * Usurpataion --- client-server protocol interface. + * + * Copyright (C) 2019 Ramūnas Mažeikis + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef PROTOCOL_H_INCLUDED +#define PROTOCOL_H_INCLUDED + +#include <errno.h> + +#define SUCCESS (0) +#define TLV_OVERFLOW (1 << 0) + +enum packet_type { + REGURAL, + HEARTBEAT, + DISCOVERY +}; + +enum tlv_type { + TEXT, /* NULL-terminated string. */ + FPI1, /* Fixed point. 1 decimal digit of precision. */ + TIMESTAMP, + REQUEST, + REPLY, + UUID +}; + +struct packet_data { + enum packet_type type; + size_t packet_size; + char *data; /* Bytes representing tlv's */ +}; + +struct tlv { + enum tlv_type type; + size_t length; + void *data; +}; + +/* + * Reads last packets received, parses and stores them to be later retreived + * via get_tlv. + * */ +void get_last_data(void); + +/* Returns tlv's parsed by get_last_data. Returned tlv is only valid until + * next call to get_tlv. + * */ +struct tlv * get_tlv(void); + +/* Any modifications made to the pending outgoing packet are nullified. + * */ +void clear_data(void); + +/* Appends data to the next packet to be sent. Type of data is determined by + * enum tlv_type. + * */ +void push_data(char *data, enum tlv_type); + +/* Sends packet towards the other end. + * */ +void flush_data(void); + +#endif /* PROTOCOL_H_INCLUDED */ diff --git a/include/utils.h b/include/utils.h new file mode 100644 index 0000000..ca2d2ee --- /dev/null +++ b/include/utils.h @@ -0,0 +1,11 @@ +#ifdef PROJECT_UTILS_H +#define PROJECT_UTILS_H + +typedef int fpi1_t; + +fpi1_t add(fpi1_t a, fpi1_t b); +fpi1_t sub(fpi1_t a, fpi1_t b); +fpi1_t mul(fpi1_t a, fpi1_t b); +fpi1_t div(fpi1_t a, fpi1_t b); + +#endif /* PROJECT_UTILS_H */ diff --git a/project.vim b/project.vim new file mode 100644 index 0000000..024222d --- /dev/null +++ b/project.vim @@ -0,0 +1,3 @@ +syn keyword ProjectTypes fpi1_t + +hi ProjectTypes ctermfg=green diff --git a/src/common/protocol.c b/src/common/protocol.c new file mode 100644 index 0000000..8243c8a --- /dev/null +++ b/src/common/protocol.c @@ -0,0 +1,169 @@ +/* + * Usurpataion --- clinet-server protocol implementation. + * + * Copyright (C) 2019 Ramūnas Mažeikis + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "protocol.h" +#include "protocol_private.h" +#include "net.h" +#include <stdlib.h> +#include <string.h> + +#define READ_INT(x) (*((int*)(x))) +#define READ_TLV_TYPE(x) (*((int*))(x)) +#define READ_SIZE_T(x) (*((size_t)(x))) +#define READ_AS(from, type) (*(type*)(from)) + +#define GET_MSG_CHAR(i) (msg_buf[(i) % MSG_BUF_SIZE]) +#define SET_MSG_CHAR(i, ch) msg_buf[(i) % MSG_BUF_SIZE] = (ch) + +/* Increment message cursor */ +#define IMC(x) ((msg_cursor + (x)) % MSG_BUF_SIZE) + +/* Begins at 2 because this way we'll have two null's at the beggining + * indicating that going back is not possible. + * */ +static const int msg_cursor = 2; +/* Two consecutive null's indicate that going back is not possible. + * */ +static char msg_buf[MSG_BUF_SIZE] = {0}; + +static int tlv_cursor = 0; +static struct tlv tlv_buf[TLV_BUF_SIZE] = {0}; + +static size_t packet_cursor = 0; +/* Outgoing packet. + * */ +static char packet_buf[PACKET_MAX_SIZE] = {0}; + +static void push_bytes(const void * const data, const size_t size) +{ + memcpy(packet_buf + packet_cursor, data, size); + packet_cursor += size; +} + +void clear_data(void) +{ + packet_cursor = 0; +} + +void push_data(char *data, enum tlv_type type) +{ + switch (type) { + case TEXT: + case FPI1: + case TIMESTAMP: + case REQUEST: + case REPLY: + case UUID: + } +} + +void push_string(char *str) +{ + size_t size = strlen(str); + + *((enum tlv_type*)packet_buf) = TEXT; + packet_cursor += sizeof(enum tlv_type); + *((size_t*)packet_buf) = strlen(str); + packet_cursor += sizeof(size_t); + push_bytes(); +} + +void push_fpi1(fpi1_t num); + +void push_timestamp(char *data); + +void push_request(char *data); + +void push_reply(char *data); + +void push_uuid(char *data); + +void get_last_data() +{ + msg_cursor = 2; + msg_buf[0] = '\0'; + msg_buf[1] = '\0'; + tlv_cursor = 0; + /* Get packet here. Somehow. TODO */ + get_tlvs(packet_buf, tlv_buf, TLV_BUF_SIZE); +} + +struct tlv * get_tlv(void) +{ + if (tlv_buf[tlv_cursor] != NULL) { + struct tlv *ret = tlv_buf[tlv_cursor++]; + } else { + ret = NULL; + } + return ret; +} + +int tlv_count(const struct packet_data * const packet) +{ + size_t cursor = 0; + size_t length = 0; + size_t ret = 0; + + while (cursor < packet->packet_size) { + cursor += sizeof(enum tlv_type); + length = READ_SIZE_T(packet->data + cursor); + cursor += sizeof(size_t) + length; + ret++; + } + if (cursor != packet->packet_size) { + errno = TLV_OVERFLOW; + } + return ret; +} + +size_t get_tlvs( const struct packet_data * const data, + const struct tlv *buf, + size_t buf_size) +{ + size_t tlvs_read = 0; + size_t cursor = 0; + + while (cursor < data->packet_size && tlvs_read <= buf_size) { + cursor += parse_tlv(data->data, cursor, buf + tlvs_read); + tlvs_read++; + } + + if (cursor > data->packet_length) { + errno = TLV_OVERFLOW; + } + + return tlvs_read; +} + +/* Returns how many bytes were consumed by parser. + * */ +size_t parse_tlv(char *data, size_t cursor, struct tlv *t) +{ + char *begin = data + cursor; + + t->type = READ_TLV_TYPE(data + cursor); + cursor += sizeof(enum tlv_type); + t->length += READ_SIZE_T(data + cursor); + data += sizeof(size_t); + t->data = data + cursor; + + return data + cursor - begin + 1UL; +} + diff --git a/src/common/protocol_private.h b/src/common/protocol_private.h new file mode 100644 index 0000000..3a4b1b2 --- /dev/null +++ b/src/common/protocol_private.h @@ -0,0 +1,66 @@ +/* + * Usurpataion --- server-client protocol private interface. + * + * Copyright (C) 2019 Ramūnas Mažeikis + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef PROTOCOL_H_PRIVATE +#define PROTOCOL_H_PRIVATE + +#define TLV_ARR_SIZE (16) + +/* Pease don't rape the buffer with long messages, daemon-kun. */ +#define MSG_BUF_SIZE (257) + +/* UDP can carry bigger packets but memory is hard to come by and more won't be + * needed anyway. + * */ +#define PACKET_MAX_SIZE (512) + +/* Returns the amount of tlv's int a packet. + * + * If a tlv reports length that goes beyond the end of a packet, errno is set + * to TLV_OVERFLOW. To check this, set errno to 0 first. + * */ +size_t tlv_count(const struct packet_data * const packet); + +/* Parses a data packet, fills buffer of tlv's of size `buf_size` and returns + * the number of tlv's actually parsed. + * + * To check for errors, set errno to 0 and check after calling. + * */ +size_t get_tlvs( const struct packet_data * const data, + const struct tlv *buf, + size_t buf_size); + +/* Takes a null-terminated string and appends it to the next outgoing packet. + * */ +void push_string(char *str); + +void push_fpi1(fpi1_t num); + +void push_timestamp(char *data); + +void push_request(char *data); + +void push_reply(char *data); + +void push_uuid(char *data); + + + +#endif /* PROTOCOL_H_PRIVATE */ diff --git a/src/common/utils.c b/src/common/utils.c new file mode 100644 index 0000000..7bcf767 --- /dev/null +++ b/src/common/utils.c @@ -0,0 +1,22 @@ +#include "utils.h" + +fpi1_t add(fpi1_t a, fpi1_t b) +{ + return a + b; +} + +fpi1_t sub(fpi1_t a, fpi1_t b) +{ + return a - b; +} + +fpi1_t mul(fpi1_t a, fpi1_t b) +{ + return (fpi1_t)(((long)a * (long)b) / 100); +} + +fpi1_t div(fpi1_t a, fpi1_t b) +{ + return (fpi1_t)(((long)a * 10) / ((long)b * 10)); +} + |