Commit bfc050ed authored by Marcin Siodelski's avatar Marcin Siodelski

[2312] Initialize structure holding buffer for data fields.

parent 7c73dd5e
......@@ -60,7 +60,36 @@ OptionCustom::createBuffers() {
// to use it to split the data_ buffer into set of sub buffers.
definition_.validate();
// @todo create buffers here
std::vector<OptionBuffer> buffers;
if (definition_.getType() == OPT_RECORD_TYPE) {
const OptionDefinition::RecordFieldsCollection& fields =
definition_.getRecordFields();
OptionBuffer::iterator data = data_.begin();
for (OptionDefinition::RecordFieldsConstIter field = fields.begin();
field != fields.end(); ++field) {
int data_size = OptionDataTypeUtil::getDataTypeLen(*field);
if (data_size == 0) {
if (*field == OPT_IPV4_ADDRESS_TYPE) {
data_size = asiolink::V4ADDRESS_LEN;
} else if (*field == OPT_IPV6_ADDRESS_TYPE) {
data_size = asiolink::V6ADDRESS_LEN;
} else if (*field == OPT_STRING_TYPE ||
*field == OPT_FQDN_TYPE ||
*field == OPT_BINARY_TYPE) {
data_size = std::distance(data, data_.end());
} else {
isc_throw(InvalidDataType, "invalid option data type"
<< " used in the option record");
}
}
if (std::distance(data, data_.end()) < data_size ||
data_size == 0) {
isc_throw(OutOfRange, "option buffer truncated");
}
buffers_.push_back(OptionBuffer(data, data + data_size));
data += data_size;
}
}
}
void
......
......@@ -18,6 +18,25 @@
namespace isc {
namespace dhcp {
int
OptionDataTypeUtil::getDataTypeLen(const OptionDataType data_type) {
switch (data_type) {
case OPT_BOOLEAN_TYPE:
case OPT_INT8_TYPE:
case OPT_UINT8_TYPE:
return (1);
case OPT_INT16_TYPE:
case OPT_UINT16_TYPE:
return (2);
case OPT_INT32_TYPE:
case OPT_UINT32_TYPE:
return (4);
default:
;
}
return (0);
}
void
OptionDataTypeUtil::readAddress(const std::vector<uint8_t>& buf,
const short family,
......
......@@ -178,6 +178,20 @@ struct OptionDataTypeTraits<std::string> {
class OptionDataTypeUtil {
public:
/// @brief Get data type size.
///
/// This functionm returs the size of a particular data type.
/// Values retured by this function correspond to the data type
/// sizes defined in OptionDataTypeTraits so they rather indicate
/// the fixed length of the data being written into the buffer,
/// not the sizeof the particular data type. Thus for data types
/// such as string, binary etc. for which the buffer length can't
/// be determined this function returns 0.
///
/// @param data_type data type which size is to be returned.
/// @return data type size or zero for variable length types.
static int getDataTypeLen(const OptionDataType data_type);
/// @brief Read IPv4 or IPv6 addres from a buffer.
///
/// @param buf input buffer.
......
......@@ -51,7 +51,7 @@ public:
template<typename T>
void writeInt(T value, std::vector<uint8_t>& buf) {
for (int i = 0; i < sizeof(T); ++i) {
buf.push_back(value >> ((3 - i) * 8) & 0xFF);
buf.push_back(value >> ((sizeof(T) - i - 1) * 8) & 0xFF);
}
}
......@@ -70,7 +70,7 @@ TEST_F(OptionCustomTest, constructor) {
ASSERT_THROW(opt_def1.validate(), isc::Exception); */
}
TEST_F(OptionCustomTest, setData) {
TEST_F(OptionCustomTest, setRecordData) {
OptionDefinition opt_def("OPTION_FOO", 1000, "record");
ASSERT_NO_THROW(opt_def.addRecordField("uint16"));
ASSERT_NO_THROW(opt_def.addRecordField("boolean"));
......@@ -80,17 +80,17 @@ TEST_F(OptionCustomTest, setData) {
OptionBuffer buf;
writeInt<uint16_t>(8712, buf);
buf.push_back(1);
buf.push_back(static_cast<unsigned short>(1));
writeAddress(IOAddress("192.168.0.1"), buf);
writeAddress(IOAddress("2001:db8:1::1"), buf);
writeString("ABCD", buf);
OptionCustom option(opt_def, Option::V6, buf_.begin(), buf_.begin() + 30);
OptionCustom option(opt_def, Option::V6, buf.begin(), buf.begin() + 27);
ASSERT_TRUE(option.valid());
uint16_t value0 = 0;
ASSERT_NO_THROW(value0 = option.readInteger<uint16_t>(0));
EXPECT_EQ(0x0001, value0);
EXPECT_EQ(8712, value0);
bool value1 = false;
ASSERT_NO_THROW(value1 = option.readBoolean(1));
EXPECT_TRUE(value1);
......
......@@ -652,11 +652,6 @@ TEST_F(OptionDefinitionTest, uint8Tokenized) {
std::vector<std::string> values;
values.push_back("123");
values.push_back("456");
try {
option_v6 = opt_def.optionFactory(Option::V6, D6O_PREFERENCE, values);
} catch (std::exception& ex) {
std::cout << ex.what() << std::endl;
}
ASSERT_NO_THROW(
option_v6 = opt_def.optionFactory(Option::V6, D6O_PREFERENCE, values);
);
......
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