From: Paul Selkirk Date: Fri, 22 Mar 2013 03:08:58 +0000 (-0400) Subject: [2391] update AFSDB to use the MasterLexer X-Git-Tag: bind10-1.1.0beta1-release~22^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9a551ccda02b841bf296ecbce5c0bbf04721024a;p=thirdparty%2Fkea.git [2391] update AFSDB to use the MasterLexer --- diff --git a/src/lib/dns/rdata/generic/afsdb_18.cc b/src/lib/dns/rdata/generic/afsdb_18.cc index ec76ee0e00..f76dc7ad33 100644 --- a/src/lib/dns/rdata/generic/afsdb_18.cc +++ b/src/lib/dns/rdata/generic/afsdb_18.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2011-2013 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 @@ -25,9 +25,12 @@ #include +#include + using namespace std; +using boost::lexical_cast; using namespace isc::util; -using namespace isc::util::str; +using isc::dns::rdata::generic::detail::createNameFromLexer; // BEGIN_ISC_NAMESPACE // BEGIN_RDATA_NAMESPACE @@ -52,24 +55,58 @@ using namespace isc::util::str; AFSDB::AFSDB(const std::string& afsdb_str) : subtype_(0), server_(Name::ROOT_NAME()) { - istringstream iss(afsdb_str); - try { - const uint32_t subtype = tokenToNum(getToken(iss)); - const Name servername(getToken(iss)); + std::istringstream ss(afsdb_str); + MasterLexer lexer; + lexer.pushSource(ss); - if (!iss.eof()) { - isc_throw(InvalidRdataText, "Unexpected input for AFSDB" - "RDATA: " << afsdb_str); + createFromLexer(lexer, NULL); + + if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { + isc_throw(InvalidRdataText, "extra input text for AFSDB: " + << afsdb_str); } + } catch (const MasterLexer::LexerError& ex) { + isc_throw(InvalidRdataText, "Failed to construct AFSDB from '" << + afsdb_str << "': " << ex.what()); + } +} - subtype_ = subtype; - server_ = servername; +/// \brief Constructor with a context of MasterLexer. +/// +/// The \c lexer should point to the beginning of valid textual representation +/// of an AFSDB RDATA. The EXCHANGE field can be non-absolute if \c origin +/// is non-NULL, in which case \c origin is used to make it absolute. +/// It must not be represented as a quoted string. +/// +/// The SUBTYPE field must be a valid decimal representation of an +/// unsigned 16-bit integer. +/// +/// \throw MasterLexer::LexerError General parsing error such as missing field. +/// \throw Other Exceptions from the Name and RRTTL constructors if +/// construction of textual fields as these objects fail. +/// +/// \param lexer A \c MasterLexer object parsing a master file for the +/// RDATA to be created +/// \param origin If non NULL, specifies the origin of EXCHANGE when it +/// is non-absolute. +AFSDB::AFSDB(MasterLexer& lexer, const Name* origin, + MasterLoader::Options, MasterLoaderCallbacks&) : + subtype_(0), server_(".") +{ + createFromLexer(lexer, origin); +} - } catch (const StringTokenError& ste) { - isc_throw(InvalidRdataText, "Invalid AFSDB text: " << - ste.what() << ": " << afsdb_str); +void +AFSDB::createFromLexer(MasterLexer& lexer, const Name* origin) +{ + const uint32_t num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); + if (num > 65535) { + isc_throw(InvalidRdataText, "Invalid AFSDB subtype: " << num); } + subtype_ = static_cast(num); + + server_ = createNameFromLexer(lexer, origin); } /// \brief Constructor from wire-format data. @@ -111,7 +148,7 @@ AFSDB::operator=(const AFSDB& source) { /// \return A \c string object that represents the \c AFSDB object. string AFSDB::toText() const { - return (boost::lexical_cast(subtype_) + " " + server_.toText()); + return (lexical_cast(subtype_) + " " + server_.toText()); } /// \brief Render the \c AFSDB in the wire format without name compression. diff --git a/src/lib/dns/rdata/generic/afsdb_18.h b/src/lib/dns/rdata/generic/afsdb_18.h index 4a4677502c..359a6e4a40 100644 --- a/src/lib/dns/rdata/generic/afsdb_18.h +++ b/src/lib/dns/rdata/generic/afsdb_18.h @@ -1,4 +1,4 @@ -// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2011-2013 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 @@ -61,6 +61,8 @@ public: uint16_t getSubtype() const; private: + void createFromLexer(MasterLexer& lexer, const Name* origin); + uint16_t subtype_; Name server_; }; diff --git a/src/lib/dns/tests/rdata_afsdb_unittest.cc b/src/lib/dns/tests/rdata_afsdb_unittest.cc index 9bb64b7229..9a628cd178 100644 --- a/src/lib/dns/tests/rdata_afsdb_unittest.cc +++ b/src/lib/dns/tests/rdata_afsdb_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2011-2013 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 @@ -34,7 +34,7 @@ using namespace isc::dns::rdata; const char* const afsdb_text = "1 afsdb.example.com."; const char* const afsdb_text2 = "0 root.example.com."; const char* const too_long_label("012345678901234567890123456789" - "0123456789012345678901234567890123"); + "0123456789012345678901234567890123."); namespace { class Rdata_AFSDB_Test : public RdataTest { @@ -68,9 +68,17 @@ TEST_F(Rdata_AFSDB_Test, badText) { // number of fields (must be 2) is incorrect EXPECT_THROW(const generic::AFSDB rdata_afsdb("10 afsdb. example.com."), InvalidRdataText); + // No origin and relative + EXPECT_THROW(const generic::AFSDB rdata_afsdb("1 afsdb.example.com"), + MissingNameOrigin); // bad name EXPECT_THROW(const generic::AFSDB rdata_afsdb("1 afsdb.example.com." + - string(too_long_label)), TooLongLabel); + string(too_long_label)), TooLongLabel); +} + +TEST_F(Rdata_AFSDB_Test, copy) { + const generic::AFSDB rdata_afsdb2(rdata_afsdb); + EXPECT_EQ(0, rdata_afsdb.compare(rdata_afsdb2)); } TEST_F(Rdata_AFSDB_Test, assignment) { @@ -119,9 +127,24 @@ TEST_F(Rdata_AFSDB_Test, createFromLexer) { *test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(), afsdb_text))); + // test::createRdataUsingLexer() constructs relative to + // "example.org." origin. + generic::AFSDB tmp = generic::AFSDB("1 afsdb2.example.org."); + EXPECT_EQ(0, tmp.compare( + *test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(), + "1 afsdb2"))); + // Exceptions cause NULL to be returned. EXPECT_FALSE(test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(), "1root.example.com.")); + + // 65536 is larger than maximum possible subtype + EXPECT_FALSE(test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(), + "65536 afsdb.example.com.")); + + // Extra text at end of line + EXPECT_FALSE(test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(), + "1 afsdb.example.com. extra.")); } TEST_F(Rdata_AFSDB_Test, toWireBuffer) { @@ -197,9 +220,9 @@ TEST_F(Rdata_AFSDB_Test, compare) { EXPECT_EQ(0, rdata_afsdb.compare(generic::AFSDB("1 " "AFSDB.example.com."))); - const generic::AFSDB small1("10 afsdb.example.com"); - const generic::AFSDB large1("65535 afsdb.example.com"); - const generic::AFSDB large2("256 afsdb.example.com"); + const generic::AFSDB small1("10 afsdb.example.com."); + const generic::AFSDB large1("65535 afsdb.example.com."); + const generic::AFSDB large2("256 afsdb.example.com."); // confirm these are compared as unsigned values EXPECT_GT(0, rdata_afsdb.compare(large1)); @@ -210,7 +233,7 @@ TEST_F(Rdata_AFSDB_Test, compare) { EXPECT_LT(0, large2.compare(small1)); // another AFSDB whose server name is larger than that of rdata_afsdb. - const generic::AFSDB large3("256 zzzzz.example.com"); + const generic::AFSDB large3("256 zzzzz.example.com."); EXPECT_GT(0, large2.compare(large3)); EXPECT_LT(0, large3.compare(large2));