Parcourir la source

[trac1128] Add more comments, avoid including useless header, and some
minor fixes.

chenzhengzhang il y a 13 ans
Parent
commit
c8710633f9

+ 0 - 172
src/lib/dns/rdata/generic/srv_33.cc

@@ -1,172 +0,0 @@
-// Copyright (C) 2011  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 <iostream>
-#include <string>
-#include <sstream>
-#include <vector>
-
-#include <boost/lexical_cast.hpp>
-
-#include <util/buffer.h>
-
-#include <dns/messagerenderer.h>
-#include <dns/name.h>
-#include <dns/rdata.h>
-#include <dns/rdataclass.h>
-
-using namespace std;
-using namespace isc::util;
-
-// BEGIN_ISC_NAMESPACE
-// BEGIN_RDATA_NAMESPACE
-
-struct SRVImpl {
-    // straightforward representation of SRV RDATA fields
-    SRVImpl(uint16_t priority, uint16_t weight, uint16_t port,
-           const Name& target) :
-        priority_(priority), weight_(weight), port_(port),
-        target_(target)
-    {}
-
-    uint16_t priority_;
-    uint16_t weight_;
-    uint16_t port_;
-    Name target_;
-};
-
-SRV::SRV(const string& srv_str) :
-    impl_(NULL)
-{
-    istringstream iss(srv_str);
-    string targetname;
-    unsigned int priority, weight, port;
-
-    iss >> priority >> weight >> port >> targetname;
-    if (iss.bad() || iss.fail()) {
-        isc_throw(InvalidRdataText, "Invalid SRV text");
-    }
-    if (priority > 0xffff) {
-        isc_throw(InvalidRdataText, "SRV priority out of range");
-    }
-    if (weight > 0xffff) {
-        isc_throw(InvalidRdataText, "SRV weight out of range");
-    }
-    if (port > 0xffff) {
-        isc_throw(InvalidRdataText, "SRV port out of range");
-    }
-
-    impl_ = new SRVImpl(priority, weight, port, Name(targetname));
-}
-
-SRV::SRV(InputBuffer& buffer, size_t rdata_len) {
-    if (rdata_len < 6) {
-        isc_throw(InvalidRdataLength, "SRV too short");
-    }
-
-    uint16_t priority = buffer.readUint16();
-    uint16_t weight = buffer.readUint16();
-    uint16_t port = buffer.readUint16();
-    const Name targetname(buffer);
-
-    impl_ = new SRVImpl(priority, weight, port, targetname);
-}
-
-SRV::SRV(const SRV& source) :
-    Rdata(), impl_(new SRVImpl(*source.impl_))
-{}
-
-SRV&
-SRV::operator=(const SRV& source) {
-    if (impl_ == source.impl_) {
-        return (*this);
-    }
-
-    SRVImpl* newimpl = new SRVImpl(*source.impl_);
-    delete impl_;
-    impl_ = newimpl;
-
-    return (*this);
-}
-
-SRV::~SRV() {
-    delete impl_;
-}
-
-string
-SRV::toText() const {
-    using namespace boost;
-    return (lexical_cast<string>(static_cast<int>(impl_->priority_)) +
-        " " + lexical_cast<string>(static_cast<int>(impl_->weight_)) +
-        " " + lexical_cast<string>(static_cast<int>(impl_->port_)) +
-        " " + impl_->target_.toText());
-}
-
-void
-SRV::toWire(OutputBuffer& buffer) const {
-    buffer.writeUint16(impl_->priority_);
-    buffer.writeUint16(impl_->weight_);
-    buffer.writeUint16(impl_->port_);
-    impl_->target_.toWire(buffer);
-}
-
-void
-SRV::toWire(AbstractMessageRenderer& renderer) const {
-    renderer.writeUint16(impl_->priority_);
-    renderer.writeUint16(impl_->weight_);
-    renderer.writeUint16(impl_->port_);
-    // According to RFC 2782, name compression is not
-    // to be used for this field.
-    renderer.writeName(impl_->target_, false);
-}
-
-int
-SRV::compare(const Rdata& other) const {
-    const SRV& other_srv = dynamic_cast<const SRV&>(other);
-
-    if (impl_->priority_ != other_srv.impl_->priority_) {
-        return (impl_->priority_ < other_srv.impl_->priority_ ? -1 : 1);
-    }
-    if (impl_->weight_ != other_srv.impl_->weight_) {
-        return (impl_->weight_ < other_srv.impl_->weight_ ? -1 : 1);
-    }
-    if (impl_->port_ != other_srv.impl_->port_) {
-        return (impl_->port_ < other_srv.impl_->port_ ? -1 : 1);
-    }
-
-    return (compareNames(impl_->target_, other_srv.impl_->target_));
-}
-
-uint16_t
-SRV::getPriority() const {
-    return (impl_->priority_);
-}
-
-uint16_t
-SRV::getWeight() const {
-    return (impl_->weight_);
-}
-
-uint16_t
-SRV::getPort() const {
-    return (impl_->port_);
-}
-
-const Name&
-SRV::getTarget() const {
-    return (impl_->target_);
-}
-
-// END_RDATA_NAMESPACE
-// END_ISC_NAMESPACE

