From 45a6d021881342dfd6c5924841b215aeea65e10a Mon Sep 17 00:00:00 2001 From: Jan Kadlec <jan.kadlec@nic.cz> Date: Tue, 8 Apr 2014 15:09:33 +0200 Subject: [PATCH] new_node: Moved RRSet serialization/deserialization into new file. - all serialize/deserialize functions should be moved here eventually. --- Knot.files | 2 + src/Makefile.am | 2 + src/knot/server/serialization.c | 196 ++++++++++++++++++++++++++++++++ src/knot/server/serialization.h | 65 +++++++++++ src/knot/server/zones.c | 184 +----------------------------- 5 files changed, 267 insertions(+), 182 deletions(-) create mode 100644 src/knot/server/serialization.c create mode 100644 src/knot/server/serialization.h diff --git a/Knot.files b/Knot.files index 3bacb3a69..4a28db2c2 100644 --- a/Knot.files +++ b/Knot.files @@ -293,3 +293,5 @@ tests/slab.c tests/wire.c tests/zonedb.c tests/ztree.c +src/knot/server/serialization.c +src/knot/server/serialization.h diff --git a/src/Makefile.am b/src/Makefile.am index 7f7790871..cc67ce21a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -256,6 +256,8 @@ libknotd_la_SOURCES = \ knot/server/zone-load.h \ knot/server/zones.c \ knot/server/zones.h \ + knot/server/serialization.c \ + knot/server/serialization.h \ knot/updates/acl.c \ knot/updates/acl.h \ knot/updates/changesets.c \ diff --git a/src/knot/server/serialization.c b/src/knot/server/serialization.c new file mode 100644 index 000000000..cce3eea58 --- /dev/null +++ b/src/knot/server/serialization.c @@ -0,0 +1,196 @@ +/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <assert.h> + +#include "knot/server/serialization.h" +#include "common/errcode.h" + +static size_t rr_binary_size(const knot_rrset_t *rrset, size_t rdata_pos) +{ + const knot_rr_t *rr = knot_rrs_rr(&rrset->rrs, rdata_pos); + if (rr) { + // RR size + TTL + return knot_rr_rdata_size(rr) + sizeof(uint32_t); + } else { + return 0; + } +} + +static uint64_t rrset_binary_size(const knot_rrset_t *rrset) +{ + if (rrset == NULL || knot_rrset_rr_count(rrset) == 0) { + return 0; + } + uint64_t size = sizeof(uint64_t) + // size at the beginning + knot_dname_size(rrset->owner) + // owner data + sizeof(uint16_t) + // type + sizeof(uint16_t) + // class + sizeof(uint16_t); //RR count + uint16_t rdata_count = knot_rrset_rr_count(rrset); + for (uint16_t i = 0; i < rdata_count; i++) { + /* Space to store length of one RR. */ + size += sizeof(uint32_t); + /* Actual data. */ + size += rr_binary_size(rrset, i); + } + + return size; +} + +static void serialize_rr(const knot_rrset_t *rrset, size_t rdata_pos, + uint8_t *stream) +{ + const knot_rr_t *rr = knot_rrs_rr(&rrset->rrs, rdata_pos); + assert(rr); + uint32_t ttl = knot_rr_ttl(rr); + memcpy(stream, &ttl, sizeof(uint32_t)); + memcpy(stream + sizeof(uint32_t), knot_rr_rdata(rr), knot_rr_rdata_size(rr)); +} + +static int deserialize_rr(knot_rrset_t *rrset, const uint8_t *stream, uint32_t rdata_size) +{ + uint32_t ttl; + memcpy(&ttl, stream, sizeof(uint32_t)); + return knot_rrset_add_rr(rrset, stream + sizeof(uint32_t), + rdata_size - sizeof(uint32_t), ttl, NULL); +} + +int changeset_binary_size(const knot_changeset_t *chgset, size_t *size) +{ + if (chgset == NULL || size == NULL) { + return KNOT_EINVAL; + } + + size_t soa_from_size = rrset_binary_size(chgset->soa_from); + size_t soa_to_size = rrset_binary_size(chgset->soa_to); + + size_t remove_size = 0; + knot_rr_ln_t *rr_node = NULL; + WALK_LIST(rr_node, chgset->remove) { + knot_rrset_t *rrset = rr_node->rr; + remove_size += rrset_binary_size(rrset); + } + + size_t add_size = 0; + WALK_LIST(rr_node, chgset->add) { + knot_rrset_t *rrset = rr_node->rr; + add_size += rrset_binary_size(rrset); + } + + *size = soa_from_size + soa_to_size + remove_size + add_size; + /* + Changeset flags. */ + *size += sizeof(uint32_t); + + return KNOT_EOK; +} + +int rrset_serialize(const knot_rrset_t *rrset, uint8_t *stream, size_t *size) +{ + if (rrset == NULL || rrset->rrs.data == NULL) { + return KNOT_EINVAL; + } + + uint64_t rrset_length = rrset_binary_size(rrset); + memcpy(stream, &rrset_length, sizeof(uint64_t)); + + size_t offset = sizeof(uint64_t); + /* Save RR count. */ + const uint16_t rr_count = knot_rrset_rr_count(rrset); + memcpy(stream + offset, &rr_count, sizeof(uint16_t)); + offset += sizeof(uint16_t); + /* Save owner. */ + offset += knot_dname_to_wire(stream + offset, rrset->owner, rrset_length - offset); + + /* Save static data. */ + memcpy(stream + offset, &rrset->type, sizeof(uint16_t)); + offset += sizeof(uint16_t); + memcpy(stream + offset, &rrset->rclass, sizeof(uint16_t)); + offset += sizeof(uint16_t); + + /* Copy RDATA. */ + for (uint16_t i = 0; i < rr_count; i++) { + uint32_t knot_rr_size = rr_binary_size(rrset, i); + memcpy(stream + offset, &knot_rr_size, sizeof(uint32_t)); + offset += sizeof(uint32_t); + serialize_rr(rrset, i, stream + offset); + offset += knot_rr_size; + } + + *size = offset; + assert(*size == rrset_length); + return KNOT_EOK; +} + +int rrset_deserialize(const uint8_t *stream, size_t *stream_size, + knot_rrset_t **rrset) +{ + if (sizeof(uint64_t) > *stream_size) { + return KNOT_ESPACE; + } + uint64_t rrset_length = 0; + memcpy(&rrset_length, stream, sizeof(uint64_t)); + if (rrset_length > *stream_size) { + return KNOT_ESPACE; + } + + size_t offset = sizeof(uint64_t); + uint16_t rdata_count = 0; + memcpy(&rdata_count, stream + offset, sizeof(uint16_t)); + offset += sizeof(uint16_t); + /* Read owner from the stream. */ + unsigned owner_size = knot_dname_size(stream + offset); + knot_dname_t *owner = knot_dname_copy_part(stream + offset, owner_size, NULL); + assert(owner); + offset += owner_size; + /* Read type. */ + uint16_t type = 0; + memcpy(&type, stream + offset, sizeof(uint16_t)); + offset += sizeof(uint16_t); + /* Read class. */ + uint16_t rclass = 0; + memcpy(&rclass, stream + offset, sizeof(uint16_t)); + offset += sizeof(uint16_t); + + /* Create new RRSet. */ + *rrset = knot_rrset_new(owner, type, rclass, NULL); + if (*rrset == NULL) { + knot_dname_free(&owner, NULL); + return KNOT_ENOMEM; + } + + /* Read RRs. */ + for (uint16_t i = 0; i < rdata_count; i++) { + /* + * There's always size of rdata in the beginning. + * Needed because of remainders. + */ + uint32_t rdata_size = 0; + memcpy(&rdata_size, stream + offset, sizeof(uint32_t)); + offset += sizeof(uint32_t); + int ret = deserialize_rr((*rrset), stream + offset, rdata_size); + if (ret != KNOT_EOK) { + knot_rrset_free(rrset, NULL); + return ret; + } + offset += rdata_size; + } + + *stream_size = *stream_size - offset; + + return KNOT_EOK; +} + diff --git a/src/knot/server/serialization.h b/src/knot/server/serialization.h new file mode 100644 index 000000000..4627d6069 --- /dev/null +++ b/src/knot/server/serialization.h @@ -0,0 +1,65 @@ +/*! + * \file rr.h + * + * \author Jan Kadlec <jan.kadlec@nic.cz> + * + * \brief API for changeset serialization. + * + * \addtogroup server + * @{ + */ +/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <stdint.h> +#include "libknot/rrset.h" +#include "knot/updates/changesets.h" + +/*! + * \brief Returns size of changeset in serialized form. + * + * \param chgset Changeset whose size we want to compute. + * \param size Output size parameter. + * + * \return KNOT_E* + */ +int changeset_binary_size(const knot_changeset_t *chgset, size_t *size); + +/*! + * \brief Serializes one RRSet into given stream. + * + * \param rrset RRSet to be serialized. + * \param stream Stream to store RRSet into. + * \param size Output size of serialized RRSet in the stream. + * + * \return KNOT_E* + */ +int rrset_serialize(const knot_rrset_t *rrset, uint8_t *stream, size_t *size); + +/*! + * \brief Deserializes RRSet from given stream. + * + * \param stream Stream containing serialized RRSet. + * \param stream_size Output stream size after RRSet has been deserialized. + * \param rrset Output deserialized rrset. + * + * \return KNOT_E* + */ +int rrset_deserialize(const uint8_t *stream, size_t *stream_size, + knot_rrset_t **rrset); + diff --git a/src/knot/server/zones.c b/src/knot/server/zones.c index 538ff715f..bd3538966 100644 --- a/src/knot/server/zones.c +++ b/src/knot/server/zones.c @@ -27,6 +27,7 @@ #include "knot/server/xfr-handler.h" #include "knot/server/zone-load.h" #include "knot/server/zones.h" +#include "knot/server/serialization.h" #include "knot/zone/zone-dump.h" #include "libknot/dname.h" #include "libknot/dnssec/random.h" @@ -470,9 +471,6 @@ static inline uint64_t ixfrdb_key_make(uint32_t from, uint32_t to) /*----------------------------------------------------------------------------*/ -static int rrset_deserialize(const uint8_t *stream, size_t *stream_size, - knot_rrset_t **rrset); - int zones_changesets_from_binary(knot_changesets_t *chgsets) { /*! \todo #1291 Why doesn't this just increment stream ptr? */ @@ -1174,184 +1172,6 @@ int zones_save_zone(const knot_ns_xfr_t *xfr) /* Changeset serialization and storing (new) */ /*----------------------------------------------------------------------------*/ -static size_t rr_binary_size(const knot_rrset_t *rrset, size_t rdata_pos) -{ - const knot_rr_t *rr = knot_rrs_rr(&rrset->rrs, rdata_pos); - if (rr) { - // RR size + TTL - return knot_rr_rdata_size(rr) + sizeof(uint32_t); - } else { - return 0; - } -} - -static uint64_t rrset_binary_size(const knot_rrset_t *rrset) -{ - if (rrset == NULL || knot_rrset_rr_count(rrset) == 0) { - return 0; - } - uint64_t size = sizeof(uint64_t) + // size at the beginning - knot_dname_size(rrset->owner) + // owner data - sizeof(uint16_t) + // type - sizeof(uint16_t) + // class - sizeof(uint16_t); //RR count - uint16_t rdata_count = knot_rrset_rr_count(rrset); - for (uint16_t i = 0; i < rdata_count; i++) { - /* Space to store length of one RR. */ - size += sizeof(uint32_t); - /* Actual data. */ - size += rr_binary_size(rrset, i); - } - - return size; -} - -int zones_changeset_binary_size(const knot_changeset_t *chgset, size_t *size) -{ - if (chgset == NULL || size == NULL) { - return KNOT_EINVAL; - } - - size_t soa_from_size = rrset_binary_size(chgset->soa_from); - size_t soa_to_size = rrset_binary_size(chgset->soa_to); - - size_t remove_size = 0; - knot_rr_ln_t *rr_node = NULL; - WALK_LIST(rr_node, chgset->remove) { - knot_rrset_t *rrset = rr_node->rr; - remove_size += rrset_binary_size(rrset); - } - - size_t add_size = 0; - WALK_LIST(rr_node, chgset->add) { - knot_rrset_t *rrset = rr_node->rr; - add_size += rrset_binary_size(rrset); - } - - /*! \todo How is the changeset serialized? Any other parts? */ - *size = soa_from_size + soa_to_size + remove_size + add_size; - /* + Changeset flags. */ - *size += sizeof(uint32_t); - - return KNOT_EOK; -} - -static void serialize_rr(const knot_rrset_t *rrset, size_t rdata_pos, - uint8_t *stream) -{ - const knot_rr_t *rr = knot_rrs_rr(&rrset->rrs, rdata_pos); - assert(rr); - uint32_t ttl = knot_rr_ttl(rr); - memcpy(stream, &ttl, sizeof(uint32_t)); - memcpy(stream + sizeof(uint32_t), knot_rr_rdata(rr), knot_rr_rdata_size(rr)); -} - -static int deserialize_rr(knot_rrset_t *rrset, - const uint8_t *stream, uint32_t rdata_size) -{ - uint32_t ttl; - memcpy(&ttl, stream, sizeof(uint32_t)); - return knot_rrset_add_rr(rrset, stream + sizeof(uint32_t), - rdata_size - sizeof(uint32_t), ttl, NULL); -} - -static int rrset_serialize(const knot_rrset_t *rrset, uint8_t *stream, - size_t *size) -{ - if (rrset == NULL || rrset->rrs.data == NULL) { - return KNOT_EINVAL; - } - - uint64_t rrset_length = rrset_binary_size(rrset); - memcpy(stream, &rrset_length, sizeof(uint64_t)); - - size_t offset = sizeof(uint64_t); - /* Save RR count. */ - const uint16_t rr_count = knot_rrset_rr_count(rrset); - memcpy(stream + offset, &rr_count, sizeof(uint16_t)); - offset += sizeof(uint16_t); - /* Save owner. */ - offset += knot_dname_to_wire(stream + offset, rrset->owner, rrset_length - offset); - - /* Save static data. */ - memcpy(stream + offset, &rrset->type, sizeof(uint16_t)); - offset += sizeof(uint16_t); - memcpy(stream + offset, &rrset->rclass, sizeof(uint16_t)); - offset += sizeof(uint16_t); - - /* Copy RDATA. */ - for (uint16_t i = 0; i < rr_count; i++) { - uint32_t knot_rr_size = rr_binary_size(rrset, i); - memcpy(stream + offset, &knot_rr_size, sizeof(uint32_t)); - offset += sizeof(uint32_t); - serialize_rr(rrset, i, stream + offset); - offset += knot_rr_size; - } - - *size = offset; - assert(*size == rrset_length); - return KNOT_EOK; -} - -static int rrset_deserialize(const uint8_t *stream, size_t *stream_size, - knot_rrset_t **rrset) -{ - if (sizeof(uint64_t) > *stream_size) { - return KNOT_ESPACE; - } - uint64_t rrset_length = 0; - memcpy(&rrset_length, stream, sizeof(uint64_t)); - if (rrset_length > *stream_size) { - return KNOT_ESPACE; - } - - size_t offset = sizeof(uint64_t); - uint16_t rdata_count = 0; - memcpy(&rdata_count, stream + offset, sizeof(uint16_t)); - offset += sizeof(uint16_t); - /* Read owner from the stream. */ - unsigned owner_size = knot_dname_size(stream + offset); - knot_dname_t *owner = knot_dname_copy_part(stream + offset, owner_size, NULL); - assert(owner); - offset += owner_size; - /* Read type. */ - uint16_t type = 0; - memcpy(&type, stream + offset, sizeof(uint16_t)); - offset += sizeof(uint16_t); - /* Read class. */ - uint16_t rclass = 0; - memcpy(&rclass, stream + offset, sizeof(uint16_t)); - offset += sizeof(uint16_t); - - /* Create new RRSet. */ - *rrset = knot_rrset_new(owner, type, rclass, NULL); - if (*rrset == NULL) { - knot_dname_free(&owner, NULL); - return KNOT_ENOMEM; - } - - /* Read RRs. */ - for (uint16_t i = 0; i < rdata_count; i++) { - /* - * There's always size of rdata in the beginning. - * Needed because of remainders. - */ - uint32_t rdata_size = 0; - memcpy(&rdata_size, stream + offset, sizeof(uint32_t)); - offset += sizeof(uint32_t); - int ret = deserialize_rr((*rrset), stream + offset, rdata_size); - if (ret != KNOT_EOK) { - knot_rrset_free(rrset, NULL); - return ret; - } - offset += rdata_size; - } - - *stream_size = *stream_size - offset; - - return KNOT_EOK; -} - static int zones_rrset_write_to_mem(const knot_rrset_t *rr, char **entry, size_t *remaining) { size_t written = 0; @@ -1429,7 +1249,7 @@ static int zones_store_changeset(const knot_changeset_t *chs, journal_t *j, /* Count the size of the entire changeset in serialized form. */ size_t entry_size = 0; - int ret = zones_changeset_binary_size(chs, &entry_size); + int ret = changeset_binary_size(chs, &entry_size); assert(ret == KNOT_EOK); dbg_xfr_verb("Size in serialized form: %zu\n", entry_size); -- GitLab