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