+ 271 - 0
src/lib/dns/rdata/in_1/srv_33.cc

@@ -0,0 +1,271 @@
+// Copyright (C) 2011  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 <iostream>
+#include <sstream>
+
+#include <boost/lexical_cast.hpp>
+
+#include <util/buffer.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+using namespace std;
+using namespace isc::util;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+struct SRVImpl {
+    // straightforward representation of SRV RDATA fields
+    SRVImpl(uint16_t priority, uint16_t weight, uint16_t port,
+           const Name& target) :
+        priority_(priority), weight_(weight), port_(port),
+        target_(target)
+    {}
+
+    uint16_t priority_;
+    uint16_t weight_;
+    uint16_t port_;
+    Name target_;
+};
+
+namespace {
+string
+getToken(istringstream& iss, const string& full_input) {
+    string token;
+    iss >> token;
+    if (iss.bad() || iss.fail()) {
+        isc_throw(InvalidRdataText, "Invalid SRV text: parse error " <<
+                  full_input);
+    }
+    return (token);
+}
+
+// This helper function converts a string token to an *unsigned* integer.
+// NumType is a *signed* integral type (e.g. int32_t) that is sufficiently
+// wide to store resulting integers.
+template <typename NumType, int BitSize>
+NumType
+tokenToNum(const string& num_token) {
+    NumType num;
+    try {
+        num = lexical_cast<NumType>(num_token);
+    } catch (const boost::bad_lexical_cast& ex) {
+        isc_throw(InvalidRdataText, "Invalid SRV numeric parameter: " <<
+                  num_token);
+    }
+    if (num < 0 || num >= (static_cast<NumType>(1) << BitSize)) {
+        isc_throw(InvalidRdataText, "Numeric SRV parameter out of range: " <<
+                  num);
+    }
+    return (num);
+}
+}
+
+/// \brief Constructor from string.
+///
+/// \c srv_str must be formatted as follows:
+/// \code <Priority> <Weight> <Port> <Target>
+/// \endcode
+/// where
+/// - <Priority>, <Weight>, and <Port> are an unsigned 16-bit decimal
+///   integer.
+/// - <Target> is a valid textual representation of domain name.
+///
+/// An example of valid string is:
+/// \code "1 5 1500 example.com." \endcode
+///
+/// <b>Exceptions</b>
+///
+/// If <Target> is not a valid domain name, a corresponding exception from
+/// the \c Name class will be thrown;
+/// if %any of the other bullet points above is not met, an exception of
+/// class \c InvalidRdataText will be thrown.
+/// This constructor internally involves resource allocation, and if it fails
+/// a corresponding standard exception will be thrown.
+SRV::SRV(const string& srv_str) :
+    impl_(NULL)
+{
+    istringstream iss(srv_str);
+
+    const int32_t priority = tokenToNum<int32_t, 16>(getToken(iss, srv_str));
+    const int32_t weight = tokenToNum<int32_t, 16>(getToken(iss, srv_str));
+    const int32_t port = tokenToNum<int32_t, 16>(getToken(iss, srv_str));
+    const Name targetname(getToken(iss, srv_str));
+
+    if (!iss.eof()) {
+        isc_throw(InvalidRdataText, "Unexpected input for SRV RDATA: " <<
+                  srv_str);
+    }
+
+    impl_ = new SRVImpl(priority, weight, port, targetname);
+}
+
+/// \brief Constructor from wire-format data.
+///
+/// When a read operation on \c buffer fails (e.g., due to a corrupted
+/// message) a corresponding exception from the \c InputBuffer class will
+/// be thrown.
+/// If the wire-format data does not begin with a valid domain name,
+/// a corresponding exception from the \c Name class will be thrown.
+/// In addition, this constructor internally involves resource allocation,
+/// and if it fails a corresponding standard exception will be thrown.
+///
+/// According to RFC2782, the Target field must be a non compressed form
+/// of domain name.  But this implementation accepts a %SRV RR even if that
+/// field is compressed.
+///
+/// \param buffer A buffer storing the wire format data.
+/// \param rdata_len The length of the RDATA in bytes, normally expected
+/// to be the value of the RDLENGTH field of the corresponding RR.
+SRV::SRV(InputBuffer& buffer, size_t rdata_len) {
+    if (rdata_len < 6) {
+        isc_throw(InvalidRdataLength, "SRV too short");
+    }
+
+    uint16_t priority = buffer.readUint16();
+    uint16_t weight = buffer.readUint16();
+    uint16_t port = buffer.readUint16();
+    const Name targetname(buffer);
+
+    impl_ = new SRVImpl(priority, weight, port, targetname);
+}
+
+/// \brief The copy constructor.
+///
+/// It internally allocates a resource, and if it fails a corresponding
+/// standard exception will be thrown.
+/// This constructor never throws an exception otherwise.
+SRV::SRV(const SRV& source) :
+    Rdata(), impl_(new SRVImpl(*source.impl_))
+{}
+
+SRV&
+SRV::operator=(const SRV& source) {
+    if (impl_ == source.impl_) {
+        return (*this);
+    }
+
+    SRVImpl* newimpl = new SRVImpl(*source.impl_);
+    delete impl_;
+    impl_ = newimpl;
+
+    return (*this);
+}
+
+SRV::~SRV() {
+    delete impl_;
+}
+
+/// \brief Convert the \c SRV to a string.
+///
+/// The output of this method is formatted as described in the "from string"
+/// constructor (\c SRV(const std::string&))).
+///
+/// If internal resource allocation fails, a corresponding
+/// standard exception will be thrown.
+///
+/// \return A \c string object that represents the \c SRV object.
+string
+SRV::toText() const {
+    using namespace boost;
+    return (lexical_cast<string>(impl_->priority_) +
+        " " + lexical_cast<string>(impl_->weight_) +
+        " " + lexical_cast<string>(impl_->port_) +
+        " " + impl_->target_.toText());
+}
+
+/// \brief Render the \c SRV in the wire format without name compression.
+///
+/// If internal resource allocation fails, a corresponding
+/// standard exception will be thrown.
+/// This method never throws an exception otherwise.
+///
+/// \param buffer An output buffer to store the wire data.
+void
+SRV::toWire(OutputBuffer& buffer) const {
+    buffer.writeUint16(impl_->priority_);
+    buffer.writeUint16(impl_->weight_);
+    buffer.writeUint16(impl_->port_);
+    impl_->target_.toWire(buffer);
+}
+
+/// \brief Render the \c SRV in the wire format with taking into account
+/// compression.
+///
+/// As specified in RFC2782, the Target field (a domain name) will not be
+/// compressed.  However, the domain name could be a target of compression
+/// of other compressible names (though pretty unlikely), the offset
+/// information of the algorithm name may be recorded in \c renderer.
+///
+/// If internal resource allocation fails, a corresponding
+/// standard exception will be thrown.
+/// This method never throws an exception otherwise.
+///
+/// \param renderer DNS message rendering context that encapsulates the
+/// output buffer and name compression information.
+void
+SRV::toWire(AbstractMessageRenderer& renderer) const {
+    renderer.writeUint16(impl_->priority_);
+    renderer.writeUint16(impl_->weight_);
+    renderer.writeUint16(impl_->port_);
+    renderer.writeName(impl_->target_, false);
+}
+
+/// \brief Compare two instances of \c SRV RDATA.
+///
+/// See documentation in \c Rdata.
+int
+SRV::compare(const Rdata& other) const {
+    const SRV& other_srv = dynamic_cast<const SRV&>(other);
+
+    if (impl_->priority_ != other_srv.impl_->priority_) {
+        return (impl_->priority_ < other_srv.impl_->priority_ ? -1 : 1);
+    }
+    if (impl_->weight_ != other_srv.impl_->weight_) {
+        return (impl_->weight_ < other_srv.impl_->weight_ ? -1 : 1);
+    }
+    if (impl_->port_ != other_srv.impl_->port_) {
+        return (impl_->port_ < other_srv.impl_->port_ ? -1 : 1);
+    }
+
+    return (compareNames(impl_->target_, other_srv.impl_->target_));
+}
+
+uint16_t
+SRV::getPriority() const {
+    return (impl_->priority_);
+}
+
+uint16_t
+SRV::getWeight() const {
+    return (impl_->weight_);
+}
+
+uint16_t
+SRV::getPort() const {
+    return (impl_->port_);
+}
+
+const Name&
+SRV::getTarget() const {
+    return (impl_->target_);
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE

+ 38 - 4
src/lib/dns/rdata/generic/srv_33.h

@@ -14,11 +14,7 @@
 
 #include <stdint.h>
 
-#include <string>
-
 #include <dns/name.h>
-#include <dns/rrtype.h>
-#include <dns/rrttl.h>
 #include <dns/rdata.h>
 
 // BEGIN_HEADER_GUARD
@@ -30,21 +26,59 @@
 
 // BEGIN_RDATA_NAMESPACE
 
+/// \brief \c rdata::SRV class represents the SRV RDATA as defined %in
+/// RFC2782.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// SRV RDATA.
+
 struct SRVImpl;
 
 class SRV : public Rdata {
 public:
     // BEGIN_COMMON_MEMBERS
     // END_COMMON_MEMBERS
+
+    /// \brief Assignment operator.
+    ///
+    /// It internally allocates a resource, and if it fails a corresponding
+    /// standard exception will be thrown.
+    /// This operator never throws an exception otherwise.
+    ///
+    /// This operator provides the strong exception guarantee: When an
+    /// exception is thrown the content of the assignment target will be
+    /// intact.
     SRV& operator=(const SRV& source);
+
+    /// \brief The destructor.
     ~SRV();
 
     ///
     /// Specialized methods
     ///
+
+    /// \brief Return the value of the priority field.
+    ///
+    /// This method never throws an exception.
     uint16_t getPriority() const;
+
+    /// \brief Return the value of the weight field.
+    ///
+    /// This method never throws an exception.
     uint16_t getWeight() const;
+
+    /// \brief Return the value of the port field.
+    ///
+    /// This method never throws an exception.
     uint16_t getPort() const;
+
+    /// \brief Return the value of the target field.
+    ///
+    /// \return A reference to a \c Name class object corresponding to the
+    /// internal target name.
+    ///
+    /// This method never throws an exception.
     const Name& getTarget() const;
 
 private:

+ 21 - 19
src/lib/dns/tests/rdata_srv_unittest.cc

@@ -50,8 +50,8 @@ const uint8_t wiredata_srv2[] = {
     0x00, 0x01, 0x00, 0x05, 0x05, 0x78, 0x07, 0x65, 0x78, 0x61, 0x6d,
     0x70, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00};
 
-const generic::SRV rdata_srv(srv_txt);
-const generic::SRV rdata_srv2(srv_txt2);
+const in::SRV rdata_srv(srv_txt);
+const in::SRV rdata_srv2(srv_txt2);
 
 TEST_F(Rdata_SRV_Test, createFromText) {
     EXPECT_EQ(1, rdata_srv.getPriority());
@@ -62,30 +62,32 @@ TEST_F(Rdata_SRV_Test, createFromText) {
 
 TEST_F(Rdata_SRV_Test, badText) {
     // priority is too large (2814...6 is 2^48)
-    EXPECT_THROW(generic::SRV("281474976710656 5 1500 a.example.com."),
+    EXPECT_THROW(in::SRV("281474976710656 5 1500 a.example.com."),
                  InvalidRdataText);
     // weight is too large
-    EXPECT_THROW(generic::SRV("1 281474976710656 1500 a.example.com."),
+    EXPECT_THROW(in::SRV("1 281474976710656 1500 a.example.com."),
                  InvalidRdataText);
     // port is too large
-    EXPECT_THROW(generic::SRV("1 5 281474976710656 a.example.com."),
+    EXPECT_THROW(in::SRV("1 5 281474976710656 a.example.com."),
                  InvalidRdataText);
     // incomplete text
-    EXPECT_THROW(generic::SRV("1 5 a.example.com."),
+    EXPECT_THROW(in::SRV("1 5 a.example.com."),
+                 InvalidRdataText);
+    EXPECT_THROW(in::SRV("1 5 1500a.example.com."),
                  InvalidRdataText);
     // bad name
-    EXPECT_THROW(generic::SRV("1 5 1500 a.example.com." + too_long_label),
+    EXPECT_THROW(in::SRV("1 5 1500 a.example.com." + too_long_label),
                  TooLongLabel);
 }
 
 TEST_F(Rdata_SRV_Test, assignment) {
-    generic::SRV copy((string(srv_txt2)));
+    in::SRV copy((string(srv_txt2)));
     copy = rdata_srv;
     EXPECT_EQ(0, copy.compare(rdata_srv));
 
     // Check if the copied data is valid even after the original is deleted
-    generic::SRV* copy2 = new generic::SRV(rdata_srv);
-    generic::SRV copy3((string(srv_txt2)));
+    in::SRV* copy2 = new in::SRV(rdata_srv);
+    in::SRV copy3((string(srv_txt2)));
     copy3 = *copy2;
     delete copy2;
     EXPECT_EQ(0, copy3.compare(rdata_srv));
@@ -148,18 +150,18 @@ TEST_F(Rdata_SRV_Test, toText) {
 
 TEST_F(Rdata_SRV_Test, compare) {
     // test RDATAs, sorted in the ascendent order.
-    vector<generic::SRV> compare_set;
-    compare_set.push_back(generic::SRV("1 5 1500 a.example.com."));
-    compare_set.push_back(generic::SRV("2 5 1500 a.example.com."));
-    compare_set.push_back(generic::SRV("2 6 1500 a.example.com."));
-    compare_set.push_back(generic::SRV("2 6 1600 a.example.com."));
-    compare_set.push_back(generic::SRV("2 6 1600 example.com."));
+    vector<in::SRV> compare_set;
+    compare_set.push_back(in::SRV("1 5 1500 a.example.com."));
+    compare_set.push_back(in::SRV("2 5 1500 a.example.com."));
+    compare_set.push_back(in::SRV("2 6 1500 a.example.com."));
+    compare_set.push_back(in::SRV("2 6 1600 a.example.com."));
+    compare_set.push_back(in::SRV("2 6 1600 example.com."));
 
     EXPECT_EQ(0, compare_set[0].compare(
-                  generic::SRV("1 5 1500 a.example.com.")));
+                  in::SRV("1 5 1500 a.example.com.")));
 
-    vector<generic::SRV>::const_iterator it;
-    vector<generic::SRV>::const_iterator it_end = compare_set.end();
+    vector<in::SRV>::const_iterator it;
+    vector<in::SRV>::const_iterator it_end = compare_set.end();
     for (it = compare_set.begin(); it != it_end - 1; ++it) {
         EXPECT_GT(0, (*it).compare(*(it + 1)));
         EXPECT_LT(0, (*(it + 1)).compare(*it));