From: Marcin Siodelski Date: Mon, 26 Nov 2012 11:25:42 +0000 (+0100) Subject: [2312] Added utility class to write data of various types to a buffer. X-Git-Tag: bind10-1.0.0-beta-release~46^2~18^2~22 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f957fa651d7cb9b7e8364a58a7c438c367abb659;p=thirdparty%2Fkea.git [2312] Added utility class to write data of various types to a buffer. --- diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am index 732fcc5e1f..e9333e2f76 100644 --- a/src/lib/dhcp/Makefile.am +++ b/src/lib/dhcp/Makefile.am @@ -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 diff --git a/src/lib/dhcp/option_data_types.cc b/src/lib/dhcp/option_data_types.cc new file mode 100644 index 0000000000..e21d8f6f44 --- /dev/null +++ b/src/lib/dhcp/option_data_types.cc @@ -0,0 +1,85 @@ +// 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 +#include + +namespace isc { +namespace dhcp { + +void +OptionDataTypeUtil::writeBinary(const std::string& hex_str, + std::vector& 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& buf) { + if (value) { + buf.push_back(static_cast(1)); + } else { + buf.push_back(static_cast(0)); + } +} + +void +OptionDataTypeUtil::writeAddress(const asiolink::IOAddress& address, + std::vector& 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& 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 diff --git a/src/lib/dhcp/option_data_types.h b/src/lib/dhcp/option_data_types.h index 99b42205b0..7952f5276d 100644 --- a/src/lib/dhcp/option_data_types.h +++ b/src/lib/dhcp/option_data_types.h @@ -16,7 +16,9 @@ #define OPTION_DATA_TYPES_H #include +#include #include +#include #include @@ -172,6 +174,74 @@ struct OptionDataTypeTraits { 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& 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& 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& 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 + static void writeInt(const T value, + std::vector& buf) { + if (!OptionDataTypeTraits::is_integer) { + isc_throw(InvalidDataType, "provided data type is not the supported."); + } + switch (OptionDataTypeTraits::len) { + case 1: + buf.push_back(static_cast(value)); + break; + case 2: + buf.resize(buf.size() + 2); + isc::util::writeUint16(static_cast(value), &buf[buf.size() - 2]); + break; + case 4: + buf.resize(buf.size() + 4); + isc::util::writeUint32(static_cast(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& buf); + +}; + + } // isc::dhcp namespace } // isc namespace