Commit ecfc86a4 authored by chenzhengzhang's avatar chenzhengzhang
Browse files

[trac749] commit directory src/lib/util

parent 36dd3d4b
SUBDIRS = . tests
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += -I$(top_srcdir)/src/lib/util -I$(top_builddir)/src/lib/util
AM_CPPFLAGS += -I$(top_srcdir)/src/lib/exceptions -I$(top_builddir)/src/lib/exceptions
AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CXXFLAGS = $(B10_CXXFLAGS)
lib_LTLIBRARIES = libutil.la
libutil_la_SOURCES = filename.h filename.cc
libutil_la_SOURCES += locks.h lru_list.h
libutil_la_SOURCES += strutil.h strutil.cc
libutil_la_SOURCES += compat/base16_from_binary.h
libutil_la_SOURCES += compat/base32hex.h compat/base64.h
libutil_la_SOURCES += compat/base32hex_from_binary.h
libutil_la_SOURCES += compat/base_n.cc compat/hex.h
libutil_la_SOURCES += compat/binary_from_base32hex.h
libutil_la_SOURCES += compat/binary_from_base16.h
libutil_la_SOURCES += compat/sha1.h compat/sha1.cc
libutil_la_SOURCES += compat/time_utilities.h
libutil_la_SOURCES += compat/time_utilities.cc
libutil_la_SOURCES += io/buffer.h io/io_utilities.h
libutil_la_SOURCES += random/qid_gen.h random/qid_gen.cc
libutil_la_SOURCES += random/random_number_generator.h
libutil_la_LIBADD = $(top_builddir)/src/lib/exceptions/libexceptions.la
CLEANFILES = *.gcno *.gcda
This "util" directory is provided for utility header files and
implementations.
.
The functionality provided in these tools is generally available in
other external or perhaps system supplied libraries. The basic
development policy of BIND 10 is to avoid "reinventing wheels" unless
they belong to the exact technology area that BIND 10 targets (e.g.,
DNS). However, libdns++ is a very core part of BIND 10, and is also
intended to be used as a public library, so dependency from libdns++
to external libraries should be minimized. The utilities in this
directory are provided balancing two policies and as a kind of
compromise.
The header files in this directory are therefore not intended to be
installed. Likewise, classes and public functions defined in this
directory are not intended to be used outside libdns++, although we
cannot prohibit it at the language level.
They are not even expected to be used in other modules of BIND 10 than
libdns++ based on the basic policy explained above. Other modules
should only rely on the DNS specific interface that may internally
rely on these utility interfaces, or should use external libraries if
the other module really needs to use the utility feature directly.
There seem to be some violations as of this writing, but we should
eventually fix it. A notable example is the SHA1 interfaces. They
are defined here in the context of NSEC3 processing, but, in fact,
they are not even used from any of the other libdns++ classes or
functions. The SHA1 related interfaces should be moved to the
application that needs it or the application should only access it
through DNS specific interfaces defined in libdns++.
#ifndef BOOST_ARCHIVE_ITERATORS_BASE16_FROM_BINARY_HPP
#define BOOST_ARCHIVE_ITERATORS_BASE16_FROM_BINARY_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// base16_from_binary.h (derived from boost base64_from_binary.hpp)
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#include <cassert>
#include <cstddef> // size_t
#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{
using ::size_t;
} // namespace std
#endif
// See base32hex_from_binary.h for why we need base64_from...hpp here.
#include <boost/archive/iterators/base64_from_binary.hpp>
namespace boost {
namespace archive {
namespace iterators {
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// convert binary integers to base16 characters
namespace detail {
template<class CharType>
struct from_4_bit {
typedef CharType result_type;
CharType operator()(CharType t) const{
const char * lookup_table =
"0123456789"
"ABCDEF";
assert(t < 16);
return (lookup_table[static_cast<size_t>(t)]);
}
};
} // namespace detail
// note: what we would like to do is
// template<class Base, class CharType = BOOST_DEDUCED_TYPENAME Base::value_type>
// typedef transform_iterator<
// from_4_bit<CharType>,
// transform_width<Base, 4, sizeof(Base::value_type) * 8, CharType>
// > base16_from_binary;
// but C++ won't accept this. Rather than using a "type generator" and
// using a different syntax, make a derivation which should be equivalent.
//
// Another issue addressed here is that the transform_iterator doesn't have
// a templated constructor. This makes it incompatible with the dataflow
// ideal. This is also addressed here.
//template<class Base, class CharType = BOOST_DEDUCED_TYPENAME Base::value_type>
template<
class Base,
class CharType = BOOST_DEDUCED_TYPENAME boost::iterator_value<Base>::type
>
class base16_from_binary :
public transform_iterator<
detail::from_4_bit<CharType>,
Base
>
{
friend class boost::iterator_core_access;
typedef transform_iterator<
BOOST_DEDUCED_TYPENAME detail::from_4_bit<CharType>,
Base
> super_t;
public:
// make composible buy using templated constructor
template<class T>
base16_from_binary(BOOST_PFTO_WRAPPER(T) start) :
super_t(
Base(BOOST_MAKE_PFTO_WRAPPER(static_cast<T>(start))),
detail::from_4_bit<CharType>()
)
{}
// intel 7.1 doesn't like default copy constructor
base16_from_binary(const base16_from_binary & rhs) :
super_t(
Base(rhs.base_reference()),
detail::from_4_bit<CharType>()
)
{}
// base16_from_binary(){};
};
} // namespace iterators
} // namespace archive
} // namespace boost
#endif // BOOST_ARCHIVE_ITERATORS_BASE16_FROM_BINARY_HPP
// Copyright (C) 2009 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.
#ifndef __BASE32HEX_H
#define __BASE32HEX_H 1
#include <stdint.h>
#include <string>
#include <vector>
//
// Note: this helper module isn't specific to the DNS protocol per se.
// We should probably move this to somewhere else, possibly in some common
// utility area.
//
namespace isc {
namespace util {
namespace compat {
/// \brief Encode binary data in the base32hex format.
///
/// The underlying implementation is shared with \c encodeBase64, and all
/// description except the format (base32hex) equally applies.
///
/// Note: the encoding format is base32hex, not base32.
///
/// \param binary A vector object storing the data to be encoded.
/// \return A newly created string that stores base32hex encoded value for
/// binary.
std::string encodeBase32Hex(const std::vector<uint8_t>& binary);
/// \brief Decode a text encoded in the base32hex format into the
/// original %data.
///
/// The underlying implementation is shared with \c decodeBase64, and all
/// description except the format (base32hex) equally applies.
///
/// Note: the encoding format is base32hex, not base32.
///
/// \param input A text encoded in the base32hex format.
/// \param result A vector in which the decoded %data is to be stored.
void decodeBase32Hex(const std::string& input, std::vector<uint8_t>& result);
} // namespace compat
} // namespace util
} // namespace isc
#endif // __BASE32HEX_H
// Local Variables:
// mode: c++
// End:
#ifndef BOOST_ARCHIVE_ITERATORS_BASE32HEX_FROM_BINARY_HPP
#define BOOST_ARCHIVE_ITERATORS_BASE32HEX_FROM_BINARY_HPP
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// base32hex_from_binary.h (derived from boost base64_from_binary.hpp)
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#include <cassert>
#include <cstddef> // size_t
#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{
using ::size_t;
} // namespace std
#endif
// We use the same boost header files used in "base64_from_". Since the
// precise path to these headers may vary depending on the boost version we
// simply include the base64 header here.
#include <boost/archive/iterators/base64_from_binary.hpp>
namespace boost {
namespace archive {
namespace iterators {
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// convert binary integers to base32hex characters
namespace detail {
template<class CharType>
struct from_5_bit {
typedef CharType result_type;
CharType operator()(CharType t) const{
const char * lookup_table =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUV";
assert(t < 32);
return (lookup_table[static_cast<size_t>(t)]);
}
};
} // namespace detail
// note: what we would like to do is
// template<class Base, class CharType = BOOST_DEDUCED_TYPENAME Base::value_type>
// typedef transform_iterator<
// from_5_bit<CharType>,
// transform_width<Base, 5, sizeof(Base::value_type) * 8, CharType>
// > base32hex_from_binary;
// but C++ won't accept this. Rather than using a "type generator" and
// using a different syntax, make a derivation which should be equivalent.
//
// Another issue addressed here is that the transform_iterator doesn't have
// a templated constructor. This makes it incompatible with the dataflow
// ideal. This is also addressed here.
//template<class Base, class CharType = BOOST_DEDUCED_TYPENAME Base::value_type>
template<
class Base,
class CharType = BOOST_DEDUCED_TYPENAME boost::iterator_value<Base>::type
>
class base32hex_from_binary :
public transform_iterator<
detail::from_5_bit<CharType>,
Base
>
{
friend class boost::iterator_core_access;
typedef transform_iterator<
BOOST_DEDUCED_TYPENAME detail::from_5_bit<CharType>,
Base
> super_t;
public:
// make composible buy using templated constructor
template<class T>
base32hex_from_binary(BOOST_PFTO_WRAPPER(T) start) :
super_t(
Base(BOOST_MAKE_PFTO_WRAPPER(static_cast<T>(start))),
detail::from_5_bit<CharType>()
)
{}
// intel 7.1 doesn't like default copy constructor
base32hex_from_binary(const base32hex_from_binary & rhs) :
super_t(
Base(rhs.base_reference()),
detail::from_5_bit<CharType>()
)
{}
// base32hex_from_binary(){};
};
} // namespace iterators
} // namespace archive
} // namespace boost
#endif // BOOST_ARCHIVE_ITERATORS_BASE32HEX_FROM_BINARY_HPP
// Copyright (C) 2009 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.
#ifndef __BASE64_H
#define __BASE64_H 1
#include <stdint.h>
#include <string>
#include <vector>
//
// Note: this helper module isn't specific to the DNS protocol per se.
// We should probably move this to somewhere else, possibly in some common
// utility area.
//
namespace isc {
namespace util {
namespace compat {
/// \brief Encode binary data in the base64 format.
///
/// This function returns a new \c std::string object that stores a text
/// encoded in the base64 format for the given \c binary %data.
/// The resulting string will be a valid, canonical form of base64
/// representation as specified in RFC4648.
///
/// If memory allocation for the returned string fails, a corresponding
/// standard exception will be thrown. This function never throws exceptions
/// otherwise.
///
/// \param binary A vector object storing the data to be encoded.
/// \return A newly created string that stores base64 encoded value for binary.
std::string encodeBase64(const std::vector<uint8_t>& binary);
/// \brief Decode a text encoded in the base64 format into the original %data.
///
/// The \c input argument must be a valid string represented in the base64
/// format as specified in RFC4648. Space characters (spaces, tabs, newlines)
/// can be included in \c input and will be ignored. Without spaces, the
/// length of string must be a multiple of 4 bytes with necessary paddings.
/// Also it must be encoded using the canonical encoding (see RFC4648).
/// If any of these conditions is not met, an exception of class
/// \c isc::BadValue will be thrown.
///
/// If \c result doesn't have sufficient capacity to store all decoded %data
/// and memory allocation fails, a corresponding standard exception will be
/// thrown. If the caller knows the necessary length (which can in theory
/// be calculated from the input string), this situation can be avoided by
/// reserving sufficient space for \c result beforehand.
///
/// Any existing %data in \c result will be removed. This is the case in some
/// of the cases where an exception is thrown; that is, this function only
/// provides the basic exception guarantee.
///
/// \param input A text encoded in the base64 format.
/// \param result A vector in which the decoded %data is to be stored.
void decodeBase64(const std::string& input, std::vector<uint8_t>& result);
} // namespace compat
} // namespace util
} // namespace isc
#endif // __BASE64_H
// Local Variables:
// mode: c++
// End:
// 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 <stdint.h>
#include <cassert>
#include <iterator>
#include <string>
#include <vector>
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/math/common_factor.hpp>
#include <util/compat/base32hex_from_binary.h>
#include <util/compat/binary_from_base32hex.h>
#include <util/compat/base16_from_binary.h>
#include <util/compat/binary_from_base16.h>
#include <util/compat/base32hex.h>
#include <util/compat/base64.h>
#include <exceptions/exceptions.h>
using namespace std;
using namespace boost::archive::iterators;
namespace isc {
namespace util {
namespace compat {
// In the following anonymous namespace, we provide a generic framework
// to encode/decode baseN format. We use the following tools:
// - boost base64_from_binary/binary_from_base64: provide mapping table for
// base64.
// These classes take another iterator (Base) as a template argument, and
// their dereference operator (operator*()) first retrieves an input value
// from Base via Base::operator* and converts the value using their mapping
// table. The converted value is returned as their own operator*.
// - base{32hex,16}_from_binary/binary_from_base{32hex,16}: provide mapping
// table for base32hex and base16. A straightforward variation of their
// base64 counterparts.
// - EncodeNormalizer/DecodeNormalizer: supplemental filter handling baseN
// padding characters (=)
// - boost transform_width: an iterator framework for handling data stream
// per bit-group. It takes another iterator (Base) and output/input bit
// numbers (BitsOut/BitsIn) template arguments. A transform_width object
// internally maintains a bit stream, which can be retrieved per BitsOut
// bits via its dereference operator (operator*()). It builds the stream
// by internally iterating over the Base object via Base::operator++ and
// Base::operator*, using the least BitsIn bits of the result of
// Base::operator*. In our usage BitsIn for encoding and BitsOut for
// decoding are always 8 (# of bits for one byte).
//
// Its dereference operator
// retrieves BitsIn bits from the result of "*Base" (if necessary it
// internally calls ++Base)
//
// A conceptual description of how the encoding and decoding work is as
// follows:
// Encoding:
// input binary data => Normalizer (append sufficient number of 0 bits)
// => transform_width (extract bit groups from the original
// stream)
// => baseXX_from_binary (convert each bit group to an
// encoded byte using the mapping)
// Decoding:
// input baseXX text => Normalizer (convert '='s to the encoded characters
// corresponding to 0, e.g. 'A's in base64)
// => binary_from_baseXX (convert each encoded byte into
// the original group bit)
// => transform_width (build original byte stream by
// concatenating the decoded bit
// stream)
//
// Below, we define a set of templated classes to handle different parameters
// for different encoding algorithms.
namespace {
// Common constants used for all baseN encoding.
const char BASE_PADDING_CHAR = '=';
const uint8_t BINARY_ZERO_CODE = 0;
// EncodeNormalizer is an input iterator intended to be used as a filter
// between the binary stream and baseXX_from_binary translator (via
// transform_width). An EncodeNormalizer object is configured with two
// iterators (base and base_end), specifying the head and end of the input
// stream. It internally iterators over the original stream, and return
// each byte of the stream intact via its dereference operator until it
// reaches the end of the stream. After that the EncodeNormalizer object
// will return 0 no matter how many times it is subsequently incremented.
// This is necessary because the input binary stream may not contain
// sufficient bits for a full encoded text while baseXX_from_binary expects
// a sufficient length of input.
// Note: this class is intended to be used within this implementation file,
// and assumes "base < base_end" on construction without validating the
// arguments. The behavior is undefined if this assumption doesn't hold.
class EncodeNormalizer : public iterator<input_iterator_tag, uint8_t> {
public:
EncodeNormalizer(const vector<uint8_t>::const_iterator& base,
const vector<uint8_t>::const_iterator& base_end) :
base_(base), base_end_(base_end), in_pad_(false)
{}
EncodeNormalizer& operator++() {
if (!in_pad_) {
++base_;
}
if (base_ == base_end_) {
in_pad_ = true;
}
return (*this);
}
const uint8_t& operator*() const {
if (in_pad_) {
return (BINARY_ZERO_CODE);
} else {
return (*base_);
}
}
bool operator==(const EncodeNormalizer& other) const {
return (base_ == other.base_);
}
private:
vector<uint8_t>::const_iterator base_;
const vector<uint8_t>::const_iterator base_end_;
bool in_pad_;
};
// DecodeNormalizer is an input iterator intended to be used as a filter
// between the encoded baseX stream and binary_from_baseXX.
// A DecodeNormalizer object is configured with three string iterators
// (base, base_beinpad, and base_beginpad), specifying the head of the string,
// the beginning position of baseX padding (when there's padding), and
// end of the string, respectively. It internally iterators over the original
// stream, and return each character of the encoded string via its dereference
// operator until it reaches base_beginpad. After that the DecodeNormalizer
// will return the encoding character corresponding to the all-0 value
// (which is specified on construction via base_zero_code. see also
// BaseZeroCode below). This translation is necessary because
// binary_from_baseXX doesn't accept the padding character (i.e. '=').
// Note: this class is intended to be used within this implementation file,
// and for simplicity assumes "base < base_beginpad <= base_end" on
// construction without validating the arguments. The behavior is undefined
// if this assumption doesn't hold.
class DecodeNormalizer : public iterator<input_iterator_tag, char> {
public:
DecodeNormalizer(const char base_zero_code,
const string::const_iterator& base,
const string::const_iterator& base_beginpad,
const string::const_iterator& base_end) :
base_zero_code_(base_zero_code),
base_(base), base_beginpad_(base_beginpad), base_end_(base_end),
in_pad_(false)
{}
DecodeNormalizer& operator++() {
++base_;
while (base_ != base_end_ && isspace(*base_)) {
++base_;
}
if (base_ == base_beginpad_) {
in_pad_ = true;
}
return (*this);
}
const char& operator*() const {
if (in_pad_ && *base_ == BASE_PADDING_CHAR) {
return (base_zero_code_);
} else {
return (*base_);
}
}
bool operator==(const DecodeNormalizer& other) const {
return (base_ == other.base_);
}
private:
const char base_zero_code_;
string::const_iterator base_;
const string::const_iterator base_beginpad_;
const string::const_iterator base_end_;
bool in_pad_;