summaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/meson.build1
-rw-r--r--src/common/protocol_private.h48
-rw-r--r--src/common/tlv.c (renamed from src/common/protocol.c)145
3 files changed, 73 insertions, 121 deletions
diff --git a/src/common/meson.build b/src/common/meson.build
index b0f0c82..da8b656 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -1,4 +1,5 @@
common_filenames = [
+ 'tlv.c'
]
common_sources = files(common_filenames)
diff --git a/src/common/protocol_private.h b/src/common/protocol_private.h
deleted file mode 100644
index 51d5431..0000000
--- a/src/common/protocol_private.h
+++ /dev/null
@@ -1,48 +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.
- */
-
-#ifndef PROTOCOL_PRIVATE_H
-#define PROTOCOL_PRIVATE_H
-
-#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 */
diff --git a/src/common/protocol.c b/src/common/tlv.c
index b2e0d40..c25f008 100644
--- a/src/common/protocol.c
+++ b/src/common/tlv.c
@@ -27,107 +27,106 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
-#include "protocol.h"
-#include "protocol_private.h"
+#include "tlv.h"
#include "net.h"
#include "utils.h"
-int push_tlv(struct tlv_packet *packet, enum tlv_type type, char *data)
+int tlv_get(struct tlv_parser *parser, struct tlv *ret)
{
- int ret = 0;
- size_t size;
+ int retval = 0;
- switch (type) {
- case TEXT:
- size = strlen(data) + 1;
- 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;
+ if (parser->offset + sizeof(ret->type) + sizeof(ret->length) >= parser->size) {
+ retval = E_TLV_OVERFLOW;
+ } else if (parser -> offset == parser->size) {
+ retval = END_OF_PACKET;
+ } else {
+ 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) {
+ retval = E_TLV_OVERFLOW;
+ } else {
+ memcpy(ret->data, parser->data, ret->length);
+ }
}
- ret |= push_tlv_header(packet, type, size);
- ret |= push_bytes(packet, data, size);
- return ret;
-}
-
-void clear_data(struct tlv_packet *packet)
-{
- packet->offset = 0;
- packet->type = 0;
- memset(packet->data, 0, packet->size);
+ return retval;
}
-static int push_bytes(struct tlv_packet *packet, char *data, size_t size)
+size_t tlv_data_size(struct tlv_parser *parser)
{
- int ret = 0;
+ size_t size;
- if (packet->offset + size >= packet->size) {
- ret = E_TLV_OVERFLOW;
+ if (parser->offset + sizeof(enum tlv_type) + sizeof(size_t) >= parser->size) {
+ size = 0;
} else {
- memcpy(packet->data + packet->offset, data, size);
- packet->offset += size;
+ memcpy(&size, parser->data + parser->offset + sizeof(enum tlv_type), sizeof(size_t));
}
+ return size;
}
-static int push_tlv_header(struct tlv_packet *packet, enum tlv_type type, size_t size)
+void tlv_destroy(struct tlv *t)
{
- 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);
+ size_t i = 0;
+ size_t tlv_count;
+ struct tlv *arr;
+ switch (t->type)
+ {
+ case REGURAL:
+ case HEARTBEAT:
+ case DISCOVERY:
+ tlv_count = t->length / sizeof(struct tlv);
+ arr = t->data;
+ for (i = 0; i < tlv_count; i++) {
+ tlv_destroy(&arr[i]);
+ }
+ default:
+ free(t->data);
+ t->length = 0;
+ break;
}
- return ret;
}
-int get_tlv(struct tlv_parser *parser, struct tlv *ret)
+size_t tlv_raw_size(const struct tlv *t)
{
- int ret = 0;
+ return sizeof(*t) + t->length;
+}
- if (parser->offset + sizeof(ret->type) + sizeof(ret->length) >= parser->size) {
+int tlv_push_data(struct tlv *t, const char *data, size_t size)
+{
+ int ret = 0;
+ size_t final_size = tlv_raw_size(t) + size;
+ if (final_size > TLV_SZ_MAX_RAW) {
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);
- 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);
- }
+ t->data = realloc(t->data, final_size);
+ memcpy(t->data + t->length, data, size);
+ t->length = final_size;
}
return ret;
}
-size_t tlv_data_size(struct tlv_parser *parser)
+void tlv_init(struct tlv *t, enum tlv_type type)
{
- size_t size;
+ t->type = type;
+ t->length = 0;
+ t->data = NULL;
+}
- if (parser->offset + sizeof(enum tlv_type) + sizeof(size_t) >= parser->size) {
- size = 0;
+int tlv_push_tlv(struct tlv *t, const struct tlv *other)
+{
+ int ret = 0;
+ size_t other_size;
+ size_t final_size;
+
+ other_size = tlv_raw_size(other);
+ final_size = tlv_raw_size(t) + other_size;
+ if (final_size > TLV_SZ_MAX_RAW) {
+ ret = E_TLV_OVERFLOW;
} else {
- memcpy(&size, parser->data + parser->offset + sizeof(enum tlv_type), sizeof(size_t));
+ tlv_get_raw(other, t->data + t->length);
+ t->length = final_size;
}
- return size;
+
+ return ret;
}