Commit 077ed33f authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

- moved concrete Rdata class definitions to separate directories under rdata/

- introduced unified auto-code generation with a python script for the rdata
  related definitions


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/parkinglot@633 e5f2f494-b856-4b98-b285-d166d9295462
parent 3342ceb6
......@@ -180,6 +180,7 @@ AC_OUTPUT([src/bin/cfgmgr/b10-cfgmgr.py
src/bin/msgq/msgq_test
src/bin/msgq/run_msgq.sh
src/bin/parkinglot/config.h
src/lib/dns/cpp/gen-rdatacode.py
], [
chmod +x src/bin/cfgmgr/run_b10-cfgmgr.sh
chmod +x src/bin/cmdctl/run_b10-cmdctl.sh
......@@ -187,5 +188,6 @@ AC_OUTPUT([src/bin/cfgmgr/b10-cfgmgr.py
chmod +x src/bin/bindctl/bindctl
chmod +x src/bin/msgq/run_msgq.sh
chmod +x src/bin/msgq/msgq_test
chmod +x src/lib/dns/cpp/gen-rdatacode.py
])
AC_OUTPUT
......@@ -29,6 +29,7 @@
#include <dns/cpp/messagerenderer.h>
#include <dns/cpp/name.h>
#include <dns/cpp/question.h>
#include <dns/cpp/rdataclass.h>
#include <dns/cpp/rrset.h>
#include <dns/cpp/rrttl.h>
#include <dns/cpp/message.h>
......
......@@ -25,6 +25,7 @@
#include <dns/cpp/messagerenderer.h>
#include <dns/cpp/name.h>
#include <dns/cpp/rdata.h>
#include <dns/cpp/rdataclass.h>
#include <dns/cpp/rrclass.h>
#include <dns/cpp/rrtype.h>
#include <dns/cpp/rrttl.h>
......
#include <boost/foreach.hpp>
#include <dns/cpp/rdataclass.h>
#include <dns/cpp/rrttl.h>
#include "data_source_plot.h"
......
AM_CPPFLAGS = -I$(top_srcdir)/ext
CLEANFILES = *.gcno *.gcda
CLEANFILES += rrclass.h rrtype.h rrparamregistry.cc rdataclass.h rdataclass.cc
lib_LTLIBRARIES = libdns.la
libdns_la_SOURCES = buffer.h name.cc name.h messagerenderer.h messagerenderer.cc
libdns_la_SOURCES += rrparamregistry.h rrparamregistry.cc
libdns_la_SOURCES += rrclass.h rrclass.cc rrtype.h rrtype.cc rrttl.h rrttl.cc
libdns_la_SOURCES += rdata.h rdata.cc rrset.h rrset.cc
libdns_la_SOURCES += rrparamregistry.h
libdns_la_SOURCES += rrclass.cc rrtype.cc rrttl.h rrttl.cc
libdns_la_SOURCES += rdata.h rdata.cc
libdns_la_SOURCES += rdataclass.h rdataclass.cc
libdns_la_SOURCES += rrset.h rrset.cc
libdns_la_SOURCES += question.h question.cc
libdns_la_SOURCES += message.h message.cc
libdns_la_SOURCES += exceptions.h exceptions.cc
# auto-generate by gen-rdatacode.py:
libdns_la_SOURCES += rrclass.h rrtype.h rrparamregistry.cc
rrclass.h: rrclass-placeholder.h
rrtype.h: rrtype-placeholder.h
rrparamregistry.cc: rrparamregistry-placeholder.cc
rrclass.h rrtype.h rrparamregistry.cc rdataclass.h rdataclass.cc: Makefile
./gen-rdatacode.py
TESTS =
if HAVE_GTEST
......
#!@PYTHON@
# Copyright (C) 2010 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.
# $Id$
"""\
This is a supplemental script to (half) auto-generate DNS Rdata related
classes and constants.
"""
import os
import re
import sys
re_typecode = re.compile('([a-z]+)_(\d+)')
classcode2txt = {}
typecode2txt = {}
typeandclass = []
generic_code = 65536 # something larger than any code value
class_declarations = ''
class_definitions = ''
copyright_file = '@top_srcdir@' + os.sep + 'COPYING'
def import_classdef(class_txt, file):
rdata_source = open(file, 'r')
content = ''
for line in rdata_source.readlines():
if re.match('// BEGIN_ISC_NAMESPACE', line):
content += 'namespace isc {\n'
content += 'namespace dns {\n'
continue
if re.match('// BEGIN_RDATA_NAMESPACE', line):
content += 'namespace rdata {\n'
content += 'namespace ' + class_txt + ' {\n'
continue
if re.match('// END_ISC_NAMESPACE', line):
content += '} // end of namespace "dns"\n'
content += '} // end of namespace "isc"\n'
continue
if re.match('// END_RDATA_NAMESPACE', line):
content += '} // end of namespace "' + class_txt +'"\n'
content += '} // end of namespace "rdata"\n'
continue
content += line
rdata_source.close()
return content
def import_classheader(class_txt, type_txt, type_code, file):
# for each CLASS_n/TYPE_m.h
rdata_header = open(file, 'r')
content = ''
guard_macro = '__' + class_txt.upper() + '_' + type_txt.upper()
guard_macro += '_' + type_code + '_H'
for line in rdata_header.readlines():
if re.match('// BEGIN_HEADER_GUARD', line):
content += '#ifndef ' + guard_macro + '\n'
content += '#define ' + guard_macro + ' 1\n'
continue
if re.match('// END_HEADER_GUARD', line):
content += '#endif // ' + guard_macro + '\n'
continue
if re.match('// BEGIN_ISC_NAMESPACE', line):
content += 'namespace isc {\n'
content += 'namespace dns {\n'
continue
if re.match('// BEGIN_RDATA_NAMESPACE', line):
content += 'namespace rdata {\n'
content += 'namespace ' + class_txt + ' {\n'
continue
if re.match('// END_ISC_NAMESPACE', line):
content += '} // end of namespace "dns"\n'
content += '} // end of namespace "isc"\n'
continue
if re.match('// END_RDATA_NAMESPACE', line):
content += '} // end of namespace "' + class_txt +'"\n'
content += '} // end of namespace "rdata"\n'
continue
if re.match('// Local Variables:', line):
break
content += line
if re.match('// BEGIN_COMMON_DECLARATIONS', line):
content += '''
class InputBuffer;
class OutputBuffer;
class MessageRenderer;\n\n'''
if re.match('\s+// BEGIN_COMMON_MEMBERS$', line):
content += '''
explicit ''' + type_utxt + '''(const std::string& type_str);
explicit ''' + type_utxt + '''(InputBuffer& buffer, size_t rdata_len);
''' + type_utxt + '''(const ''' + type_utxt + '''& other);
virtual std::string toText() const;
virtual void toWire(OutputBuffer& buffer) const;
virtual void toWire(MessageRenderer& renderer) const;
virtual int compare(const Rdata& other) const;\n\n'''
rdata_header.close()
return content
def import_copyright():
copyright_txt = ''
f = open(copyright_file, 'r')
for line in f.readlines():
copyright_txt += '// ' + line
f.close()
copyright_txt += '''
///////////////
///////////////
/////////////// THIS FILE IS AUTOMATICALLY GENERATED BY gen-rdatacode.py.
/////////////// DO NOT EDIT!
///////////////
///////////////
'''
return copyright_txt
if __name__ == "__main__":
copyright_txt = import_copyright()
for dir in list(os.listdir('rdata')):
classdir = 'rdata' + os.sep + dir
m = re_typecode.match(dir)
if os.path.isdir(classdir) and (m != None or dir == 'generic'):
if dir == 'generic':
class_txt = 'generic'
class_code = generic_code
else:
class_txt = m.group(1)
class_code = m.group(2)
if not class_code in classcode2txt:
classcode2txt[class_code] = class_txt
for file in list(os.listdir(classdir)):
file = classdir + os.sep + file
m = re_typecode.match(os.path.split(file)[1])
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):
class_definitions += import_classdef(class_txt, file)
elif re.search('\h$', file):
class_declarations += import_classheader(class_txt,
type_txt,
type_code,
file)
typeandclass.append((type_txt, int(type_code),
(class_txt, class_txt),
int(class_code)))
if class_txt == 'generic':
typeandclass.append((type_txt, int(type_code),
(class_txt, 'in'), 1))
rdata_deffile = open('rdataclass.cc', 'w')
rdata_deffile.write(copyright_txt)
rdata_deffile.write(class_definitions)
rdata_deffile.close()
class_declarations += '''
// Local Variables:
// mode: c++
// End:
'''
rdata_header = open('rdataclass.h', 'w')
rdata_header.write(copyright_txt)
rdata_header.write(class_declarations)
rdata_header.close()
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 + '''()
{
static RRType rrtype(''' + code + ''');
return (rrtype);
}\n
'''
rrtype_header_temp = open('rrtype-placeholder.h', 'r')
rrtype_header_out = open('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('rrclass-placeholder.h', 'r')
rrclass_header_out = open('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()
# 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)
(type_txt, type_code, class_tuple, class_code) = param
type_utxt = type_txt.upper()
class_txt = class_tuple[0]
class_utxt = class_tuple[1].upper()
indent = ' ' * 8
typeandclassparams += indent
if class_tuple[1] != 'generic':
typeandclassparams += 'add("' + type_utxt + '", '
typeandclassparams += str(type_code) + ', "' + class_utxt
typeandclassparams += '", ' + str(class_code)
typeandclassparams += ', RdataFactoryPtr(new RdataFactory<'
typeandclassparams += class_txt + '::' + type_utxt + '>()));\n'
else:
typeandclassparams += 'add("' + type_utxt + '", ' + str(type_code)
typeandclassparams += ', RdataFactoryPtr(new RdataFactory<'
typeandclassparams += class_txt + '::' + type_utxt + '>()));\n'
rrparam_temp = open('rrparamregistry-placeholder.cc', 'r')
rrparam_out = open('rrparamregistry.cc', 'w')
rrparam_out.write(copyright_txt)
for line in rrparam_temp.readlines():
rrparam_out.write(line)
if re.match('\s+// BEGIN_WELL_KNOWN_PARAMS', line):
rrparam_out.write(typeandclassparams)
rrparam_temp.close()
rrparam_out.close()
......@@ -18,6 +18,7 @@
#include "message.h"
#include "messagerenderer.h"
#include "question.h"
#include "rdataclass.h"
#include "rrclass.h"
#include "rrttl.h"
#include "rrtype.h"
......
......@@ -143,446 +143,12 @@ Generic::compare(const Rdata& other) const
}
}
NS::NS(InputBuffer& buffer, size_t rdata_len) :
nsname_(buffer)
{
// we don't need rdata_len for parsing. if necessary, the caller will
// check consistency.
}
NS::NS(const NS& other) :
nsname_(other.nsname_)
{}
void
NS::toWire(OutputBuffer& buffer) const
{
nsname_.toWire(buffer);
}
void
NS::toWire(MessageRenderer& renderer) const
{
renderer.writeName(nsname_);
}
string
NS::toText() const
{
return (nsname_.toText());
}
int
NS::compare(const Rdata& other) const
{
const NS& other_ns = dynamic_cast<const NS&>(other);
return (compareNames(nsname_, other_ns.nsname_));
}
const Name&
NS::getNSName() const
{
return (nsname_);
}
SOA::SOA(InputBuffer& buffer, size_t rdata_len) :
mname_(buffer), rname_(buffer)
{
// we don't need rdata_len for parsing. if necessary, the caller will
// check consistency.
buffer.readData(numdata_, sizeof(numdata_));
}
SOA::SOA(const std::string& soastr) :
mname_("."), rname_(".")
{
dns_throw(InvalidRdataText, "Not implemented yet");
}
SOA::SOA(const Name& mname, const Name& rname, uint32_t serial,
uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum) :
mname_(mname), rname_(rname)
{
OutputBuffer b(20);
b.writeUint32(serial);
b.writeUint32(refresh);
b.writeUint32(retry);
b.writeUint32(expire);
b.writeUint32(minimum);
assert(b.getLength() == sizeof(numdata_));
memcpy(numdata_, b.getData(), sizeof(numdata_));
}
SOA::SOA(const SOA& other) :
mname_(other.mname_), rname_(other.rname_)
{
memcpy(numdata_, other.numdata_, sizeof(numdata_));
}
void
SOA::toWire(OutputBuffer& buffer) const
{
mname_.toWire(buffer);
rname_.toWire(buffer);
buffer.writeData(numdata_, sizeof(numdata_));
}
void
SOA::toWire(MessageRenderer& renderer) const
{
renderer.writeName(mname_);
renderer.writeName(rname_);
renderer.writeData(numdata_, sizeof(numdata_));
}
string
SOA::toText() const
{
InputBuffer b(numdata_, sizeof(numdata_));
uint32_t serial = b.readUint32();
uint32_t refresh = b.readUint32();
uint32_t retry = b.readUint32();
uint32_t expire = b.readUint32();
uint32_t minimum = b.readUint32();
return (mname_.toText() + " " + rname_.toText() + " " +
lexical_cast<string>(serial) + " " +
lexical_cast<string>(refresh) + " " +
lexical_cast<string>(retry) + " " +
lexical_cast<string>(expire) + " " +
lexical_cast<string>(minimum));
}
int
SOA::compare(const Rdata& other) const
{
const SOA& other_soa = dynamic_cast<const SOA&>(other);
int order = compareNames(mname_, other_soa.mname_);
if (order != 0) {
return (order);
}
order = compareNames(rname_, other_soa.rname_);
if (order != 0) {
return (order);
}
return (memcmp(numdata_, other_soa.numdata_, sizeof(numdata_)));
}
MX::MX(InputBuffer& buffer, size_t rdata_len) :
preference_(buffer.readUint16()), mxname_(buffer)
{
// we don't need rdata_len for parsing. if necessary, the caller will
// check consistency.
}
MX::MX(const std::string& mxstr) :
preference_(0), mxname_(".")
{
dns_throw(InvalidRdataText, "Not implemented yet");
}
MX::MX(uint16_t preference, const Name& mxname) :
preference_(preference), mxname_(mxname)
{}
MX::MX(const MX& other) :
preference_(other.preference_), mxname_(other.mxname_)
{}
void
MX::toWire(OutputBuffer& buffer) const
{
buffer.writeUint16(preference_);
mxname_.toWire(buffer);
}
void
MX::toWire(MessageRenderer& renderer) const
{
renderer.writeUint16(preference_);
renderer.writeName(mxname_);
}
string
MX::toText() const
{
return (lexical_cast<string>(preference_) + " " + mxname_.toText());
}
int
MX::compare(const Rdata& other) const
{
const MX& other_mx = dynamic_cast<const MX&>(other);
if (preference_ < other_mx.preference_) {
return (-1);
} else if (preference_ > other_mx.preference_) {
return (1);
}
return (compareNames(mxname_, other_mx.mxname_));
}
TXT::TXT(InputBuffer& buffer, size_t rdata_len)
{
uint8_t len;
// TBD: this is a simple, incomplete implementation that only supports
// a single character-string.
len = buffer.readUint8();
vector<uint8_t> data(len + 1);
data[0] = len;
buffer.readData(&data[0] + 1, len);
string_list_.push_back(data);
}
TXT::TXT(const std::string& txtstr)
{
size_t length = txtstr.size();
size_t pos_begin = 0;
if (length > 1 && txtstr[0] == '"' && txtstr[length - 1] == '"') {
pos_begin = 1;
length -= 2;
}
if (length > MAX_CHARSTRING_LEN) {
dns_throw(CharStringTooLong, "");
}
vector<uint8_t> data;
data.reserve(length + 1);
data.push_back(length);
data.insert(data.end(), txtstr.begin() + pos_begin,
txtstr.begin() + pos_begin + length);
string_list_.push_back(data);
}
TXT::TXT(const TXT& other) :
string_list_(other.string_list_)
{}
void
TXT::toWire(OutputBuffer& buffer) const
{
for (vector<vector<uint8_t> >::const_iterator it = string_list_.begin();
it != string_list_.end();
++it)
{
buffer.writeData(&(*it)[0], (*it).size());
}
}
void
TXT::toWire(MessageRenderer& renderer) const
{
for (vector<vector<uint8_t> >::const_iterator it = string_list_.begin();
it != string_list_.end();
++it)
{
renderer.writeData(&(*it)[0], (*it).size());
}
}
string
TXT::toText() const
{
string s;
// XXX: this implementation is not entirely correct. for example, it
// should escape double-quotes if they appear in the character string.
for (vector<vector<uint8_t> >::const_iterator it = string_list_.begin();
it != string_list_.end();
++it)
{
if (!s.empty()) {
s.push_back(' ');
}
s.push_back('"');
s.insert(s.end(), (*it).begin() + 1, (*it).end());
s.push_back('"');
}
return (s);
}
int
TXT::compare(const Rdata& other) const
{
const TXT& other_txt = dynamic_cast<const TXT&>(other);
// This implementation is not efficient. Revisit this (TBD).
OutputBuffer this_buffer(0);
toWire(this_buffer);