Commit cebd8442 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[3806] Added and/or fixed toText implementations for various options.

parent 4ffbeb9f
......@@ -195,29 +195,50 @@ bool Option::delOption(uint16_t opt_type) {
}
std::string Option::toText(int indent /* =0 */ ) {
std::stringstream tmp;
for (int i = 0; i < indent; i++)
tmp << " ";
tmp << "type=" << type_ << ", len=" << len()-getHeaderLen() << ": ";
std::string Option::toText(int indent) {
std::stringstream output;
output << headerToText(indent) << ": ";
for (unsigned int i = 0; i < data_.size(); i++) {
if (i) {
tmp << ":";
output << ":";
}
tmp << setfill('0') << setw(2) << hex
output << setfill('0') << setw(2) << hex
<< static_cast<unsigned short>(data_[i]);
}
// print suboptions
for (OptionCollection::const_iterator opt = options_.begin();
opt != options_.end();
++opt) {
tmp << (*opt).second->toText(indent+2);
// Append suboptions.
output << suboptionsToText(indent + 2);
return (output.str());
}
std::string
Option::headerToText(const int indent) {
std::stringstream output;
for (int i = 0; i < indent; i++)
output << " ";
int field_len = (getUniverse() == V4 ? 3 : 5);
output << "type=" << std::setw(field_len) << std::setfill('0')
<< type_ << ", len=" << std::setw(field_len) << std::setfill('0')
<< len()-getHeaderLen();
return (output.str());
}
std::string
Option::suboptionsToText(const int indent) const {
std::stringstream output;
if (!options_.empty()) {
output << "," << std::endl << "options:";
for (OptionCollection::const_iterator opt = options_.begin();
opt != options_.end(); ++opt) {
output << std::endl << (*opt).second->toText(indent);
}
}
return tmp.str();
return (output.str());
}
uint16_t
......
// Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-2015 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
......@@ -423,7 +423,31 @@ protected:
/// those into one exception which can be documented here.
void unpackOptions(const OptionBuffer& buf);
/// @brief A private method used for option correctness.
/// @brief Returns option header in the textual format.
///
/// This protected method should be called by the derived classes in
/// their respective @c toText implementations.
///
/// @param indent Number of spaces to insert before the text.
///
/// @return Option header in the textual format.
std::string headerToText(const int indent = 0);
/// @brief Returns collection of suboptions in the textual format.
///
/// This protected method should be called by the derived classes
/// in their respective @c toText implementations to append the
/// suboptions held by this option. Note that there are some
/// option types which don't have suboptions because they contain
/// variable length fields. For such options this method is not
/// called.
///
/// @param indent Number of spaces to insert before the text.
///
//// @return Suboptions in the textual format.
std::string suboptionsToText(const int indent = 0) const;
/// @brief A protected method used for option correctness.
///
/// It is used in constructors. In there are any problems detected
/// (like specifying type > 255 for DHCPv4 option), it will throw
......
// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-2012,2015 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
......@@ -120,21 +120,16 @@ uint16_t Option4AddrLst::len() {
return (getHeaderLen() + addrs_.size() * V4ADDRESS_LEN);
}
std::string Option4AddrLst::toText(int indent /* =0 */ ) {
std::stringstream tmp;
for (int i = 0; i < indent; i++) {
tmp << " ";
}
tmp << "type=" << type_ << ", len=" << len()-getHeaderLen() << ":";
std::string Option4AddrLst::toText(int indent) {
std::stringstream output;
output << headerToText(indent) << ":";
for (AddressContainer::const_iterator addr = addrs_.begin();
addr != addrs_.end(); ++addr) {
tmp << " " << (*addr);
output << " " << (*addr);
}
return tmp.str();
return (output.str());
}
} // end of isc::dhcp namespace
......
// Copyright (C) 2011-2012, 2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-2012,2015 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
......@@ -97,18 +97,15 @@ void Option6AddrLst::unpack(OptionBufferConstIter begin,
}
}
std::string Option6AddrLst::toText(int indent /* =0 */) {
stringstream tmp;
for (int i = 0; i < indent; i++)
tmp << " ";
tmp << "type=" << type_ << " " << addrs_.size() << "addr(s): ";
std::string Option6AddrLst::toText(int indent) {
stringstream output;
output << headerToText(indent) << ":";
for (AddressContainer::const_iterator addr = addrs_.begin();
addr != addrs_.end(); ++addr) {
tmp << *addr << " ";
output << " " << *addr;
}
return tmp.str();
return (output.str());
}
uint16_t Option6AddrLst::len() {
......
// Copyright (C) 2012-2013, 2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2013,2015 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
......@@ -349,17 +349,17 @@ OptionCustom::dataFieldToText(const OptionDataType data_type,
text << readAddress(index);
break;
case OPT_FQDN_TYPE:
text << readFqdn(index);
text << "\"" << readFqdn(index) << "\"";
break;
case OPT_STRING_TYPE:
text << readString(index);
text << "\"" << readString(index) << "\"";
break;
default:
;
}
// Append data field type in brackets.
text << " ( " << OptionDataTypeUtil::getDataTypeName(data_type) << " ) ";
text << " (" << OptionDataTypeUtil::getDataTypeName(data_type) << ")";
return (text.str());
}
......@@ -532,13 +532,9 @@ void OptionCustom::initialize(const OptionBufferConstIter first,
}
std::string OptionCustom::toText(int indent) {
std::stringstream tmp;
std::stringstream output;
for (int i = 0; i < indent; ++i)
tmp << " ";
tmp << "type=" << type_ << ", len=" << len()-getHeaderLen()
<< ", data fields:" << std::endl;
output << headerToText(indent) << ":";
OptionDataType data_type = definition_.getType();
if (data_type == OPT_RECORD_TYPE) {
......@@ -550,13 +546,8 @@ std::string OptionCustom::toText(int indent) {
// with them.
for (OptionDefinition::RecordFieldsConstIter field = fields.begin();
field != fields.end(); ++field) {
for (int j = 0; j < indent + 2; ++j) {
tmp << " ";
}
tmp << "#" << std::distance(fields.begin(), field) << " "
<< dataFieldToText(*field, std::distance(fields.begin(),
field))
<< std::endl;
output << " " << dataFieldToText(*field, std::distance(fields.begin(),
field));
}
} else {
// For non-record types we iterate over all buffers
......@@ -565,22 +556,14 @@ std::string OptionCustom::toText(int indent) {
// and non-arrays as they only differ in such a way that
// non-arrays have just single data field.
for (unsigned int i = 0; i < getDataFieldsNum(); ++i) {
for (int j = 0; j < indent + 2; ++j) {
tmp << " ";
}
tmp << "#" << i << " "
<< dataFieldToText(definition_.getType(), i)
<< std::endl;
output << " " << dataFieldToText(definition_.getType(), i);
}
}
// print suboptions
for (OptionCollection::const_iterator opt = options_.begin();
opt != options_.end();
++opt) {
tmp << (*opt).second->toText(indent+2);
}
return tmp.str();
// Append suboptions.
output << suboptionsToText(indent + 2);
return (output.str());
}
} // end of isc::dhcp namespace
......
......@@ -21,6 +21,7 @@
#include <util/io_utilities.h>
#include <stdint.h>
#include <sstream>
namespace isc {
namespace dhcp {
......@@ -205,6 +206,36 @@ public:
return (length);
}
/// @brief Returns option carrying an integer value in the textual
/// format.
///
/// The returned value also includes the suboptions if present.
///
/// @param indent Number of spaces to be inserted before the text.
virtual std::string toText(int indent = 0) {
std::stringstream output;
output << headerToText(indent) << ": ";
// For 1 byte long data types we need to cast to the integer
// because they are usually implemented as "char" types, in
// which case the character rather than number would be printed.
if (OptionDataTypeTraits<T>::len == 1) {
output << static_cast<int>(getValue());
} else {
output << getValue();
}
// Append data type name.
output << " ("
<< OptionDataTypeUtil::getDataTypeName(OptionDataTypeTraits<T>::type)
<< ")";
// Append suboptions.
output << suboptionsToText(indent + 2);
return (output.str());
}
private:
T value_; ///< Value conveyed by the option.
......
// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2013,2015 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
......@@ -19,7 +19,7 @@
#include <dhcp/option.h>
#include <dhcp/option_data_types.h>
#include <util/io_utilities.h>
#include <sstream>
#include <stdint.h>
namespace isc {
......@@ -249,6 +249,25 @@ public:
return (length);
}
/// @brief Returns textual representation of the option.
///
/// @param indent Number of space characters to be inserted before
/// the text.
///
/// @return textual representation of the option.
virtual std::string toText(int indent = 0) {
std::stringstream output;
output << headerToText(indent) << ":";
std::string data_type = OptionDataTypeUtil::getDataTypeName(OptionDataTypeTraits<T>::type);
for (typename std::vector<T>::const_iterator value = values_.begin();
value != values_.end(); ++value) {
output << " " << *value << " (" << data_type << ")";
}
return (output.str());
}
private:
std::vector<T> values_;
......
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013,2015 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
......@@ -13,6 +13,7 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <dhcp/option_string.h>
#include <sstream>
namespace isc {
namespace dhcp {
......@@ -82,5 +83,14 @@ OptionString::unpack(OptionBufferConstIter begin,
setData(begin, end);
}
std::string
OptionString::toText(int indent) {
std::ostringstream output;
output << headerToText(indent) << ": "
<< "\"" << getValue() << "\" (string)";
return (output.str());
}
} // end of isc::dhcp namespace
} // end of isc namespace
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013,2015 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
......@@ -103,6 +103,13 @@ public:
/// @throw isc::OutOfRange if provided buffer is truncated.
virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end);
/// @brief Returns option information in the textual format.
///
/// @param indent Number of space characters to be inserted before
/// the text.
///
/// @return Option information in the textual format.
virtual std::string toText(int indent = 0);
};
/// Pointer to the OptionString object.
......
// Copyright (C) 2013, 2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013,2015 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
......@@ -17,6 +17,7 @@
#include <dhcp/dhcp4.h>
#include <dhcp/dhcp6.h>
#include <dhcp/option_vendor.h>
#include <sstream>
using namespace isc::dhcp;
......@@ -42,8 +43,7 @@ void OptionVendor::pack(isc::util::OutputBuffer& buf) {
// Calculate and store data-len as follows:
// data-len = total option length - header length
// - enterprise id field length - data-len field size
buf.writeUint8(len() - getHeaderLen() -
sizeof(uint32_t) - sizeof(uint8_t));
buf.writeUint8(dataLen());
}
packOptions(buf);
......@@ -85,3 +85,28 @@ uint16_t OptionVendor::len() {
}
return (length);
}
uint8_t
OptionVendor::dataLen() {
// Calculate and store data-len as follows:
// data-len = total option length - header length
// - enterprise id field length - data-len field size
return (len() - getHeaderLen() - sizeof(uint32_t) - sizeof(uint8_t));
}
std::string
OptionVendor::toText(int indent) {
std::stringstream output;
output << headerToText(indent) << ": "
<< getVendorId() << " (uint32)";
// For the DHCPv4 there is one more field.
if (getUniverse() == Option::V4) {
output << " " << static_cast<int>(dataLen()) << " (uint8)";
}
// Append suboptions.
output << suboptionsToText(indent + 2);
return (output.str());
}
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013,2015 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
......@@ -92,8 +92,25 @@ public:
/// @return length of this option
virtual uint16_t len();
/// @brief Returns the option in the textual format.
///
/// @param indent Number of spaces to be inserted before the text.
///
/// @return Vendor option in the textual format.
virtual std::string toText(int indent = 0);
private:
/// @brief Calculates the data-len value for DHCPv4.
///
/// The data-len field is only present in DHCPv4 space. It follows
/// the vendor-id field. This method is called from the
/// @c OptionVendor::pack and @c OptionVendor::toText to calculate
/// this value.
///
/// @return Returns calculated data-len value.
uint8_t dataLen();
uint32_t vendor_id_; ///< Enterprise-id
};
......
......@@ -161,7 +161,7 @@ public:
/// implementations of this method.
///
/// @return string with text representation
virtual std::string toText() = 0;
virtual std::string toText() const = 0;
/// @brief Returns packet size in binary format.
///
......
......@@ -358,21 +358,22 @@ Pkt4::makeLabel(const HWAddrPtr& hwaddr, const ClientIdPtr& client_id,
std::string
Pkt4::toText() {
stringstream tmp;
tmp << "localAddr=" << local_addr_ << ":" << local_port_
<< " remoteAddr=" << remote_addr_
<< ":" << remote_port_ << ", msgtype=" << static_cast<int>(getType())
<< ", transid=0x" << hex << transid_ << dec << endl;
for (isc::dhcp::OptionCollection::iterator opt=options_.begin();
opt != options_.end();
++opt) {
tmp << " " << opt->second->toText();
Pkt4::toText() const {
stringstream output;
output << "local_address=" << local_addr_ << ":" << local_port_
<< ", remote_adress=" << remote_addr_
<< ":" << remote_port_ << ", msg_type=" << static_cast<int>(getType())
<< ", transid=0x" << hex << transid_ << dec;
if (!options_.empty()) {
output << "," << std::endl << "options:";
for (isc::dhcp::OptionCollection::const_iterator opt = options_.begin();
opt != options_.end(); ++opt) {
output << std::endl << opt->second->toText(2);
}
}
return tmp.str();
return (output.str());
}
void
......
......@@ -137,7 +137,7 @@ public:
/// This function is useful mainly for debugging.
///
/// @return string with text representation
std::string toText();
std::string toText() const;
/// @brief Returns the size of the required buffer to build the packet.
///
......
......@@ -496,14 +496,14 @@ Pkt6::getMACFromDUID() {
}
std::string
Pkt6::toText() {
Pkt6::toText() const {
stringstream tmp;
tmp << "localAddr=[" << local_addr_ << "]:" << local_port_
<< " remoteAddr=[" << remote_addr_
<< "]:" << remote_port_ << endl;
tmp << "msgtype=" << static_cast<int>(msg_type_) << ", transid=0x" <<
hex << transid_ << dec << endl;
for (isc::dhcp::OptionCollection::iterator opt=options_.begin();
for (isc::dhcp::OptionCollection::const_iterator opt=options_.begin();
opt != options_.end();
++opt) {
tmp << opt->second->toText() << std::endl;
......
......@@ -162,7 +162,7 @@ public:
/// This function is useful mainly for debugging.
///
/// @return string with text representation
virtual std::string toText();
virtual std::string toText() const;
/// @brief Returns length of the packet.
///
......
// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2013,2015 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
......@@ -1570,4 +1570,38 @@ TEST_F(OptionCustomTest, invalidIndex) {
EXPECT_THROW(option->readInteger<uint32_t>(11), isc::OutOfRange);
}
// This test checks that the custom option holding a record of data
// fields can be presented in the textual format.
TEST_F(OptionCustomTest, toTextRecord) {
OptionDefinition opt_def("foo", 123, "record");
opt_def.addRecordField("uint32");
opt_def.addRecordField("string");
OptionCustom option(opt_def, Option::V4);
option.writeInteger<uint32_t>(10);
option.writeString("lorem ipsum", 1);
EXPECT_EQ("type=123, len=015: 10 (uint32) \"lorem ipsum\" (string)",
option.toText());
}
// This test checks that the custom option holding other data type
// than "record" be presented in the textual format.
TEST_F(OptionCustomTest, toTextNoRecord) {
OptionDefinition opt_def("foo", 234, "uint32");
OptionCustom option(opt_def, Option::V6);
option.writeInteger<uint32_t>(123456);
OptionDefinition sub_opt_def("bar", 333, "fqdn");
OptionCustomPtr sub_opt(new OptionCustom(sub_opt_def, Option::V6));
sub_opt->writeFqdn("myhost.example.org.");
option.addOption(sub_opt);
EXPECT_EQ("type=00234, len=00028: 123456 (uint32),\n"
"options:\n"
" type=00333, len=00020: \"myhost.example.org.\" (fqdn)",
option.toText());
}
} // anonymous namespace
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012,2015 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
......@@ -464,4 +464,14 @@ TEST_F(OptionIntArrayTest, addValuesInt32) {
addValuesTest<int16_t>();
}
TEST_F(OptionIntArrayTest, toText) {
OptionUint32Array option(Option::V4, 128);