diff --git a/src/lib/asiolink/Makefile.am b/src/lib/asiolink/Makefile.am index b3968f0661..b0ce027ee2 100644 --- a/src/lib/asiolink/Makefile.am +++ b/src/lib/asiolink/Makefile.am @@ -35,6 +35,7 @@ libasiolink_la_SOURCES += tcp_socket.h libasiolink_la_SOURCES += udp_endpoint.h libasiolink_la_SOURCES += udp_server.h udp_server.cc libasiolink_la_SOURCES += udp_socket.h +libasiolink_la_SOURCES += qid_gen.cc qid_gen.h # Note: the ordering matters: -Wno-... must follow -Wextra (defined in # B10_CXXFLAGS) libasiolink_la_CXXFLAGS = $(AM_CXXFLAGS) diff --git a/src/lib/asiolink/io_fetch.cc b/src/lib/asiolink/io_fetch.cc index d1f722cf86..a68c4c5e10 100644 --- a/src/lib/asiolink/io_fetch.cc +++ b/src/lib/asiolink/io_fetch.cc @@ -26,6 +26,8 @@ #include #include +#include + #include #include @@ -34,8 +36,9 @@ using namespace isc::dns; using namespace isc::log; using namespace std; -namespace asiolink { + +namespace asiolink { /// IOFetch Constructor - just initialize the private data IOFetch::IOFetch(int protocol, IOService& service, @@ -64,8 +67,7 @@ IOFetch::operator()(error_code ec, size_t length) { { Message msg(Message::RENDER); - // TODO: replace with boost::random or some other suitable PRNG - msg.setQid(0); + msg.setQid(QidGenerator::getInstance().generateQid()); msg.setOpcode(Opcode::QUERY()); msg.setRcode(Rcode::NOERROR()); msg.setHeaderFlag(Message::HEADERFLAG_RD); diff --git a/src/lib/asiolink/qid_gen.cc b/src/lib/asiolink/qid_gen.cc new file mode 100644 index 0000000000..1361b95b92 --- /dev/null +++ b/src/lib/asiolink/qid_gen.cc @@ -0,0 +1,56 @@ +// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +// qid_gen defines a generator for query id's +// +// We probably want to merge this with the weighted random in the nsas +// (and other parts where we need randomness, perhaps another thing +// for a general libutil?) + +#include + +#include + +namespace { + asiolink::QidGenerator qid_generator_instance; +} + +namespace asiolink { + +QidGenerator& +QidGenerator::getInstance() { + return (qid_generator_instance); +} + +QidGenerator::QidGenerator() : dist_(0, 65535), + vgen_(generator_, dist_) +{ + seed(); +} + +void +QidGenerator::seed() { + struct timeval tv; + gettimeofday(&tv, 0); + long int seed; + seed = (tv.tv_sec * 1000000) + tv.tv_usec; + generator_.seed(seed); +} + +isc::dns::qid_t +QidGenerator::generateQid() { + return (vgen_()); +} + +} // namespace asiolink diff --git a/src/lib/asiolink/qid_gen.h b/src/lib/asiolink/qid_gen.h new file mode 100644 index 0000000000..ba3c23193c --- /dev/null +++ b/src/lib/asiolink/qid_gen.h @@ -0,0 +1,85 @@ +// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +// qid_gen defines a generator for query id's +// +// We probably want to merge this with the weighted random in the nsas +// (and other parts where we need randomness, perhaps another thing +// for a general libutil?) + +#ifndef __QID_GEN_H +#define __QID_GEN_H + +#include +#include +#include +#include + + +namespace asiolink { + +/// This class generates Qids for outgoing queries +/// +/// It is implemented as a singleton; the public way to access it +/// is to call getInstance()->generateQid(). +/// +/// It automatically seeds it with the current time when it is first +/// used. +class QidGenerator { +public: + /// \brief Returns the singleton instance of the QidGenerator + /// + /// Returns a reference to the singleton instance of the generator + static QidGenerator& getInstance(); + + /// \brief Default constructor + /// + /// It is recommended that getInstance is used rather than creating + /// separate instances of this class. + /// + /// The constructor automatically seeds the generator with the + /// current time. + QidGenerator(); + + /// Generate a Qid + /// + /// \return A random Qid + isc::dns::qid_t generateQid(); + + /// \brief Seeds the QidGenerator (based on the current time) + /// + /// This is automatically called by the constructor + void seed(); + +private: + // "Mersenne Twister: A 623-dimensionally equidistributed + // uniform pseudo-random number generator", Makoto Matsumoto and + // Takuji Nishimura, ACM Transactions on Modeling and Computer + // Simulation: Special Issue on Uniform Random Number Generation, + // Vol. 8, No. 1, January 1998, pp. 3-30. + // + // mt19937 is an implementation of one of the pseudo random + // generators described in this paper. + boost::mt19937 generator_; + + // For qid's we want a uniform distribution + boost::uniform_int<> dist_; + + boost::variate_generator > vgen_; +}; + + +} // namespace asiolink + +#endif // __QID_GEN_H diff --git a/src/lib/asiolink/tests/Makefile.am b/src/lib/asiolink/tests/Makefile.am index b4f0a87739..ba5d962e98 100644 --- a/src/lib/asiolink/tests/Makefile.am +++ b/src/lib/asiolink/tests/Makefile.am @@ -27,6 +27,7 @@ run_unittests_SOURCES += interval_timer_unittest.cc run_unittests_SOURCES += recursive_query_unittest.cc run_unittests_SOURCES += udp_endpoint_unittest.cc run_unittests_SOURCES += udp_socket_unittest.cc +run_unittests_SOURCES += qid_gen_unittest.cc run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) diff --git a/src/lib/asiolink/tests/qid_gen_unittest.cc b/src/lib/asiolink/tests/qid_gen_unittest.cc new file mode 100644 index 0000000000..3ad8a03c51 --- /dev/null +++ b/src/lib/asiolink/tests/qid_gen_unittest.cc @@ -0,0 +1,59 @@ +// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + + +/// \brief Test of QidGenerator +/// + +#include + +#include +#include + +// Tests the operation of the Qid generator + +// Check that getInstance returns a singleton +TEST(QidGenerator, singleton) { + asiolink::QidGenerator& g1 = asiolink::QidGenerator::getInstance(); + asiolink::QidGenerator& g2 = asiolink::QidGenerator::getInstance(); + + EXPECT_TRUE(&g1 == &g2); +} + +TEST(QidGenerator, generate) { + // We'll assume that boost's generator is 'good enough', and won't + // do full statistical checking here. Let's just call it the xkcd + // test (http://xkcd.com/221/), and check if three consecutive + // generates are not all the same. + isc::dns::qid_t one, two, three; + asiolink::QidGenerator& gen = asiolink::QidGenerator::getInstance(); + one = gen.generateQid(); + two = gen.generateQid(); + three = gen.generateQid(); + ASSERT_FALSE((one == two) && (one == three)); +}