/* * 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 #include #include #include "protocol.h" #include "protocol_private.h" #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; size_t size; 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; } void clear_data(struct tlv_packet *packet) { packet->offset = 0; packet->type = 0; memset(packet->data, 0, packet->size); } static int push_bytes(struct tlv_packet *packet, char *data, size_t size) { 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) { 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) { 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; }