Browse Source

[trac583] Added a qid_gen for random qids

Simple uniform random number generator using boost.

At this moment, it is in asiolink, because that is where it is used. It should be moved to a lib/util (or something), together with the non-uniform nsas rng.

Also note that IOFetch now *sets* a random qid, but does not actually check it when it receives an answer.
Jelte Jansen 14 years ago
parent
commit
b723719cda

+ 1 - 0
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)

+ 5 - 2
src/lib/asiolink/io_fetch.cc

@@ -26,6 +26,8 @@
 #include <dns/rcode.h>
 #include <log/dummylog.h>
 
+#include <asiolink/qid_gen.h>
+
 #include <asio.hpp>
 #include <asiolink/io_fetch.h>
 
@@ -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,
@@ -65,7 +68,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);

+ 62 - 0
src/lib/asiolink/qid_gen.cc

@@ -0,0 +1,62 @@
+// 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 <asiolink/qid_gen.h>
+
+#include <sys/time.h>
+
+namespace {
+    asiolink::QidGenerator* qid_generator_instance = NULL;
+}
+
+namespace asiolink {
+QidGenerator*
+QidGenerator::getInstance() {
+    if (!qid_generator_instance) {
+        qid_generator_instance = new QidGenerator();
+        qid_generator_instance->seed();
+    }
+
+    return qid_generator_instance;
+}
+
+void
+QidGenerator::cleanInstance() {
+    delete qid_generator_instance;
+    qid_generator_instance = NULL;
+}
+
+QidGenerator::QidGenerator() : dist(0, 65535), vgen(generator, dist) {}
+
+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

+ 74 - 0
src/lib/asiolink/qid_gen.h

@@ -0,0 +1,74 @@
+// 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_
+#define __QID_GEN_
+
+#include <dns/message.h>
+#include <boost/random/mersenne_twister.hpp>
+#include <boost/random/uniform_int.hpp>
+#include <boost/random/variate_generator.hpp>
+
+
+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
+    ///
+    /// Initializes a new instance if there is none.
+    static QidGenerator* getInstance();
+
+    /// \brief Cleans up the singleton instance.
+    ///
+    /// This is added so that we can run memory checkers and
+    /// not get complaints about leaking data. If getInstance()
+    /// is called after cleanInstance, a new one would be created.
+    static void cleanInstance();
+
+    /// 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 when getInstance() is called
+    /// the first time.
+    void seed();
+    
+private:
+    QidGenerator();
+    boost::mt19937 generator;
+    boost::uniform_int<> dist;
+    boost::variate_generator<boost::mt19937&, boost::uniform_int<> > vgen;
+};
+
+
+} // namespace asiolink
+
+#endif // __QID_GEN_

+ 1 - 0
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)
 

+ 63 - 0
src/lib/asiolink/tests/qid_gen_unittest.cc

@@ -0,0 +1,63 @@
+// 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 <gtest/gtest.h>
+
+#include <asiolink/qid_gen.h>
+#include <dns/message.h>
+
+// 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);
+
+    asiolink::QidGenerator::cleanInstance();
+    // Is there any way to make sure a newly allocated one gets
+    // a new address?
+}
+
+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));
+}