[svn] commit: r973 - in /trunk: ./ doc/ src/bin/parkinglot/ src/lib/dns/cpp/ src/lib/dns/cpp/rdata/ src/lib/dns/cpp/rdata/generic/ src/lib/dns/cpp/testdata/ src/lib/dns/cpp/tests/ src/lib/dns/cpp/tests/testdata/
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Feb 25 22:50:58 UTC 2010
Author: jinmei
Date: Thu Feb 25 22:50:58 2010
New Revision: 973
Log:
merged the jinmei-dnsrdata2 branch into trunk
Added:
trunk/src/bin/parkinglot/ (props changed)
- copied from r972, branches/jinmei-dnsrdata2/src/bin/parkinglot/
trunk/src/lib/dns/cpp/tests/ (props changed)
- copied from r972, branches/jinmei-dnsrdata2/src/lib/dns/cpp/tests/
trunk/src/lib/dns/cpp/tests/testdata/question_fromWire
- copied unchanged from r971, trunk/src/lib/dns/cpp/testdata/question_fromWire
trunk/src/lib/dns/cpp/tests/testdata/question_toWire1
- copied unchanged from r971, trunk/src/lib/dns/cpp/testdata/question_toWire1
trunk/src/lib/dns/cpp/tests/testdata/question_toWire2
- copied unchanged from r971, trunk/src/lib/dns/cpp/testdata/question_toWire2
Removed:
trunk/src/lib/dns/cpp/base64_unittest.cc
trunk/src/lib/dns/cpp/buffer_unittest.cc
trunk/src/lib/dns/cpp/message_unittest.cc
trunk/src/lib/dns/cpp/messagerenderer_unittest.cc
trunk/src/lib/dns/cpp/name_unittest.cc
trunk/src/lib/dns/cpp/question_unittest.cc
trunk/src/lib/dns/cpp/rdata_unittest.cc
trunk/src/lib/dns/cpp/rrclass_unittest.cc
trunk/src/lib/dns/cpp/rrparamregistry_unittest.cc
trunk/src/lib/dns/cpp/rrset_unittest.cc
trunk/src/lib/dns/cpp/rrttl_unittest.cc
trunk/src/lib/dns/cpp/rrtype_unittest.cc
trunk/src/lib/dns/cpp/run_unittests.cc
trunk/src/lib/dns/cpp/testdata/question_fromWire
trunk/src/lib/dns/cpp/testdata/question_toWire1
trunk/src/lib/dns/cpp/testdata/question_toWire2
trunk/src/lib/dns/cpp/unittest_util.cc
trunk/src/lib/dns/cpp/unittest_util.h
Modified:
trunk/ (props changed)
trunk/configure.ac
trunk/doc/Doxyfile
trunk/src/lib/dns/cpp/ (props changed)
trunk/src/lib/dns/cpp/Makefile.am
trunk/src/lib/dns/cpp/gen-rdatacode.py.in (contents, props changed)
trunk/src/lib/dns/cpp/rdata.cc
trunk/src/lib/dns/cpp/rdata.h
trunk/src/lib/dns/cpp/rdata/generic/rrsig_46.cc (props changed)
trunk/src/lib/dns/cpp/rdata/generic/txt_16.h
trunk/src/lib/dns/cpp/rdata/template.h
trunk/src/lib/dns/cpp/rrparamregistry-placeholder.cc (contents, props changed)
trunk/src/lib/dns/cpp/rrparamregistry.h
Modified: trunk/configure.ac
==============================================================================
--- trunk/configure.ac (original)
+++ trunk/configure.ac Thu Feb 25 22:50:58 2010
@@ -165,6 +165,7 @@
src/lib/config/python/isc/config/Makefile
src/lib/dns/Makefile
src/lib/dns/cpp/Makefile
+ src/lib/dns/cpp/tests/Makefile
src/lib/exceptions/cpp/Makefile
src/lib/exceptions/Makefile
src/lib/auth/Makefile
Modified: trunk/doc/Doxyfile
==============================================================================
--- trunk/doc/Doxyfile (original)
+++ trunk/doc/Doxyfile Thu Feb 25 22:50:58 2010
@@ -611,7 +611,7 @@
# against the file with absolute path, so to exclude all test directories
# for example use the pattern */test/*
-EXCLUDE_PATTERNS = *unittest*.h
+EXCLUDE_PATTERNS = */*-placeholder.* */cpp/*.py
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
Modified: trunk/src/lib/dns/cpp/Makefile.am
==============================================================================
--- trunk/src/lib/dns/cpp/Makefile.am (original)
+++ trunk/src/lib/dns/cpp/Makefile.am Thu Feb 25 22:50:58 2010
@@ -1,3 +1,5 @@
+SUBDIRS = . tests
+
AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/ext
CLEANFILES = *.gcno *.gcda
@@ -23,27 +25,3 @@
rrparamregistry.cc: rrparamregistry-placeholder.cc
rrclass.h rrtype.h rrparamregistry.cc rdataclass.h rdataclass.cc: Makefile
./gen-rdatacode.py
-
-TESTS =
-if HAVE_GTEST
-TESTS += run_unittests
-run_unittests_SOURCES = unittest_util.h unittest_util.cc
-run_unittests_SOURCES += buffer_unittest.cc name_unittest.cc
-run_unittests_SOURCES += messagerenderer_unittest.cc
-run_unittests_SOURCES += rrclass_unittest.cc rrtype_unittest.cc
-run_unittests_SOURCES += rrttl_unittest.cc
-run_unittests_SOURCES += rdata_unittest.cc
-run_unittests_SOURCES += rrset_unittest.cc
-run_unittests_SOURCES += rrsetlist_unittest.cc
-run_unittests_SOURCES += question_unittest.cc
-run_unittests_SOURCES += rrparamregistry_unittest.cc
-run_unittests_SOURCES += message_unittest.cc
-run_unittests_SOURCES += base64_unittest.cc
-run_unittests_SOURCES += run_unittests.cc
-run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
-run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
-run_unittests_LDADD = .libs/libdns.a $(GTEST_LDADD)
-run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/cpp/.libs/libexceptions.a
-endif
-
-noinst_PROGRAMS = $(TESTS)
Modified: trunk/src/lib/dns/cpp/gen-rdatacode.py.in
==============================================================================
--- trunk/src/lib/dns/cpp/gen-rdatacode.py.in (original)
+++ trunk/src/lib/dns/cpp/gen-rdatacode.py.in Thu Feb 25 22:50:58 2010
@@ -22,6 +22,7 @@
"""
import os
+from os.path import getmtime
import re
import sys
@@ -30,13 +31,16 @@
typecode2txt = {}
typeandclass = []
generic_code = 65536 # something larger than any code value
-class_declarations = ''
+rdata_declarations = ''
class_definitions = ''
+classdir_mtime = 0
+rdatadef_mtime = 0
+rdatahdr_mtime = 0
copyright_file = '@top_srcdir@' + os.sep + 'COPYING'
def import_classdef(class_txt, file):
+ content = ''
rdata_source = open(file, 'r')
- content = ''
for line in rdata_source.readlines():
if re.match('// BEGIN_ISC_NAMESPACE', line):
content += 'namespace isc {\n'
@@ -59,6 +63,9 @@
return content
def import_classheader(class_txt, type_txt, type_code, file):
+ type_utxt = type_txt.upper()
+ class_utxt = class_txt.upper()
+
# for each CLASS_n/TYPE_m.h
rdata_header = open(file, 'r')
content = ''
@@ -125,12 +132,19 @@
'''
return copyright_txt
-if __name__ == "__main__":
- copyright_txt = import_copyright()
+def import_definitions(classcode2txt, typecode2txt, typeandclass):
+ global rdata_declarations
+ global class_definitions
+ global classdir_mtime
+ global rdatadef_mtime
+ global rdatahdr_mtime
+
for dir in list(os.listdir('@srcdir@/rdata')):
classdir = '@srcdir@/rdata' + os.sep + dir
m = re_typecode.match(dir)
if os.path.isdir(classdir) and (m != None or dir == 'generic'):
+ if classdir_mtime < getmtime(classdir):
+ classdir_mtime = getmtime(classdir)
if dir == 'generic':
class_txt = 'generic'
class_code = generic_code
@@ -145,15 +159,16 @@
if m != None:
type_txt = m.group(1)
type_code = m.group(2)
- type_utxt = type_txt.upper()
- class_utxt = class_txt.upper()
-
if not type_code in typecode2txt:
typecode2txt[type_code] = type_txt
if re.search('\cc$', file):
+ if rdatadef_mtime < getmtime(file):
+ rdatadef_mtime = getmtime(file)
class_definitions += import_classdef(class_txt, file)
elif re.search('\h$', file):
- class_declarations += import_classheader(class_txt,
+ if rdatahdr_mtime < getmtime(file):
+ rdatahdr_mtime = getmtime(file)
+ rdata_declarations += import_classheader(class_txt,
type_txt,
type_code,
file)
@@ -163,78 +178,89 @@
if class_txt == 'generic':
typeandclass.append((type_txt, int(type_code),
(class_txt, 'in'), 1))
- rdata_deffile = open('@srcdir@/rdataclass.cc', 'w')
+
+def need_generate(file, mtime):
+ '''Check if we need to generate the specified file.
+
+ To avoid unnecessary compilation, we skip (re)generating the file when
+ the file already exists and newer than the base file.
+ '''
+ if os.path.exists(file) and getmtime(file) > mtime:
+ return False
+ return True
+
+def generate_rdatadef(file, copyright_txt, basemtime):
+ if not need_generate(file, basemtime):
+ print('skip generating ' + file);
+ return
+ rdata_deffile = open(file, 'w')
rdata_deffile.write(copyright_txt)
rdata_deffile.write(class_definitions)
rdata_deffile.close()
- class_declarations += '''
+def generate_rdatahdr(file, copyright_txt, declarations, basemtime):
+ if not need_generate(file, basemtime):
+ print('skip generating ' + file);
+ return
+ declarations += '''
// Local Variables:
// mode: c++
// End:
'''
- rdata_header = open('@srcdir@/rdataclass.h', 'w')
+ rdata_header = open(file, 'w')
rdata_header.write(copyright_txt)
- rdata_header.write(class_declarations)
+ rdata_header.write(declarations)
rdata_header.close()
-
+
+def generate_typeclasscode(fileprefix, basemtime, code2txt, type_or_class):
+ placeholder = fileprefix + '-placeholder.h'
+ outputfile = fileprefix + '.h'
+ upper_key = type_or_class.upper() # TYPE or CLASS
+ lower_key = 'rr' + type_or_class.lower() # rrtype or rrclass
+ cap_key = type_or_class # Type or Class
+
+ if not need_generate(outputfile, basemtime) and getmtime(outputfile) > getmtime(placeholder):
+ print('skip generating ' + outputfile)
+ return
+
declarationtxt = ''
deftxt = ''
- for code in typecode2txt.keys():
- # for rrtype.h
- rrtype = typecode2txt[code].upper()
- declarationtxt += ' ' * 4 + 'static const RRType& ' + rrtype + '();\n'
- deftxt += '''inline const RRType&
-RRType::''' + rrtype + '''()
+ for code in code2txt.keys():
+ codetxt = code2txt[code].upper()
+ declarationtxt += ' ' * 4 + 'static const RR' + cap_key + '& ' + codetxt + '();\n'
+ deftxt += '''inline const RR''' + cap_key + '''&
+RR''' + cap_key + '''::''' + codetxt + '''()
{
- static RRType rrtype(''' + code + ''');
- return (rrtype);
+ static RR''' + cap_key + ''' ''' + lower_key + '''(''' + code + ''');
+ return (''' + lower_key + ''');
}\n
'''
- rrtype_header_temp = open('@srcdir@/rrtype-placeholder.h', 'r')
- rrtype_header_out = open('@srcdir@/rrtype.h', 'w')
- rrtype_header_out.write(copyright_txt)
- for line in rrtype_header_temp.readlines():
- rrtype_header_out.write(line)
- if re.match('\s+// BEGIN_WELL_KNOWN_TYPE_DECLARATIONS$', line):
- rrtype_header_out.write(declarationtxt)
- if re.match('// BEGIN_WELL_KNOWN_TYPE_DEFINITIONS$', line):
- rrtype_header_out.write('\n' + deftxt)
- rrtype_header_out.close()
- rrtype_header_temp.close()
-
- declarationtxt = ''
- deftxt = ''
- for code in classcode2txt.keys():
- # for rrclass.h
- rrclass = classcode2txt[code].upper()
- declarationtxt += ' ' * 4 + 'static const RRClass& ' + rrclass + '();\n'
- deftxt += '''inline const RRClass&
-RRClass::''' + rrclass + '''()
-{
- static RRClass rrclass(''' + code + ''');
- return (rrclass);
-}\n
-'''
-
- rrclass_header_temp = open('@srcdir@/rrclass-placeholder.h', 'r')
- rrclass_header_out = open('@srcdir@/rrclass.h', 'w')
- rrclass_header_out.write(copyright_txt)
- for line in rrclass_header_temp.readlines():
- rrclass_header_out.write(line)
- if re.match('\s+// BEGIN_WELL_KNOWN_CLASS_DECLARATIONS$', line):
- rrclass_header_out.write(declarationtxt)
- if re.match('// BEGIN_WELL_KNOWN_CLASS_DEFINITIONS$', line):
- rrclass_header_out.write('\n' + deftxt)
- rrclass_header_out.close()
- rrclass_header_temp.close()
+ header_temp = open(placeholder, 'r')
+ header_out = open(outputfile, 'w')
+ header_out.write(copyright_txt)
+ for line in header_temp.readlines():
+ header_out.write(line)
+ if re.match('\s+// BEGIN_WELL_KNOWN_' + upper_key + '_DECLARATIONS$', line):
+ header_out.write(declarationtxt)
+ if re.match('// BEGIN_WELL_KNOWN_' + upper_key + '_DEFINITIONS$', line):
+ header_out.write('\n' + deftxt)
+ header_out.close()
+ header_temp.close()
+
+def generate_rrparam(fileprefix, basemtime):
+ placeholder = fileprefix + '-placeholder.cc'
+ outputfile = fileprefix + '.cc'
+ if not need_generate(outputfile, basemtime) and getmtime(outputfile) > getmtime(placeholder):
+ print('skip generating ' + outputfile)
+ return
# sort by class, then by type
typeandclassparams = ''
typeandclass.sort(key = lambda x: (x[3], x[1]))
for param in typeandclass:
- # for rdata.cc
- # each param is a tuple of (type_txt, type_code, class_tuple, class_code)
+ # for rrparamregistry.cc
+ # each param is a tuple of (type_txt, type_code, class_tuple,
+ # class_code)
(type_txt, type_code, class_tuple, class_code) = param
type_utxt = type_txt.upper()
class_txt = class_tuple[0]
@@ -252,8 +278,8 @@
typeandclassparams += ', RdataFactoryPtr(new RdataFactory<'
typeandclassparams += class_txt + '::' + type_utxt + '>()));\n'
- rrparam_temp = open('@srcdir@/rrparamregistry-placeholder.cc', 'r')
- rrparam_out = open('@srcdir@/rrparamregistry.cc', 'w')
+ rrparam_temp = open(placeholder, 'r')
+ rrparam_out = open(outputfile, 'w')
rrparam_out.write(copyright_txt)
for line in rrparam_temp.readlines():
rrparam_out.write(line)
@@ -261,3 +287,22 @@
rrparam_out.write(typeandclassparams)
rrparam_temp.close()
rrparam_out.close()
+
+if __name__ == "__main__":
+ try:
+ copyright_txt = import_copyright()
+ import_definitions(classcode2txt, typecode2txt, typeandclass)
+ generate_rdatadef('@srcdir@/rdataclass.cc', copyright_txt,
+ rdatadef_mtime)
+ generate_rdatahdr('@srcdir@/rdataclass.h', copyright_txt,
+ rdata_declarations, rdatahdr_mtime)
+ generate_typeclasscode('@srcdir@/rrtype',
+ max(rdatadef_mtime, rdatahdr_mtime),
+ typecode2txt, 'Type')
+ generate_typeclasscode('@srcdir@/rrclass', classdir_mtime,
+ classcode2txt, 'Class')
+ generate_rrparam('@srcdir@/rrparamregistry', rdatahdr_mtime)
+ except:
+ sys.stderr.write('Code generation failed due to exception: %s\n' %
+ sys.exc_info()[1])
+ exit(1)
Modified: trunk/src/lib/dns/cpp/rdata.cc
==============================================================================
--- trunk/src/lib/dns/cpp/rdata.cc (original)
+++ trunk/src/lib/dns/cpp/rdata.cc Thu Feb 25 22:50:58 2010
@@ -14,16 +14,20 @@
// $Id$
+#include <algorithm>
#include <cctype>
#include <string>
+#include <sstream>
+#include <iomanip>
+#include <ios>
+#include <ostream>
+#include <vector>
#include <stdint.h>
#include <string.h>
#include <boost/lexical_cast.hpp>
#include <boost/shared_ptr.hpp>
-
-#include <arpa/inet.h> // XXX: for inet_pton/ntop(), not exist in C++ standards
#include "buffer.h"
#include "name.h"
@@ -53,6 +57,10 @@
createRdata(const RRType& rrtype, const RRClass& rrclass,
InputBuffer& buffer, size_t len)
{
+ if (len > MAX_RDLENGTH) {
+ dns_throw(InvalidRdataLength, "RDLENGTH too large");
+ }
+
size_t old_pos = buffer.getPosition();
RdataPtr rdata =
@@ -78,14 +86,14 @@
{
size_t len1 = n1.getLength();
size_t len2 = n2.getLength();
- size_t cmplen = (len1 < len2) ? len1 : len2;
+ size_t cmplen = min(len1, len2);
for (size_t i = 0; i < cmplen; ++i) {
uint8_t c1 = tolower(n1.at(i));
uint8_t c2 = tolower(n2.at(i));
if (c1 < c2) {
return (-1);
- } else if (c2 > c1) {
+ } else if (c1 > c2) {
return (1);
}
}
@@ -94,62 +102,181 @@
}
namespace generic {
-Generic::Generic(InputBuffer& buffer, size_t rdata_len) :
- data_(rdata_len)
-{
- buffer.readData(&data_[0], rdata_len);
- data_.resize(rdata_len);
+struct GenericImpl {
+ GenericImpl(const vector<uint8_t>& data) : data_(data) {}
+ vector<uint8_t> data_;
+};
+
+Generic::Generic(InputBuffer& buffer, size_t rdata_len)
+{
+ if (rdata_len > MAX_RDLENGTH) {
+ dns_throw(InvalidRdataLength, "RDLENGTH too large");
+ }
+
+ vector<uint8_t> data(rdata_len);
+ buffer.readData(&data[0], rdata_len);
+ data.resize(rdata_len);
+
+ impl_ = new GenericImpl(data);
}
Generic::Generic(const string& rdata_string)
{
- // parse the \# n xx xx... format (TBD)
+ istringstream iss(rdata_string);
+ string unknown_mark;
+ iss >> unknown_mark;
+ if (unknown_mark != "\\#") {
+ dns_throw(InvalidRdataText,
+ "Missing the special token (\\#) for generic RDATA encoding");
+ }
+
+ // RDLENGTH: read into a string so that we can easily reject invalid tokens
+ string rdlen_txt;
+ iss >> rdlen_txt;
+ istringstream iss_rdlen(rdlen_txt);
+ int32_t rdlen;
+ iss_rdlen >> rdlen;
+ if (iss_rdlen.rdstate() != ios::eofbit) {
+ dns_throw(InvalidRdataText,
+ "Invalid representation for a generic RDLENGTH");
+ }
+ if (rdlen < 0 || rdlen > 0xffff) {
+ dns_throw(InvalidRdataLength, "RDATA length is out of range");
+ }
+ iss >> ws; // skip any white spaces
+
+ // Hexadecimal encoding of RDATA: each segment must consist of an even
+ // number of hex digits.
+ vector<uint8_t> data;
+ while (!iss.eof() && data.size() < rdlen) {
+ // extract two characters, which should compose a single byte of data.
+ char buf[2];
+ iss.read(buf, sizeof(buf));
+ if ((iss.rdstate() & (ios::badbit | ios::failbit)) != 0) {
+ dns_throw(InvalidRdataText,
+ "Invalid hex encoding of generic RDATA");
+ }
+
+ // convert it to a single byte integer as a hex digit.
+ istringstream iss_byte(string(buf, sizeof(buf)));
+ unsigned int ch;
+ iss_byte >> hex >> ch;
+ if (iss_byte.rdstate() != ios::eofbit) {
+ dns_throw(InvalidRdataText,
+ "Invalid hex encoding of generic RDATA");
+ }
+ data.push_back(ch);
+ iss >> ws; // skip spaces
+ }
+
+ if (!iss.eof()) {
+ dns_throw(InvalidRdataLength,
+ "RDLENGTH is too small for generic RDATA");
+ }
+
+ if (data.size() != rdlen) {
+ dns_throw(InvalidRdataLength,
+ "Generic RDATA code doesn't match RDLENGTH");
+ }
+
+ impl_ = new GenericImpl(data);
+}
+
+Generic::~Generic()
+{
+ delete impl_;
+}
+
+Generic::Generic(const Generic& source) :
+ impl_(new GenericImpl(*source.impl_))
+{}
+
+Generic&
+Generic::operator=(const Generic& source)
+{
+ if (impl_ == source.impl_) {
+ return (*this);
+ }
+
+ GenericImpl* newimpl = new GenericImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+namespace {
+class UnknownRdataDumper {
+public:
+ UnknownRdataDumper(ostringstream& oss) : oss_(&oss) {}
+ void operator()(const unsigned char d)
+ {
+ *oss_ << setw(2) << static_cast<unsigned int>(d);
+ }
+private:
+ ostringstream* oss_;
+};
}
string
Generic::toText() const
{
- // return rdata in the \# n xx xx format (TBD)
- dns_throw(InvalidRdataText, "Not implemented yet");
+ ostringstream oss;
+
+ oss << "\\# " << impl_->data_.size() << " ";
+ oss.fill('0');
+ oss << right << hex;
+ for_each(impl_->data_.begin(), impl_->data_.end(), UnknownRdataDumper(oss));
+
+ return (oss.str());
}
void
Generic::toWire(OutputBuffer& buffer) const
{
- buffer.writeData(&data_[0], data_.size());
+ buffer.writeData(&impl_->data_[0], impl_->data_.size());
}
void
Generic::toWire(MessageRenderer& renderer) const
{
- renderer.writeData(&data_[0], data_.size());
-}
-
-int
-Generic::compare(const Rdata& other) const
-{
- const Generic& other_rdata = dynamic_cast<const Generic&>(other);
-
- size_t this_len = data_.size();
- size_t other_len = other_rdata.data_.size();
+ renderer.writeData(&impl_->data_[0], impl_->data_.size());
+}
+
+namespace {
+inline int
+compare_internal(const GenericImpl& lhs, const GenericImpl& rhs)
+{
+ size_t this_len = lhs.data_.size();
+ size_t other_len = rhs.data_.size();
size_t len = (this_len < other_len) ? this_len : other_len;
int cmp;
- if ((cmp = memcmp(&data_[0], &other_rdata.data_[0], len)) != 0) {
+ if ((cmp = memcmp(&lhs.data_[0], &rhs.data_[0], len))
+ != 0) {
return (cmp);
} else {
return ((this_len == other_len) ? 0 :
(this_len < other_len) ? -1 : 1);
}
}
-
+}
+
+int
+Generic::compare(const Rdata& other) const
+{
+ const Generic& other_rdata = dynamic_cast<const Generic&>(other);
+
+ return (compare_internal(*impl_, *other_rdata.impl_));
+}
+
+std::ostream&
+operator<<(std::ostream& os, const Generic& rdata)
+{
+ return (os << rdata.toText());
+}
} // end of namespace generic
-namespace in {
-} // end of namespace in
-
-namespace ch {
-} // end of namespace ch
} // end of namespace rdata
}
}
Modified: trunk/src/lib/dns/cpp/rdata.h
==============================================================================
--- trunk/src/lib/dns/cpp/rdata.h (original)
+++ trunk/src/lib/dns/cpp/rdata.h Thu Feb 25 22:50:58 2010
@@ -21,8 +21,6 @@
#include <boost/shared_ptr.hpp>
-#include "name.h"
-
namespace isc {
namespace dns {
class InputBuffer;
@@ -55,7 +53,9 @@
};
///
-/// \brief A standard DNS module exception that is thrown if ...TBD
+/// \brief A standard DNS module exception that is thrown if RDATA parser
+/// parser encounters a character-string (as defined in RFC1035) exceeding
+/// the maximum allowable length (\c MAX_CHARSTRING_LEN).
///
class CharStringTooLong : public Exception {
public:
@@ -63,89 +63,403 @@
isc::Exception(file, line, what) {}
};
+// Forward declaration to define RdataPtr.
class Rdata;
+
+///
+/// The \c RdataPtr type is a pointer-like type, pointing to an
+/// object of some concrete derived class of \c Rdata.
+///
typedef boost::shared_ptr<Rdata> RdataPtr;
typedef boost::shared_ptr<const Rdata> ConstRdataPtr;
-/// Abstract RDATA class
+/// \brief Possible maximum length of RDATA, which is the maximum unsigned
+/// 16 bit value.
+const size_t MAX_RDLENGTH = 65535;
+
+/// \brief The maximum allowable length of character-string containing in
+/// RDATA as defined in RFC1035, not including the 1-byte length field.
+const unsigned int MAX_CHARSTRING_LEN = 255;
+
+/// \brief The \c Rdata class is an abstract base class that provides
+/// a set of common interfaces to manipulate concrete RDATA objects.
+///
+/// Generally, a separate derived class directly inherited from the base
+/// \c Rdata class is defined for each well known RDATA.
+/// Each of such classes will define the common logic based on the
+/// corresponding protocol standard.
+///
+/// Since some types of RRs are class specific and the corresponding RDATA
+/// may have different semantics (e.g. type A for class IN and type A for
+/// class CH have different representations and semantics), we separate
+/// \c Rdata derived classes for such RR types in different namespaces.
+/// The namespace of types specific to a class is named the lower-cased class
+/// name; for example, RDATA of class IN-specific types are defined in the
+/// \c in namespace, and RDATA of class CH-specific types are defined in
+/// the \c ch namespace, and so on.
+/// The derived classes are named using the RR type name (upper cased) such as
+/// \c A or \c AAAA.
+/// Thus RDATA of type A RR for class IN and CH are defined as \c in::A and
+/// \c ch::A, respectively.
+/// Many other RR types are class independent; the derived \c Rdata classes
+/// for such RR types are defined in the \c generic namespace. Examples are
+/// \c generic::NS and \c generic::SOA.
+///
+/// If applications need to refer to these derived classes, it is generally
+/// recommended to prepend at least some part of the namespace because the
+/// same class name can be used in different namespaces.
+/// So, instead of doing
+/// \code using namespace isc::dns::rdata::in;
+/// A& rdata_type_a; \endcode
+/// it is advisable to prepend at least \c in from the namespace:
+/// \code using namespace isc::dns::rdata;
+/// in::A& rdata_type_a; \endcode
+///
+/// In many cases, however, an application doesn't have to care about such
+/// derived classes.
+/// For instance, to parse an incoming DNS message an application wouldn't
+/// have to perform type specific operation unless the application is
+/// specifically concerned about a particular type.
+/// So, this API generally handles \c Rdata in a polymorphic way through
+/// a pointer or reference to this base abstract class.
class Rdata {
+ ///
+ /// \name Constructors and Destructor
+ ///
+ /// Note: The copy constructor and the assignment operator are intentionally
+ /// defined as private. Concrete classes should generally specialize their
+ /// own versions of these methods.
+ //@{
protected:
+ /// The default constructor.
+ ///
+ /// This is intentionally defined as \c protected as this base class should
+ /// never be instantiated (except as part of a derived class). In many
+ /// cases, the derived class wouldn't define a public default constructor
+ /// either, because an \c Rdata object without concrete data isn't
+ /// meaningful.
Rdata() {}
private:
- /// Copy constructor is intentionally private. Concrete classes should
- /// generally specialize their own versions of copy constructor.
Rdata(const Rdata& source);
void operator=(const Rdata& source);
public:
+ /// The destructor.
virtual ~Rdata() {};
-
- ///
- /// \name Getter Methods
- //
- // need generic method for getting n-th field? c.f. ldns
- // e.g. string getField(int n);
+ //@}
+
+ ///
+ /// \name Converter methods
///
//@{
- // It's not yet clear if we really need to contain the RR type (and/or
- // RR class) in RDATA.
- //virtual const RRType& getType() const = 0;
- //@}
-
- ///
- /// \name Converter methods
- ///
- //@{
+ /// \brief Convert an \c Rdata to a string.
+ ///
+ /// This method returns a \c std::string object representing the \c Rdata.
+ ///
+ /// This is a pure virtual method without the definition; the actual
+ /// representation is specific to each derived concrete class and
+ /// should be explicitly defined in the derived class.
+ ///
+ /// \return A string representation of \c Rdata.
virtual std::string toText() const = 0;
+ /// \brief Render the \c Rdata in the wire format into a buffer.
+ ///
+ /// This is a pure virtual method without the definition; the actual
+ /// conversion is specific to each derived concrete class and
+ /// should be explicitly defined in the derived class.
+ ///
+ /// \param buffer An output buffer to store the wire data.
virtual void toWire(OutputBuffer& buffer) const = 0;
+ /// \brief Render the \c Rdata in the wire format into a
+ /// \c MessageRenderer object.
+ ///
+ /// This is a pure virtual method without the definition; the actual
+ /// conversion is specific to each derived concrete class and
+ /// should be explicitly defined in the derived class.
+ ///
+ /// \param renderer DNS message rendering context that encapsulates the
+ /// output buffer in which the \c Rdata is to be stored.
virtual void toWire(MessageRenderer& renderer) const = 0;
//@}
- /// Note about implementation choice: the current implementation relies on
- /// dynamic_cast to ensure that the \c other is the same concrete Rdata
- /// class as \c this object. Alternatively, we could first convert the
- /// data into wire-format and compare the pair as opaque data. This would
- /// be more polymorphic, but might involve significant overhead, especially
- /// for a large size of RDATA.
+ ///
+ /// \name Comparison method
+ ///
+ //@{
+ /// \brief Compare two instances of \c Rdata.
+ ///
+ /// This method compares \c this and the \c other Rdata objects
+ /// in terms of the DNSSEC sorting order as defined in RFC4034, and returns
+ /// the result as an integer.
+ ///
+ /// This is a pure virtual method without the definition; the actual
+ /// comparison logic is specific to each derived concrete class and
+ /// should be explicitly defined in the derived class.
+ ///
+ /// Specific implementations of this method must confirm that \c this
+ /// and the \c other are objects of the same concrete derived class of
+ /// \c Rdata. This is normally done by \c dynamic_cast in the
+ /// implementation. It also means if the assumption isn't met
+ /// an exception of class \c std::bad_cast will be thrown.
+ ///
+ /// Here is an implementation choice: instead of relying on
+ /// \c dynamic_cast, we could first convert the data into wire-format
+ /// and compare the pair as opaque data. This would be more polymorphic,
+ /// but might involve significant overhead, especially for a large size
+ /// of RDATA.
+ ///
+ /// \param other the right-hand operand to compare against.
+ /// \return < 0 if \c this would be sorted before \c other.
+ /// \return 0 if \c this is identical to \c other in terms of sorting order.
+ /// \return > 0 if \c this would be sorted after \c other.
virtual int compare(const Rdata& other) const = 0;
-
- // not yet:
- // methods specific derived classes: throw an exception by default
- //virtual Address& getAddress() = 0;
- //virtual Name& getName() = 0;
-
- // polymorphic copy constructor (XXX should revisit it)
- //virtual Rdata* copy() const = 0;
+ //@}
};
namespace generic {
+
+/// \brief The \c GenericImpl class is the actual implementation of the
+/// \c generic::Generic class.
+///
+/// The implementation is hidden from applications. This approach requires
+/// dynamic memory allocation on construction, copy, or assignment, but
+/// we believe it should be acceptable as "unknown" RDATA should be pretty
+/// rare.
+struct GenericImpl;
+
+/// \brief The \c generic::Generic class represents generic "unknown" RDATA.
+///
+/// This class is used as a placeholder for all non well-known type of RDATA.
+/// By definition, the stored data is regarded as opaque binary without
+/// assuming any structure.
class Generic : public Rdata {
public:
+ ///
+ /// \name Constructors, Assignment Operator and Destructor.
+ ///
+ //@{
+ /// \brief Constructor from a string.
+ ///
+ /// This method constructs a \c generic::Generic object from a textual
+ /// representation as defined in RFC3597.
+ ///
+ /// If \c rdata_string isn't a valid textual representation of this type
+ /// of RDATA, an exception of class \c InvalidRdataText or
+ /// \c InvalidRdataLength will be thrown.
+ /// If resource allocation to store the data fails, a corresponding standard
+ /// exception will be thrown.
+ ///
+ /// \param rdata_string A string of textual representation of generic
+ /// RDATA.
explicit Generic(const std::string& rdata_string);
- explicit Generic(InputBuffer& buffer, size_t rdata_len);
+ ///
+ /// \brief Constructor from wire-format data.
+ ///
+ /// The \c buffer parameter normally stores a complete DNS message
+ /// containing the generic RDATA to be constructed.
+ /// The current read position of the buffer points to the head of the
+ /// data.
+ ///
+ /// This method reads \c rdata_len bytes from the \c buffer, and internally
+ /// stores the data as an opaque byte sequence.
+ ///
+ /// \c rdata_len must not exceed \c MAX_RDLENGTH; otherwise, an exception
+ /// of class \c InvalidRdataLength will be thrown.
+ /// If resource allocation to hold the data fails, a corresponding standard
+ /// exception will be thrown; if the \c buffer doesn't contain \c rdata_len
+ /// bytes of unread data, an exception of class \c InvalidBufferPosition
+ /// will be thrown.
+ ///
+ /// \param buffer A reference to an \c InputBuffer object storing the
+ /// \c Rdata to parse.
+ /// \param rdata_len The length in buffer of the \c Rdata. In bytes.
+ Generic(InputBuffer& buffer, size_t rdata_len);
+ ///
+ /// \brief The destructor.
+ virtual ~Generic();
+ ///
+ /// \brief The copy constructor.
+ ///
+ /// If resource allocation to copy the data fails, a corresponding standard
+ /// exception will be thrown.
+ ///
+ /// \param source A reference to a \c generic::Generic object to copy from.
+ Generic(const Generic& source);
+ ///
+ /// \brief The assignment operator.
+ ///
+ /// If resource allocation to copy the data fails, a corresponding standard
+ /// exception will be thrown.
+ ///
+ /// \param source A reference to a \c generic::Generic object to copy from.
+ Generic& operator=(const Generic& source);
+ //@}
+ ///
+ /// \name Converter methods
+ ///
+ //@{
+ /// \brief Convert an \c generic::Generic object to a string.
+ ///
+ /// This method converts a generic "unknown" RDATA object into a textual
+ /// representation of such unknown data as defined in RFC3597.
+ ///
+ /// If resource allocation to copy the data fails, a corresponding standard
+ /// exception will be thrown.
+ ///
+ /// \return A string representation of \c generic::Generic.
virtual std::string toText() const;
+ ///
+ /// \brief Render the \c generic::Generic in the wire format into a buffer.
+ ///
+ /// This will require \c rdata_len bytes of remaining capacity in the
+ /// \c buffer. If this is not the case and resource allocation for the
+ /// necessary memory space fails, a corresponding standard exception will
+ /// be thrown.
+ ///
+ /// \param buffer An output buffer to store the wire data.
virtual void toWire(OutputBuffer& buffer) const;
+ /// \brief Render the \c generic::Generic in the wire format into a
+ /// \c MessageRenderer object.
+ ///
+ /// This will require \c rdata_len bytes of remaining capacity in the
+ /// \c buffer. If this is not the case and resource allocation for the
+ /// necessary memory space fails, a corresponding standard exception will
+ /// be thrown.
+ ///
+ /// \param renderer DNS message rendering context that encapsulates the
+ /// output buffer in which the \c Generic object is to be stored.
virtual void toWire(MessageRenderer& renderer) const;
- ///
- /// Note: the comparison is RR type/class agnostic: this method doesn't
- /// check whether the two Rdata objects to compare are of the comparable
- /// RR type/class. The caller must ensure this condition.
- ///
+ //@}
+ ///
+ /// \name Comparison method
+ ///
+ //@{
+ /// \brief Compare two instances of \c generic::Generic objects.
+ ///
+ /// As defined in RFC4034, this method simply compares the wire-format
+ /// representations of the two objects as left-justified unsigned octet
+ /// sequences.
+ ///
+ /// The object referenced by \c other must have been instantiated as
+ /// a c generic::Generic class object; otherwise, an exception of class
+ /// \c std::bad_cast will be thrown.
+ /// Note that the comparison is RR type/class agnostic: this method doesn't
+ /// check whether the two \c Rdata objects to compare are of the comparable
+ /// RR type/class. For example, \c this object may come from an \c RRset
+ /// of \c RRType x, and the \c other may come from a different \c RRset
+ /// of \c RRType y (where x != y). This situation would be considered a
+ /// bug, but this method cannot detect this type of error.
+ /// The caller must ensure this condition.
+ ///
+ /// \param other the right-hand operand to compare against.
+ /// \return < 0 if \c this would be sorted before \c other.
+ /// \return 0 if \c this is identical to \c other in terms of sorting order.
+ /// \return > 0 if \c this would be sorted after \c other.
virtual int compare(const Rdata& other) const;
+ //@}
private:
- std::vector<uint8_t> data_;
+ GenericImpl* impl_;
};
+
+///
+/// \brief Insert the name as a string into stream.
+///
+/// This method convert the \c rdata into a string and inserts it into the
+/// output stream \c os.
+///
+/// This function overloads the global \c operator<< to behave as described in
+/// \c ostream::operator<< but applied to \c generic::Generic Rdata objects.
+///
+/// \param os A \c std::ostream object on which the insertion operation is
+/// performed.
+/// \param rdata The \c Generic object output by the operation.
+/// \return A reference to the same \c std::ostream object referenced by
+/// parameter \c os after the insertion operation.
+std::ostream& operator<<(std::ostream& os, const Generic& rdata);
} // end of namespace "generic"
-///
-/// Non class-member functions related to Rdata
-///
-/// TBD: document them
+//
+// Non class-member functions related to Rdata
+//
+
+///
+/// \name Parameterized Polymorphic RDATA Factories
+///
+/// This set of global functions provide a unified interface to create an
+/// \c Rdata object in a parameterized polymorphic way,
+/// that is, these functions take a pair of \c RRType and \c RRClass
+/// objects and data specific to that pair, and create an object of
+/// the corresponding concrete derived class of \c Rdata.
+///
+/// These will be useful when parsing/constructing a DNS message or
+/// parsing a master file, where information for a specific type of RDATA
+/// is given but the resulting object, once created, should better be used
+/// in a polymorphic way.
+///
+/// For example, if a master file parser encounters an NS RR
+/// \verbatim example.com. 3600 IN NS ns.example.com.\endverbatim
+/// it stores the text fragments "IN", "NS", and "ns.example.com." in
+/// \c std::string objects \c class_txt, \c type_txt, and \c nsname_txt,
+/// respectively, then it would create a new \c RdataPtr object as follows:
+/// \code RdataPtr rdata = createRdata(RRType(type_txt), RRClass(class_txt),
+/// nsname_txt); \endcode
+/// On success, \c rdata will point to an object of the \c generic::NS class
+/// that internally holds a domain name of "ns.example.com."
+///
+/// Internally, these functions uses the corresponding
+/// \c RRParamRegistry::createRdata methods of the \c RRParamRegistry.
+/// See also the description on these methods for related notes.
+//@{
+/// \brief Create RDATA of a given pair of RR type and class from a string.
+///
+/// This method creates from a string an \c Rdata object of the given pair
+/// of RR type and class.
+///
+/// \param rrtype An \c RRType object specifying the type/class pair.
+/// \param rrclass An \c RRClass object specifying the type/class pair.
+/// \param rdata_string A string of textual representation of the \c Rdata.
+/// \return An \c RdataPtr object pointing to the created \c Rdata
+/// object.
RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
const std::string& rdata_string);
+/// \brief Create RDATA of a given pair of RR type and class from
+/// wire-format data.
+///
+/// This method creates from wire-format binary data an \c Rdata object
+/// of the given pair of RR type and class.
+///
+/// \c len must not exceed the protocol defined maximum value, \c MAX_RDLENGTH;
+/// otherwise, an exception of class \c InvalidRdataLength will be thrown.
+///
+/// In some cases, the length of the RDATA is determined without the
+/// information of \c len. For example, the RDATA length of an IN/A RR
+/// must always be 4. If \c len is not equal to the actual length in such
+/// cases, an exception of class InvalidRdataLength will be thrown.
+///
+/// \param rrtype An \c RRType object specifying the type/class pair.
+/// \param rrclass An \c RRClass object specifying the type/class pair.
+/// \param buffer A reference to an \c InputBuffer object storing the
+/// \c Rdata to parse.
+/// \param len The length in buffer of the \c Rdata. In bytes.
+/// \return An \c RdataPtr object pointing to the created \c Rdata
+/// object.
RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
InputBuffer& buffer, size_t len);
+/// \brief Create RDATA of a given pair of RR type and class, copying
+/// of another RDATA of same kind.
+///
+/// This method creates an \c Rdata object of the given pair of
+/// RR type and class, copying the content of the given \c Rdata,
+/// \c source.
+///
+/// \param rrtype An \c RRType object specifying the type/class pair.
+/// \param rrclass An \c RRClass object specifying the type/class pair.
+/// \param source A reference to an \c Rdata object whose content
+/// is to be copied to the created \c Rdata object.
+/// \return An \c RdataPtr object pointing to the created
+/// \c Rdata object.
RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
const Rdata& source);
+//@}
///
/// \brief Gives relative ordering of two names in terms of DNSSEC RDATA
@@ -165,6 +479,9 @@
/// This function is publicly open, however, for the convenience of
/// external developers who want to implement new or experimental RR types.
///
+/// This function never throws an exception as long as the given names are
+/// valid \c Name objects.
+///
/// Additional note about applicability: In fact, BIND9's similar function,
/// \c dns_name_rdatacompare(), is only used in rdata implementations and
/// for testing purposes.
@@ -174,8 +491,7 @@
/// \return 0 if \c n1 is identical to \c n2 in terms of sorting order.
/// \return 1 if \c n1 would be sorted after \c n2.
///
-int
-compareNames(const Name& n1, const Name& n2);
+int compareNames(const Name& n1, const Name& n2);
} // end of namespace "rdata"
}
Modified: trunk/src/lib/dns/cpp/rdata/generic/txt_16.h
==============================================================================
--- trunk/src/lib/dns/cpp/rdata/generic/txt_16.h (original)
+++ trunk/src/lib/dns/cpp/rdata/generic/txt_16.h Thu Feb 25 22:50:58 2010
@@ -37,7 +37,6 @@
private:
/// Note: this is a prototype version; we may reconsider
/// this representation later.
- static const unsigned int MAX_CHARSTRING_LEN = 255;
std::vector<std::vector<uint8_t> > string_list_;
};
Modified: trunk/src/lib/dns/cpp/rdata/template.h
==============================================================================
--- trunk/src/lib/dns/cpp/rdata/template.h (original)
+++ trunk/src/lib/dns/cpp/rdata/template.h Thu Feb 25 22:50:58 2010
@@ -37,10 +37,15 @@
// "RR-type specific members" space (please make them private). In addition,
// you may want to define some specific member functions, either public or
// private (or, though unlikely for a leaf class, protected).
+//
+// Note: do not remove the comment lines beginning with "BEGIN_" and "END_".
+// These are markers used by a script for auto-generating build-able source
+// files.
class MyType : public Rdata {
public:
// BEGIN_COMMON_MEMBERS
+ // Do not remove the BEGIN_xxx and END_xxx comment lines.
// END_COMMON_MEMBERS
private:
// RR-type specific members are here.
Modified: trunk/src/lib/dns/cpp/rrparamregistry-placeholder.cc
==============================================================================
--- trunk/src/lib/dns/cpp/rrparamregistry-placeholder.cc (original)
+++ trunk/src/lib/dns/cpp/rrparamregistry-placeholder.cc Thu Feb 25 22:50:58 2010
@@ -12,7 +12,7 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
-// $Id: rrparamregistry.cc 530 2010-01-26 22:15:42Z jinmei $
+// $Id$
#include <cassert>
#include <algorithm>
@@ -72,22 +72,43 @@
/// magic constants
static const unsigned int MAX_CODE = 0xffff;
- static const string UNKNOWN_PREFIX;
- static const size_t UNKNOWN_PREFIXLEN;
- static const string UNKNOWN_MAX;
- static const size_t UNKNOWN_MAXLEN;
+ static const string& UNKNOWN_PREFIX();
+ static size_t UNKNOWN_PREFIXLEN();
+ static const string& UNKNOWN_MAX();
+ static size_t UNKNOWN_MAXLEN();
};
typedef shared_ptr<RRTypeParam> RRTypeParamPtr;
typedef map<string, RRTypeParamPtr, CIStringLess> StrRRTypeMap;
typedef map<uint16_t, RRTypeParamPtr> CodeRRTypeMap;
-const string RRTypeParam::UNKNOWN_PREFIX = "TYPE";
-const size_t RRTypeParam::UNKNOWN_PREFIXLEN =
- RRTypeParam::UNKNOWN_PREFIX.size();
-const string RRTypeParam::UNKNOWN_MAX = "TYPE65535";
-const size_t RRTypeParam::UNKNOWN_MAXLEN =
- RRTypeParam::UNKNOWN_MAX.size();
+inline const string&
+RRTypeParam::UNKNOWN_PREFIX()
+{
+ static const string p("TYPE");
+ return (p);
+}
+
+inline size_t
+RRTypeParam::UNKNOWN_PREFIXLEN()
+{
+ static size_t plen = UNKNOWN_PREFIX().size();
+ return (plen);
+}
+
+inline const string&
+RRTypeParam::UNKNOWN_MAX()
+{
+ static const string p("TYPE65535");
+ return (p);
+}
+
+inline size_t
+RRTypeParam::UNKNOWN_MAXLEN()
+{
+ static size_t plen = UNKNOWN_MAX().size();
+ return (plen);
+}
struct RRClassParam {
RRClassParam(const string& code_string, uint16_t code) :
@@ -97,23 +118,44 @@
/// magic constants
static const unsigned int MAX_CODE = 0xffff;
- static const string UNKNOWN_PREFIX;
- static const size_t UNKNOWN_PREFIXLEN;
- static const string UNKNOWN_MAX;
- static const size_t UNKNOWN_MAXLEN;
+ static const string& UNKNOWN_PREFIX();
+ static size_t UNKNOWN_PREFIXLEN();
+ static const string& UNKNOWN_MAX();
+ static size_t UNKNOWN_MAXLEN();
};
typedef shared_ptr<RRClassParam> RRClassParamPtr;
typedef map<string, RRClassParamPtr, CIStringLess> StrRRClassMap;
typedef map<uint16_t, RRClassParamPtr> CodeRRClassMap;
-const string RRClassParam::UNKNOWN_PREFIX = "CLASS";
-const size_t RRClassParam::UNKNOWN_PREFIXLEN =
- RRClassParam::UNKNOWN_PREFIX.size();
-const string RRClassParam::UNKNOWN_MAX = "CLASS65535";
-const size_t RRClassParam::UNKNOWN_MAXLEN =
- RRClassParam::UNKNOWN_MAX.size();
-}
+inline const string&
+RRClassParam::UNKNOWN_PREFIX()
+{
+ static const string p("CLASS");
+ return (p);
+}
+
+inline size_t
+RRClassParam::UNKNOWN_PREFIXLEN()
+{
+ static size_t plen = UNKNOWN_PREFIX().size();
+ return (plen);
+}
+
+inline const string&
+RRClassParam::UNKNOWN_MAX()
+{
+ static const string p("CLASS65535");
+ return (p);
+}
+
+inline size_t
+RRClassParam::UNKNOWN_MAXLEN()
+{
+ static size_t plen = UNKNOWN_MAX().size();
+ return (plen);
+}
+} // end of anonymous namespace
/// Note: the element ordering in the type/class pair is intentional.
/// The standard library will perform inequality comparison (i.e, '<')
@@ -132,17 +174,17 @@
public:
virtual RdataPtr create(const string& rdata_str) const
{
- return (shared_ptr<T>(new T(rdata_str)));
+ return (RdataPtr(new T(rdata_str)));
}
virtual RdataPtr create(InputBuffer& buffer, size_t rdata_len) const
{
- return (shared_ptr<T>(new T(buffer, rdata_len)));
+ return (RdataPtr(new T(buffer, rdata_len)));
}
virtual RdataPtr create(const Rdata& source) const
{
- return (shared_ptr<T>(new T(dynamic_cast<const T&>(source))));
+ return (RdataPtr(new T(dynamic_cast<const T&>(source))));
}
};
@@ -171,7 +213,6 @@
impl_ = new RRParamRegistryImpl;
// set up parameters for well-known RRs
- // XXX: this should eventually be more automatic.
try {
// BEGIN_WELL_KNOWN_PARAMS
// END_WELL_KNOWN_PARAMS
@@ -244,6 +285,33 @@
}
}
+bool
+RRParamRegistry::removeRdataFactory(const RRType& rrtype,
+ const RRClass& rrclass)
+{
+ RdataFactoryMap::iterator found =
+ impl_->rdata_factories.find(RRTypeClass(rrtype, rrclass));
+ if (found != impl_->rdata_factories.end()) {
+ impl_->rdata_factories.erase(found);
+ return (true);
+ }
+
+ return (false);
+}
+
+bool
+RRParamRegistry::removeRdataFactory(const RRType& rrtype)
+{
+ GenericRdataFactoryMap::iterator found =
+ impl_->genericrdata_factories.find(rrtype);
+ if (found != impl_->genericrdata_factories.end()) {
+ impl_->genericrdata_factories.erase(found);
+ return (true);
+ }
+
+ return (false);
+}
+
namespace {
///
/// These are helper functions to implement case-insensitive string comparison.
@@ -338,12 +406,13 @@
}
size_t l = code_str.size();
- if (l > PT::UNKNOWN_PREFIXLEN &&
- l <= PT::UNKNOWN_MAXLEN &&
- caseStringEqual(code_str, PT::UNKNOWN_PREFIX, PT::UNKNOWN_PREFIXLEN)) {
+ if (l > PT::UNKNOWN_PREFIXLEN() &&
+ l <= PT::UNKNOWN_MAXLEN() &&
+ caseStringEqual(code_str, PT::UNKNOWN_PREFIX(),
+ PT::UNKNOWN_PREFIXLEN())) {
unsigned int code;
- istringstream iss(code_str.substr(PT::UNKNOWN_PREFIXLEN,
- l - PT::UNKNOWN_PREFIXLEN));
+ istringstream iss(code_str.substr(PT::UNKNOWN_PREFIXLEN(),
+ l - PT::UNKNOWN_PREFIXLEN()));
iss >> dec >> code;
if (iss.rdstate() == ios::eofbit && code <= PT::MAX_CODE) {
return (code);
@@ -365,7 +434,7 @@
ostringstream ss;
ss << code;
- return (PT::UNKNOWN_PREFIX + ss.str());
+ return (PT::UNKNOWN_PREFIX() + ss.str());
}
}
@@ -444,7 +513,7 @@
return (genfound->second->create(rdata_string));
}
- dns_throw(InvalidRdataText, "Unrecognized Rdata type to create from text");
+ return (RdataPtr(new generic::Generic(rdata_string)));
}
RdataPtr
@@ -463,7 +532,6 @@
return (genfound->second->create(buffer, rdata_len));
}
- // construct an "unknown" type of RDATA
return (RdataPtr(new generic::Generic(buffer, rdata_len)));
}
@@ -483,7 +551,8 @@
return (genfound->second->create(source));
}
- dns_throw(InvalidRdataText, "TBD");
-}
-}
-}
+ return (RdataPtr(new rdata::generic::Generic(
+ dynamic_cast<const generic::Generic&>(source))));
+}
+}
+}
Modified: trunk/src/lib/dns/cpp/rrparamregistry.h
==============================================================================
--- trunk/src/lib/dns/cpp/rrparamregistry.h (original)
+++ trunk/src/lib/dns/cpp/rrparamregistry.h Thu Feb 25 22:50:58 2010
@@ -52,26 +52,79 @@
isc::Exception(file, line, what) {}
};
-class InvalidRdataText : public Exception {
-public:
- InvalidRdataText(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
-};
-
namespace rdata {
+/// \brief The \c AbstractRdataFactory class is an abstract base class to
+/// encapsulate a set of Rdata factory methods in a polymorphic way.
+///
+/// An external developers who want to introduce a new or experimental RR type
+/// are expected to define a corresponding derived class of \c
+/// AbstractRdataFactory and register it via \c RRParamRegistry.
+///
+/// For other users of this API normally do not have to care about this class
+/// or its derived classes; this class is generally intended to be used
+/// as an internal utility of the API implementation.
class AbstractRdataFactory {
+ ///
+ /// \name Constructors and Destructor
+ ///
+ //@{
protected:
+ /// The default constructor
+ ///
+ /// This is intentionally defined as \c protected as this base class should
+ /// never be instantiated (except as part of a derived class).
AbstractRdataFactory() {}
public:
+ /// The destructor.
virtual ~AbstractRdataFactory() {};
-
- // Factory methods for polymorphic creation:
+ //@}
+
+ ///
+ /// \name Factory methods for polymorphic creation.
+ ///
+ //@{
+ ///
+ /// \brief Create RDATA from a string.
+ ///
+ /// This method creates from a string an \c Rdata object of specific class
+ /// corresponding to the specific derived class of \c AbstractRdataFactory.
+ ///
+ /// \param rdata_str A string of textual representation of the \c Rdata.
+ /// \return An \c RdataPtr object pointing to the created \c Rdata object.
virtual RdataPtr create(const std::string& rdata_str) const = 0;
+ ///
+ /// \brief Create RDATA from wire-format data.
+ ///
+ /// This method creates from wire-format binary data an \c Rdata object
+ /// of specific class corresponding to the specific derived class of
+ /// \c AbstractRdataFactory.
+ ///
+ /// \param buffer A reference to an \c InputBuffer object storing the
+ /// \c Rdata to parse.
+ /// \param rdata_len The length in buffer of the \c Rdata. In bytes.
+ /// \return An \c RdataPtr object pointing to the created \c Rdata object.
virtual RdataPtr create(InputBuffer& buffer, size_t rdata_len) const = 0;
+ ///
+ /// \brief Create RDATA from another \c Rdata object of the same type.
+ ///
+ /// This method creates an \c Rdata object of specific class corresponding
+ /// to the specific derived class of \c AbstractRdataFactory, copying the
+ /// content of the given \c Rdata, \c source.
+ ///
+ /// \c source must be an object of the concrete derived class corresponding
+ /// to the specific derived class of \c AbstractRdataFactory;
+ /// otherwise, an exception of class \c std::bad_cast will be thrown.
+ ///
+ /// \param source A reference to an \c Rdata object whose content is to
+ /// be copied to the created \c Rdata object.
+ /// \return An \c RdataPtr object pointing to the created \c Rdata object.
virtual RdataPtr create(const rdata::Rdata& source) const = 0;
+ //@}
};
-///
-/// TBD: describe it
+
+///
+/// The \c RdataFactoryPtr type is a pointer-like type, pointing to an
+/// object of some concrete derived class of \c AbstractRdataFactory.
///
typedef boost::shared_ptr<AbstractRdataFactory> RdataFactoryPtr;
} // end of namespace rdata
@@ -158,7 +211,7 @@
/// representations.
///
/// Regarding the mappings between textual representations and integer
- /// codes, this methods behaves in the same way as \c addType() and
+ /// codes, this method behaves in the same way as \c addType() and
/// \c addClass(). That is, it ignores any overriding attempt as
/// long as the mapping is the same; otherwise the corresponding exception
/// will be thrown.
@@ -168,18 +221,25 @@
/// stored in the registry; if this method throws an exception the
/// registry will remain in the state before this method is called.
///
- /// Note: this method will be extended to support more parameters in a
- /// near future version.
- ///
/// \param type_string The textual representation of the RR type.
/// \param type_code The integer code of the RR type.
/// \param class_string The textual representation of the RR class.
/// \param class_code The integer code of the RR class.
+ /// \param rdata_factory An \c RdataFactoryPtr object pointing to a
+ /// concrete RDATA factory.
void add(const std::string& type_string, uint16_t type_code,
const std::string& class_string, uint16_t class_code,
rdata::RdataFactoryPtr rdata_factory);
- /// TBD
+ /// \brief Add a set of parameters for a class-independent RR type.
+ ///
+ /// This method behaves as exactly same as the other \c add method except
+ /// that it handles class-independent types (such as NS, CNAME, or SOA).
+ ///
+ /// \param type_string The textual representation of the RR type.
+ /// \param type_code The integer code of the RR type.
+ /// \param rdata_factory An \c RdataFactoryPtr object pointing to a
+ /// concrete RDATA factory.
void add(const std::string& type_string, uint16_t type_code,
rdata::RdataFactoryPtr rdata_factory);
@@ -219,7 +279,7 @@
/// exist in the registry. If not, this method simply ignores the attempt
/// and returns \c false.
///
- /// This method never throw an exception.
+ /// This method never throws an exception.
///
/// \param type_code The integer code of the RR type.
/// \return \c true if mappings for the specified RR type exists and is
@@ -251,7 +311,8 @@
///
/// \param class_string The textual representation of the RR class.
/// \param class_code The integer code of the RR class.
- /// \return
+ /// \return \c true if a new mapping is added to the repository; \c false
+ /// if the same mapping is already registered.
bool addClass(const std::string& class_string, uint16_t class_code);
/// \brief Remove mappings between RR class code and textual representation
@@ -261,11 +322,43 @@
/// exist in the registry. If not, this method simply ignores the attempt
/// and returns \c false.
///
- /// This method never throw an exception.
+ /// This method never throws an exception.
///
/// \param class_code The integer code of the RR class.
- /// \return
+ /// \return \c true if mappings for the specified RR type exists and is
+ /// removed; \c false if no such mapping is in the registry.
bool removeClass(uint16_t class_code);
+
+ /// \brief Remove registered RDATA factory for the given pair of \c RRType
+ /// and \c RRClass.
+ ///
+ /// This method can safely be called whether or not the specified factory
+ /// object exist in the registry. If not, this method simply ignores the
+ /// attempt and returns \c false.
+ ///
+ /// This method never throws an exception.
+ ///
+ /// \param rrtype An \c RRType object specifying the type/class pair.
+ /// \param rrclass An \c RRClass object specifying the type/class pair.
+ /// \return \c true if a factory object for the specified RR type/class
+ /// pair exists and is removed; \c false if no such object is in the
+ /// registry.
+ bool removeRdataFactory(const RRType& rrtype, const RRClass& rrclass);
+
+ /// \brief Remove registered RDATA factory for the given pair of \c RRType
+ /// and \c RRClass.
+ ///
+ /// This method can safely be called whether or not the specified factory
+ /// object exist in the registry. If not, this method simply ignores the
+ /// attempt and returns \c false.
+ ///
+ /// This method never throws an exception.
+ ///
+ /// \param rrtype An \c RRType object specifying the type/class pair.
+ /// \return \c true if a factory object for the specified RR type/class
+ /// pair exists and is removed; \c false if no such object is in the
+ /// registry.
+ bool removeRdataFactory(const RRType& rrtype);
//@}
///
@@ -338,14 +431,72 @@
///
/// \name RDATA Factories
///
+ /// This set of methods provide a unified interface to create an
+ /// \c rdata::Rdata object in a parameterized polymorphic way,
+ /// that is, these methods take a pair of \c RRType and \c RRClass
+ /// objects and data specific to that pair, and create an object of
+ /// the corresponding concrete derived class of \c rdata::Rdata.
+ ///
+ /// These methods first search the \c RRParamRegistry for a factory
+ /// method (a member of a concrete derived class of
+ /// \c AbstractRdataFactory) for the given RR type and class pair.
+ /// If the search fails, they then search for a factory method for
+ /// the given type ignoring the class, in case a RRClass independent
+ /// factory method is registered.
+ /// If it still fails, these methods assume the RDATA is of an "unknown"
+ /// type, and creates a new object by calling a constructor of the
+ /// \c rdata::generic::Generic class.
+ ///
//@{
- /// \brief TBD
+ /// \brief Create RDATA of a given pair of RR type and class from a string.
+ ///
+ /// This method creates from a string an \c Rdata object of the given pair
+ /// of RR type and class.
+ ///
+ /// \param rrtype An \c RRType object specifying the type/class pair.
+ /// \param rrclass An \c RRClass object specifying the type/class pair.
+ /// \param rdata_string A string of textual representation of the \c Rdata.
+ /// \return An \c rdata::RdataPtr object pointing to the created \c Rdata
+ /// object.
rdata::RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
const std::string& rdata_string);
- /// \brief TBD
+ /// \brief Create RDATA of a given pair of RR type and class from
+ /// wire-format data.
+ ///
+ /// This method creates from wire-format binary data an \c Rdata object
+ /// of the given pair of RR type and class.
+ ///
+ /// \param rrtype An \c RRType object specifying the type/class pair.
+ /// \param rrclass An \c RRClass object specifying the type/class pair.
+ /// \param buffer A reference to an \c InputBuffer object storing the
+ /// \c Rdata to parse.
+ /// \param len The length in buffer of the \c Rdata. In bytes.
+ /// \return An \c rdata::RdataPtr object pointing to the created \c Rdata
+ /// object.
rdata::RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
InputBuffer& buffer, size_t len);
- /// \brief Polymorphic copy constructor (detailed TBD)
+ /// \brief Create RDATA of a given pair of RR type and class, copying
+ /// of another RDATA of same kind.
+ ///
+ /// This method creates an \c Rdata object of the given pair of
+ /// RR type and class, copying the content of the given \c Rdata,
+ /// \c source.
+ ///
+ /// \c source must be an object of the concrete derived class of
+ /// \c rdata::Rdata for the given pair of RR type and class;
+ /// otherwise, an exception of class \c std::bad_cast will be thrown.
+ /// In case the \c RRParamRegistry doesn't have a factory method for
+ /// the given pair and it is assumed to be of an "unknown" type,
+ /// \c source must reference an object of class
+ /// \c rdata::generic::Generic; otherwise, an exception of class
+ /// \c std::bad_cast will be thrown.
+ ///
+ /// \param rrtype An \c RRType object specifying the type/class pair.
+ /// \param rrclass An \c RRClass object specifying the type/class pair.
+ /// \param source A reference to an \c rdata::Rdata object whose content
+ /// is to be copied to the created \c rdata::Rdata object.
+ /// \return An \c rdata::RdataPtr object pointing to the created
+ /// \c rdata::Rdata object.
rdata::RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
const rdata::Rdata& source);
//@}
More information about the bind10-changes
mailing list