Commit f957fa65 authored by Marcin Siodelski's avatar Marcin Siodelski

[2312] Added utility class to write data of various types to a buffer.

parent 08d0d10d
......@@ -21,7 +21,7 @@ libb10_dhcp___la_SOURCES += iface_mgr_linux.cc
libb10_dhcp___la_SOURCES += iface_mgr_sun.cc
libb10_dhcp___la_SOURCES += libdhcp++.cc libdhcp++.h
libb10_dhcp___la_SOURCES += option.cc option.h
libb10_dhcp___la_SOURCES += option_data_types.h
libb10_dhcp___la_SOURCES += option_data_types.cc option_data_types.h
libb10_dhcp___la_SOURCES += option_definition.cc option_definition.h
libb10_dhcp___la_SOURCES += option_custom.cc option_custom.h
libb10_dhcp___la_SOURCES += option6_ia.cc option6_ia.h
......
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <dhcp/option_data_types.h>
#include <util/encode/hex.h>
namespace isc {
namespace dhcp {
void
OptionDataTypeUtil::writeBinary(const std::string& hex_str,
std::vector<uint8_t>& buf) {
// Binary value means that the value is encoded as a string
// of hexadecimal deigits. We need to decode this string
// to the binary format here.
OptionBuffer binary;
try {
util::encode::decodeHex(hex_str, binary);
} catch (const Exception& ex) {
isc_throw(BadDataTypeCast, "unable to cast " << hex_str
<< " to binary data type: " << ex.what());
}
// Decode was successful so append decoded binary value
// to the buffer.
buf.insert(buf.end(), binary.begin(), binary.end());
}
void
OptionDataTypeUtil::writeBool(const bool value,
std::vector<uint8_t>& buf) {
if (value) {
buf.push_back(static_cast<uint8_t>(1));
} else {
buf.push_back(static_cast<uint8_t>(0));
}
}
void
OptionDataTypeUtil::writeAddress(const asiolink::IOAddress& address,
std::vector<uint8_t>& buf) {
if (address.getAddress().is_v4()) {
asio::ip::address_v4::bytes_type addr_bytes =
address.getAddress().to_v4().to_bytes();
// Increase the buffer size by the size of IPv4 address.
buf.resize(buf.size() + addr_bytes.size());
std::copy_backward(addr_bytes.begin(), addr_bytes.end(),
buf.end());
} else if (address.getAddress().is_v6()) {
asio::ip::address_v6::bytes_type addr_bytes =
address.getAddress().to_v6().to_bytes();
// Incresase the buffer size by the size of IPv6 address.
buf.resize(buf.size() + addr_bytes.size());
std::copy_backward(addr_bytes.begin(), addr_bytes.end(),
buf.end());
} else {
isc_throw(BadDataTypeCast, "the address " << address.toText()
<< " is neither valid IPv4 not IPv6 address.");
}
}
void
OptionDataTypeUtil::writeString(const std::string& value,
std::vector<uint8_t>& buf) {
if (value.size() > 0) {
// Increase the size of the storage by the size of the string.
buf.resize(buf.size() + value.size());
// Assuming that the string is already UTF8 encoded.
std::copy_backward(value.c_str(), value.c_str() + value.size(),
buf.end());
}
}
} // end of isc::dhcp namespace
} // end of isc namespace
......@@ -16,7 +16,9 @@
#define OPTION_DATA_TYPES_H
#include <asiolink/io_address.h>
#include <dhcp/option.h>
#include <exceptions/exceptions.h>
#include <util/io_utilities.h>
#include <stdint.h>
......@@ -172,6 +174,74 @@ struct OptionDataTypeTraits<std::string> {
static const OptionDataType type = OPT_STRING_TYPE;
};
/// @brief Utility class to write/read data to/from a buffer.
class OptionDataTypeUtil {
public:
/// @brief Write IPv4 or IPv6 address into a buffer.
///
/// @param address IPv4 or IPv6 address.
/// @param [out] buf output buffer.
static void writeAddress(const asiolink::IOAddress& address,
std::vector<uint8_t>& buf);
/// @brief Write hex-encoded binary values into a buffer.
///
/// @param hex_str string representing a binary value encoded
/// with hexadecimal digits (without 0x prefix).
/// @param [out] output buffer.
static void writeBinary(const std::string& hex_str,
std::vector<uint8_t>& buf);
/// @brief Write boolean value into a buffer.
///
/// The bool value is encoded in a buffer in such a way that
/// "1" means "true" and "0" means "false".
///
/// @param boolean value to be written.
/// @param [out] buf output buffer.
static void writeBool(const bool value, std::vector<uint8_t>& buf);
/// @brief Write integer or unsiged integer value into a buffer.
///
/// @param value an integer value to be written into a buffer.
/// @param [out] buf output buffer.
/// @tparam data type of the value.
template<typename T>
static void writeInt(const T value,
std::vector<uint8_t>& buf) {
if (!OptionDataTypeTraits<T>::is_integer) {
isc_throw(InvalidDataType, "provided data type is not the supported.");
}
switch (OptionDataTypeTraits<T>::len) {
case 1:
buf.push_back(static_cast<uint8_t>(value));
break;
case 2:
buf.resize(buf.size() + 2);
isc::util::writeUint16(static_cast<uint16_t>(value), &buf[buf.size() - 2]);
break;
case 4:
buf.resize(buf.size() + 4);
isc::util::writeUint32(static_cast<uint32_t>(value), &buf[buf.size() - 4]);
break;
default:
// The cases above cover whole range of possible data lengths because
// we check at the beginning of this function that given data type is
// a supported integer type which can be only 1,2 or 4 bytes long.
;
}
}
/// @brief Write utf8-encoded string into a buffer.
///
/// @param value string value to be written into a buffer.
/// @param [out] buf output buffer.
static void writeString(const std::string& value,
std::vector<uint8_t>& buf);
};
} // isc::dhcp namespace
} // isc namespace
......
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