Commit 45a6d021 authored by Jan Kadlec's avatar Jan Kadlec

new_node: Moved RRSet serialization/deserialization into new file.

- all serialize/deserialize functions should be moved here eventually.
parent 3e3920b8
......@@ -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
......@@ -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 \
......
/* 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;
}
/*!
* \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);
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment