Commit f3da5ed9 authored by Marcin Siodelski's avatar Marcin Siodelski

[2312] Added functions to read data of different types from buffer.

parent f957fa65
......@@ -18,6 +18,52 @@
namespace isc {
namespace dhcp {
void
OptionDataTypeUtil::readAddress(const std::vector<uint8_t>& buf,
const short family,
asiolink::IOAddress& address) {
using namespace isc::asiolink;
if (family == AF_INET) {
if (buf.size() < V4ADDRESS_LEN) {
isc_throw(BadDataTypeCast, "unavle to read data from the buffer as"
<< " IPv4 address. Invalid buffer size: " << buf.size());
}
address = IOAddress::from_bytes(AF_INET, &buf[0]);
} else if (buf.size() == V6ADDRESS_LEN) {
if (buf.size() < V6ADDRESS_LEN) {
isc_throw(BadDataTypeCast, "unavle to read data from the buffer as"
<< " IPv6 address. Invalid buffer size: " << buf.size());
}
address = IOAddress::from_bytes(AF_INET6, &buf[0]);
} else {
isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
"IP address. Invalid family: " << family);
}
}
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::writeBinary(const std::string& hex_str,
std::vector<uint8_t>& buf) {
......@@ -36,6 +82,21 @@ OptionDataTypeUtil::writeBinary(const std::string& hex_str,
buf.insert(buf.end(), binary.begin(), binary.end());
}
bool
OptionDataTypeUtil::readBool(const std::vector<uint8_t>& buf) {
if (buf.size() < 1) {
isc_throw(BadDataTypeCast, "unable to read the buffer as boolean"
<< " value. Invalid buffer size " << buf.size());
}
if (buf[0] == 1) {
return (true);
} else if (buf[0] == 0) {
return (false);
}
isc_throw(BadDataTypeCast, "unable to read the buffer as boolean"
<< " value. Inavlid value " << static_cast<int>(buf[0]));
}
void
OptionDataTypeUtil::writeBool(const bool value,
std::vector<uint8_t>& buf) {
......@@ -47,26 +108,9 @@ OptionDataTypeUtil::writeBool(const bool value,
}
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.");
}
OptionDataTypeUtil::readString(const std::vector<uint8_t>& buf,
std::string& value) {
value.insert(value.end(), buf.begin(), buf.end());
}
void
......
......@@ -177,6 +177,16 @@ struct OptionDataTypeTraits<std::string> {
/// @brief Utility class to write/read data to/from a buffer.
class OptionDataTypeUtil {
public:
/// @brief Read IPv4 or IPv6 addres from a buffer.
///
/// @param buf input buffer.
/// @param family address family: AF_INET or AF_INET6.
/// @param [out] address being read.
static void readAddress(const std::vector<uint8_t>& buf,
const short family,
asiolink::IOAddress& address);
/// @brief Write IPv4 or IPv6 address into a buffer.
///
/// @param address IPv4 or IPv6 address.
......@@ -190,7 +200,13 @@ public:
/// with hexadecimal digits (without 0x prefix).
/// @param [out] output buffer.
static void writeBinary(const std::string& hex_str,
std::vector<uint8_t>& buf);
std::vector<uint8_t>& buf);
/// @brief Read boolean value from a buffer.
///
/// @param buf input buffer.
/// @return boolean value read from a buffer.
static bool readBool(const std::vector<uint8_t>& buf);
/// @brief Write boolean value into a buffer.
///
......@@ -201,6 +217,39 @@ public:
/// @param [out] buf output buffer.
static void writeBool(const bool value, std::vector<uint8_t>& buf);
/// @brief Read integer value from a buffer.
///
/// @param buf input buffer.
/// @tparam integer type of the returned value.
/// @return integer value being read.
template<typename T>
T readInt(const std::vector<uint8_t>& buf) {
if (!OptionDataTypeTraits<T>::integer_type) {
isc_throw(isc::dhcp::InvalidDataType, "specified data type to be returned"
" by readInteger is not supported integer type");
}
assert(buf.size() == OptionDataTypeTraits<T>::len);
T value;
switch (OptionDataTypeTraits<T>::len) {
case 1:
value = *(buf.begin());
break;
case 2:
value = isc::util::readUint16(&(*buf.begin()));
break;
case 4:
value = isc::util::readUint32(&(*buf.begin()));
break;
default:
// This should not happen because we made checks on data types
// but it does not hurt to keep throw statement here.
isc_throw(isc::dhcp::InvalidDataType,
"invalid size of the data type to be read as integer.");
}
return (value);
}
/// @brief Write integer or unsiged integer value into a buffer.
///
/// @param value an integer value to be written into a buffer.
......@@ -232,6 +281,13 @@ public:
}
}
/// @brief Read string value from a buffer.
///
/// @param buf input buffer.
/// @param [out] value string value being read.
void readString(const std::vector<uint8_t>& buf,
std::string& value);
/// @brief Write utf8-encoded string into a buffer.
///
/// @param value string value to be written into a buffer.
......
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