Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
457ef261
Commit
457ef261
authored
Apr 20, 2011
by
chenzhengzhang
Browse files
Merge branch 'master' of
ssh://bind10.isc.org/var/bind10/git/bind10
parents
8038f6ef
e87e34cd
Changes
56
Hide whitespace changes
Inline
Side-by-side
configure.ac
View file @
457ef261
...
...
@@ -682,6 +682,7 @@ AC_CONFIG_FILES([Makefile
src/lib/dns/tests/testdata/Makefile
src/lib/dns/python/Makefile
src/lib/dns/python/tests/Makefile
src/lib/dns/benchmarks/Makefile
src/lib/exceptions/Makefile
src/lib/exceptions/tests/Makefile
src/lib/datasrc/Makefile
...
...
src/bin/xfrin/tests/Makefile.am
View file @
457ef261
...
...
@@ -6,7 +6,7 @@ EXTRA_DIST = $(PYTESTS)
# required by loadable python modules.
LIBRARY_PATH_PLACEHOLDER
=
if
SET_ENV_LIBRARY_PATH
LIBRARY_PATH_PLACEHOLDER
+=
$(ENV_LIBRARY_PATH)
=
$(abs_top_builddir)
/src/lib/dns/.libs:
$(abs_top_builddir)
/src/lib/exceptions/.libs:
$(abs_top_builddir)
/src/lib/xfr/.libs:
$$$(ENV_LIBRARY_PATH)
LIBRARY_PATH_PLACEHOLDER
+=
$(ENV_LIBRARY_PATH)
=
$(abs_top_builddir)
/src/lib/dns/.libs:
$(abs_top_builddir)
/src/lib/
util/.libs:
$(abs_top_builddir)
/src/lib/
exceptions/.libs:
$(abs_top_builddir)
/src/lib/xfr/.libs:
$$$(ENV_LIBRARY_PATH)
endif
# test using command-line arguments, so use check-local target instead of TESTS
...
...
src/bin/xfrout/tests/Makefile.am
View file @
457ef261
...
...
@@ -6,7 +6,7 @@ EXTRA_DIST = $(PYTESTS)
# required by loadable python modules.
LIBRARY_PATH_PLACEHOLDER
=
if
SET_ENV_LIBRARY_PATH
LIBRARY_PATH_PLACEHOLDER
+=
$(ENV_LIBRARY_PATH)
=
$(abs_top_builddir)
/src/lib/dns/.libs:
$(abs_top_builddir)
/src/lib/exceptions/.libs:
$(abs_top_builddir)
/src/lib/util/io/.libs:
$$$(ENV_LIBRARY_PATH)
LIBRARY_PATH_PLACEHOLDER
+=
$(ENV_LIBRARY_PATH)
=
$(abs_top_builddir)
/src/lib/dns/.libs:
$(abs_top_builddir)
/src/lib/
util/.libs:
$(abs_top_builddir)
/src/lib/
exceptions/.libs:
$(abs_top_builddir)
/src/lib/util/io/.libs:
$$$(ENV_LIBRARY_PATH)
endif
# test using command-line arguments, so use check-local target instead of TESTS
...
...
src/cppcheck-suppress.lst
View file @
457ef261
...
...
@@ -3,13 +3,13 @@
debug
missingInclude
// This is a template, and should be excluded from the check
unreadVariable:src/lib/dns/rdata/template.cc:
59
unreadVariable:src/lib/dns/rdata/template.cc:
60
// These three trigger warnings due to the incomplete implementation. This is
// our problem, but we need to suppress the warnings for now.
functionConst:src/lib/cache/resolver_cache.h
functionConst:src/lib/cache/message_cache.h
functionConst:src/lib/cache/rrset_cache.h
// Intentional self assignment tests. Suppress warning about them.
selfAssignment:src/lib/dns/tests/name_unittest.cc:29
2
selfAssignment:src/lib/dns/tests/rdata_unittest.cc:22
7
selfAssignment:src/lib/dns/tests/name_unittest.cc:29
3
selfAssignment:src/lib/dns/tests/rdata_unittest.cc:22
8
selfAssignment:src/lib/dns/tests/tsigkey_unittest.cc:104
src/lib/dns/Makefile.am
View file @
457ef261
SUBDIRS
=
.
tests python
SUBDIRS
=
.
tests python
benchmarks
AM_CPPFLAGS
=
-I
$(top_srcdir)
/src/lib
-I
$(top_builddir)
/src/lib
AM_CPPFLAGS
+=
-I
$(top_srcdir)
/src/lib/dns
-I
$(top_builddir)
/src/lib/dns
...
...
@@ -72,6 +72,7 @@ libdns___la_SOURCES += name.h name.cc
libdns___la_SOURCES
+=
opcode.h opcode.cc
libdns___la_SOURCES
+=
rcode.h rcode.cc
libdns___la_SOURCES
+=
rdata.h rdata.cc
libdns___la_SOURCES
+=
rdatafields.h rdatafields.cc
libdns___la_SOURCES
+=
rrclass.cc
libdns___la_SOURCES
+=
rrparamregistry.h
libdns___la_SOURCES
+=
rrset.h rrset.cc
...
...
src/lib/dns/benchmarks/Makefile.am
0 → 100644
View file @
457ef261
AM_CPPFLAGS
=
-I
$(top_srcdir)
/src/lib
-I
$(top_builddir)
/src/lib
AM_CPPFLAGS
+=
$(BOOST_INCLUDES)
AM_CXXFLAGS
=
$(B10_CXXFLAGS)
if
USE_STATIC_LINK
AM_LDFLAGS
=
-static
endif
CLEANFILES
=
*
.gcno
*
.gcda
noinst_PROGRAMS
=
rdatarender_bench
rdatarender_bench_SOURCES
=
rdatarender_bench.cc
rdatarender_bench_LDADD
=
$(top_builddir)
/src/lib/dns/libdns++.la
rdatarender_bench_LDADD
+=
$(top_builddir)
/src/lib/exceptions/libexceptions.la
rdatarender_bench_LDADD
+=
$(SQLITE_LIBS)
src/lib/dns/benchmarks/README
0 → 100644
View file @
457ef261
- rdatarender_bench
This is a benchmark for RDATA rendering performance comparing the basic
Rdata objects and RdataField objects. It takes a command line argument
that specifies an input data file. Each line of the data file should
specify a single RDATA with its RR class and type, e.g.
IN A 192.0.2.1
IN NS ns.example.com.
Lines beginning with '#' and empty lines will be ignored. Sample input
files can be found in benchmarkdata/rdatarender_*.
src/lib/dns/benchmarks/benchmarkdata/rdatarender_data_com
0 → 100644
View file @
457ef261
# This is sample input data for rdatarender_bench.
# These are RDATA in the authority and additional sections in a response from
# a root server for a query domain under COM.
IN NS g.gtld-servers.net.
IN NS a.gtld-servers.net.
IN NS k.gtld-servers.net.
IN NS c.gtld-servers.net.
IN NS d.gtld-servers.net.
IN NS m.gtld-servers.net.
IN NS h.gtld-servers.net.
IN NS b.gtld-servers.net.
IN NS j.gtld-servers.net.
IN NS l.gtld-servers.net.
IN NS e.gtld-servers.net.
IN NS f.gtld-servers.net.
IN NS i.gtld-servers.net.
IN A 192.5.6.30
IN A 192.33.14.30
IN A 192.26.92.30
IN A 192.31.80.30
IN A 192.12.94.30
IN A 192.35.51.30
IN A 192.42.93.30
IN A 192.54.112.30
IN A 192.43.172.30
IN A 192.48.79.30
IN A 192.52.178.30
IN A 192.41.162.30
IN A 192.55.83.30
IN AAAA 2001:503:a83e::2:30
IN AAAA 2001:503:231d::2:30
src/lib/dns/benchmarks/benchmarkdata/rdatarender_data_nxdomain
0 → 100644
View file @
457ef261
# This is sample input data for rdatarender_bench.
# These are RDATA in the authority section in a response from
# a root server for a non existent query domain (with DNSSEC).
IN SOA a.root-servers.net. nstld.verisign-grs.com. 2010110301 1800 900 604800 86400
IN RRSIG SOA 8 0 86400 20101110000000 20101102230000 40288 . WtvYyX2nIsaqjWqkIG1WHFE5PnJ6eno0KqF6azU/MFJ/t1JpKWQ1P4rA 61rnoq0p252fg7wT4XzEz9UDxmpB5pvF2VApe2w9LvSWxsWIIOg8ue5u e9NAAYdzjd0rsYObQQ6msf7WchyAUbnmrqKvf8/CK6+s1xFihXp5DpYL 6K0=
IN NSEC ac. NS SOA RRSIG NSEC DNSKEY
IN RRSIG NSEC 8 0 86400 20101110000000 20101102230000 40288 . rWfgg4YUDFAjhiUOT+niJy/qbaIbydqoXg5oB/5j//ZjNFy4hqU8DvdM xJr9UybQpEvu7pvmKQ0jRYO98Fw/UTlY5KiKbhVBJ1t8AE93cbU+s5gX d3Q6+wRcFX5MjZyIe+f30llKrYOZHjRyEFALCkLt4XEmr0xsua+ztAFY 65k=
IN NSEC np. NS RRSIG NSEC
IN RRSIG NSEC 8 1 86400 20101110000000 20101102230000 40288 . G32LGynsGA2fyDnesyeCtBCoM3ERMgGS4touDUuoBYW1NrZub76kz5fc z93p8VZfoYWAW7LuC8vJ1jl2sUgBNns4zN4RsfFeopcYjjFnGbGuoZnO NmTU+NKO53Ub7uIcCSeqV+COAaL8XqDfyk1FmVdQvtrBaOW/PWpRahVq 7E8=
src/lib/dns/benchmarks/benchmarkdata/rdatarender_data_org
0 → 100644
View file @
457ef261
# This is sample input data for rdatarender_bench.
# These are RDATA in the authority and additional sections in a response from
# a root server for a query domain under ORG.
IN NS b0.org.afilias-nst.org.
IN NS a2.org.afilias-nst.info.
IN NS a0.org.afilias-nst.info.
IN NS c0.org.afilias-nst.info.
IN NS d0.org.afilias-nst.org.
IN NS b2.org.afilias-nst.org.
IN A 199.19.56.1
IN A 199.249.112.1
IN A 199.19.54.1
IN A 199.249.120.1
IN A 199.19.53.1
IN A 199.19.57.1
IN AAAA 2001:500:e::1
IN AAAA 2001:500:40::1
IN AAAA 2001:500:c::1
IN AAAA 2001:500:48::1
IN AAAA 2001:500:b::1
IN AAAA 2001:500:f::1
src/lib/dns/benchmarks/rdatarender_bench.cc
0 → 100644
View file @
457ef261
// 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.
#include
<iostream>
#include
<fstream>
#include
<string>
#include
<vector>
#include
<boost/shared_ptr.hpp>
#include
<bench/benchmark.h>
#include
<util/buffer.h>
#include
<dns/messagerenderer.h>
#include
<dns/rdata.h>
#include
<dns/rdatafields.h>
#include
<dns/rrclass.h>
#include
<dns/rrtype.h>
using
namespace
std
;
using
namespace
isc
::
bench
;
using
namespace
isc
::
dns
;
using
namespace
isc
::
dns
::
rdata
;
using
isc
::
util
::
OutputBuffer
;
namespace
{
// This templated benchmark class is constructed with a vector of Rdata-like
// (pointer) objects which should have a "toWire()" method. In its run(),
// it calls toWire() for each element of the vector.
template
<
typename
T
>
class
RdataRenderBenchMark
{
public:
RdataRenderBenchMark
(
const
vector
<
T
>&
dataset
)
:
dataset_
(
dataset
),
buffer_
(
4096
),
renderer_
(
buffer_
)
{}
unsigned
int
run
()
{
typename
vector
<
T
>::
const_iterator
data
;
typename
vector
<
T
>::
const_iterator
data_end
=
dataset_
.
end
();
for
(
data
=
dataset_
.
begin
();
data
!=
data_end
;
++
data
)
{
renderer_
.
clear
();
(
*
data
)
->
toWire
(
renderer_
);
}
return
(
dataset_
.
size
());
}
private:
const
vector
<
T
>&
dataset_
;
OutputBuffer
buffer_
;
MessageRenderer
renderer_
;
};
// This supplemental class emulates an RRset like class that internally
// uses RdataFields. On construction it stores RDATA information in the
// form of RdataFields fields. Its toWire() method restores the data as
// an RdataFields object for the rendering.
class
RdataFieldsStore
{
public:
RdataFieldsStore
(
ConstRdataPtr
rdata
)
{
const
RdataFields
fields
(
*
rdata
);
spec_size_
=
fields
.
getFieldSpecDataSize
();
spec_store_
.
resize
(
spec_size_
);
void
*
cp_spec
=
&
spec_store_
[
0
];
memcpy
(
cp_spec
,
fields
.
getFieldSpecData
(),
spec_store_
.
size
());
spec_ptr_
=
cp_spec
;
data_length_
=
fields
.
getDataLength
();
data_store_
.
resize
(
data_length_
);
void
*
cp_data
=
&
data_store_
[
0
];
memcpy
(
cp_data
,
fields
.
getData
(),
data_store_
.
size
());
// Vector guarantees that the elements are stored in continuous array
// in memory, so this is actually correct by the standard
data_ptr_
=
cp_data
;
}
void
toWire
(
MessageRenderer
&
renderer
)
const
{
RdataFields
(
spec_ptr_
,
spec_size_
,
data_ptr_
,
data_length_
).
toWire
(
renderer
);
}
private:
vector
<
unsigned
char
>
spec_store_
;
vector
<
unsigned
char
>
data_store_
;
const
void
*
spec_ptr_
;
const
void
*
data_ptr_
;
unsigned
int
spec_size_
;
size_t
data_length_
;
};
// We wouldn't necessarily have to use a shared pointer, but it's easier
// to use pointer-like values to adjust them with the RdataRenderBenchMark
// template.
typedef
boost
::
shared_ptr
<
const
RdataFieldsStore
>
ConstRdataFieldsStorePtr
;
void
readInputFile
(
const
char
*
const
input_file
,
vector
<
ConstRdataPtr
>&
rdata_sets
,
vector
<
ConstRdataFieldsStorePtr
>&
fields_sets
)
{
ifstream
ifs
;
ifs
.
open
(
input_file
,
ios_base
::
in
);
if
((
ifs
.
rdstate
()
&
istream
::
failbit
)
!=
0
)
{
cerr
<<
"Failed to read input file: "
<<
input_file
<<
endl
;
exit
(
1
);
}
string
line
;
unsigned
int
linenum
=
0
;
while
(
getline
(
ifs
,
line
),
!
ifs
.
eof
())
{
++
linenum
;
if
(
ifs
.
bad
()
||
ifs
.
fail
())
{
cerr
<<
"Unexpected input at line "
<<
linenum
<<
endl
;
exit
(
1
);
}
if
(
line
.
empty
()
||
line
[
0
]
==
'#'
)
{
continue
;
// skip comment and blank lines
}
istringstream
iss
(
line
);
string
rrclass_string
,
rrtype_string
;
stringbuf
rdatabuf
;
iss
>>
rrclass_string
>>
rrtype_string
>>
&
rdatabuf
;
if
(
iss
.
bad
()
||
iss
.
fail
())
{
cerr
<<
"Unexpected input at line "
<<
linenum
<<
endl
;
exit
(
1
);
}
ConstRdataPtr
rdata
=
createRdata
(
RRType
(
rrtype_string
),
RRClass
(
rrclass_string
),
rdatabuf
.
str
());
rdata_sets
.
push_back
(
rdata
);
fields_sets
.
push_back
(
ConstRdataFieldsStorePtr
(
new
RdataFieldsStore
(
rdata
)));
}
ifs
.
close
();
}
void
usage
()
{
cerr
<<
"Usage: rdatafields_bench [-n iterations] input_file"
<<
endl
;
exit
(
1
);
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
ch
;
int
iteration
=
10000
;
while
((
ch
=
getopt
(
argc
,
argv
,
"n:"
))
!=
-
1
)
{
switch
(
ch
)
{
case
'n'
:
iteration
=
atoi
(
optarg
);
break
;
case
'?'
:
default:
usage
();
}
}
argc
-=
optind
;
argv
+=
optind
;
if
(
argc
<
1
)
{
usage
();
}
const
char
*
const
input_file
=
argv
[
0
];
vector
<
ConstRdataPtr
>
rdata_sets
;
vector
<
ConstRdataFieldsStorePtr
>
fields_sets
;
readInputFile
(
input_file
,
rdata_sets
,
fields_sets
);
cout
<<
"Parameters:"
<<
endl
;
cout
<<
" Iterations: "
<<
iteration
<<
endl
;
cout
<<
" Input File: "
<<
input_file
<<
endl
;
typedef
RdataRenderBenchMark
<
ConstRdataPtr
>
RdataBenchMark
;
cout
<<
"Benchmark for rendering with standard Rdata"
<<
endl
;
BenchMark
<
RdataBenchMark
>
(
iteration
,
RdataBenchMark
(
rdata_sets
));
typedef
RdataRenderBenchMark
<
ConstRdataFieldsStorePtr
>
FieldsBenchMark
;
cout
<<
"Benchmark for rendering with RdataFields"
<<
endl
;
BenchMark
<
FieldsBenchMark
>
(
iteration
,
FieldsBenchMark
(
fields_sets
));
return
(
0
);
}
src/lib/dns/gen-rdatacode.py.in
View file @
457ef261
...
...
@@ -110,7 +110,7 @@ class OutputBuffer;\n'''
content += line
if re.match('// BEGIN_COMMON_DECLARATIONS', line):
content += '''
class MessageRenderer;\n\n'''
class
Abstract
MessageRenderer;\n\n'''
if re.match('\s+// BEGIN_COMMON_MEMBERS$', line):
content += '''
explicit ''' + type_utxt + '''(const std::string& type_str);
...
...
@@ -118,7 +118,7 @@ class MessageRenderer;\n\n'''
''' + type_utxt + '''(const ''' + type_utxt + '''& other);
virtual std::string toText() const;
virtual void toWire(isc::util::OutputBuffer& buffer) const;
virtual void toWire(MessageRenderer& renderer) const;
virtual void toWire(
Abstract
MessageRenderer& renderer) const;
virtual int compare(const Rdata& other) const;\n\n'''
rdata_header.close()
return content
...
...
src/lib/dns/messagerenderer.cc
View file @
457ef261
...
...
@@ -152,12 +152,10 @@ struct MessageRenderer::MessageRendererImpl {
///
/// \param buffer An \c OutputBuffer object to which wire format data is
/// written.
MessageRendererImpl
(
OutputBuffer
&
buffer
)
:
buffer_
(
buffer
),
nbuffer_
(
Name
::
MAX_WIRE
),
msglength_limit_
(
512
),
MessageRendererImpl
()
:
nbuffer_
(
Name
::
MAX_WIRE
),
msglength_limit_
(
512
),
truncated_
(
false
),
compress_mode_
(
MessageRenderer
::
CASE_INSENSITIVE
)
{}
/// The buffer that holds the entire DNS message.
OutputBuffer
&
buffer_
;
/// A local working buffer to convert each given name into wire format.
/// This could be a local variable of the \c writeName() method, but
/// we keep it in the class so that we can reuse it and avoid construction
...
...
@@ -176,26 +174,17 @@ struct MessageRenderer::MessageRendererImpl {
};
MessageRenderer
::
MessageRenderer
(
OutputBuffer
&
buffer
)
:
impl_
(
new
MessageRendererImpl
(
buffer
))
AbstractMessageRenderer
(
buffer
),
impl_
(
new
MessageRendererImpl
)
{}
MessageRenderer
::~
MessageRenderer
()
{
delete
impl_
;
}
void
MessageRenderer
::
skip
(
const
size_t
len
)
{
impl_
->
buffer_
.
skip
(
len
);
}
void
MessageRenderer
::
trim
(
const
size_t
len
)
{
impl_
->
buffer_
.
trim
(
len
);
}
void
MessageRenderer
::
clear
()
{
impl_
->
buffer_
.
clear
();
AbstractMessageRenderer
::
clear
();
impl_
->
nbuffer_
.
clear
();
impl_
->
nodeset_
.
clear
();
impl_
->
msglength_limit_
=
512
;
...
...
@@ -203,41 +192,6 @@ MessageRenderer::clear() {
impl_
->
compress_mode_
=
CASE_INSENSITIVE
;
}
void
MessageRenderer
::
writeUint8
(
const
uint8_t
data
)
{
impl_
->
buffer_
.
writeUint8
(
data
);
}
void
MessageRenderer
::
writeUint16
(
const
uint16_t
data
)
{
impl_
->
buffer_
.
writeUint16
(
data
);
}
void
MessageRenderer
::
writeUint16At
(
const
uint16_t
data
,
const
size_t
pos
)
{
impl_
->
buffer_
.
writeUint16At
(
data
,
pos
);
}
void
MessageRenderer
::
writeUint32
(
const
uint32_t
data
)
{
impl_
->
buffer_
.
writeUint32
(
data
);
}
void
MessageRenderer
::
writeData
(
const
void
*
const
data
,
const
size_t
len
)
{
impl_
->
buffer_
.
writeData
(
data
,
len
);
}
const
void
*
MessageRenderer
::
getData
()
const
{
return
(
impl_
->
buffer_
.
getData
());
}
size_t
MessageRenderer
::
getLength
()
const
{
return
(
impl_
->
buffer_
.
getLength
());
}
size_t
MessageRenderer
::
getLengthLimit
()
const
{
return
(
impl_
->
msglength_limit_
);
...
...
@@ -293,15 +247,15 @@ MessageRenderer::writeName(const Name& name, const bool compress) {
}
// Record the current offset before extending the buffer.
const
size_t
offset
=
impl_
->
buffer_
.
getLength
();
const
size_t
offset
=
getLength
();
// Write uncompress part...
impl_
->
buffer_
.
writeData
(
impl_
->
nbuffer_
.
getData
(),
compress
?
i
:
impl_
->
nbuffer_
.
getLength
());
writeData
(
impl_
->
nbuffer_
.
getData
(),
compress
?
i
:
impl_
->
nbuffer_
.
getLength
());
if
(
compress
&&
n
!=
notfound
)
{
// ...and compression pointer if available.
uint16_t
pointer
=
(
*
n
).
pos_
;
pointer
|=
Name
::
COMPRESS_POINTER_MARK16
;
impl_
->
buffer_
.
writeUint16
(
pointer
);
writeUint16
(
pointer
);
}
// Finally, add to the set the newly rendered name and its ancestors that
...
...
@@ -313,11 +267,17 @@ MessageRenderer::writeName(const Name& name, const bool compress) {
if
(
offset
+
j
>
Name
::
MAX_COMPRESS_POINTER
)
{
break
;
}
impl_
->
nodeset_
.
insert
(
NameCompressNode
(
*
this
,
impl_
->
b
uffer
_
,
impl_
->
nodeset_
.
insert
(
NameCompressNode
(
*
this
,
getB
uffer
()
,
offset
+
j
,
impl_
->
nbuffer_
.
getLength
()
-
j
));
}
}
void
AbstractMessageRenderer
::
clear
()
{
buffer_
.
clear
();
}
}
}
src/lib/dns/messagerenderer.h
View file @
457ef261
...
...
@@ -15,67 +15,64 @@
#ifndef __MESSAGERENDERER_H
#define __MESSAGERENDERER_H 1
#include
<util/buffer.h>
namespace
isc
{
namespace
util
{
class
OutputBuffer
;
}
namespace
dns
{
// forward declarations
class
Name
;
/// \brief The \c AbstractMessageRenderer class is an abstract base class
/// that provides common interfaces for rendering a DNS message into a buffer
/// in wire format.
///
/// \brief The \c MessageRenderer class encapsulates implementation details
/// of rendering a DNS message into a buffer in wire format.
/// A specific derived class of \c AbstractMessageRenderer (we call it
/// a renderer class hereafter) is simply responsible for name compression at
/// least in the current design. A renderer class object (conceptually)
/// manages the positions of names rendered in some sort of buffer and uses
/// that information to render subsequent names with compression.
///
/// In effect, it's simply responsible for name compression at least in the
/// current implementation. A \c MessageRenderer class object manages the
/// positions of names rendered in a buffer and uses that information to render
/// subsequent names with compression.
///
/// This class is mainly intended to be used as a helper for a more
/// A renderer class is mainly intended to be used as a helper for a more
/// comprehensive \c Message class internally; normal applications won't have
/// to care about this class.
///
/// A \c MessageRenderer class object is constructed with a \c OutputBuffer
/// object, which is the buffer into which the rendered %data will be written.
/// Normally the buffer is expected to be empty on construction, but it doesn't
/// have to be so; the \c MessageRenderer object will start rendering from the
/// end of the buffer at the time of construction. However, if the
/// pre-existing portion of the buffer contains DNS names, these names won't
/// be considered for name compression.
/// to care about details of this class.
///
/// Once a
\c MessageR
enderer object is constructed with a buffer, it is
/// generally expected that all rendering operations are performed via th
e
///
\c MessageRenderer
object. If the application modifies the buffer in
/// parallel with the
\c MessageR
enderer, the result will be undefined.
/// Once a
r
enderer
class
object is constructed with a buffer, it is
/// generally expected that all rendering operations are performed via th
at
/// object. If the application modifies the buffer in
/// parallel with the
r
enderer, the result will be undefined.
///
/// Note to developers: we introduced a separate class for name compression
/// because previous benchmark with BIND9 showed compression affects overall
/// response performance very much. By having a separate class dedicated for
/// this purpose, we'll be able to change the internal implementation of name
/// compression in the future without affecting other part of the API and
/// implementation. For the same reason, we adopt the "pimpl" idiom in the
/// class definition (i.e., using a pointer to a \c MessageRendererImpl class,
/// which is defined with the class implementation, not in the header file):
/// we may want to modify the compression implementation without modifying the
/// header file thereby requesting rebuild the package.
/// implementation.
///
/// Furthermore, we may eventually want to allow other developers to develop
/// and use their own compression implementation. Should such a case become
/// realistic, we may want to make the \c MessageRendererImpl class an abstract
/// base class and let concrete derived classes have their own implementations.
/// At the moment we don't the strong need for it, so we rather avoid over
/// abstraction and keep the definition simpler.
class
MessageRenderer
{
/// In addition, by introducing a class hierarchy from
/// \c AbstractMessageRenderer, we allow an application to use a customized
/// renderer class for specific purposes. For example, a high performance
/// DNS server may want to use an optimized renderer class assuming some
/// specific underlying data representation.
///
/// \note Some functions (like writeUint8) are not virtual. It is because
/// it is hard to imagine any version of message renderer that would
/// do anything else than just putting the data into a buffer, so we
/// provide a default implementation and having them virtual would only
/// hurt the performance with no real gain. If it would happen a different
/// implementation is really needed, we can make them virtual in future.
/// The only one that is virtual is writeName and it's because this
/// function is much more complicated, therefore there's a lot of space
/// for different implementations or behaviours.
class
AbstractMessageRenderer
{
public:
/// \brief Compression mode constants.
///
/// The \c CompressMode enum type represents the name compression mode
/// for
the \c MessageRenderer
.
/// for
renderer classes
.
/// \c CASE_INSENSITIVE means compress names in case-insensitive manner;
/// \c CASE_SENSITIVE means compress names in case-sensitive manner.
/// By default,
\c MessageR
enderer compresses names in case-insensitive
/// By default,
a r
enderer compresses names in case-insensitive
/// manner.
/// Compression mode can be dynamically modified by the
/// \c setCompressMode() method.
...
...
@@ -83,7 +80,7 @@ public:
/// is not an intended usage. In this case the names already compressed
/// are intact; only names being compressed after the mode change are
/// affected by the change.
/// If
the internal \c MessageRenderer
is reinitialized by the \c clear()
/// If
a renderer class object
is reinitialized by the \c clear()
/// method, the compression mode will be reset to the default, which is
/// \c CASE_INSENSITIVE
///
...
...
@@ -96,25 +93,39 @@ public:
CASE_INSENSITIVE
,
//!< Compress names case-insensitive manner (default)
CASE_SENSITIVE
//!< Compress names case-sensitive manner
};
p
ublic
:
p
rotected
:
///
/// \name Constructors and Destructor
//@{
/// \brief Constructor from an output buffer.
///
/// \param buffer An \c OutputBuffer object to which wire format data is
/// written.
MessageRenderer
(
isc
::
util