From 9c8ece1538d31dba9a416c9f29f88e18510f4c75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Sat, 18 May 2019 16:32:20 +0300 Subject: Whole-project: partial implementation of protocol. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit is part of ticket #31. Branch is not in a compiling state. Work is being done on utility functions and protocol implementation. To be completed later. Signed-off-by: Ramūnas Mažeikis --- include/protocol.h | 80 ++++++++++++++++++++ include/utils.h | 11 +++ project.vim | 3 + src/common/protocol.c | 169 ++++++++++++++++++++++++++++++++++++++++++ src/common/protocol_private.h | 66 +++++++++++++++++ src/common/utils.c | 22 ++++++ 6 files changed, 351 insertions(+) create mode 100644 include/protocol.h create mode 100644 include/utils.h create mode 100644 project.vim create mode 100644 src/common/protocol.c create mode 100644 src/common/protocol_private.h create mode 100644 src/common/utils.c 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 + +#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 +#include + +#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)); +} + -- cgit v1.2.3 From b4165ee0b257aaa9064c5ac82200ff2569a02955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Sun, 19 May 2019 13:52:43 +0300 Subject: Protocol: more work on protocol implementation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Additional functions implemented for protocol and basic functions to work with uuid. Source is buildable but actual build files are not edited to accomodate the changes. Signed-off-by: Ramūnas Mažeikis --- include/protocol.h | 23 ++++++++++++-- include/utils.h | 15 ++++++++- src/common/protocol.c | 73 +++++++++++++++++++++++++++++++------------ src/common/protocol_private.h | 40 ++++++++++++++++++++---- src/common/utils.c | 17 ++++++++++ 5 files changed, 138 insertions(+), 30 deletions(-) diff --git a/include/protocol.h b/include/protocol.h index c1b786c..5872fa3 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifdef PROTOCOL_H_INCLUDED +#ifndef PROTOCOL_H_INCLUDED #define PROTOCOL_H_INCLUDED #include @@ -33,11 +33,28 @@ enum packet_type { }; enum tlv_type { - TEXT, /* NULL-terminated string. */ - FPI1, /* Fixed point. 1 decimal digit of precision. */ + /* NULL-terminated string. */ + TEXT, + + /* Fixed point. 1 decimal digit of precision. */ + FPI1, + + /* Literally time_t*/ TIMESTAMP, + + /* Represents a request for lost message. Data is unsigned integer + * that uniquely identifies the message. + */ REQUEST, + + /* Response to request. Begins with unsigned integer that represents + * which message is begin repeated and the actual null-terminated + * message after that. + */ REPLY, + + /* UUID that represents a particular device. + */ UUID }; diff --git a/include/utils.h b/include/utils.h index ca2d2ee..daea864 100644 --- a/include/utils.h +++ b/include/utils.h @@ -1,6 +1,19 @@ -#ifdef PROJECT_UTILS_H +#ifndef PROJECT_UTILS_H #define PROJECT_UTILS_H +#include + +typedef struct uuid_s { + uint64_t low; + uint64_t hi; +} uuid_t; + +int cmp_uuid(uuid_t *first, uuid_t *second); + +/* Prints uuid in cannonical format. + */ +void uuid_to_str(uuid_t *to_print, char *buf); + typedef int fpi1_t; fpi1_t add(fpi1_t a, fpi1_t b); diff --git a/src/common/protocol.c b/src/common/protocol.c index 8243c8a..270fa81 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -23,10 +23,8 @@ #include "net.h" #include #include +#include -#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]) @@ -38,7 +36,7 @@ /* 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; +static int msg_cursor = 2; /* Two consecutive null's indicate that going back is not possible. * */ static char msg_buf[MSG_BUF_SIZE] = {0}; @@ -78,22 +76,45 @@ 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(); + push_tlv_header(TEXT, size); + push_bytes(str, size); } -void push_fpi1(fpi1_t num); +void push_fpi1(char *num) +{ + push_tlv_header(FPI1, sizeof(fpi1_t)); + push_bytes(num, sizeof(fpi1_t)); +} -void push_timestamp(char *data); +void push_timestamp(char *data) +{ + push_tlv_header(TIMESTAMP, sizeof(time_t)); + push_bytes(data, sizeof(time_t)); +} -void push_request(char *data); +void push_request(char *data) +{ + (void)data; +} -void push_reply(char *data); +void push_reply(char *data) +{ + (void)data; +} -void push_uuid(char *data); +void push_uuid(char *data) +{ + push_tlv_header(UUID, sizeof(uuid_t)); + push_bytes(data, sizeof(uuid_t)); +} + +void push_tlv_header(enum tlv_type type, size_t size) +{ + READ_AS(packet_buf, enum tlv_type) = type; + packet_cursor += sizeof(type); + READ_AS(packet_buf, size_t) = size; + packet_cursor += sizeof(size); +} void get_last_data() { @@ -107,15 +128,16 @@ void get_last_data() struct tlv * get_tlv(void) { - if (tlv_buf[tlv_cursor] != NULL) { - struct tlv *ret = tlv_buf[tlv_cursor++]; + struct tlv *ret; + 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 tlv_count(const struct packet_data * const packet) { size_t cursor = 0; size_t length = 0; @@ -123,7 +145,7 @@ int tlv_count(const struct packet_data * const packet) while (cursor < packet->packet_size) { cursor += sizeof(enum tlv_type); - length = READ_SIZE_T(packet->data + cursor); + length = READ_AS(packet->data + cursor, enum tlv_type); cursor += sizeof(size_t) + length; ret++; } @@ -133,6 +155,18 @@ int tlv_count(const struct packet_data * const packet) return ret; } +/** + * Parses tlv's from packet data and writes them to a buffer of given size. + * + * Returns how many tlv's were actually parsed. + * + * Not yet implemented. + * + * @param data + * + * @return Number of tlv's actually parsed. Greter than or equal to buffer + * size, if an error occurs. + */ size_t get_tlvs( const struct packet_data * const data, const struct tlv *buf, size_t buf_size) @@ -145,7 +179,7 @@ size_t get_tlvs( const struct packet_data * const data, tlvs_read++; } - if (cursor > data->packet_length) { + if (cursor > data->packet_size) { errno = TLV_OVERFLOW; } @@ -166,4 +200,3 @@ size_t parse_tlv(char *data, size_t cursor, struct tlv *t) return data + cursor - begin + 1UL; } - diff --git a/src/common/protocol_private.h b/src/common/protocol_private.h index 3a4b1b2..653d19c 100644 --- a/src/common/protocol_private.h +++ b/src/common/protocol_private.h @@ -18,10 +18,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifdef PROTOCOL_H_PRIVATE +#ifndef PROTOCOL_H_PRIVATE #define PROTOCOL_H_PRIVATE -#define TLV_ARR_SIZE (16) +#include "utils.h" + +#define TLV_BUF_SIZE (16) /* Pease don't rape the buffer with long messages, daemon-kun. */ #define MSG_BUF_SIZE (257) @@ -38,10 +40,22 @@ * */ 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. + +/** + * Parses tlv's from packet data and writes them to a buffer of given size. + * + * Returns how many tlv's were actually parsed. * * To check for errors, set errno to 0 and check after calling. + * + * Not yet implemented. + * + * @param data Data from network packet + * @param buf Buffer to store parsed tlv's + * @param buf_size Size of buffer used to store tlv's + * + * @return Number of tlv's actually parsed. Greter than or equal to buffer + * size, if an error occurs. * */ size_t get_tlvs( const struct packet_data * const data, const struct tlv *buf, @@ -51,16 +65,30 @@ size_t get_tlvs( const struct packet_data * const data, * */ void push_string(char *str); -void push_fpi1(fpi1_t num); +/* Reinterprets char * as fpi1_t * and appends it to the outgoing packet as a + * tlv. + */ +void push_fpi1(char *num); +/* Reinterprets char * as time_t * and appends it to the outgoing packet as a + * tlv. + */ void push_timestamp(char *data); +/* Not implemented yet. */ void push_request(char *data); +/* Not implemented yet. */ void push_reply(char *data); +/* Reinterprets char * as uuid_t * and appends it to the outgoing packet as a + * tlv. + */ void push_uuid(char *data); - +/* Appends tlv_type and size of data to a packet effectively creating a tlv + * header. + */ +void push_tlv_header(enum tlv_type type, size_t size); #endif /* PROTOCOL_H_PRIVATE */ diff --git a/src/common/utils.c b/src/common/utils.c index 7bcf767..7e4caa5 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -1,5 +1,22 @@ #include "utils.h" +int cmp_uuid(uuid_t *first, uuid_t *second) +{ + if (first->hi == second->hi) { + if (first->low == second->low) { + return 0; + } else if (first->low < second->low) { + return -1; + } else { + return 1; + } + } else if (first->hi < second->hi) { + return -1; + } else { + return 1; + } +} + fpi1_t add(fpi1_t a, fpi1_t b) { return a + b; -- cgit v1.2.3 From 031caaf9b7745bfc552cc86fb475de1f18d0fd6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Sun, 19 May 2019 17:50:53 +0300 Subject: Protocol: Implemented protocol error reporting. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now public functions of the protocol can return an error code. More work is done on actual logic. Protocol code has bare-bones doxygen documentation. Signed-off-by: Ramūnas Mažeikis --- include/protocol.h | 32 +++++++++---------- include/utils.h | 7 +---- src/common/protocol.c | 73 +++++++++++++++++++++++++------------------ src/common/protocol_private.h | 44 ++++++++++++++++---------- src/common/utils.c | 16 ++-------- 5 files changed, 88 insertions(+), 84 deletions(-) diff --git a/include/protocol.h b/include/protocol.h index 5872fa3..9d5b518 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -23,8 +23,8 @@ #include -#define SUCCESS (0) -#define TLV_OVERFLOW (1 << 0) +#define E_TLV_OVERFLOW (1 << 0) +#define E_UNKNOWN_TYPE (1 << 1) enum packet_type { REGURAL, @@ -33,27 +33,27 @@ enum packet_type { }; enum tlv_type { - /* NULL-terminated string. */ + /** NULL-terminated string. */ TEXT, - - /* Fixed point. 1 decimal digit of precision. */ + + /** Fixed point. 1 decimal digit of precision. */ FPI1, - - /* Literally time_t*/ + + /** Literally time_t*/ TIMESTAMP, - - /* Represents a request for lost message. Data is unsigned integer - * that uniquely identifies the message. + + /** Represents a request for lost message. Data is unsigned integer + * that uniquely identifies the message. */ REQUEST, - - /* Response to request. Begins with unsigned integer that represents - * which message is begin repeated and the actual null-terminated + + /** Response to request. Begins with unsigned integer that represents + * which message is being repeated and the actual null-terminated * message after that. */ REPLY, - - /* UUID that represents a particular device. + + /** UUID that represents a particular device. */ UUID }; @@ -88,7 +88,7 @@ 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); +int push_data(const char *data, enum tlv_type); /* Sends packet towards the other end. * */ diff --git a/include/utils.h b/include/utils.h index daea864..e4feb9a 100644 --- a/include/utils.h +++ b/include/utils.h @@ -4,16 +4,11 @@ #include typedef struct uuid_s { - uint64_t low; - uint64_t hi; + char bytes[16]; } uuid_t; int cmp_uuid(uuid_t *first, uuid_t *second); -/* Prints uuid in cannonical format. - */ -void uuid_to_str(uuid_t *to_print, char *buf); - typedef int fpi1_t; fpi1_t add(fpi1_t a, fpi1_t b); diff --git a/src/common/protocol.c b/src/common/protocol.c index 270fa81..2ac8280 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -49,10 +49,14 @@ static size_t packet_cursor = 0; * */ static char packet_buf[PACKET_MAX_SIZE] = {0}; -static void push_bytes(const void * const data, const size_t size) +static int push_bytes(const void * const data, const size_t size) { + if (packet_cursor + size >= PACKET_MAX_SIZE) { + return E_PACKET_OVERFLOW; + } memcpy(packet_buf + packet_cursor, data, size); packet_cursor += size; + return 0; } void clear_data(void) @@ -60,60 +64,81 @@ void clear_data(void) packet_cursor = 0; } -void push_data(char *data, enum tlv_type type) +int push_data(const char *data, enum tlv_type type) { + int ret = E_UNKNOWN_TYPE; switch (type) { case TEXT: + ret = push_string(data); + break; case FPI1: + ret = push_fpi1(data); + break; case TIMESTAMP: + ret = push_timestamp(data); + break; case REQUEST: + ret = push_request(data); + break; case REPLY: + ret = push_reply(data); + break; case UUID: + ret = push_uuid(data); + break; } + return ret; } -void push_string(char *str) +static int push_string(char *str) { size_t size = strlen(str); push_tlv_header(TEXT, size); push_bytes(str, size); + return 0; } -void push_fpi1(char *num) +static int push_fpi1(char *num) { - push_tlv_header(FPI1, sizeof(fpi1_t)); - push_bytes(num, sizeof(fpi1_t)); + return push_tlv_header(FPI1, sizeof(fpi1_t)) + | push_bytes(num, sizeof(fpi1_t)); } -void push_timestamp(char *data) +static int push_timestamp(char *data) { - push_tlv_header(TIMESTAMP, sizeof(time_t)); - push_bytes(data, sizeof(time_t)); + return push_tlv_header(TIMESTAMP, sizeof(time_t)) + | push_bytes(data, sizeof(time_t)); } -void push_request(char *data) +static int push_request(char *data) { (void)data; + return 0; } -void push_reply(char *data) +static int push_reply(char *data) { (void)data; + return 0; } -void push_uuid(char *data) +static int push_uuid(char *data) { - push_tlv_header(UUID, sizeof(uuid_t)); - push_bytes(data, sizeof(uuid_t)); + return push_tlv_header(UUID, sizeof(uuid_t)) + | push_bytes(data, sizeof(uuid_t)); } -void push_tlv_header(enum tlv_type type, size_t size) +int push_tlv_header(enum tlv_type type, size_t size) { + if (size + sizeof(type) + packet_cursor >= PACKET_MAX_SIZE) { + return E_PACKET_OVERFLOW; + } READ_AS(packet_buf, enum tlv_type) = type; packet_cursor += sizeof(type); READ_AS(packet_buf, size_t) = size; packet_cursor += sizeof(size); + return 0; } void get_last_data() @@ -150,23 +175,11 @@ size_t tlv_count(const struct packet_data * const packet) ret++; } if (cursor != packet->packet_size) { - errno = TLV_OVERFLOW; + errno = E_TLV_OVERFLOW; } return ret; } -/** - * Parses tlv's from packet data and writes them to a buffer of given size. - * - * Returns how many tlv's were actually parsed. - * - * Not yet implemented. - * - * @param data - * - * @return Number of tlv's actually parsed. Greter than or equal to buffer - * size, if an error occurs. - */ size_t get_tlvs( const struct packet_data * const data, const struct tlv *buf, size_t buf_size) @@ -180,14 +193,12 @@ size_t get_tlvs( const struct packet_data * const data, } if (cursor > data->packet_size) { - errno = TLV_OVERFLOW; + errno = E_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; diff --git a/src/common/protocol_private.h b/src/common/protocol_private.h index 653d19c..0c0b7f9 100644 --- a/src/common/protocol_private.h +++ b/src/common/protocol_private.h @@ -23,37 +23,44 @@ #include "utils.h" +#define E_PACKET_OVERFLOW (1 << 0) + +/** Read as "A maximum of 16 tlv's per packet". */ #define TLV_BUF_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. +/* Maximum size of packet that can fit into the packet buffer. 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. +/** 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. + * + * @param packet data parsed from a packet. Function cannot use raw packets. + * + * @return Amount of tlv's in a packet. * */ -size_t tlv_count(const struct packet_data * const packet); - +size_t tlv_count(const struct packet_data * const packet_data); /** * Parses tlv's from packet data and writes them to a buffer of given size. - * + * * Returns how many tlv's were actually parsed. * * To check for errors, set errno to 0 and check after calling. - * + * * Not yet implemented. - * + * * @param data Data from network packet * @param buf Buffer to store parsed tlv's * @param buf_size Size of buffer used to store tlv's - * + * * @return Number of tlv's actually parsed. Greter than or equal to buffer * size, if an error occurs. * */ @@ -61,34 +68,37 @@ 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. +/** Takes a null-terminated string and appends it to the next outgoing packet. + * + * @return Returns 0 on success. Otherwise: E_PACKET_OVERFLOW. + * * */ -void push_string(char *str); +int push_string(char *str); /* Reinterprets char * as fpi1_t * and appends it to the outgoing packet as a * tlv. */ -void push_fpi1(char *num); +int push_fpi1(char *num); /* Reinterprets char * as time_t * and appends it to the outgoing packet as a * tlv. */ -void push_timestamp(char *data); +int push_timestamp(char *data); /* Not implemented yet. */ -void push_request(char *data); +int push_request(char *data); /* Not implemented yet. */ -void push_reply(char *data); +int push_reply(char *data); /* Reinterprets char * as uuid_t * and appends it to the outgoing packet as a * tlv. */ -void push_uuid(char *data); +int push_uuid(char *data); /* Appends tlv_type and size of data to a packet effectively creating a tlv * header. */ -void push_tlv_header(enum tlv_type type, size_t size); +int push_tlv_header(enum tlv_type type, size_t size); #endif /* PROTOCOL_H_PRIVATE */ diff --git a/src/common/utils.c b/src/common/utils.c index 7e4caa5..956ef1b 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -1,20 +1,9 @@ #include "utils.h" +#include "string.h" int cmp_uuid(uuid_t *first, uuid_t *second) { - if (first->hi == second->hi) { - if (first->low == second->low) { - return 0; - } else if (first->low < second->low) { - return -1; - } else { - return 1; - } - } else if (first->hi < second->hi) { - return -1; - } else { - return 1; - } + return memcmp(first, second, sizeof(*first)); } fpi1_t add(fpi1_t a, fpi1_t b) @@ -36,4 +25,3 @@ fpi1_t div(fpi1_t a, fpi1_t b) { return (fpi1_t)(((long)a * 10) / ((long)b * 10)); } - -- cgit v1.2.3 From bb70fccb66f55e9cc2b9ed0bf366479828f41346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Mon, 20 May 2019 21:50:19 +0300 Subject: Protocol: implemented request and reply pushing to packet. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First implementation of complete protocol interface. While the first implementation does compile, the interface might change due to demands from other parts of the project. For now reqest is a tlv that is an unsigned int which represents what message to repeat from daemon. A reply is also a tlv made of two parts --- message sequence number of type msg_ixd_t and the actual null terminated string. All of the above is subject to change. More docs. Doxygen is on the way. Signed-off-by: Ramūnas Mažeikis --- include/protocol.h | 7 +++++++ include/utils.h | 3 +++ src/common/protocol.c | 14 ++++++++------ src/common/protocol_private.h | 26 +++++++++++++++++++++----- 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/include/protocol.h b/include/protocol.h index 9d5b518..ac83154 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -32,6 +32,13 @@ enum packet_type { DISCOVERY }; +/** + * Message sequence number since beggining of sesssion. + * + * Mainly used for identifying lost messages. + */ +typedef unsigned int msg_idx_t; + enum tlv_type { /** NULL-terminated string. */ TEXT, diff --git a/include/utils.h b/include/utils.h index e4feb9a..f92e0fa 100644 --- a/include/utils.h +++ b/include/utils.h @@ -9,6 +9,9 @@ typedef struct uuid_s { int cmp_uuid(uuid_t *first, uuid_t *second); +/** + * Fixed point number with one decimal digit of precision. + */ typedef int fpi1_t; fpi1_t add(fpi1_t a, fpi1_t b); diff --git a/src/common/protocol.c b/src/common/protocol.c index 2ac8280..2243dad 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -113,14 +113,17 @@ static int push_timestamp(char *data) static int push_request(char *data) { - (void)data; - return 0; + return push_tlv_header(REQUEST, sizeof(msg_idx_t)) + | push_bytes(data, sizeof(msg_idx_t)); } static int push_reply(char *data) { - (void)data; - return 0; + int ret = 0; + size_t msglen = strlen(data + sizeof(msg_idx_t)); + ret |= push_tlv_header(REPLY, msglen + sizeof(msg_idx_t)); + ret |= push_bytes(data, msglen); + return ret; } static int push_uuid(char *data) @@ -129,7 +132,7 @@ static int push_uuid(char *data) | push_bytes(data, sizeof(uuid_t)); } -int push_tlv_header(enum tlv_type type, size_t size) +static int push_tlv_header(enum tlv_type type, size_t size) { if (size + sizeof(type) + packet_cursor >= PACKET_MAX_SIZE) { return E_PACKET_OVERFLOW; @@ -147,7 +150,6 @@ void get_last_data() 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); } diff --git a/src/common/protocol_private.h b/src/common/protocol_private.h index 0c0b7f9..b74c0eb 100644 --- a/src/common/protocol_private.h +++ b/src/common/protocol_private.h @@ -75,23 +75,39 @@ size_t get_tlvs( const struct packet_data * const data, * */ int push_string(char *str); -/* Reinterprets char * as fpi1_t * and appends it to the outgoing packet as a +/** Reinterprets char * as fpi1_t * and appends it to the outgoing packet as a * tlv. */ int push_fpi1(char *num); -/* Reinterprets char * as time_t * and appends it to the outgoing packet as a +/** Reinterprets char * as time_t * and appends it to the outgoing packet as a * tlv. */ int push_timestamp(char *data); -/* Not implemented yet. */ +/** + * Pushes a request for daemon to repeat a message identified by a msg_index_t. + * + * @param data Pointer to a msg_index_t. + * + * @return 0 on success or E_PACKET_OVERFLOW, if not enough space is available + * to push all the data. + */ int push_request(char *data); -/* Not implemented yet. */ +/** + * Pushes a message to the outgoing packet buffer as a reply. A reply is just + * a null terminated string. + * + * @param data msg_idx_t representing sequence number since beggining of + * connection and a null-terminated string. + * + * @return On success --- 0 or E_PACKET_OVERFLOW, if not enough buffer is + * available. + */ int push_reply(char *data); -/* Reinterprets char * as uuid_t * and appends it to the outgoing packet as a +/** Reinterprets char * as uuid_t * and appends it to the outgoing packet as a * tlv. */ int push_uuid(char *data); -- cgit v1.2.3 From cabb90c1240015ee5cd17d91573588527bcc2482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Tue, 21 May 2019 17:41:21 +0300 Subject: Protocol: changes to interface and some re-implementation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most functions exposed in protocol.h take a connection descriptor (cd_t) as first argument. This allows for multiple connections. Device gets only one connection which means that cd_t is effectively 0 all the time. Additionaly, any function that actually does anything with a connection descriptor instead of just passing it to another function must be implemented separately in device and daemon. Signed-off-by: Ramūnas Mažeikis --- include/protocol.h | 58 ++++++++++++++----- include/utils.h | 8 +-- src/common/protocol.c | 109 ++++++++++++++--------------------- src/common/protocol_private.h | 17 +++--- src/common/utils.c | 8 +-- src/device/protocol_device.ino | 38 ++++++++++++ src/device/protocol_device_private.h | 37 ++++++++++++ 7 files changed, 179 insertions(+), 96 deletions(-) create mode 100755 src/device/protocol_device.ino create mode 100755 src/device/protocol_device_private.h diff --git a/include/protocol.h b/include/protocol.h index ac83154..60d31ea 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -23,15 +23,28 @@ #include -#define E_TLV_OVERFLOW (1 << 0) -#define E_UNKNOWN_TYPE (1 << 1) +#define E_TLV_OVERFLOW (1 << 0) +#define E_UNKNOWN_TYPE (1 << 1) +#define E_IVALID_DESCRIPTOR (1 << 2) +/** + * Regular packets contain tlv's defined by tlv_type. + * + * Hearbeat packet tell daemon that device is still alive and listening. + * + * Discovery packets are used for what they say. + */ enum packet_type { REGURAL, HEARTBEAT, DISCOVERY }; +/** + * Connection descriptor. + */ +typedef unsigned int cd_t; + /** * Message sequence number since beggining of sesssion. * @@ -40,13 +53,16 @@ enum packet_type { typedef unsigned int msg_idx_t; enum tlv_type { - /** NULL-terminated string. */ + /** + * NULL-terminated string. To be put in a queue to display on the + * screen. + */ TEXT, /** Fixed point. 1 decimal digit of precision. */ FPI1, - /** Literally time_t*/ + /** Literally time_t */ TIMESTAMP, /** Represents a request for lost message. Data is unsigned integer @@ -54,51 +70,63 @@ enum tlv_type { */ REQUEST, - /** Response to request. Begins with unsigned integer that represents + /** + * Response to request. Begins with unsigned integer that represents * which message is being repeated and the actual null-terminated * message after that. */ REPLY, - /** UUID that represents a particular device. + /** + * UUID that represents a particular device. */ UUID }; +/** + * Packet data itself is a special type of tlv. A packet is either regular, + * hearbeat or discovery. + */ struct packet_data { enum packet_type type; size_t packet_size; char *data; /* Bytes representing tlv's */ }; +/** + * Literally type-length-value + * */ 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); +void get_last_data(cd_t connection); -/* Returns tlv's parsed by get_last_data. Returned tlv is only valid until +/** 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. +/** + * Any modifications made to the pending outgoing packet are nullified. * */ -void clear_data(void); +void clear_data(cd_t connection); -/* Appends data to the next packet to be sent. Type of data is determined by +/** + * Appends data to the next packet to be sent. Type of data is determined by * enum tlv_type. * */ -int push_data(const char *data, enum tlv_type); +int push_data(cd_t connection, const char *data, enum tlv_type); -/* Sends packet towards the other end. +/** + * Sends packet towards the other end. * */ -void flush_data(void); +void flush_data(cd_t connection); #endif /* PROTOCOL_H_INCLUDED */ diff --git a/include/utils.h b/include/utils.h index f92e0fa..c769917 100644 --- a/include/utils.h +++ b/include/utils.h @@ -14,9 +14,9 @@ int cmp_uuid(uuid_t *first, uuid_t *second); */ 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); +fpi1_t fpi1_add(fpi1_t a, fpi1_t b); +fpi1_t fpi1_sub(fpi1_t a, fpi1_t b); +fpi1_t fpi1_mul(fpi1_t a, fpi1_t b); +fpi1_t fpi1_div(fpi1_t a, fpi1_t b); #endif /* PROJECT_UTILS_H */ diff --git a/src/common/protocol.c b/src/common/protocol.c index 2243dad..3d63771 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -18,6 +18,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +/** + * Common parts of protocol implementation. Handling of anything that actually + * deals with connection descriptor has to be implemented by device and daemon + * separately. + */ + #include "protocol.h" #include "protocol_private.h" #include "net.h" @@ -37,7 +43,11 @@ * indicating that going back is not possible. * */ static int msg_cursor = 2; -/* Two consecutive null's indicate that going back is not possible. + +/** + * Message buffer. + * + * Two consecutive null's indicate that going back is not possible. * */ static char msg_buf[MSG_BUF_SIZE] = {0}; @@ -49,7 +59,7 @@ static size_t packet_cursor = 0; * */ static char packet_buf[PACKET_MAX_SIZE] = {0}; -static int push_bytes(const void * const data, const size_t size) +static int push_bytes(cd_t connection, const void * const data, const size_t size) { if (packet_cursor + size >= PACKET_MAX_SIZE) { return E_PACKET_OVERFLOW; @@ -59,109 +69,78 @@ static int push_bytes(const void * const data, const size_t size) return 0; } -void clear_data(void) +void clear_data(cd_t connection) { packet_cursor = 0; } -int push_data(const char *data, enum tlv_type type) +int push_data(cd_t connection, const char *data, enum tlv_type type) { int ret = E_UNKNOWN_TYPE; switch (type) { case TEXT: - ret = push_string(data); + ret = push_string(connection, data); break; case FPI1: - ret = push_fpi1(data); + ret = push_fpi1(connection, data); break; case TIMESTAMP: - ret = push_timestamp(data); + ret = push_timestamp(connection, data); break; case REQUEST: - ret = push_request(data); + ret = push_request(connection, data); break; case REPLY: - ret = push_reply(data); + ret = push_reply(connection, data); break; case UUID: - ret = push_uuid(data); + ret = push_uuid(connection, data); break; } return ret; } -static int push_string(char *str) +static int push_string(cd_t connection, char *str) { + int ret = 0; size_t size = strlen(str); - push_tlv_header(TEXT, size); - push_bytes(str, size); - return 0; -} - -static int push_fpi1(char *num) -{ - return push_tlv_header(FPI1, sizeof(fpi1_t)) - | push_bytes(num, sizeof(fpi1_t)); -} - -static int push_timestamp(char *data) -{ - return push_tlv_header(TIMESTAMP, sizeof(time_t)) - | push_bytes(data, sizeof(time_t)); -} - -static int push_request(char *data) -{ - return push_tlv_header(REQUEST, sizeof(msg_idx_t)) - | push_bytes(data, sizeof(msg_idx_t)); + ret |= push_tlv_header(connection, TEXT, size); + ret |= push_bytes(connection, str, size); + return ret; } -static int push_reply(char *data) +static int push_fpi1(cd_t connection, char *num) { - int ret = 0; - size_t msglen = strlen(data + sizeof(msg_idx_t)); - ret |= push_tlv_header(REPLY, msglen + sizeof(msg_idx_t)); - ret |= push_bytes(data, msglen); - return ret; + return push_tlv_header(connection, FPI1, sizeof(fpi1_t)) + | push_bytes(connection, num, sizeof(fpi1_t)); } -static int push_uuid(char *data) +static int push_timestamp(cd_t connection, char *data) { - return push_tlv_header(UUID, sizeof(uuid_t)) - | push_bytes(data, sizeof(uuid_t)); + return push_tlv_header(connection, TIMESTAMP, sizeof(time_t)) + | push_bytes(connection, data, sizeof(time_t)); } -static int push_tlv_header(enum tlv_type type, size_t size) +static int push_request(cd_t connection, char *data) { - if (size + sizeof(type) + packet_cursor >= PACKET_MAX_SIZE) { - return E_PACKET_OVERFLOW; - } - READ_AS(packet_buf, enum tlv_type) = type; - packet_cursor += sizeof(type); - READ_AS(packet_buf, size_t) = size; - packet_cursor += sizeof(size); - return 0; + return push_tlv_header(connection, REQUEST, sizeof(msg_idx_t)) + | push_bytes(connection, data, sizeof(msg_idx_t)); } -void get_last_data() +static int push_reply(cd_t connection, char *data) { - msg_cursor = 2; - msg_buf[0] = '\0'; - msg_buf[1] = '\0'; - tlv_cursor = 0; - get_tlvs(packet_buf, tlv_buf, TLV_BUF_SIZE); + int ret = 0; + size_t msglen = strlen(data + sizeof(msg_idx_t)); + ret |= push_tlv_header(connection, REPLY, msglen + sizeof(msg_idx_t)); + ret |= push_bytes(connection, data, msglen); + return ret; } -struct tlv * get_tlv(void) +static int push_uuid(cd_t connection, char *data) { - struct tlv *ret; - if (tlv_buf + tlv_cursor != NULL) { - struct tlv *ret = &tlv_buf[tlv_cursor++]; - } else { - ret = NULL; - } - return ret; + return push_tlv_header(connection, UUID, sizeof(uuid_t)) + | push_bytes(connection, data, sizeof(uuid_t)); } size_t tlv_count(const struct packet_data * const packet) @@ -182,7 +161,7 @@ size_t tlv_count(const struct packet_data * const packet) return ret; } -size_t get_tlvs( const struct packet_data * const data, +size_t get_tlvs( const struct packet_data * const data, const struct tlv *buf, size_t buf_size) { diff --git a/src/common/protocol_private.h b/src/common/protocol_private.h index b74c0eb..eecbc15 100644 --- a/src/common/protocol_private.h +++ b/src/common/protocol_private.h @@ -37,7 +37,8 @@ * */ #define PACKET_MAX_SIZE (512) -/** Returns the amount of tlv's int a packet. +/** + * 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. @@ -73,17 +74,17 @@ size_t get_tlvs( const struct packet_data * const data, * @return Returns 0 on success. Otherwise: E_PACKET_OVERFLOW. * * */ -int push_string(char *str); +int push_string(cd_t connection, char *str); /** Reinterprets char * as fpi1_t * and appends it to the outgoing packet as a * tlv. */ -int push_fpi1(char *num); +int push_fpi1(cd_t connection, char *num); /** Reinterprets char * as time_t * and appends it to the outgoing packet as a * tlv. */ -int push_timestamp(char *data); +int push_timestamp(cd_t connection, char *data); /** * Pushes a request for daemon to repeat a message identified by a msg_index_t. @@ -93,7 +94,7 @@ int push_timestamp(char *data); * @return 0 on success or E_PACKET_OVERFLOW, if not enough space is available * to push all the data. */ -int push_request(char *data); +int push_request(cd_t connection, char *data); /** * Pushes a message to the outgoing packet buffer as a reply. A reply is just @@ -105,16 +106,16 @@ int push_request(char *data); * @return On success --- 0 or E_PACKET_OVERFLOW, if not enough buffer is * available. */ -int push_reply(char *data); +int push_reply(cd_t connection, char *data); /** Reinterprets char * as uuid_t * and appends it to the outgoing packet as a * tlv. */ -int push_uuid(char *data); +int push_uuid(cd_t connection, char *data); /* Appends tlv_type and size of data to a packet effectively creating a tlv * header. */ -int push_tlv_header(enum tlv_type type, size_t size); +int push_tlv_header(cd_t connection, enum tlv_type type, size_t size); #endif /* PROTOCOL_H_PRIVATE */ diff --git a/src/common/utils.c b/src/common/utils.c index 956ef1b..0619517 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -6,22 +6,22 @@ int cmp_uuid(uuid_t *first, uuid_t *second) return memcmp(first, second, sizeof(*first)); } -fpi1_t add(fpi1_t a, fpi1_t b) +fpi1_t fpi1_add(fpi1_t a, fpi1_t b) { return a + b; } -fpi1_t sub(fpi1_t a, fpi1_t b) +fpi1_t fpi1_sub(fpi1_t a, fpi1_t b) { return a - b; } -fpi1_t mul(fpi1_t a, fpi1_t b) +fpi1_t fpi1_mul(fpi1_t a, fpi1_t b) { return (fpi1_t)(((long)a * (long)b) / 100); } -fpi1_t div(fpi1_t a, fpi1_t b) +fpi1_t fpi1_div(fpi1_t a, fpi1_t b) { return (fpi1_t)(((long)a * 10) / ((long)b * 10)); } diff --git a/src/device/protocol_device.ino b/src/device/protocol_device.ino new file mode 100755 index 0000000..778196d --- /dev/null +++ b/src/device/protocol_device.ino @@ -0,0 +1,38 @@ +#include "protocol.h" +#include "protocol_private.h" +#include "protocol_device_private.h" +#include +#include +#include + +static struct connection_t connection; + +static int push_bytes(cd_t cd, char *data, size_t size) +{ + int ret = 0; + + if (cd >= MAX_CONNECTIONS) { + ret = E_IVALID_DESCRIPTOR; + } else if (connection.outp_crs + size >= sizeof(connection.outp_buf)) { + ret = E_PACKET_OVERFLOW; + } else { + + } + return ret; +} + +static int push_tlv_header(cd_t connection, enum tlv_type type, size_t size) +{ + return 0; +} + +struct tlv * get_tlv() +{ + return NULL; +} + + +void get_last_data(cd_t connection) +{ + +} diff --git a/src/device/protocol_device_private.h b/src/device/protocol_device_private.h new file mode 100755 index 0000000..0fb46c7 --- /dev/null +++ b/src/device/protocol_device_private.h @@ -0,0 +1,37 @@ +#ifndef PROTOCOL_DEVICE_PRIVATE_H +#define PROTOCOL_DEVICE_PRIVATE_H + +#define MAX_PACKET_SIZE_OUT (64) +#define MAX_PACKET_SIZE_IN (512) +#define MAX_CONNECTIONS (1UL) + +/** + * Device's view of connection to daemon. + */ +struct connection_t { + /** + * Initially 0, non-zero when connection is open, 0 when connection + * is closed again. + */ + int is_live; + + /** Daemon IP adress */ + IPAddress address; + + /** Time last packet was reveived */ + time_t last_packet_sec; + + /** Incoming packet buffer */ + char inp_buf[MAX_PACKET_SIZE_IN]; + + /** Incoming packet cursor */ + size_t inp_crs; + + /** Outgoing packet buffer */ + char outp_buf[MAX_PACKET_SIZE_OUT]; + + /** Outgoing packet cursor */ + size_t outp_crs; +}; + +#endif /* PROTOCOL_DEVICE_PRIVATE_H */ \ No newline at end of file -- cgit v1.2.3 From 36b3e7f310c624b7b4e31829090dd02131c528d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Tue, 21 May 2019 19:16:22 +0300 Subject: Protocol: implementation of device-side protocol. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parts of protocol specific for device are implementepd to reflect the fact that the device is a client. This effectively means that device gets a single connection only and severe memory restrictions about which the daemon might get informed about in the future. Signed-off-by: Ramūnas Mažeikis --- include/net.h | 14 +++++- include/protocol.h | 6 ++- src/device/protocol_device.c | 86 ++++++++++++++++++++++++++++++++++++ src/device/protocol_device.ino | 38 ---------------- src/device/protocol_device_private.h | 27 ++++++++++- 5 files changed, 128 insertions(+), 43 deletions(-) create mode 100755 src/device/protocol_device.c delete mode 100755 src/device/protocol_device.ino diff --git a/include/net.h b/include/net.h index 34f557a..6860455 100644 --- a/include/net.h +++ b/include/net.h @@ -33,9 +33,21 @@ enum response { TMPFILE, }; - +/** + * Initialises connection with daemon and returns a network descriptor. + */ int net_init(const unsigned short int port); + +/** + * Closes connection associated with network descriptor. + */ int net_close(int nd); + +/** + * Get last data received from connection associated with network descriptor. + * Function mallocates a buffer for data received from packet. Don't forget to + * free the buffer. + */ int net_getlastdata(int nd, char * const data); #endif /* NET_H_INCLUDED */ diff --git a/include/protocol.h b/include/protocol.h index 60d31ea..c5e657b 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -106,12 +106,12 @@ struct tlv { * Reads last packets received, parses and stores them to be later retreived * via get_tlv. * */ -void get_last_data(cd_t connection); +int get_last_data(cd_t connection); /** Returns tlv's parsed by get_last_data. Returned tlv is only valid until * next call to get_tlv. * */ -struct tlv * get_tlv(void); +struct tlv * get_tlv(cd_t cd); /** * Any modifications made to the pending outgoing packet are nullified. @@ -129,4 +129,6 @@ int push_data(cd_t connection, const char *data, enum tlv_type); * */ void flush_data(cd_t connection); +cd_t protocol_init(void); + #endif /* PROTOCOL_H_INCLUDED */ diff --git a/src/device/protocol_device.c b/src/device/protocol_device.c new file mode 100755 index 0000000..3b3d8c8 --- /dev/null +++ b/src/device/protocol_device.c @@ -0,0 +1,86 @@ +#include "net.h" +#include "protocol.h" +#include "protocol_private.h" +#include "protocol_device_private.h" +#include "settings.h" +#include +#include +#include + +#define READ_AS(type, from) (*((type*)(from))) + +static struct connection_t connection; + +cd_t protocol_init(void) +{ + connection.is_live = 1; + connection.nd = net_init(setting_port()); + return 0; +} + +static int push_bytes(cd_t cd, char *data, size_t size) +{ + int ret = 0; + + if (cd >= MAX_CONNECTIONS) { + ret = E_IVALID_DESCRIPTOR; + } else if (connection.outp_crs + size >= sizeof(connection.outp_buf)) { + ret = E_PACKET_OVERFLOW; + } else { + memcpy(connection.outp_buf, data, size); + connection.outp_crs += size; + } + return ret; +} + +static int push_tlv_header(cd_t cd, enum tlv_type type, size_t size) +{ + int ret = 0; + + if (cd >= MAX_CONNECTIONS) { + errno = E_IVALID_DESCRIPTOR; + ret = NULL; + } else if (connection.outp_crs >= MAX_PACKET_SIZE_IN) { + errno = E_TLV_OVERFLOW; + ret = NULL; + } else { + READ_AS(enum tlv_type, connection.outp_buf + connection.outp_crs) + = type; + connection.outp_crs += sizeof(enum tlv_type); + READ_AS(size_t, connection.outp_buf + connection.outp_crs) = size; + connection.outp_crs += sizeof(size_t); + } + return ret; +} + +struct tlv * get_tlv(cd_t cd) +{ + struct tlv *ret = &connection.next_tlv; + size_t offset = connection.inp_crs; + char *data = connection.inp_buf; + + if (cd >= MAX_CONNECTIONS) { + errno = E_IVALID_DESCRIPTOR; + ret = NULL; + } else if (offset >= MAX_PACKET_SIZE_IN) { + errno = E_TLV_OVERFLOW; + ret = NULL; + } else { + ret->type = READ_AS(enum tlv_type, data + offset); + offset += sizeof(enum tlv_type); + ret->length = READ_AS(size_t, data + offset); + offset += sizeof(size_t); + ret->data = data + offset; + connection.inp_crs = offset; + } + return ret; +} + + +int get_last_data(cd_t cd) +{ + if (cd >= MAX_CONNECTIONS) { + return E_IVALID_DESCRIPTOR; + } + net_getlastdata(connection.nd, connection.inp_buf); +} diff --git a/src/device/protocol_device.ino b/src/device/protocol_device.ino deleted file mode 100755 index 778196d..0000000 --- a/src/device/protocol_device.ino +++ /dev/null @@ -1,38 +0,0 @@ -#include "protocol.h" -#include "protocol_private.h" -#include "protocol_device_private.h" -#include -#include -#include - -static struct connection_t connection; - -static int push_bytes(cd_t cd, char *data, size_t size) -{ - int ret = 0; - - if (cd >= MAX_CONNECTIONS) { - ret = E_IVALID_DESCRIPTOR; - } else if (connection.outp_crs + size >= sizeof(connection.outp_buf)) { - ret = E_PACKET_OVERFLOW; - } else { - - } - return ret; -} - -static int push_tlv_header(cd_t connection, enum tlv_type type, size_t size) -{ - return 0; -} - -struct tlv * get_tlv() -{ - return NULL; -} - - -void get_last_data(cd_t connection) -{ - -} diff --git a/src/device/protocol_device_private.h b/src/device/protocol_device_private.h index 0fb46c7..29ff567 100755 --- a/src/device/protocol_device_private.h +++ b/src/device/protocol_device_private.h @@ -1,10 +1,27 @@ #ifndef PROTOCOL_DEVICE_PRIVATE_H #define PROTOCOL_DEVICE_PRIVATE_H +#include "net.h" + #define MAX_PACKET_SIZE_OUT (64) + +/* Maximum size of packet that can fit into the packet buffer. UDP can carry + * bigger packets but memory is hard to come by and more won't be needed + * anyway. + * */ #define MAX_PACKET_SIZE_IN (512) + +/** + * Device only gets one connection. Because daemon. + */ #define MAX_CONNECTIONS (1UL) +/** + * Error which says that writing any more to packet buffer will overflow + * outgoing buffer. + */ +#define E_PACKET_OVERFLOW (1 << 0) + /** * Device's view of connection to daemon. */ @@ -15,8 +32,8 @@ struct connection_t { */ int is_live; - /** Daemon IP adress */ - IPAddress address; + /** Network descriptor that maps to daemon */ + int nd; /** Time last packet was reveived */ time_t last_packet_sec; @@ -32,6 +49,12 @@ struct connection_t { /** Outgoing packet cursor */ size_t outp_crs; + + /** + * Next tlv to be returned via get_tlv. NULL initially and after last + * element. + * */ + struct tlv next_tlv; }; #endif /* PROTOCOL_DEVICE_PRIVATE_H */ \ No newline at end of file -- cgit v1.2.3 From 5ca7e24e58f6bd657787b9235247149ffff420ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Tue, 21 May 2019 19:28:23 +0300 Subject: Protocol: common no longer has device-specific implementations. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Forgot to remove device-specific code from common protocol code. Signed-off-by: Ramūnas Mažeikis --- src/common/protocol.c | 41 ----------------------------------------- src/common/protocol_private.h | 14 -------------- src/device/protocol_device.c | 5 +++++ 3 files changed, 5 insertions(+), 55 deletions(-) diff --git a/src/common/protocol.c b/src/common/protocol.c index 3d63771..dc0f532 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -33,47 +33,6 @@ #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 int msg_cursor = 2; - -/** - * Message buffer. - * - * 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 int push_bytes(cd_t connection, const void * const data, const size_t size) -{ - if (packet_cursor + size >= PACKET_MAX_SIZE) { - return E_PACKET_OVERFLOW; - } - memcpy(packet_buf + packet_cursor, data, size); - packet_cursor += size; - return 0; -} - -void clear_data(cd_t connection) -{ - packet_cursor = 0; -} - int push_data(cd_t connection, const char *data, enum tlv_type type) { int ret = E_UNKNOWN_TYPE; diff --git a/src/common/protocol_private.h b/src/common/protocol_private.h index eecbc15..7433ff0 100644 --- a/src/common/protocol_private.h +++ b/src/common/protocol_private.h @@ -23,20 +23,6 @@ #include "utils.h" -#define E_PACKET_OVERFLOW (1 << 0) - -/** Read as "A maximum of 16 tlv's per packet". */ -#define TLV_BUF_SIZE (16) - -/* Pease don't rape the buffer with long messages, daemon-kun. */ -#define MSG_BUF_SIZE (257) - -/* Maximum size of packet that can fit into the packet buffer. 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. * diff --git a/src/device/protocol_device.c b/src/device/protocol_device.c index 3b3d8c8..3e38e19 100755 --- a/src/device/protocol_device.c +++ b/src/device/protocol_device.c @@ -18,6 +18,11 @@ cd_t protocol_init(void) return 0; } +void clear_data(void) +{ + connection.inp_crs = 0; +} + static int push_bytes(cd_t cd, char *data, size_t size) { int ret = 0; -- cgit v1.2.3 From fe71239fc0d1e65e06ba9dcf2fb35239bff21466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Tue, 21 May 2019 20:01:08 +0300 Subject: Protocol: moved udp code out of main. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An effor was made to increase modularity of device code. It was a partial success. IP adress, communications port, and wifi login details had to be made static and visible in main. Time is scarce and I am not about to push this further. Signed-off-by: Ramūnas Mažeikis --- include/protocol.h | 4 ++-- include/udp.h | 16 ++++++++++++++++ src/device/main.ino | 29 +---------------------------- src/device/protocol_device.c | 14 ++++++++++++-- src/device/protocol_device_private.h | 3 +-- src/device/udp.ino | 25 +++++++++++++++++++++++++ 6 files changed, 57 insertions(+), 34 deletions(-) create mode 100755 include/udp.h create mode 100755 src/device/udp.ino diff --git a/include/protocol.h b/include/protocol.h index c5e657b..8d5c535 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -116,7 +116,7 @@ struct tlv * get_tlv(cd_t cd); /** * Any modifications made to the pending outgoing packet are nullified. * */ -void clear_data(cd_t connection); +int clear_data(cd_t connection); /** * Appends data to the next packet to be sent. Type of data is determined by @@ -127,7 +127,7 @@ int push_data(cd_t connection, const char *data, enum tlv_type); /** * Sends packet towards the other end. * */ -void flush_data(cd_t connection); +int flush_data(cd_t connection); cd_t protocol_init(void); diff --git a/include/udp.h b/include/udp.h new file mode 100755 index 0000000..358e585 --- /dev/null +++ b/include/udp.h @@ -0,0 +1,16 @@ +#ifndef DEVICE_UDP_H +#define DEVICE_UDP_H + +#include +#include + +static const int com_port = 6996; +IPAddress ip; /* Daemon IP */ +WiFiUDP Udp; + +extern void discover_client(const int port); +extern void udp_init_packet(IPAddress ip, const int port); +extern void udp_push(const void * const data, const size_t size); +extern int udp_flush(void); + +#endif /* DEVICE_UDP_H */ \ No newline at end of file diff --git a/src/device/main.ino b/src/device/main.ino index 1a34859..d4e092d 100644 --- a/src/device/main.ino +++ b/src/device/main.ino @@ -26,25 +26,17 @@ #include #include "SSD1306Wire.h" #include "DejaVu_Sans_Mono_13.h" +#include "udp.h" -static char udppacketbuffer[32] = {0}; -static char *udppacketcursor = NULL; static const unsigned int internal_led = 2; static unsigned int led_state = 0; static const char servermagic[] = "I love coffee!"; static const char clientmagic[] = "I love tea!"; -static const int com_port = 6996; -IPAddress ip; /* Daemon IP */ -WiFiUDP Udp; SSD1306Wire display(0x3c, 4, 5, GEOMETRY_128_32); static void init_OLED(void); unsigned int toggle_led(const int ip); static int wifi_connect(const char * const ssid, const char * const password, const char doblink, const int ledpin); -static void discover_client(const int port); -static void udp_init_packet(IPAddress ip, const int port); -static void udp_push(const void * const data, const size_t size); -static int udp_flush(void); static void blink_led(const int pin, const int ontime, const int offtime); void setup(void) @@ -166,25 +158,6 @@ static void discover_client(const int port) } while (!done); } -static void udp_init_packet(IPAddress ip, const int port) -{ - Udp.beginPacket(ip, port); - memset(udppacketbuffer, 0, sizeof(udppacketbuffer)); - udppacketcursor = udppacketbuffer; -} - -static void udp_push(const void * const data, const size_t size) -{ - memcpy(udppacketcursor, data, size); - udppacketcursor += size; -} - -static int udp_flush(void) -{ - Udp.write((const uint8_t *) udppacketbuffer, udppacketcursor - udppacketbuffer); - return Udp.endPacket(); -} - static void blink_led(const int pin, const int ontime, const int offtime) { toggle_led(pin); diff --git a/src/device/protocol_device.c b/src/device/protocol_device.c index 3e38e19..5910546 100755 --- a/src/device/protocol_device.c +++ b/src/device/protocol_device.c @@ -18,9 +18,15 @@ cd_t protocol_init(void) return 0; } -void clear_data(void) +int clear_data(cd_t cd) { - connection.inp_crs = 0; + int ret = 0; + if (cd >= MAX_CONNECTIONS) { + ret = E_IVALID_DESCRIPTOR; + } else { + connection.inp_crs = 0; + } + return ret; } static int push_bytes(cd_t cd, char *data, size_t size) @@ -81,6 +87,10 @@ struct tlv * get_tlv(cd_t cd) return ret; } +int flush_data(cd_t cd) +{ + return 0; +} int get_last_data(cd_t cd) { diff --git a/src/device/protocol_device_private.h b/src/device/protocol_device_private.h index 29ff567..6754ecf 100755 --- a/src/device/protocol_device_private.h +++ b/src/device/protocol_device_private.h @@ -9,8 +9,7 @@ * bigger packets but memory is hard to come by and more won't be needed * anyway. * */ -#define MAX_PACKET_SIZE_IN (512) - +#define MAX_PACKET_SIZE_IN 512 /** * Device only gets one connection. Because daemon. */ diff --git a/src/device/udp.ino b/src/device/udp.ino new file mode 100755 index 0000000..3074b65 --- /dev/null +++ b/src/device/udp.ino @@ -0,0 +1,25 @@ +#include "udp.h" +#include +#include + +static char udppacketbuffer[32] = {0}; +static char *udppacketcursor = NULL; + +void udp_init_packet(IPAddress ip, const int port) +{ + Udp.beginPacket(ip, port); + memset(udppacketbuffer, 0, sizeof(udppacketbuffer)); + udppacketcursor = udppacketbuffer; +} + +void udp_push(const void * const data, const size_t size) +{ + memcpy(udppacketcursor, data, size); + udppacketcursor += size; +} + +int udp_flush(void) +{ + Udp.write((const uint8_t *) udppacketbuffer, udppacketcursor - udppacketbuffer); + return Udp.endPacket(); +} -- cgit v1.2.3 From 4bf68f9e9d553c924924296375269703c70c500a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Tue, 21 May 2019 20:04:52 +0300 Subject: Protocol: forgot to commit updated udp.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ramūnas Mažeikis --- include/udp.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/udp.h b/include/udp.h index 358e585..9b3f785 100755 --- a/include/udp.h +++ b/include/udp.h @@ -5,8 +5,8 @@ #include static const int com_port = 6996; -IPAddress ip; /* Daemon IP */ -WiFiUDP Udp; +extern IPAddress ip; /* Daemon IP */ +extern WiFiUDP Udp; extern void discover_client(const int port); extern void udp_init_packet(IPAddress ip, const int port); -- cgit v1.2.3 From 8a94a75975ea776c69238b3fff87da78d0567bba Mon Sep 17 00:00:00 2001 From: Gediminas Jakutis Date: Tue, 21 May 2019 20:25:34 +0300 Subject: device: strip CRs. Signed-off-by: Gediminas Jakutis --- src/device/udp.ino | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/device/udp.ino b/src/device/udp.ino index 3074b65..b88f314 100755 --- a/src/device/udp.ino +++ b/src/device/udp.ino @@ -1,25 +1,25 @@ -#include "udp.h" -#include -#include - -static char udppacketbuffer[32] = {0}; -static char *udppacketcursor = NULL; - -void udp_init_packet(IPAddress ip, const int port) -{ - Udp.beginPacket(ip, port); - memset(udppacketbuffer, 0, sizeof(udppacketbuffer)); - udppacketcursor = udppacketbuffer; -} - -void udp_push(const void * const data, const size_t size) -{ - memcpy(udppacketcursor, data, size); - udppacketcursor += size; -} - -int udp_flush(void) -{ - Udp.write((const uint8_t *) udppacketbuffer, udppacketcursor - udppacketbuffer); - return Udp.endPacket(); -} +#include "udp.h" +#include +#include + +static char udppacketbuffer[32] = {0}; +static char *udppacketcursor = NULL; + +void udp_init_packet(IPAddress ip, const int port) +{ + Udp.beginPacket(ip, port); + memset(udppacketbuffer, 0, sizeof(udppacketbuffer)); + udppacketcursor = udppacketbuffer; +} + +void udp_push(const void * const data, const size_t size) +{ + memcpy(udppacketcursor, data, size); + udppacketcursor += size; +} + +int udp_flush(void) +{ + Udp.write((const uint8_t *) udppacketbuffer, udppacketcursor - udppacketbuffer); + return Udp.endPacket(); +} -- cgit v1.2.3 From d9aeb50a22f1a49663151a48c23c32797f983696 Mon Sep 17 00:00:00 2001 From: Gediminas Jakutis Date: Tue, 21 May 2019 20:28:56 +0300 Subject: device: fix shoddy file permissions. Signed-off-by: Gediminas Jakutis --- src/device/protocol_device.c | 0 src/device/protocol_device_private.h | 0 src/device/udp.ino | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/device/protocol_device.c mode change 100755 => 100644 src/device/protocol_device_private.h mode change 100755 => 100644 src/device/udp.ino diff --git a/src/device/protocol_device.c b/src/device/protocol_device.c old mode 100755 new mode 100644 diff --git a/src/device/protocol_device_private.h b/src/device/protocol_device_private.h old mode 100755 new mode 100644 diff --git a/src/device/udp.ino b/src/device/udp.ino old mode 100755 new mode 100644 -- cgit v1.2.3 From 13015f9a8d2b6b982d7d84e62943fbba15aee05a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Wed, 22 May 2019 10:49:08 +0300 Subject: Protocol: switched files to C++ and did minor fixes. The code has a chance to compile now. No changes to actual build files yet. --- include/udp.h | 4 +- src/common/protocol.c | 153 ----------------------------------------- src/common/protocol.cpp | 153 +++++++++++++++++++++++++++++++++++++++++ src/device/protocol_device.c | 101 --------------------------- src/device/protocol_device.ino | 102 +++++++++++++++++++++++++++ src/device/udp.ino | 50 +++++++------- 6 files changed, 282 insertions(+), 281 deletions(-) delete mode 100644 src/common/protocol.c create mode 100644 src/common/protocol.cpp delete mode 100755 src/device/protocol_device.c create mode 100755 src/device/protocol_device.ino diff --git a/include/udp.h b/include/udp.h index 9b3f785..358e585 100755 --- a/include/udp.h +++ b/include/udp.h @@ -5,8 +5,8 @@ #include static const int com_port = 6996; -extern IPAddress ip; /* Daemon IP */ -extern WiFiUDP Udp; +IPAddress ip; /* Daemon IP */ +WiFiUDP Udp; extern void discover_client(const int port); extern void udp_init_packet(IPAddress ip, const int port); diff --git a/src/common/protocol.c b/src/common/protocol.c deleted file mode 100644 index dc0f532..0000000 --- a/src/common/protocol.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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 - */ - -/** - * Common parts of protocol implementation. Handling of anything that actually - * deals with connection descriptor has to be implemented by device and daemon - * separately. - */ - -#include "protocol.h" -#include "protocol_private.h" -#include "net.h" -#include -#include -#include - -#define READ_AS(from, type) (*(type*)(from)) - -int push_data(cd_t connection, const char *data, enum tlv_type type) -{ - int ret = E_UNKNOWN_TYPE; - switch (type) { - case TEXT: - ret = push_string(connection, data); - break; - case FPI1: - ret = push_fpi1(connection, data); - break; - case TIMESTAMP: - ret = push_timestamp(connection, data); - break; - case REQUEST: - ret = push_request(connection, data); - break; - case REPLY: - ret = push_reply(connection, data); - break; - case UUID: - ret = push_uuid(connection, data); - break; - } - return ret; -} - -static int push_string(cd_t connection, char *str) -{ - int ret = 0; - size_t size = strlen(str); - - ret |= push_tlv_header(connection, TEXT, size); - ret |= push_bytes(connection, str, size); - return ret; -} - -static int push_fpi1(cd_t connection, char *num) -{ - return push_tlv_header(connection, FPI1, sizeof(fpi1_t)) - | push_bytes(connection, num, sizeof(fpi1_t)); -} - -static int push_timestamp(cd_t connection, char *data) -{ - return push_tlv_header(connection, TIMESTAMP, sizeof(time_t)) - | push_bytes(connection, data, sizeof(time_t)); -} - -static int push_request(cd_t connection, char *data) -{ - return push_tlv_header(connection, REQUEST, sizeof(msg_idx_t)) - | push_bytes(connection, data, sizeof(msg_idx_t)); -} - -static int push_reply(cd_t connection, char *data) -{ - int ret = 0; - size_t msglen = strlen(data + sizeof(msg_idx_t)); - ret |= push_tlv_header(connection, REPLY, msglen + sizeof(msg_idx_t)); - ret |= push_bytes(connection, data, msglen); - return ret; -} - -static int push_uuid(cd_t connection, char *data) -{ - return push_tlv_header(connection, UUID, sizeof(uuid_t)) - | push_bytes(connection, data, sizeof(uuid_t)); -} - -size_t 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_AS(packet->data + cursor, enum tlv_type); - cursor += sizeof(size_t) + length; - ret++; - } - if (cursor != packet->packet_size) { - errno = E_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_size) { - errno = E_TLV_OVERFLOW; - } - - return tlvs_read; -} - -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.cpp b/src/common/protocol.cpp new file mode 100644 index 0000000..dc0f532 --- /dev/null +++ b/src/common/protocol.cpp @@ -0,0 +1,153 @@ +/* + * 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 + */ + +/** + * Common parts of protocol implementation. Handling of anything that actually + * deals with connection descriptor has to be implemented by device and daemon + * separately. + */ + +#include "protocol.h" +#include "protocol_private.h" +#include "net.h" +#include +#include +#include + +#define READ_AS(from, type) (*(type*)(from)) + +int push_data(cd_t connection, const char *data, enum tlv_type type) +{ + int ret = E_UNKNOWN_TYPE; + switch (type) { + case TEXT: + ret = push_string(connection, data); + break; + case FPI1: + ret = push_fpi1(connection, data); + break; + case TIMESTAMP: + ret = push_timestamp(connection, data); + break; + case REQUEST: + ret = push_request(connection, data); + break; + case REPLY: + ret = push_reply(connection, data); + break; + case UUID: + ret = push_uuid(connection, data); + break; + } + return ret; +} + +static int push_string(cd_t connection, char *str) +{ + int ret = 0; + size_t size = strlen(str); + + ret |= push_tlv_header(connection, TEXT, size); + ret |= push_bytes(connection, str, size); + return ret; +} + +static int push_fpi1(cd_t connection, char *num) +{ + return push_tlv_header(connection, FPI1, sizeof(fpi1_t)) + | push_bytes(connection, num, sizeof(fpi1_t)); +} + +static int push_timestamp(cd_t connection, char *data) +{ + return push_tlv_header(connection, TIMESTAMP, sizeof(time_t)) + | push_bytes(connection, data, sizeof(time_t)); +} + +static int push_request(cd_t connection, char *data) +{ + return push_tlv_header(connection, REQUEST, sizeof(msg_idx_t)) + | push_bytes(connection, data, sizeof(msg_idx_t)); +} + +static int push_reply(cd_t connection, char *data) +{ + int ret = 0; + size_t msglen = strlen(data + sizeof(msg_idx_t)); + ret |= push_tlv_header(connection, REPLY, msglen + sizeof(msg_idx_t)); + ret |= push_bytes(connection, data, msglen); + return ret; +} + +static int push_uuid(cd_t connection, char *data) +{ + return push_tlv_header(connection, UUID, sizeof(uuid_t)) + | push_bytes(connection, data, sizeof(uuid_t)); +} + +size_t 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_AS(packet->data + cursor, enum tlv_type); + cursor += sizeof(size_t) + length; + ret++; + } + if (cursor != packet->packet_size) { + errno = E_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_size) { + errno = E_TLV_OVERFLOW; + } + + return tlvs_read; +} + +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/device/protocol_device.c b/src/device/protocol_device.c deleted file mode 100755 index 5910546..0000000 --- a/src/device/protocol_device.c +++ /dev/null @@ -1,101 +0,0 @@ -#include "net.h" -#include "protocol.h" -#include "protocol_private.h" -#include "protocol_device_private.h" -#include "settings.h" -#include -#include -#include - -#define READ_AS(type, from) (*((type*)(from))) - -static struct connection_t connection; - -cd_t protocol_init(void) -{ - connection.is_live = 1; - connection.nd = net_init(setting_port()); - return 0; -} - -int clear_data(cd_t cd) -{ - int ret = 0; - if (cd >= MAX_CONNECTIONS) { - ret = E_IVALID_DESCRIPTOR; - } else { - connection.inp_crs = 0; - } - return ret; -} - -static int push_bytes(cd_t cd, char *data, size_t size) -{ - int ret = 0; - - if (cd >= MAX_CONNECTIONS) { - ret = E_IVALID_DESCRIPTOR; - } else if (connection.outp_crs + size >= sizeof(connection.outp_buf)) { - ret = E_PACKET_OVERFLOW; - } else { - memcpy(connection.outp_buf, data, size); - connection.outp_crs += size; - } - return ret; -} - -static int push_tlv_header(cd_t cd, enum tlv_type type, size_t size) -{ - int ret = 0; - - if (cd >= MAX_CONNECTIONS) { - errno = E_IVALID_DESCRIPTOR; - ret = NULL; - } else if (connection.outp_crs >= MAX_PACKET_SIZE_IN) { - errno = E_TLV_OVERFLOW; - ret = NULL; - } else { - READ_AS(enum tlv_type, connection.outp_buf + connection.outp_crs) - = type; - connection.outp_crs += sizeof(enum tlv_type); - READ_AS(size_t, connection.outp_buf + connection.outp_crs) = size; - connection.outp_crs += sizeof(size_t); - } - return ret; -} - -struct tlv * get_tlv(cd_t cd) -{ - struct tlv *ret = &connection.next_tlv; - size_t offset = connection.inp_crs; - char *data = connection.inp_buf; - - if (cd >= MAX_CONNECTIONS) { - errno = E_IVALID_DESCRIPTOR; - ret = NULL; - } else if (offset >= MAX_PACKET_SIZE_IN) { - errno = E_TLV_OVERFLOW; - ret = NULL; - } else { - ret->type = READ_AS(enum tlv_type, data + offset); - offset += sizeof(enum tlv_type); - ret->length = READ_AS(size_t, data + offset); - offset += sizeof(size_t); - ret->data = data + offset; - connection.inp_crs = offset; - } - return ret; -} - -int flush_data(cd_t cd) -{ - return 0; -} - -int get_last_data(cd_t cd) -{ - if (cd >= MAX_CONNECTIONS) { - return E_IVALID_DESCRIPTOR; - } - net_getlastdata(connection.nd, connection.inp_buf); -} diff --git a/src/device/protocol_device.ino b/src/device/protocol_device.ino new file mode 100755 index 0000000..218ca85 --- /dev/null +++ b/src/device/protocol_device.ino @@ -0,0 +1,102 @@ +#include "net.h" +#include "protocol.h" +#include "protocol_private.h" +#include "protocol_device_private.h" +#include "settings.h" +#include "udp.h" +#include +#include +#include + +#define READ_AS(type, from) (*((type*)(from))) + +static struct connection_t connection; + +cd_t protocol_init(void) +{ + connection.is_live = 1; + connection.nd = net_init(setting_port()); + return 0; +} + +int clear_data(cd_t cd) +{ + int ret = 0; + if (cd >= MAX_CONNECTIONS) { + ret = E_IVALID_DESCRIPTOR; + } else { + connection.inp_crs = 0; + } + return ret; +} + +static int push_bytes(cd_t cd, char *data, size_t size) +{ + int ret = 0; + + if (cd >= MAX_CONNECTIONS) { + ret = E_IVALID_DESCRIPTOR; + } else if (connection.outp_crs + size >= sizeof(connection.outp_buf)) { + ret = E_PACKET_OVERFLOW; + } else { + memcpy(connection.outp_buf, data, size); + connection.outp_crs += size; + } + return ret; +} + +static int push_tlv_header(cd_t cd, enum tlv_type type, size_t size) +{ + int ret = 0; + + if (cd >= MAX_CONNECTIONS) { + errno = E_IVALID_DESCRIPTOR; + ret = NULL; + } else if (connection.outp_crs >= MAX_PACKET_SIZE_IN) { + errno = E_TLV_OVERFLOW; + ret = NULL; + } else { + READ_AS(enum tlv_type, connection.outp_buf + connection.outp_crs) + = type; + connection.outp_crs += sizeof(enum tlv_type); + READ_AS(size_t, connection.outp_buf + connection.outp_crs) = size; + connection.outp_crs += sizeof(size_t); + } + return ret; +} + +struct tlv * get_tlv(cd_t cd) +{ + struct tlv *ret = &connection.next_tlv; + size_t offset = connection.inp_crs; + char *data = connection.inp_buf; + + if (cd >= MAX_CONNECTIONS) { + errno = E_IVALID_DESCRIPTOR; + ret = NULL; + } else if (offset >= MAX_PACKET_SIZE_IN) { + errno = E_TLV_OVERFLOW; + ret = NULL; + } else { + ret->type = READ_AS(enum tlv_type, data + offset); + offset += sizeof(enum tlv_type); + ret->length = READ_AS(size_t, data + offset); + offset += sizeof(size_t); + ret->data = data + offset; + connection.inp_crs = offset; + } + return ret; +} + +int flush_data(cd_t cd) +{ + return 0; +} + +int get_last_data(cd_t cd) +{ + if (cd >= MAX_CONNECTIONS) { + return E_IVALID_DESCRIPTOR; + } + net_getlastdata(connection.nd, connection.inp_buf); +} diff --git a/src/device/udp.ino b/src/device/udp.ino index 3074b65..b88f314 100755 --- a/src/device/udp.ino +++ b/src/device/udp.ino @@ -1,25 +1,25 @@ -#include "udp.h" -#include -#include - -static char udppacketbuffer[32] = {0}; -static char *udppacketcursor = NULL; - -void udp_init_packet(IPAddress ip, const int port) -{ - Udp.beginPacket(ip, port); - memset(udppacketbuffer, 0, sizeof(udppacketbuffer)); - udppacketcursor = udppacketbuffer; -} - -void udp_push(const void * const data, const size_t size) -{ - memcpy(udppacketcursor, data, size); - udppacketcursor += size; -} - -int udp_flush(void) -{ - Udp.write((const uint8_t *) udppacketbuffer, udppacketcursor - udppacketbuffer); - return Udp.endPacket(); -} +#include "udp.h" +#include +#include + +static char udppacketbuffer[32] = {0}; +static char *udppacketcursor = NULL; + +void udp_init_packet(IPAddress ip, const int port) +{ + Udp.beginPacket(ip, port); + memset(udppacketbuffer, 0, sizeof(udppacketbuffer)); + udppacketcursor = udppacketbuffer; +} + +void udp_push(const void * const data, const size_t size) +{ + memcpy(udppacketcursor, data, size); + udppacketcursor += size; +} + +int udp_flush(void) +{ + Udp.write((const uint8_t *) udppacketbuffer, udppacketcursor - udppacketbuffer); + return Udp.endPacket(); +} -- cgit v1.2.3 From 3fa7dd642af57b8b138e9a0d674c2d9960ebedf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Wed, 22 May 2019 11:33:51 +0300 Subject: Protocol: fixed type errors. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added const where appropriate to satisfy stricter type checking of C++. Signed-off-by: Ramūnas Mažeikis --- src/common/protocol.cpp | 28 ++++++++++++++-------------- src/common/protocol_private.h | 8 ++++++++ src/device/protocol_device.ino | 2 +- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/common/protocol.cpp b/src/common/protocol.cpp index dc0f532..135be37 100644 --- a/src/common/protocol.cpp +++ b/src/common/protocol.cpp @@ -31,7 +31,7 @@ #include #include -#define READ_AS(from, type) (*(type*)(from)) +#define READ_AS(type, from) (*((type*)(from))) int push_data(cd_t connection, const char *data, enum tlv_type type) { @@ -59,7 +59,7 @@ int push_data(cd_t connection, const char *data, enum tlv_type type) return ret; } -static int push_string(cd_t connection, char *str) +static int push_string(cd_t connection, const char *str) { int ret = 0; size_t size = strlen(str); @@ -69,25 +69,25 @@ static int push_string(cd_t connection, char *str) return ret; } -static int push_fpi1(cd_t connection, char *num) +static int push_fpi1(cd_t connection, const char *num) { return push_tlv_header(connection, FPI1, sizeof(fpi1_t)) | push_bytes(connection, num, sizeof(fpi1_t)); } -static int push_timestamp(cd_t connection, char *data) +static int push_timestamp(cd_t connection, const char *data) { return push_tlv_header(connection, TIMESTAMP, sizeof(time_t)) | push_bytes(connection, data, sizeof(time_t)); } -static int push_request(cd_t connection, char *data) +static int push_request(cd_t connection, const char *data) { return push_tlv_header(connection, REQUEST, sizeof(msg_idx_t)) | push_bytes(connection, data, sizeof(msg_idx_t)); } -static int push_reply(cd_t connection, char *data) +static int push_reply(cd_t connection, const char *data) { int ret = 0; size_t msglen = strlen(data + sizeof(msg_idx_t)); @@ -96,7 +96,7 @@ static int push_reply(cd_t connection, char *data) return ret; } -static int push_uuid(cd_t connection, char *data) +static int push_uuid(cd_t connection, const char *data) { return push_tlv_header(connection, UUID, sizeof(uuid_t)) | push_bytes(connection, data, sizeof(uuid_t)); @@ -110,7 +110,7 @@ size_t tlv_count(const struct packet_data * const packet) while (cursor < packet->packet_size) { cursor += sizeof(enum tlv_type); - length = READ_AS(packet->data + cursor, enum tlv_type); + length = READ_AS(enum tlv_type, packet->data + cursor); cursor += sizeof(size_t) + length; ret++; } @@ -121,7 +121,7 @@ size_t tlv_count(const struct packet_data * const packet) } size_t get_tlvs( const struct packet_data * const data, - const struct tlv *buf, + struct tlv *buf, size_t buf_size) { size_t tlvs_read = 0; @@ -139,15 +139,15 @@ size_t get_tlvs( const struct packet_data * const data, return tlvs_read; } -size_t parse_tlv(char *data, size_t cursor, struct tlv *t) +size_t parse_tlv(const char *data, size_t cursor, struct tlv *t) { - char *begin = data + cursor; + const char *begin = data + cursor; - t->type = READ_TLV_TYPE(data + cursor); + t->type = READ_AS(enum tlv_type, data + cursor); cursor += sizeof(enum tlv_type); - t->length += READ_SIZE_T(data + cursor); + t->length += READ_AS(enum tlv_type ,data + cursor); data += sizeof(size_t); - t->data = data + cursor; + t->data = (void*)data + cursor; return data + cursor - begin + 1UL; } diff --git a/src/common/protocol_private.h b/src/common/protocol_private.h index 7433ff0..d50a314 100644 --- a/src/common/protocol_private.h +++ b/src/common/protocol_private.h @@ -35,6 +35,14 @@ * */ size_t tlv_count(const struct packet_data * const packet_data); +/** + * Pushes bytes to outgoing packet and adjusts the offset accordingly. + * + * Returns E_PACKET_OVERFLOW, if no more bytes can fit into the packet. + */ + +int push_bytes(cd_t cd, const char *data, size_t size); + /** * Parses tlv's from packet data and writes them to a buffer of given size. * diff --git a/src/device/protocol_device.ino b/src/device/protocol_device.ino index 218ca85..22e1be1 100644 --- a/src/device/protocol_device.ino +++ b/src/device/protocol_device.ino @@ -30,7 +30,7 @@ int clear_data(cd_t cd) return ret; } -static int push_bytes(cd_t cd, char *data, size_t size) +static int push_bytes(cd_t cd, const char *data, size_t size) { int ret = 0; -- cgit v1.2.3 From 3703a6f28d48ac3f2c28d07405fab17a2a402df4 Mon Sep 17 00:00:00 2001 From: Gediminas Jakutis Date: Wed, 22 May 2019 14:44:00 +0300 Subject: device: actually make it all build and such. Signed-off-by: Gediminas Jakutis --- include/meson.build | 7 +++ include/udp.h | 16 ------- meson.build | 2 + src/common/meson.build | 4 ++ src/common/protocol.c | 6 +-- src/device/device_network.cpp | 103 ++++++++++++++++++++++++++++++++++++++++++ src/device/device_network.h | 40 ++++++++++++++++ src/device/main.ino | 48 ++++---------------- src/device/meson.build | 7 ++- src/device/protocol_device.c | 26 +++++++++-- src/device/udp.ino | 25 ---------- src/meson.build | 4 ++ 12 files changed, 201 insertions(+), 87 deletions(-) create mode 100644 include/meson.build delete mode 100755 include/udp.h create mode 100644 src/common/meson.build create mode 100644 src/device/device_network.cpp create mode 100755 src/device/device_network.h delete mode 100644 src/device/udp.ino diff --git a/include/meson.build b/include/meson.build new file mode 100644 index 0000000..33e9426 --- /dev/null +++ b/include/meson.build @@ -0,0 +1,7 @@ +header_filenames = [ + 'utils.h', + 'net.h', + 'protocol.h' +] + +fw_headers = files(header_filenames) diff --git a/include/udp.h b/include/udp.h deleted file mode 100755 index 9b3f785..0000000 --- a/include/udp.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef DEVICE_UDP_H -#define DEVICE_UDP_H - -#include -#include - -static const int com_port = 6996; -extern IPAddress ip; /* Daemon IP */ -extern WiFiUDP Udp; - -extern void discover_client(const int port); -extern void udp_init_packet(IPAddress ip, const int port); -extern void udp_push(const void * const data, const size_t size); -extern int udp_flush(void); - -#endif /* DEVICE_UDP_H */ \ No newline at end of file diff --git a/meson.build b/meson.build index 4a780c8..69bcf7c 100644 --- a/meson.build +++ b/meson.build @@ -10,6 +10,8 @@ resource_dir = join_paths(get_option('datadir'), progname) version_fallback = files('VERSION') inc = include_directories('include') +subdir('include') + resource_dir_arg = 'DATA_DIR=' + '"' + join_paths(get_option('prefix'), resource_dir) + '"' add_project_arguments('-D', resource_dir_arg, language : 'c') add_project_link_arguments('-rdynamic', language : 'c') diff --git a/src/common/meson.build b/src/common/meson.build new file mode 100644 index 0000000..b0f0c82 --- /dev/null +++ b/src/common/meson.build @@ -0,0 +1,4 @@ +common_filenames = [ +] + +common_sources = files(common_filenames) diff --git a/src/common/protocol.c b/src/common/protocol.c index dc0f532..0ffaede 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -24,12 +24,12 @@ * separately. */ -#include "protocol.h" -#include "protocol_private.h" -#include "net.h" #include #include #include +#include "protocol.h" +#include "protocol_private.h" +#include "net.h" #define READ_AS(from, type) (*(type*)(from)) diff --git a/src/device/device_network.cpp b/src/device/device_network.cpp new file mode 100644 index 0000000..d7781a0 --- /dev/null +++ b/src/device/device_network.cpp @@ -0,0 +1,103 @@ +/* + * Usurpation – wearable device udp packet handling + * + * Copyright (C) 2019 Gediminas Jakutis + * 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 +#include +#include "device_network.h" +#include "net.h" + +static struct netstate { + WiFiUDP udp; + char udppacketbuffer[1500]; + char *udppacketcursor; + IPAddress daemon_ip; + bool acquired; +} state; + + +static void udp_init_packet_expaddr(IPAddress ip, const int port); + +void udp_init(const int port) +{ + state.udp.begin(com_port); +} + +void udp_init_packet(const int port) +{ + state.udp.beginPacket(state.daemon_ip, port); + memset(state.udppacketbuffer, 0, sizeof(state.udppacketbuffer)); + state.udppacketcursor = state.udppacketbuffer; +} + +void udp_push(const void * const data, const size_t size) +{ + memcpy(state.udppacketcursor, data, size); + state.udppacketcursor += size; +} + +int udp_flush(void) +{ + state.udp.write((const uint8_t *) state.udppacketbuffer, state.udppacketcursor - state.udppacketbuffer); + return state.udp.endPacket(); +} + +void discover_client(const int port) +{ + IPAddress bcastip(255, 255, 255, 255); + char buffer[32] = {0}; + + do { + udp_init_packet_expaddr(bcastip, port); + udp_push(servermagic, sizeof(servermagic)); + udp_flush(); + delay(5); + while (state.udp.parsePacket()) { + if (state.udp.available() >= sizeof(clientmagic)) { + state.udp.read(buffer, sizeof(clientmagic)); + if (!(strcmp(clientmagic, buffer))) { + state.daemon_ip = state.udp.remoteIP(); + ++state.acquired; + } + } + } + delay(95); + } while (!state.acquired); +} + +IPAddress *get_daemon_address(void) +{ + IPAddress *ret; + if (!state.acquired) { + ret = new IPAddress(0, 0, 0, 0); + } else { + ret = new IPAddress(state.daemon_ip); + } + + return ret; +} + +static void udp_init_packet_expaddr(IPAddress ip, const int port) +{ + state.udp.beginPacket(ip, port); + memset(state.udppacketbuffer, 0, sizeof(state.udppacketbuffer)); + state.udppacketcursor = state.udppacketbuffer; +} + diff --git a/src/device/device_network.h b/src/device/device_network.h new file mode 100755 index 0000000..d8f41a1 --- /dev/null +++ b/src/device/device_network.h @@ -0,0 +1,40 @@ +/* + * Usurpation – wearable device udp packet handling + * + * Copyright (C) 2019 Gediminas Jakutis + * 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 + */ + +#ifndef DEVICE_UDP_H +#define DEVICE_UDP_H + +#include +#include + +static const int com_port = 6996; + +void udp_init(const int port); +void udp_init_packet(const int port); +void udp_push(const void * const data, const size_t size); +int udp_flush(void); +void discover_client(const int port); +IPAddress *get_daemon_address(void); + +static const char servermagic[] = "I love coffee!"; +static const char clientmagic[] = "I love tea!"; + +#endif /* DEVICE_UDP_H */ diff --git a/src/device/main.ino b/src/device/main.ino index d4e092d..66e52e8 100644 --- a/src/device/main.ino +++ b/src/device/main.ino @@ -26,16 +26,14 @@ #include #include "SSD1306Wire.h" #include "DejaVu_Sans_Mono_13.h" -#include "udp.h" +#include "device_network.h" static const unsigned int internal_led = 2; static unsigned int led_state = 0; -static const char servermagic[] = "I love coffee!"; -static const char clientmagic[] = "I love tea!"; SSD1306Wire display(0x3c, 4, 5, GEOMETRY_128_32); static void init_OLED(void); -unsigned int toggle_led(const int ip); +unsigned int toggle_led(const int pin); static int wifi_connect(const char * const ssid, const char * const password, const char doblink, const int ledpin); static void blink_led(const int pin, const int ontime, const int offtime); @@ -50,7 +48,7 @@ void setup(void) display.fillCircle(32, 16, 12); display.display(); wifi_connect(ssid, password, 1, internal_led); - Udp.begin(com_port); + udp_init(com_port); display.fillCircle(64, 16, 12); display.display(); discover_client(com_port); @@ -65,25 +63,23 @@ void loop(void) static const String daemonstr = "Daemon IP:"; static String prefix; static IPAddress ip_to_print; + static IPAddress *daemon_ip = NULL; static int print_dev_ip = 0; static unsigned int delta = 2000; /* sleep length to use (ms) */ /* static int dot_idx = 0; */ delay(delta); - udp_init_packet(ip, com_port); + udp_init_packet(com_port); udp_push(clientmagic, sizeof(clientmagic)); udp_flush(); -#if 0 - if (dot_idx >= 2) { - display.clear(); - dot_idx = 0; + + if (!daemon_ip) { + daemon_ip = get_daemon_address(); } - display.fillCircle(32 * (dot_idx + 1), 16, 12); - dot_idx++; -#endif + prefix = (print_dev_ip) ? devstr : daemonstr; - ip_to_print = (print_dev_ip) ? WiFi.localIP() : ip; + ip_to_print = (print_dev_ip) ? WiFi.localIP() : *daemon_ip; display.clear(); display.drawString(0, 0, prefix); display.drawString(0, 16, ip_to_print.toString()); @@ -134,30 +130,6 @@ static int wifi_connect(const char * const ssid, const char * const password, co return 0; } -static void discover_client(const int port) -{ - IPAddress bcastip(255, 255, 255, 255); - char buffer[32] = {0}; - size_t done = 0; - - do { - udp_init_packet(bcastip, port); - udp_push(servermagic, sizeof(servermagic)); - udp_flush(); - delay(5); - while (Udp.parsePacket()) { - if (Udp.available() >= sizeof(clientmagic)) { - Udp.read(buffer, sizeof(clientmagic)); - if (!(strcmp(clientmagic, buffer))) { - ip = Udp.remoteIP(); - ++done; - } - } - } - delay(95); - } while (!done); -} - static void blink_led(const int pin, const int ontime, const int offtime) { toggle_led(pin); diff --git a/src/device/meson.build b/src/device/meson.build index 1635f7b..d2e3c6e 100644 --- a/src/device/meson.build +++ b/src/device/meson.build @@ -17,8 +17,11 @@ if get_option('fwbuild') cat = find_program('cat') cp = find_program('cp') - fw_filenames = ['main.ino', 'DejaVu_Sans_Mono_13.h'] - fw_true_sources = files(fw_filenames) + fw_filenames = ['main.ino', + 'DejaVu_Sans_Mono_13.h', + 'device_network.cpp', + 'device_network.h'] + fw_true_sources += files(fw_filenames) fw_filenames += oledlibnames fw_true_sources += oledlib diff --git a/src/device/protocol_device.c b/src/device/protocol_device.c index 5910546..73d8ece 100644 --- a/src/device/protocol_device.c +++ b/src/device/protocol_device.c @@ -1,11 +1,31 @@ +/* + * Usurpation – wearable device udp packet handling + * + * 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 +#include +#include #include "net.h" #include "protocol.h" #include "protocol_private.h" #include "protocol_device_private.h" #include "settings.h" -#include -#include -#include #define READ_AS(type, from) (*((type*)(from))) diff --git a/src/device/udp.ino b/src/device/udp.ino deleted file mode 100644 index b88f314..0000000 --- a/src/device/udp.ino +++ /dev/null @@ -1,25 +0,0 @@ -#include "udp.h" -#include -#include - -static char udppacketbuffer[32] = {0}; -static char *udppacketcursor = NULL; - -void udp_init_packet(IPAddress ip, const int port) -{ - Udp.beginPacket(ip, port); - memset(udppacketbuffer, 0, sizeof(udppacketbuffer)); - udppacketcursor = udppacketbuffer; -} - -void udp_push(const void * const data, const size_t size) -{ - memcpy(udppacketcursor, data, size); - udppacketcursor += size; -} - -int udp_flush(void) -{ - Udp.write((const uint8_t *) udppacketbuffer, udppacketcursor - udppacketbuffer); - return Udp.endPacket(); -} diff --git a/src/meson.build b/src/meson.build index be166e6..12b583a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,3 +1,7 @@ +#subdir('common') + +fw_true_sources = [fw_headers] + subdir('daemon') subdir('device') -- cgit v1.2.3 From 27992079c057ea068a355e01365800d77b7ace13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Wed, 22 May 2019 14:56:59 +0300 Subject: Protocol: attempted to fix stupids. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ramūnas Mažeikis --- include/udp.h | 30 ++++---- src/common/protocol.c | 153 +++++++++++++++++++++++++++++++++++++++++ src/common/protocol.cpp | 153 ----------------------------------------- src/device/protocol_device.c | 102 +++++++++++++++++++++++++++ src/device/protocol_device.ino | 102 --------------------------- src/device/udp.c | 25 +++++++ src/device/udp.ino | 25 ------- 7 files changed, 295 insertions(+), 295 deletions(-) mode change 100755 => 100644 include/udp.h create mode 100644 src/common/protocol.c delete mode 100644 src/common/protocol.cpp create mode 100644 src/device/protocol_device.c delete mode 100644 src/device/protocol_device.ino create mode 100644 src/device/udp.c delete mode 100644 src/device/udp.ino diff --git a/include/udp.h b/include/udp.h old mode 100755 new mode 100644 index 358e585..0bf43ff --- a/include/udp.h +++ b/include/udp.h @@ -1,16 +1,16 @@ -#ifndef DEVICE_UDP_H -#define DEVICE_UDP_H - -#include -#include - -static const int com_port = 6996; -IPAddress ip; /* Daemon IP */ -WiFiUDP Udp; - -extern void discover_client(const int port); -extern void udp_init_packet(IPAddress ip, const int port); -extern void udp_push(const void * const data, const size_t size); -extern int udp_flush(void); - +#ifndef DEVICE_UDP_H +#define DEVICE_UDP_H + +#include +#include + +static const int com_port = 6996; +IPAddress ip; /* Daemon IP */ +WiFiUDP Udp; + +extern void discover_client(const int port); +extern void udp_init_packet(IPAddress ip, const int port); +extern void udp_push(const void * const data, const size_t size); +extern int udp_flush(void); + #endif /* DEVICE_UDP_H */ \ No newline at end of file diff --git a/src/common/protocol.c b/src/common/protocol.c new file mode 100644 index 0000000..43ff6a5 --- /dev/null +++ b/src/common/protocol.c @@ -0,0 +1,153 @@ +/* + * 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 + */ + +/** + * Common parts of protocol implementation. Handling of anything that actually + * deals with connection descriptor has to be implemented by device and daemon + * separately. + */ + +#include "protocol.h" +#include "protocol_private.h" +#include "net.h" +#include +#include +#include + +#define READ_AS(type, from) (*((type*)(from))) + +int push_data(cd_t connection, const char *data, enum tlv_type type) +{ + int ret = E_UNKNOWN_TYPE; + switch (type) { + case TEXT: + ret = push_string(connection, data); + break; + case FPI1: + ret = push_fpi1(connection, data); + break; + case TIMESTAMP: + ret = push_timestamp(connection, data); + break; + case REQUEST: + ret = push_request(connection, data); + break; + case REPLY: + ret = push_reply(connection, data); + break; + case UUID: + ret = push_uuid(connection, data); + break; + } + return ret; +} + +static int push_string(cd_t connection, const char *str) +{ + int ret = 0; + size_t size = strlen(str); + + ret |= push_tlv_header(connection, TEXT, size); + ret |= push_bytes(connection, str, size); + return ret; +} + +static int push_fpi1(cd_t connection, const char *num) +{ + return push_tlv_header(connection, FPI1, sizeof(fpi1_t)) + | push_bytes(connection, num, sizeof(fpi1_t)); +} + +static int push_timestamp(cd_t connection, const char *data) +{ + return push_tlv_header(connection, TIMESTAMP, sizeof(time_t)) + | push_bytes(connection, data, sizeof(time_t)); +} + +static int push_request(cd_t connection, const char *data) +{ + return push_tlv_header(connection, REQUEST, sizeof(msg_idx_t)) + | push_bytes(connection, data, sizeof(msg_idx_t)); +} + +static int push_reply(cd_t connection, const char *data) +{ + int ret = 0; + size_t msglen = strlen(data + sizeof(msg_idx_t)); + ret |= push_tlv_header(connection, REPLY, msglen + sizeof(msg_idx_t)); + ret |= push_bytes(connection, data, msglen); + return ret; +} + +static int push_uuid(cd_t connection, const char *data) +{ + return push_tlv_header(connection, UUID, sizeof(uuid_t)) + | push_bytes(connection, data, sizeof(uuid_t)); +} + +size_t 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_AS(enum tlv_type, packet->data + cursor); + cursor += sizeof(size_t) + length; + ret++; + } + if (cursor != packet->packet_size) { + errno = E_TLV_OVERFLOW; + } + return ret; +} + +size_t get_tlvs( const struct packet_data * const data, + 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_size) { + errno = E_TLV_OVERFLOW; + } + + return tlvs_read; +} + +size_t parse_tlv(const char *data, size_t cursor, struct tlv *t) +{ + const char *begin = data + cursor; + + t->type = READ_AS(enum tlv_type, data + cursor); + cursor += sizeof(enum tlv_type); + t->length += READ_AS(enum tlv_type ,data + cursor); + data += sizeof(size_t); + t->data = data + cursor; + + return data + cursor - begin + 1UL; +} diff --git a/src/common/protocol.cpp b/src/common/protocol.cpp deleted file mode 100644 index 135be37..0000000 --- a/src/common/protocol.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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 - */ - -/** - * Common parts of protocol implementation. Handling of anything that actually - * deals with connection descriptor has to be implemented by device and daemon - * separately. - */ - -#include "protocol.h" -#include "protocol_private.h" -#include "net.h" -#include -#include -#include - -#define READ_AS(type, from) (*((type*)(from))) - -int push_data(cd_t connection, const char *data, enum tlv_type type) -{ - int ret = E_UNKNOWN_TYPE; - switch (type) { - case TEXT: - ret = push_string(connection, data); - break; - case FPI1: - ret = push_fpi1(connection, data); - break; - case TIMESTAMP: - ret = push_timestamp(connection, data); - break; - case REQUEST: - ret = push_request(connection, data); - break; - case REPLY: - ret = push_reply(connection, data); - break; - case UUID: - ret = push_uuid(connection, data); - break; - } - return ret; -} - -static int push_string(cd_t connection, const char *str) -{ - int ret = 0; - size_t size = strlen(str); - - ret |= push_tlv_header(connection, TEXT, size); - ret |= push_bytes(connection, str, size); - return ret; -} - -static int push_fpi1(cd_t connection, const char *num) -{ - return push_tlv_header(connection, FPI1, sizeof(fpi1_t)) - | push_bytes(connection, num, sizeof(fpi1_t)); -} - -static int push_timestamp(cd_t connection, const char *data) -{ - return push_tlv_header(connection, TIMESTAMP, sizeof(time_t)) - | push_bytes(connection, data, sizeof(time_t)); -} - -static int push_request(cd_t connection, const char *data) -{ - return push_tlv_header(connection, REQUEST, sizeof(msg_idx_t)) - | push_bytes(connection, data, sizeof(msg_idx_t)); -} - -static int push_reply(cd_t connection, const char *data) -{ - int ret = 0; - size_t msglen = strlen(data + sizeof(msg_idx_t)); - ret |= push_tlv_header(connection, REPLY, msglen + sizeof(msg_idx_t)); - ret |= push_bytes(connection, data, msglen); - return ret; -} - -static int push_uuid(cd_t connection, const char *data) -{ - return push_tlv_header(connection, UUID, sizeof(uuid_t)) - | push_bytes(connection, data, sizeof(uuid_t)); -} - -size_t 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_AS(enum tlv_type, packet->data + cursor); - cursor += sizeof(size_t) + length; - ret++; - } - if (cursor != packet->packet_size) { - errno = E_TLV_OVERFLOW; - } - return ret; -} - -size_t get_tlvs( const struct packet_data * const data, - 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_size) { - errno = E_TLV_OVERFLOW; - } - - return tlvs_read; -} - -size_t parse_tlv(const char *data, size_t cursor, struct tlv *t) -{ - const char *begin = data + cursor; - - t->type = READ_AS(enum tlv_type, data + cursor); - cursor += sizeof(enum tlv_type); - t->length += READ_AS(enum tlv_type ,data + cursor); - data += sizeof(size_t); - t->data = (void*)data + cursor; - - return data + cursor - begin + 1UL; -} diff --git a/src/device/protocol_device.c b/src/device/protocol_device.c new file mode 100644 index 0000000..22e1be1 --- /dev/null +++ b/src/device/protocol_device.c @@ -0,0 +1,102 @@ +#include "net.h" +#include "protocol.h" +#include "protocol_private.h" +#include "protocol_device_private.h" +#include "settings.h" +#include "udp.h" +#include +#include +#include + +#define READ_AS(type, from) (*((type*)(from))) + +static struct connection_t connection; + +cd_t protocol_init(void) +{ + connection.is_live = 1; + connection.nd = net_init(setting_port()); + return 0; +} + +int clear_data(cd_t cd) +{ + int ret = 0; + if (cd >= MAX_CONNECTIONS) { + ret = E_IVALID_DESCRIPTOR; + } else { + connection.inp_crs = 0; + } + return ret; +} + +static int push_bytes(cd_t cd, const char *data, size_t size) +{ + int ret = 0; + + if (cd >= MAX_CONNECTIONS) { + ret = E_IVALID_DESCRIPTOR; + } else if (connection.outp_crs + size >= sizeof(connection.outp_buf)) { + ret = E_PACKET_OVERFLOW; + } else { + memcpy(connection.outp_buf, data, size); + connection.outp_crs += size; + } + return ret; +} + +static int push_tlv_header(cd_t cd, enum tlv_type type, size_t size) +{ + int ret = 0; + + if (cd >= MAX_CONNECTIONS) { + errno = E_IVALID_DESCRIPTOR; + ret = NULL; + } else if (connection.outp_crs >= MAX_PACKET_SIZE_IN) { + errno = E_TLV_OVERFLOW; + ret = NULL; + } else { + READ_AS(enum tlv_type, connection.outp_buf + connection.outp_crs) + = type; + connection.outp_crs += sizeof(enum tlv_type); + READ_AS(size_t, connection.outp_buf + connection.outp_crs) = size; + connection.outp_crs += sizeof(size_t); + } + return ret; +} + +struct tlv * get_tlv(cd_t cd) +{ + struct tlv *ret = &connection.next_tlv; + size_t offset = connection.inp_crs; + char *data = connection.inp_buf; + + if (cd >= MAX_CONNECTIONS) { + errno = E_IVALID_DESCRIPTOR; + ret = NULL; + } else if (offset >= MAX_PACKET_SIZE_IN) { + errno = E_TLV_OVERFLOW; + ret = NULL; + } else { + ret->type = READ_AS(enum tlv_type, data + offset); + offset += sizeof(enum tlv_type); + ret->length = READ_AS(size_t, data + offset); + offset += sizeof(size_t); + ret->data = data + offset; + connection.inp_crs = offset; + } + return ret; +} + +int flush_data(cd_t cd) +{ + return 0; +} + +int get_last_data(cd_t cd) +{ + if (cd >= MAX_CONNECTIONS) { + return E_IVALID_DESCRIPTOR; + } + net_getlastdata(connection.nd, connection.inp_buf); +} diff --git a/src/device/protocol_device.ino b/src/device/protocol_device.ino deleted file mode 100644 index 22e1be1..0000000 --- a/src/device/protocol_device.ino +++ /dev/null @@ -1,102 +0,0 @@ -#include "net.h" -#include "protocol.h" -#include "protocol_private.h" -#include "protocol_device_private.h" -#include "settings.h" -#include "udp.h" -#include -#include -#include - -#define READ_AS(type, from) (*((type*)(from))) - -static struct connection_t connection; - -cd_t protocol_init(void) -{ - connection.is_live = 1; - connection.nd = net_init(setting_port()); - return 0; -} - -int clear_data(cd_t cd) -{ - int ret = 0; - if (cd >= MAX_CONNECTIONS) { - ret = E_IVALID_DESCRIPTOR; - } else { - connection.inp_crs = 0; - } - return ret; -} - -static int push_bytes(cd_t cd, const char *data, size_t size) -{ - int ret = 0; - - if (cd >= MAX_CONNECTIONS) { - ret = E_IVALID_DESCRIPTOR; - } else if (connection.outp_crs + size >= sizeof(connection.outp_buf)) { - ret = E_PACKET_OVERFLOW; - } else { - memcpy(connection.outp_buf, data, size); - connection.outp_crs += size; - } - return ret; -} - -static int push_tlv_header(cd_t cd, enum tlv_type type, size_t size) -{ - int ret = 0; - - if (cd >= MAX_CONNECTIONS) { - errno = E_IVALID_DESCRIPTOR; - ret = NULL; - } else if (connection.outp_crs >= MAX_PACKET_SIZE_IN) { - errno = E_TLV_OVERFLOW; - ret = NULL; - } else { - READ_AS(enum tlv_type, connection.outp_buf + connection.outp_crs) - = type; - connection.outp_crs += sizeof(enum tlv_type); - READ_AS(size_t, connection.outp_buf + connection.outp_crs) = size; - connection.outp_crs += sizeof(size_t); - } - return ret; -} - -struct tlv * get_tlv(cd_t cd) -{ - struct tlv *ret = &connection.next_tlv; - size_t offset = connection.inp_crs; - char *data = connection.inp_buf; - - if (cd >= MAX_CONNECTIONS) { - errno = E_IVALID_DESCRIPTOR; - ret = NULL; - } else if (offset >= MAX_PACKET_SIZE_IN) { - errno = E_TLV_OVERFLOW; - ret = NULL; - } else { - ret->type = READ_AS(enum tlv_type, data + offset); - offset += sizeof(enum tlv_type); - ret->length = READ_AS(size_t, data + offset); - offset += sizeof(size_t); - ret->data = data + offset; - connection.inp_crs = offset; - } - return ret; -} - -int flush_data(cd_t cd) -{ - return 0; -} - -int get_last_data(cd_t cd) -{ - if (cd >= MAX_CONNECTIONS) { - return E_IVALID_DESCRIPTOR; - } - net_getlastdata(connection.nd, connection.inp_buf); -} diff --git a/src/device/udp.c b/src/device/udp.c new file mode 100644 index 0000000..b88f314 --- /dev/null +++ b/src/device/udp.c @@ -0,0 +1,25 @@ +#include "udp.h" +#include +#include + +static char udppacketbuffer[32] = {0}; +static char *udppacketcursor = NULL; + +void udp_init_packet(IPAddress ip, const int port) +{ + Udp.beginPacket(ip, port); + memset(udppacketbuffer, 0, sizeof(udppacketbuffer)); + udppacketcursor = udppacketbuffer; +} + +void udp_push(const void * const data, const size_t size) +{ + memcpy(udppacketcursor, data, size); + udppacketcursor += size; +} + +int udp_flush(void) +{ + Udp.write((const uint8_t *) udppacketbuffer, udppacketcursor - udppacketbuffer); + return Udp.endPacket(); +} diff --git a/src/device/udp.ino b/src/device/udp.ino deleted file mode 100644 index b88f314..0000000 --- a/src/device/udp.ino +++ /dev/null @@ -1,25 +0,0 @@ -#include "udp.h" -#include -#include - -static char udppacketbuffer[32] = {0}; -static char *udppacketcursor = NULL; - -void udp_init_packet(IPAddress ip, const int port) -{ - Udp.beginPacket(ip, port); - memset(udppacketbuffer, 0, sizeof(udppacketbuffer)); - udppacketcursor = udppacketbuffer; -} - -void udp_push(const void * const data, const size_t size) -{ - memcpy(udppacketcursor, data, size); - udppacketcursor += size; -} - -int udp_flush(void) -{ - Udp.write((const uint8_t *) udppacketbuffer, udppacketcursor - udppacketbuffer); - return Udp.endPacket(); -} -- cgit v1.2.3 From 28b26ca86cf18947d6d9543ad753ef112ff4da89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Wed, 22 May 2019 20:33:08 +0300 Subject: Protocol: interface redesign. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every function is a stub now. Reimplementaion coming up. Signed-off-by: Ramūnas Mažeikis --- include/protocol.h | 45 ++++--------- src/common/protocol.c | 102 ++++++++++------------------- src/common/protocol_private.h | 122 +++-------------------------------- src/device/protocol_device.c | 121 ---------------------------------- src/device/protocol_device_private.h | 59 ----------------- 5 files changed, 56 insertions(+), 393 deletions(-) delete mode 100644 src/device/protocol_device.c delete mode 100644 src/device/protocol_device_private.h diff --git a/include/protocol.h b/include/protocol.h index 8d5c535..d8f395d 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -23,9 +23,9 @@ #include -#define E_TLV_OVERFLOW (1 << 0) -#define E_UNKNOWN_TYPE (1 << 1) -#define E_IVALID_DESCRIPTOR (1 << 2) +#define E_TLV_OVERFLOW (1 << 0) +#define E_UNKNOWN_TYPE (1 << 1) +#define E_IVALID_DESCRIPTOR (1 << 2) /** * Regular packets contain tlv's defined by tlv_type. @@ -40,11 +40,6 @@ enum packet_type { DISCOVERY }; -/** - * Connection descriptor. - */ -typedef unsigned int cd_t; - /** * Message sequence number since beggining of sesssion. * @@ -86,10 +81,13 @@ enum tlv_type { /** * Packet data itself is a special type of tlv. A packet is either regular, * hearbeat or discovery. + * + * May be used to send data. */ -struct packet_data { +struct tlv_packet { enum packet_type type; size_t packet_size; + size_t offset; char *data; /* Bytes representing tlv's */ }; @@ -102,33 +100,18 @@ struct tlv { void *data; }; -/** - * Reads last packets received, parses and stores them to be later retreived - * via get_tlv. - * */ -int get_last_data(cd_t connection); - -/** Returns tlv's parsed by get_last_data. Returned tlv is only valid until - * next call to get_tlv. - * */ -struct tlv * get_tlv(cd_t cd); +struct tlv_parser { + char *data; + size_t offset; + size_t size; +}; -/** - * Any modifications made to the pending outgoing packet are nullified. - * */ -int clear_data(cd_t connection); +int get_tlv(struct tlv_parser *parser, struct tlv *ret); /** * Appends data to the next packet to be sent. Type of data is determined by * enum tlv_type. * */ -int push_data(cd_t connection, const char *data, enum tlv_type); - -/** - * Sends packet towards the other end. - * */ -int flush_data(cd_t connection); - -cd_t protocol_init(void); +int push_tlv(struct tlv_packet *packet, const char *data, enum tlv_type); #endif /* PROTOCOL_H_INCLUDED */ diff --git a/src/common/protocol.c b/src/common/protocol.c index 54d51f6..58a70f6 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -33,121 +33,85 @@ #define READ_AS(type, from) (*((type*)(from))) -int push_data(cd_t connection, const char *data, enum tlv_type type) +int push_data(enum tlv_type type) { - int ret = E_UNKNOWN_TYPE; + int ret = 0; switch (type) { case TEXT: - ret = push_string(connection, data); break; case FPI1: - ret = push_fpi1(connection, data); break; case TIMESTAMP: - ret = push_timestamp(connection, data); break; case REQUEST: - ret = push_request(connection, data); break; case REPLY: - ret = push_reply(connection, data); break; case UUID: - ret = push_uuid(connection, data); break; + default: + ret = E_UNKNOWN_TYPE; } return ret; } -static int push_string(cd_t connection, const char *str) +static int push_string(const char *str) { - int ret = 0; - size_t size = strlen(str); - - ret |= push_tlv_header(connection, TEXT, size); - ret |= push_bytes(connection, str, size); - return ret; + return 0; } -static int push_fpi1(cd_t connection, const char *num) +static int push_fpi1(const char *num) { - return push_tlv_header(connection, FPI1, sizeof(fpi1_t)) - | push_bytes(connection, num, sizeof(fpi1_t)); + return 0; } -static int push_timestamp(cd_t connection, const char *data) +static int push_timestamp(const char *data) { - return push_tlv_header(connection, TIMESTAMP, sizeof(time_t)) - | push_bytes(connection, data, sizeof(time_t)); + return 0; } -static int push_request(cd_t connection, const char *data) +static int push_request(const char *data) { - return push_tlv_header(connection, REQUEST, sizeof(msg_idx_t)) - | push_bytes(connection, data, sizeof(msg_idx_t)); + return 0; } -static int push_reply(cd_t connection, const char *data) +static int push_reply(const char *data) { - int ret = 0; - size_t msglen = strlen(data + sizeof(msg_idx_t)); - ret |= push_tlv_header(connection, REPLY, msglen + sizeof(msg_idx_t)); - ret |= push_bytes(connection, data, msglen); - return ret; + return 0; } -static int push_uuid(cd_t connection, const char *data) +static int push_uuid(const char *data) { - return push_tlv_header(connection, UUID, sizeof(uuid_t)) - | push_bytes(connection, data, sizeof(uuid_t)); + return 0; } size_t 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_AS(enum tlv_type, packet->data + cursor); - cursor += sizeof(size_t) + length; - ret++; - } - if (cursor != packet->packet_size) { - errno = E_TLV_OVERFLOW; - } - return ret; + return 0; } -size_t get_tlvs( const struct packet_data * const data, - struct tlv *buf, - size_t buf_size) +size_t parse_tlv(const char *data, size_t cursor, struct tlv *t) { - size_t tlvs_read = 0; - size_t cursor = 0; + return 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_size) { - errno = E_TLV_OVERFLOW; - } - - return tlvs_read; +int clear_data() +{ + return 0; } -size_t parse_tlv(const char *data, size_t cursor, struct tlv *t) +static int push_bytes(const char *data, size_t size) { - const char *begin = data + cursor; + return 0; +} - t->type = READ_AS(enum tlv_type, data + cursor); - cursor += sizeof(enum tlv_type); - t->length += READ_AS(enum tlv_type ,data + cursor); - data += sizeof(size_t); - t->data = data + cursor; +static int push_tlv_header(enum tlv_type type, size_t size) +{ + return 0; +} - return data + cursor - begin + 1UL; +int get_tlv(struct tlv_parser *parser, struct tlv *ret) +{ + return 0; } diff --git a/src/common/protocol_private.h b/src/common/protocol_private.h index d50a314..5228afd 100644 --- a/src/common/protocol_private.h +++ b/src/common/protocol_private.h @@ -1,115 +1,11 @@ -/* - * 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 - */ +#ifndef PROTOCOL_PRIVATE_H +#define PROTOCOL_PRIVATE_H -#ifndef PROTOCOL_H_PRIVATE -#define PROTOCOL_H_PRIVATE +static int push_string(const char *str); +static int push_fpi1(const char *num); +static int push_timestamp(const char *data); +static int push_request(const char *data); +static int push_reply(const char *data); +static int push_uuid(const char *data); -#include "utils.h" - -/** - * 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. - * - * @param packet data parsed from a packet. Function cannot use raw packets. - * - * @return Amount of tlv's in a packet. - * */ -size_t tlv_count(const struct packet_data * const packet_data); - -/** - * Pushes bytes to outgoing packet and adjusts the offset accordingly. - * - * Returns E_PACKET_OVERFLOW, if no more bytes can fit into the packet. - */ - -int push_bytes(cd_t cd, const char *data, size_t size); - -/** - * Parses tlv's from packet data and writes them to a buffer of given size. - * - * Returns how many tlv's were actually parsed. - * - * To check for errors, set errno to 0 and check after calling. - * - * Not yet implemented. - * - * @param data Data from network packet - * @param buf Buffer to store parsed tlv's - * @param buf_size Size of buffer used to store tlv's - * - * @return Number of tlv's actually parsed. Greter than or equal to buffer - * size, if an error occurs. - * */ -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. - * - * @return Returns 0 on success. Otherwise: E_PACKET_OVERFLOW. - * - * */ -int push_string(cd_t connection, char *str); - -/** Reinterprets char * as fpi1_t * and appends it to the outgoing packet as a - * tlv. - */ -int push_fpi1(cd_t connection, char *num); - -/** Reinterprets char * as time_t * and appends it to the outgoing packet as a - * tlv. - */ -int push_timestamp(cd_t connection, char *data); - -/** - * Pushes a request for daemon to repeat a message identified by a msg_index_t. - * - * @param data Pointer to a msg_index_t. - * - * @return 0 on success or E_PACKET_OVERFLOW, if not enough space is available - * to push all the data. - */ -int push_request(cd_t connection, char *data); - -/** - * Pushes a message to the outgoing packet buffer as a reply. A reply is just - * a null terminated string. - * - * @param data msg_idx_t representing sequence number since beggining of - * connection and a null-terminated string. - * - * @return On success --- 0 or E_PACKET_OVERFLOW, if not enough buffer is - * available. - */ -int push_reply(cd_t connection, char *data); - -/** Reinterprets char * as uuid_t * and appends it to the outgoing packet as a - * tlv. - */ -int push_uuid(cd_t connection, char *data); - -/* Appends tlv_type and size of data to a packet effectively creating a tlv - * header. - */ -int push_tlv_header(cd_t connection, enum tlv_type type, size_t size); - -#endif /* PROTOCOL_H_PRIVATE */ +#endif /* PROTOCOL_PRIVATE_H */ \ No newline at end of file diff --git a/src/device/protocol_device.c b/src/device/protocol_device.c deleted file mode 100644 index d5ec62d..0000000 --- a/src/device/protocol_device.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Usurpation – wearable device udp packet handling - * - * 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 -#include -#include -#include "net.h" -#include "protocol.h" -#include "protocol_private.h" -#include "protocol_device_private.h" -#include "settings.h" - -#define READ_AS(type, from) (*((type*)(from))) - -static struct connection_t connection; - -cd_t protocol_init(void) -{ - connection.is_live = 1; - connection.nd = net_init(setting_port()); - return 0; -} - -int clear_data(cd_t cd) -{ - int ret = 0; - if (cd >= MAX_CONNECTIONS) { - ret = E_IVALID_DESCRIPTOR; - } else { - connection.inp_crs = 0; - } - return ret; -} - -static int push_bytes(cd_t cd, const char *data, size_t size) -{ - int ret = 0; - - if (cd >= MAX_CONNECTIONS) { - ret = E_IVALID_DESCRIPTOR; - } else if (connection.outp_crs + size >= sizeof(connection.outp_buf)) { - ret = E_PACKET_OVERFLOW; - } else { - memcpy(connection.outp_buf, data, size); - connection.outp_crs += size; - } - return ret; -} - -static int push_tlv_header(cd_t cd, enum tlv_type type, size_t size) -{ - int ret = 0; - - if (cd >= MAX_CONNECTIONS) { - errno = E_IVALID_DESCRIPTOR; - ret = NULL; - } else if (connection.outp_crs >= MAX_PACKET_SIZE_IN) { - errno = E_TLV_OVERFLOW; - ret = NULL; - } else { - READ_AS(enum tlv_type, connection.outp_buf + connection.outp_crs) - = type; - connection.outp_crs += sizeof(enum tlv_type); - READ_AS(size_t, connection.outp_buf + connection.outp_crs) = size; - connection.outp_crs += sizeof(size_t); - } - return ret; -} - -struct tlv * get_tlv(cd_t cd) -{ - struct tlv *ret = &connection.next_tlv; - size_t offset = connection.inp_crs; - char *data = connection.inp_buf; - - if (cd >= MAX_CONNECTIONS) { - errno = E_IVALID_DESCRIPTOR; - ret = NULL; - } else if (offset >= MAX_PACKET_SIZE_IN) { - errno = E_TLV_OVERFLOW; - ret = NULL; - } else { - ret->type = READ_AS(enum tlv_type, data + offset); - offset += sizeof(enum tlv_type); - ret->length = READ_AS(size_t, data + offset); - offset += sizeof(size_t); - ret->data = data + offset; - connection.inp_crs = offset; - } - return ret; -} - -int flush_data(cd_t cd) -{ - return 0; -} - -int get_last_data(cd_t cd) -{ - if (cd >= MAX_CONNECTIONS) { - return E_IVALID_DESCRIPTOR; - } - net_getlastdata(connection.nd, connection.inp_buf); -} diff --git a/src/device/protocol_device_private.h b/src/device/protocol_device_private.h deleted file mode 100644 index 6754ecf..0000000 --- a/src/device/protocol_device_private.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef PROTOCOL_DEVICE_PRIVATE_H -#define PROTOCOL_DEVICE_PRIVATE_H - -#include "net.h" - -#define MAX_PACKET_SIZE_OUT (64) - -/* Maximum size of packet that can fit into the packet buffer. UDP can carry - * bigger packets but memory is hard to come by and more won't be needed - * anyway. - * */ -#define MAX_PACKET_SIZE_IN 512 -/** - * Device only gets one connection. Because daemon. - */ -#define MAX_CONNECTIONS (1UL) - -/** - * Error which says that writing any more to packet buffer will overflow - * outgoing buffer. - */ -#define E_PACKET_OVERFLOW (1 << 0) - -/** - * Device's view of connection to daemon. - */ -struct connection_t { - /** - * Initially 0, non-zero when connection is open, 0 when connection - * is closed again. - */ - int is_live; - - /** Network descriptor that maps to daemon */ - int nd; - - /** Time last packet was reveived */ - time_t last_packet_sec; - - /** Incoming packet buffer */ - char inp_buf[MAX_PACKET_SIZE_IN]; - - /** Incoming packet cursor */ - size_t inp_crs; - - /** Outgoing packet buffer */ - char outp_buf[MAX_PACKET_SIZE_OUT]; - - /** Outgoing packet cursor */ - size_t outp_crs; - - /** - * Next tlv to be returned via get_tlv. NULL initially and after last - * element. - * */ - struct tlv next_tlv; -}; - -#endif /* PROTOCOL_DEVICE_PRIVATE_H */ \ No newline at end of file -- cgit v1.2.3 From ca9e0b1cc8084b66311705b0c79da16821eb275d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Wed, 22 May 2019 20:38:29 +0300 Subject: Protocol: amendments to interface functions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ramūnas Mažeikis --- src/common/protocol.c | 22 ++++++++-------------- src/common/protocol_private.h | 16 ++++++++++------ 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/common/protocol.c b/src/common/protocol.c index 58a70f6..a7cb84f 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -55,37 +55,32 @@ int push_data(enum tlv_type type) return ret; } -static int push_string(const char *str) +static int push_string(struct tlv_packet *packet, const char *str) { return 0; } -static int push_fpi1(const char *num) +static int push_fpi1(struct tlv_packet *packet, const char *num) { return 0; } -static int push_timestamp(const char *data) +static int push_timestamp(struct tlv_packet *packet, const char *data) { return 0; } -static int push_request(const char *data) +static int push_request(struct tlv_packet *packet, const char *data) { return 0; } -static int push_reply(const char *data) +static int push_reply(struct tlv_packet *packet, const char *data) { return 0; } -static int push_uuid(const char *data) -{ - return 0; -} - -size_t tlv_count(const struct packet_data * const packet) +static int push_uuid(struct tlv_packet *packet, const char *data) { return 0; } @@ -95,18 +90,17 @@ size_t parse_tlv(const char *data, size_t cursor, struct tlv *t) return 0; } - int clear_data() { return 0; } -static int push_bytes(const char *data, size_t size) +static int push_bytes(struct tlv_packet *packet, size_t size) { return 0; } -static int push_tlv_header(enum tlv_type type, size_t size) +static int push_tlv_header(struct tlv_packet *packet, enum tlv_type type, size_t size) { return 0; } diff --git a/src/common/protocol_private.h b/src/common/protocol_private.h index 5228afd..a31103a 100644 --- a/src/common/protocol_private.h +++ b/src/common/protocol_private.h @@ -1,11 +1,15 @@ #ifndef PROTOCOL_PRIVATE_H #define PROTOCOL_PRIVATE_H -static int push_string(const char *str); -static int push_fpi1(const char *num); -static int push_timestamp(const char *data); -static int push_request(const char *data); -static int push_reply(const char *data); -static int push_uuid(const char *data); +#include "protocol_private.h" + +int push_string(struct tlv_packet *packet, const char *str); +int push_fpi1(struct tlv_packet *packet, const char *num); +int push_timestamp(struct tlv_packet *packet, const char *data); +int push_request(struct tlv_packet *packet, const char *data); +int push_reply(struct tlv_packet *packet, const char *data); +int push_uuid(struct tlv_packet *packet, const char *data); +int push_bytes(struct tlv_packet *packet, size_t size); +int push_tlv_header(struct tlv_packet *packet, enum tlv_type type, size_t size); #endif /* PROTOCOL_PRIVATE_H */ \ No newline at end of file -- cgit v1.2.3 From dd7556097b373bc62f646016a9b368899043dcc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Wed, 22 May 2019 20:48:42 +0300 Subject: Protocol: reimplemented push_string and push_fpi1. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ramūnas Mažeikis --- include/protocol.h | 2 +- src/common/protocol.c | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/include/protocol.h b/include/protocol.h index d8f395d..bf2a943 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -86,7 +86,7 @@ enum tlv_type { */ struct tlv_packet { enum packet_type type; - size_t packet_size; + size_t size; size_t offset; char *data; /* Bytes representing tlv's */ }; diff --git a/src/common/protocol.c b/src/common/protocol.c index a7cb84f..2b4e3bf 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -30,6 +30,7 @@ #include "protocol.h" #include "protocol_private.h" #include "net.h" +#include "util.h" #define READ_AS(type, from) (*((type*)(from))) @@ -57,12 +58,27 @@ int push_data(enum tlv_type type) static int push_string(struct tlv_packet *packet, const char *str) { - return 0; + size_t strsize = strlen(str); + int ret = 0; + + if (strsize + packet->offset >= packet->size) { + ret = E_TLV_OVERFLOW; + } else { + memcpy(packet->data, str, strsize); + } + return ret; } static int push_fpi1(struct tlv_packet *packet, const char *num) { - return 0; + int ret = 0; + + if (packet->offset + sizeof(fpi1_t) >= packet->size) { + ret = E_TLV_OVERFLOW; + } else { + memcpy(packet->data, num, sizeof(fpi1_t)); + } + return ret; } static int push_timestamp(struct tlv_packet *packet, const char *data) -- cgit v1.2.3 From 54f0ba9d41b446b83090dc0f3b220db9c82491d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Wed, 22 May 2019 20:52:26 +0300 Subject: Protocol: tossed a bunch of function out the window. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ramūnas Mažeikis --- include/protocol.h | 2 ++ src/common/protocol.c | 47 +------------------------------------------ src/common/protocol_private.h | 6 ------ 3 files changed, 3 insertions(+), 52 deletions(-) diff --git a/include/protocol.h b/include/protocol.h index bf2a943..4721a22 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -114,4 +114,6 @@ int get_tlv(struct tlv_parser *parser, struct tlv *ret); * */ int push_tlv(struct tlv_packet *packet, const char *data, enum tlv_type); +void clear_data(struct tlv_packet *packet); + #endif /* PROTOCOL_H_INCLUDED */ diff --git a/src/common/protocol.c b/src/common/protocol.c index 2b4e3bf..5498704 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -56,57 +56,12 @@ int push_data(enum tlv_type type) return ret; } -static int push_string(struct tlv_packet *packet, const char *str) -{ - size_t strsize = strlen(str); - int ret = 0; - - if (strsize + packet->offset >= packet->size) { - ret = E_TLV_OVERFLOW; - } else { - memcpy(packet->data, str, strsize); - } - return ret; -} - -static int push_fpi1(struct tlv_packet *packet, const char *num) -{ - int ret = 0; - - if (packet->offset + sizeof(fpi1_t) >= packet->size) { - ret = E_TLV_OVERFLOW; - } else { - memcpy(packet->data, num, sizeof(fpi1_t)); - } - return ret; -} - -static int push_timestamp(struct tlv_packet *packet, const char *data) -{ - return 0; -} - -static int push_request(struct tlv_packet *packet, const char *data) -{ - return 0; -} - -static int push_reply(struct tlv_packet *packet, const char *data) -{ - return 0; -} - -static int push_uuid(struct tlv_packet *packet, const char *data) -{ - return 0; -} - size_t parse_tlv(const char *data, size_t cursor, struct tlv *t) { return 0; } -int clear_data() +void clear_data(struct tlv_packet *packet) { return 0; } diff --git a/src/common/protocol_private.h b/src/common/protocol_private.h index a31103a..206046f 100644 --- a/src/common/protocol_private.h +++ b/src/common/protocol_private.h @@ -3,12 +3,6 @@ #include "protocol_private.h" -int push_string(struct tlv_packet *packet, const char *str); -int push_fpi1(struct tlv_packet *packet, const char *num); -int push_timestamp(struct tlv_packet *packet, const char *data); -int push_request(struct tlv_packet *packet, const char *data); -int push_reply(struct tlv_packet *packet, const char *data); -int push_uuid(struct tlv_packet *packet, const char *data); int push_bytes(struct tlv_packet *packet, size_t size); int push_tlv_header(struct tlv_packet *packet, enum tlv_type type, size_t size); -- cgit v1.2.3 From db5f3e534c1efd31a582d2309b2bc892cc2c8317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Wed, 22 May 2019 21:13:45 +0300 Subject: Protocol: reimplemented get_tlv and added tlv_data_size. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ramūnas Mažeikis --- include/protocol.h | 4 +++- src/common/protocol.c | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/include/protocol.h b/include/protocol.h index 4721a22..1f941a4 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -112,8 +112,10 @@ int get_tlv(struct tlv_parser *parser, struct tlv *ret); * Appends data to the next packet to be sent. Type of data is determined by * enum tlv_type. * */ -int push_tlv(struct tlv_packet *packet, const char *data, enum tlv_type); +int push_data(struct tlv_packet *packet, enum tlv_type type, char *data); void clear_data(struct tlv_packet *packet); +size_t tlv_data_size(struct tlv_parser *parser); + #endif /* PROTOCOL_H_INCLUDED */ diff --git a/src/common/protocol.c b/src/common/protocol.c index 5498704..8fbd197 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -34,9 +34,11 @@ #define READ_AS(type, from) (*((type*)(from))) -int push_data(enum tlv_type type) +int push_tlv(struct tlv_packet *packet, enum tlv_type type, char *data) { int ret = 0; + size_t size; + switch (type) { case TEXT: break; @@ -56,11 +58,6 @@ int push_data(enum tlv_type type) return ret; } -size_t parse_tlv(const char *data, size_t cursor, struct tlv *t) -{ - return 0; -} - void clear_data(struct tlv_packet *packet) { return 0; @@ -78,5 +75,32 @@ static int push_tlv_header(struct tlv_packet *packet, enum tlv_type type, size_t int get_tlv(struct tlv_parser *parser, struct tlv *ret) { - return 0; + int ret = 0; + + if (parser->offset + sizeof(ret->type) + sizeof(ret->length) >= parser->size) { + ret = E_TLV_OVERFLOW; + } else { + ret->type = memcpy(&ret->type, parser->data + parser->offset, sizeof(ret->type)); + parser->size += sizeof(ret->type); + ret->length = memcpy(&ret->length, parser->data + parser->offset, sizeof(ret->length)); + parser->offset += sizeof(ret->length); + if (parser->offset + ret->length >= parser->size) { + ret = E_TLV_OVERFLOW; + } else { + memcpy(ret->data, parser->data, ret->length); + } + } + return ret; } + +size_t tlv_data_size(struct tlv_parser *parser) +{ + size_t size; + + if (parser->offset + sizeof(enum tlv_type) + sizeof(size_t) >= parser->size) { + size = 0; + } else { + memcpy(&size, parser->data + parser->offset + sizeof(enum tlv_type), sizeof(size_t)); + } + return size; +} \ No newline at end of file -- cgit v1.2.3 From 5fee4a9996158479fe5503c9acace5733660f9e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Wed, 22 May 2019 21:21:25 +0300 Subject: Protocol: reimplemented push_bytes and push_tlv_header. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ramūnas Mažeikis --- src/common/protocol.c | 27 +++++++++++++++++++++++---- src/common/protocol_private.h | 2 +- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/common/protocol.c b/src/common/protocol.c index 8fbd197..e71938c 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -60,17 +60,36 @@ int push_tlv(struct tlv_packet *packet, enum tlv_type type, char *data) void clear_data(struct tlv_packet *packet) { - return 0; + packet->offset = 0; + packet->type = 0; + memset(packet->data, 0, packet->size); } -static int push_bytes(struct tlv_packet *packet, size_t size) +static int push_bytes(struct tlv_packet *packet, char *data, size_t size) { - return 0; + int ret = 0; + + if (packet->offset + size >= packet->size) { + ret = E_TLV_OVERFLOW; + } else { + memcpy(packet->data + packet->offset, data, size); + packet->offset += size; + } } static int push_tlv_header(struct tlv_packet *packet, enum tlv_type type, size_t size) { - return 0; + int ret = 0; + + if (packet->offset + sizeof(type) + sizeof(size) >= packet->size) { + ret = E_TLV_OVERFLOW; + } else { + memcpy(packet->data + packet->size, type, sizeof(type)); + packet->offset += sizeof(type); + memcpy(packet->data + packet->offset, size, sizeof(size)); + packet->offset += sizeof(size); + } + return ret; } int get_tlv(struct tlv_parser *parser, struct tlv *ret) diff --git a/src/common/protocol_private.h b/src/common/protocol_private.h index 206046f..de086cd 100644 --- a/src/common/protocol_private.h +++ b/src/common/protocol_private.h @@ -3,7 +3,7 @@ #include "protocol_private.h" -int push_bytes(struct tlv_packet *packet, size_t size); +int push_bytes(struct tlv_packet *packet, char *data, size_t size); int push_tlv_header(struct tlv_packet *packet, enum tlv_type type, size_t size); #endif /* PROTOCOL_PRIVATE_H */ \ No newline at end of file -- cgit v1.2.3 From 323292cb8a1191e1c74c7d42c6e54f589d8023d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Wed, 22 May 2019 21:29:06 +0300 Subject: Protocol: finished reimplementation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now protocol only deals with parsing and forming of packets. Signed-off-by: Ramūnas Mažeikis --- src/common/protocol.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/common/protocol.c b/src/common/protocol.c index e71938c..d3317e3 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -30,7 +30,7 @@ #include "protocol.h" #include "protocol_private.h" #include "net.h" -#include "util.h" +#include "utils.h" #define READ_AS(type, from) (*((type*)(from))) @@ -41,20 +41,28 @@ int push_tlv(struct tlv_packet *packet, enum tlv_type type, char *data) switch (type) { case TEXT: + size = strlen(data); break; case FPI1: + size = sizeof(fpi1_t); break; case TIMESTAMP: + size = sizeof(time_t); break; case REQUEST: + size = sizeof(msg_idx_t); break; case REPLY: + size = sizeof(msg_idx_t) + strlen(data + sizeof(msg_idx_t)); break; case UUID: + size = sizeof(uuid_t); break; default: ret = E_UNKNOWN_TYPE; } + ret |= push_tlv_header(packet, type, size); + ret |= push_bytes(packet, data, size); return ret; } -- cgit v1.2.3 From 446157d793c30386f994743f5a8e6ab64e66507f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Wed, 22 May 2019 21:35:46 +0300 Subject: Protocol: updated docs for functions that survived redesign. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ramūnas Mažeikis --- include/protocol.h | 5 +++++ src/common/protocol_private.h | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/include/protocol.h b/include/protocol.h index 1f941a4..cd28e2d 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -111,6 +111,11 @@ int get_tlv(struct tlv_parser *parser, struct tlv *ret); /** * Appends data to the next packet to be sent. Type of data is determined by * enum tlv_type. + * + * In case of overflow return E_TLV_OVERFLOW. + * + * Overflow can be detected after forming tlv header. This means that the + * packet may have changes. * */ int push_data(struct tlv_packet *packet, enum tlv_type type, char *data); diff --git a/src/common/protocol_private.h b/src/common/protocol_private.h index de086cd..fe28aa0 100644 --- a/src/common/protocol_private.h +++ b/src/common/protocol_private.h @@ -3,7 +3,20 @@ #include "protocol_private.h" +/** + * Convenience function that pushes bytes to the end of a packet and reports + * potential overflow. + * + * In case of detected overflow nothing is done to the packet. + */ int push_bytes(struct tlv_packet *packet, char *data, size_t size); + +/** + * Convenience function that forms a tlv header at the end of a packet. Reports + * potential overflow. + * + * In case of detected overflow nothing is done to the packet. + */ int push_tlv_header(struct tlv_packet *packet, enum tlv_type type, size_t size); #endif /* PROTOCOL_PRIVATE_H */ \ No newline at end of file -- cgit v1.2.3 From 5e22764d79e42345d512216f07880fdd8db2edf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Wed, 22 May 2019 21:41:19 +0300 Subject: Protocol: fixed a off-by-one error when copying a string. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ramūnas Mažeikis --- src/common/protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/protocol.c b/src/common/protocol.c index d3317e3..8680be7 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -41,7 +41,7 @@ int push_tlv(struct tlv_packet *packet, enum tlv_type type, char *data) switch (type) { case TEXT: - size = strlen(data); + size = strlen(data) + 1; break; case FPI1: size = sizeof(fpi1_t); -- cgit v1.2.3 From 3397ca1e68f69259cca56751af73f3f0706b6831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Wed, 22 May 2019 21:46:23 +0300 Subject: Protocol: updated get_tlv and more docs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ramūnas Mažeikis --- include/protocol.h | 11 +++++++++++ src/common/protocol.c | 2 ++ 2 files changed, 13 insertions(+) diff --git a/include/protocol.h b/include/protocol.h index cd28e2d..598b8e3 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -26,6 +26,7 @@ #define E_TLV_OVERFLOW (1 << 0) #define E_UNKNOWN_TYPE (1 << 1) #define E_IVALID_DESCRIPTOR (1 << 2) +#define END_OF_PACKET (1 << 3) /** * Regular packets contain tlv's defined by tlv_type. @@ -114,13 +115,23 @@ int get_tlv(struct tlv_parser *parser, struct tlv *ret); * * In case of overflow return E_TLV_OVERFLOW. * + * On next call after retreiving last packet returns END_OF_PACKET. + * * Overflow can be detected after forming tlv header. This means that the * packet may have changes. * */ int push_data(struct tlv_packet *packet, enum tlv_type type, char *data); + +/** + * Resets offset to 0 and set entire buffer to 0. + */ void clear_data(struct tlv_packet *packet); + +/** + * Tells what size of buffer is needed for next tlv. + */ size_t tlv_data_size(struct tlv_parser *parser); #endif /* PROTOCOL_H_INCLUDED */ diff --git a/src/common/protocol.c b/src/common/protocol.c index 8680be7..bae38d8 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -106,6 +106,8 @@ int get_tlv(struct tlv_parser *parser, struct tlv *ret) if (parser->offset + sizeof(ret->type) + sizeof(ret->length) >= parser->size) { ret = E_TLV_OVERFLOW; + } else if (parser -> offset == parser->size) { + ret = END_OF_PACKET; } else { ret->type = memcpy(&ret->type, parser->data + parser->offset, sizeof(ret->type)); parser->size += sizeof(ret->type); -- cgit v1.2.3 From b25865cc827f4a6a9c31f3d92a4e443485fd5d93 Mon Sep 17 00:00:00 2001 From: Gediminas Jakutis Date: Sun, 26 May 2019 14:46:36 +0300 Subject: common: cosmetic changes. Signed-off-by: Gediminas Jakutis --- include/net.h | 6 +++--- include/protocol.h | 6 +++--- include/utils.h | 6 +++--- src/common/protocol.c | 4 +--- src/common/protocol_private.h | 28 +++++++++++++++++++++++++++- src/common/utils.c | 20 ++++++++++++++++++++ 6 files changed, 57 insertions(+), 13 deletions(-) diff --git a/include/net.h b/include/net.h index 6860455..59071a5 100644 --- a/include/net.h +++ b/include/net.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef NET_H_INCLUDED -#define NET_H_INCLUDED +#ifndef USURPATION_NET_H_INCLUDED +#define USURPATION_NET_H_INCLUDED #define dgsize 512 @@ -50,4 +50,4 @@ int net_close(int nd); */ int net_getlastdata(int nd, char * const data); -#endif /* NET_H_INCLUDED */ +#endif /* USURPATION_NET_H_INCLUDED */ diff --git a/include/protocol.h b/include/protocol.h index 598b8e3..34ad4a3 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -18,8 +18,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef PROTOCOL_H_INCLUDED -#define PROTOCOL_H_INCLUDED +#ifndef USURPATION_PROTOCOL_H_INCLUDED +#define USURPATION_PROTOCOL_H_INCLUDED #include @@ -134,4 +134,4 @@ void clear_data(struct tlv_packet *packet); */ size_t tlv_data_size(struct tlv_parser *parser); -#endif /* PROTOCOL_H_INCLUDED */ +#endif /* USURPATION_PROTOCOL_H_INCLUDED */ diff --git a/include/utils.h b/include/utils.h index c769917..95b553d 100644 --- a/include/utils.h +++ b/include/utils.h @@ -1,5 +1,5 @@ -#ifndef PROJECT_UTILS_H -#define PROJECT_UTILS_H +#ifndef USURPATION_UTILS_H +#define USURPATION_UTILS_H #include @@ -19,4 +19,4 @@ fpi1_t fpi1_sub(fpi1_t a, fpi1_t b); fpi1_t fpi1_mul(fpi1_t a, fpi1_t b); fpi1_t fpi1_div(fpi1_t a, fpi1_t b); -#endif /* PROJECT_UTILS_H */ +#endif /* USURPATION_UTILS_H */ diff --git a/src/common/protocol.c b/src/common/protocol.c index bae38d8..b2e0d40 100644 --- a/src/common/protocol.c +++ b/src/common/protocol.c @@ -32,8 +32,6 @@ #include "net.h" #include "utils.h" -#define READ_AS(type, from) (*((type*)(from))) - int push_tlv(struct tlv_packet *packet, enum tlv_type type, char *data) { int ret = 0; @@ -132,4 +130,4 @@ size_t tlv_data_size(struct tlv_parser *parser) memcpy(&size, parser->data + parser->offset + sizeof(enum tlv_type), sizeof(size_t)); } return size; -} \ No newline at end of file +} diff --git a/src/common/protocol_private.h b/src/common/protocol_private.h index fe28aa0..51d5431 100644 --- a/src/common/protocol_private.h +++ b/src/common/protocol_private.h @@ -1,3 +1,29 @@ +/* + * 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 + */ + +/** + * Common parts of protocol implementation. Handling of anything that actually + * deals with connection descriptor has to be implemented by device and daemon + * separately. + */ + #ifndef PROTOCOL_PRIVATE_H #define PROTOCOL_PRIVATE_H @@ -19,4 +45,4 @@ int push_bytes(struct tlv_packet *packet, char *data, size_t size); */ int push_tlv_header(struct tlv_packet *packet, enum tlv_type type, size_t size); -#endif /* PROTOCOL_PRIVATE_H */ \ No newline at end of file +#endif /* PROTOCOL_PRIVATE_H */ diff --git a/src/common/utils.c b/src/common/utils.c index 0619517..7522404 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -1,3 +1,23 @@ +/* + * Usurpataion --- utility functions. + * + * 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 "utils.h" #include "string.h" -- cgit v1.2.3