done except for saving/loading cache; not being used yet but does compile (except...
authorChristian Herdtweck <christian.herdtweck@intra2net.com>
Thu, 9 Apr 2015 12:01:33 +0000 (14:01 +0200)
committerChristian Herdtweck <christian.herdtweck@intra2net.com>
Mon, 4 May 2015 14:57:57 +0000 (16:57 +0200)
src/CMakeLists.txt
src/dns_neww/dnscache.cpp
src/dns_neww/dnscache.h
src/dns_neww/dnsmaster.cpp
src/dns_neww/dnsmaster.h
src/dns_neww/dnsresolver.cpp
src/dns_neww/dnsresolver.h
src/dns_neww/ippseudoresolver.h
src/dns_neww/resolverbase.cpp [new file with mode: 0644]
src/dns_neww/resolverbase.h

index e956995..1645316 100644 (file)
@@ -62,8 +62,9 @@ set(SOURCES
     config/option/maxaddressresolutionattemptsoption.cpp
     config/option/resolvedipttlthresholdoption.cpp
     dns_neww/dnscache.cpp
-    dns_neww/dnsmaster.cpp
+    dns_neww/resolverbase.cpp
     dns_neww/dnsresolver.cpp
+    dns_neww/dnsmaster.cpp
     dns/dnsresolver.cpp
     dns/dnsresolverfactory.cpp
     dns/hostaddress.cpp
index 9e1b004..f7ae74f 100644 (file)
@@ -118,7 +118,7 @@ void DnsCache::load_from_cachefile()
  * @returns true if changed cache; returns false if new_data is same as cache
  */
 void DnsCache::update(const std::string &hostname,
-                      const HostAddressList &new_data)
+                      const HostAddressVec &new_data)
 {
     GlobalLogger.info() << "DNS Cache: update IPs for " << hostname
                         << " to " << new_data.size() << "-list";
@@ -127,7 +127,7 @@ void DnsCache::update(const std::string &hostname,
 }
 
 
-HostAddressList DnsCache::get_data(const std::string &hostname)
+HostAddressVec& DnsCache::get_data(const std::string &hostname)
 {
     GlobalLogger.info() << "DNS Cache: request IPs for " << hostname
                         << " --> " << DataCache[hostname].size() << "-list";
index 4e5d889..9600901 100644 (file)
@@ -32,7 +32,8 @@
 #include "host/pinger.h"    // for IoserviceItem
 #include "dns/hostaddress.h"
 
-typedef std::map<std::string, HostAddressList> cache_map_type;
+typedef std::vector<HostAddress> HostAddressVec;
+typedef std::map<std::string, HostAddressVec> cache_map_type;
 
 class DnsCache
 {
@@ -42,8 +43,8 @@ public:
     ~DnsCache();
 
     // accessed from ResolverBase subclasses
-    void update(const std::string &host_name, const HostAddressList &new_data);
-    HostAddressList get_data(const std::string &hostname);
+    void update(const std::string &host_name, const HostAddressVec &new_data);
+    HostAddressVec& get_data(const std::string &hostname);
 
 // variables
 private:
index 17b3dde..5c791a7 100644 (file)
 
 #include <logfunc.hpp>
 #include <boost/bind.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
 #include <boost/asio/placeholders.hpp>
 
 #include "dns_neww/ippseudoresolver.h"
 #include "dns_neww/dnsresolver.h"
 
 using boost::bind;
-using boost::posix_time::seconds;
-using boost::posix_time::minutes;
 using I2n::Logger::GlobalLogger;
 
 
@@ -59,9 +56,9 @@ DnsMaster::DnsMaster(const IoServiceItem &io_serv,
                      const boost::asio::ip::address &name_server,
                      const DnsCacheItem &cache)
     : IoService( io_serv )
-    , ResolverMap()
     , NameServer( name_server )
     , Cache(cache)
+    , ResolverMap()
 {
 }
 
@@ -87,14 +84,18 @@ ResolverItem& DnsMaster::get_resolver_for( const std::string &hostname )
         {
             GlobalLogger.info() << "Creating PseudoResolver for IP "
                                 << hostname;
-            ResolverItem new_resolver( new IpPseudoResolver(hostname, Cache) );
+            ResolverItem new_resolver( new IpPseudoResolver(IoService,
+                                                            hostname,
+                                                            Cache) );
             master->ResolverMap[hostname] = new_resolver;
         }
         else
         {
             GlobalLogger.info() << "Creating Resolver for host " << hostname;
-            ResolverItem new_resolver( new DnsResolver(hostname,  Cache,
-                                                       IoService, NameServer) );
+            ResolverItem new_resolver( new DnsResolver(IoService,
+                                                       hostname,
+                                                       Cache,
+                                                       NameServer) );
             master->ResolverMap[hostname] = new_resolver;
         }
     }
index 28ad1f4..028e831 100644 (file)
@@ -68,7 +68,7 @@ private:
 
     DnsMaster(const IoServiceItem &io_serv,
               const boost::asio::ip::address &name_server,
-              const std::string &cache_file);
+              const DnsCacheItem &cache);
 public:
     static DnsMasterItem& get_instance();
     ~DnsMaster();
@@ -76,9 +76,9 @@ public:
 // variables
 private:
     IoServiceItem IoService;
+    const boost::asio::ip::address NameServer;
     DnsCacheItem Cache;
     resolver_map_type ResolverMap;
-    const boost::asio::ip::address NameServer;
 
 
 // functions
index bbdc066..35bd772 100644 (file)
  on this file might be covered by the GNU General Public License.
 
  Christian Herdtweck, Intra2net AG 2015
+
+ with code copied from boost::net::dns::resolve.hpp
+ by Andreas Haberstroh (andreas at ibusy dot com)
+    from https://github.com/softwareace/Boost.DNS
  */
 
 #include "dns_neww/dnsresolver.h"
 
+#include <boost/foreach.hpp>
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+#include <boost/net/dns.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
 #include <logfunc.hpp>
+
 using I2n::Logger::GlobalLogger;
+using boost::posix_time::seconds;
+using boost::posix_time::minutes;
 
 namespace Config
 {
@@ -35,20 +48,18 @@ namespace Config
     const int MaxRetryCount = 5;
 }
 
-DnsResolver::DnsResolver(const std::string &hostname,
+DnsResolver::DnsResolver(IoServiceItem &io_serv,
+                         const std::string &hostname,
                          const DnsCacheItem cache,
-                         IoServiceItem &io_serv,
                          const boost::asio::ip::address &name_server)
-    : ResolverBase( hostname, cache )
-    , IoService( io_serv )
+    : ResolverBase( io_serv, hostname, cache )
     , Socket( *io_serv, ip::udp::endpoint(ip::udp::v4(), 0) )
-    , ReplyBuffer()
-    , NameServer( name_server, DNS_PORT )
+    , ReceiveBuffer()
+    , NameServer( name_server, Config::DNS_PORT )
     , ResolveTimeoutTimer( *io_serv )
     , PauseBeforeRetryTimer( *io_serv )
     , StaleDataLongtermTimer( *io_serv )
-    , CallbackList()
-    , HostAddressList::const_iterator()
+    , NextIpIndex( 0 )
     , RetryCount( 0 )
     , IsResolving( false )
 { }
@@ -61,24 +72,14 @@ DnsResolver::DnsResolver(const std::string &hostname,
 /**
  * copied here code from boost::net::dns::resolve.hpp, since want async 
  * operation and that is used only internally, there
- * --> give credit to Andreas Haberstroh (andreas at ibusy dot com)
- *     from https://github.com/softwareace/Boost.DNS
- *     
- * callbacks should be of type
- * void resolve_callback(const boost::system::error_code &error,
- *                       const bool was_success,
- *                       const int cname_count)
  */
-DnsResolver::async_resolve(const callback_type callback)
+void DnsResolver::do_resolve()
 {
-    // remember callback
-    CallbackList.push(callback);
-
     // check if resolving already
-    if (isResolving)
+    if (IsResolving)
     {
         GlobalLogger.info()
-            << "Call to async_resolve ignored since resolving already";
+            << "Call to do_resolve ignored since resolving already";
         return;
     }
 
@@ -88,13 +89,13 @@ DnsResolver::async_resolve(const callback_type callback)
     StaleDataLongtermTimer.cancel();
 
     // create DNS request
-    boost::net::dns::message dns_message( host_dns_address,
+    boost::net::dns::message dns_message( ResolverBase::Hostname,
                                           boost::net::dns::type_all );
     dns_message.recursive(false);
-    dns_message.action(dns::message::query);
-    dns_message.opcode(dns::message::squery);
-    dns_message.id(UniqueID);
-    dns_buffer_t request_buffer;
+    dns_message.action(boost::net::dns::message::query);
+    dns_message.opcode(boost::net::dns::message::squery);
+    dns_message.id(Config::UniqueID);
+    boost::net::dns_buffer_t request_buffer;
     dns_message.encode(request_buffer);
 
     // setup receipt of reply
@@ -104,12 +105,14 @@ DnsResolver::async_resolve(const callback_type callback)
             boost::bind( &DnsResolver::handle_dns_result, this,
                          boost::asio::placeholders::error,
                          boost::asio::placeholders::bytes_transferred)
-    )
+    );
 
     // schedule timeout
-    (void) ResolveTimeoutTimer.expires_from_now(seconds(ResolveTimeoutSeconds));
-    ResolveTimeout.async_wait( bind( &DnsResolver::handle_resolve_timeout,
-                                     this, boost::asio::placeholders::error) );
+    (void) ResolveTimeoutTimer.expires_from_now(
+                                        seconds(Config::ResolveTimeoutSeconds));
+    ResolveTimeoutTimer.async_wait( boost::bind(
+                                      &DnsResolver::handle_resolve_timeout,
+                                      this, boost::asio::placeholders::error) );
 
     // send dns request
     Socket.send_to( boost::asio::buffer(request_buffer.get_array()),
@@ -117,18 +120,18 @@ DnsResolver::async_resolve(const callback_type callback)
 }
 
 
-void handle_dns_result(const boost::system::error_code &error,
+void DnsResolver::handle_dns_result(const boost::system::error_code &error,
                        const std::size_t bytes_transferred)
 {
     if ( error ==  boost::asio::error::operation_aborted )   // cancelled
     {
-        resolve_log.info() << "DNS resolve operation was cancelled";
+        GlobalLogger.info() << "DNS resolve operation was cancelled";
         bool was_success = false;
         finalize_resolve(was_success);
     }
     else if (error)
     {
-        resolve_log.info() << "DNS resolve resulted in error " << error
+        GlobalLogger.info() << "DNS resolve resulted in error " << error
                             << " --> treat like unavailable";
         handle_unavailable();
         return;
@@ -137,39 +140,47 @@ void handle_dns_result(const boost::system::error_code &error,
     // next 3(+1) lines copied from boost/net/dns/resolver.hpp:
     // clamp the recvBuffer with the number of bytes transferred or decode buffr
     ReceiveBuffer.length(bytes_transferred);
-    message result_message();
+    boost::net::dns::message result_message;
     result_message.decode( ReceiveBuffer );
 
-    if (result_message.answers().size == 0)
+    // work with a regular pointer to list of answers since result_message is
+    //   owner of data and that exists until end of function
+    // Items in answers list are shared_ptr to resource_base_t
+    boost::net::dns::rr_list_t *answers = result_message.answers();
+    if (answers->size() == 0)
         handle_unavailable();
 
     // loop over answers, remembering ips and cnames
-    typedef boost::shared_ptr<resource_base_t> rr_item_type;
-    typedef boost::shared_ptr<cname_resource> cname_item_type;
-    HostAddressList ip_list;
-    std::vector<cname_item_type> cname_list;
-    BOOST_FOREACH( rr_item_type rr_item, result_message.answers() )
+    HostAddressVec result_ips;
+    std::vector<std::string> result_cnames;
+    using boost::net::dns::resource_base_t;
+    BOOST_FOREACH( boost::shared_ptr<resource_base_t> rr_item, *answers )
     {
-        GlobalLogger.debug() << std::showbase << std::hex << rr_item->rtype()
-                             << ": ";
+        GlobalLogger.debug() << std::showbase << std::hex
+                             << static_cast<unsigned>(rr_item->rtype()) << ": ";
         uint32_t ttl = rr_item->ttl();
-        type_t rr_type = rr_item->rtype();
+        boost::net::dns::type_t rr_type = rr_item->rtype();
 
         if (rr_type == boost::net::dns::type_a)
         {    // 'A' resource records carry IPv4 addresses
-            std::string ip = ( dynamic_cast<a_resource *> (rr_item.get()) )
-                             ->address();
-            ip_list.push_back( HostAddress(ip, ttl) );
+            boost::asio::ip::address_v4 ip =
+                ( dynamic_cast<boost::net::dns::a_resource *> (rr_item.get()) )
+                ->address();
+            result_ips.push_back( HostAddress(ip, ttl) );
         }
         else if (rr_type == boost::net::dns::type_a6)
         {   // 'AAAA' resource records carry IPv6 addresses
-            std::string ip = ( dynamic_cast<a6_resource *> (rr_item.get()) )
-                             ->address();
-            ip_list.push_back( HostAddress(ip, ttl) );
+            boost::asio::ip::address_v6 ip =
+                ( dynamic_cast<boost::net::dns::a6_resource *> (rr_item.get()) )
+                ->address();
+            result_ips.push_back( HostAddress(ip, ttl) );
         }
         else if (rr_type == boost::net::dns::type_cname)
         {   // 'CNAME' resource records that carry aliases
-            cname_list.push_back(dynamic_cast<cname_item_type>(rr_item));
+            std::string cname =
+                (dynamic_cast<boost::net::dns::cname_resource *>(rr_item.get()))
+                ->canonicalname();
+            result_cnames.push_back( cname );
         }
         else if (rr_type == boost::net::dns::type_ns)
             GlobalLogger.debug() << "NS resource";
@@ -191,25 +202,25 @@ void handle_dns_result(const boost::system::error_code &error,
             GlobalLogger.debug() << "unknown resource type";
     }
 
-    GlobalLogger.info() << "Have " << ip_list.size() << " IPs and "
-                        << cname_list.size() << " CNAMEs";
+    GlobalLogger.info() << "Have " << result_ips.size() << " IPs and "
+                        << result_cnames.size() << " CNAMEs";
 
     // We expect either one single CNAME and no IPs or a list of IPs.
     // But deal with other cases as well
-    if (ip_list.empty() && cname_list.empty())
+    if (result_ips.empty() && result_cnames.empty())
         handle_unavailable();   // we just got crap, this is a dead end
-    else if ( !ip_list.empty() && !cname_list.empty())
+    else if ( !result_ips.empty() && !result_cnames.empty())
         GlobalLogger.warning() << "Have CNAMEs AND IPs --> deal with both!";
 
-    BOOST_FOREACH( const cname_resource &cname, cname_list )
+    BOOST_FOREACH( const std::string &cname, result_cnames )
         handle_cname(cname);  // will schedule another DNS call
 
-    if ( !ip_list.empty() )
-        handle_ips(ip_list);
+    if ( !result_ips.empty() )
+        handle_ips(result_ips);
 }
 
 
-void DnsResolver::handle_ips(const HostAddressList &ips)
+void DnsResolver::handle_ips(const HostAddressVec &ips)
 {
     // save in cache
     ResolverBase::update_cache( ips );
@@ -223,10 +234,11 @@ void DnsResolver::handle_ips(const HostAddressList &ips)
 void DnsResolver::handle_unavailable()
 {
     // schedule new attempt in quite a while
-    StaleDataLongtermTimer.expires_from_now(minutes(StaleDataLongtermMinutes));
+    StaleDataLongtermTimer.expires_from_now(
+                                     minutes(Config::StaleDataLongtermMinutes));
     StaleDataLongtermTimer.async_wait(
-            bind( &DnsResolver::wait_timer_timeout_handler,
-                  this, boost::asio::placeholders::error
+            boost::bind( &DnsResolver::wait_timer_timeout_handler,
+                         this, boost::asio::placeholders::error
             )
     );
 
@@ -240,46 +252,24 @@ void DnsResolver::handle_cname(const std::string &canonical_name)
     // get resolver for canonical name
     ResolverItem resolver = DnsMaster::get_instance()
                             ->get_resolver_for(canonical_name);
-    resolver->async_resolve(
-            bind( &DnsResolver::cname_resolve_callback,
-                  this, boost::asio::placeholders::error,
-                  canonical_name, _1, _2
-            )
-    );
+    callback_type callback = boost::bind( &DnsResolver::cname_resolve_callback,
+                                          this, canonical_name, _1, _2 );
+    resolver->async_resolve( callback );
 
     stop_trying();
 }
 
 
-void cname_resolve_callback(const boost::system::error_code &error,
-                            const std::string &canonical_name,
-                            const bool was_success,
-                            const int cname_count)
+void DnsResolver::cname_resolve_callback(const std::string &canonical_name,
+                                         const bool was_success,
+                                         const int cname_count)
 {
-    bool was_success = true;
-
-    if ( error ==  boost::asio::error::operation_aborted )   // cancelled
-    {
-        GlobalLogger.warning()
-            << "Recursive resolution of cname was cancelled!";
-        was_success = false;
-    }
-    else if (error)
-    {
-        GlobalLogger.warning() << "Error " << error
-            << " waiting for callback from cname resolution!"
-        was_success = false;
-    }
     if (was_success)
-    {   // tell cache to return cname's ips if queried for our hostname
+        // tell cache to return cname's ips if queried for our hostname
         ResolverBase::update_cache(
                              ResolverBase::get_cached_results(canonical_name) );
-    }
     else
-    {
         GlobalLogger.info() << "Cname resolution failed";
-        was_success = false;
-    }
 
     finalize_resolve(was_success, cname_count+1);
 }
@@ -294,13 +284,7 @@ void DnsResolver::finalize_resolve(const bool was_success,
     // else was called already from handle_cname
 
     // schedule callbacks, clearing callback list
-    while ( !CallbackList.empty )
-    {
-        IoService.post( bind( CallbackList.front(),
-                              boost::asio::placeholders::error,
-                              was_success, cname_count ) );
-        CallbackList.pop();
-    }
+    ResolverBase::schedule_callbacks(was_success, cname_count);
 
     // finalize
     GlobalLogger.notice() << "Done resolving"
@@ -321,7 +305,7 @@ void DnsResolver::stop_trying()
     RetryCount = 0;
 }
 
-viod DnsResolver::handle_resolve_timeout(const boost::system::error_code &error)
+void DnsResolver::handle_resolve_timeout(const boost::system::error_code &error)
 {
     if ( error ==  boost::asio::error::operation_aborted )   // cancelled
     {
@@ -340,7 +324,7 @@ viod DnsResolver::handle_resolve_timeout(const boost::system::error_code &error)
     // increment timer
     ++RetryCount;
 
-    if (RetryCount > MaxRetryCount)
+    if (RetryCount > Config::MaxRetryCount)
     {
         handle_unavailable();
         RetryCount = 0;
@@ -348,10 +332,10 @@ viod DnsResolver::handle_resolve_timeout(const boost::system::error_code &error)
     else
     {   // schedule retry
         PauseBeforeRetryTimer.expires_from_now(
-                seconds(PauseBeforeRetrySeconds));
+                seconds(Config::PauseBeforeRetrySeconds));
         PauseBeforeRetryTimer.async_wait(
-                bind( &DnsResolver::wait_timer_timeout_handler,
-                      this, boost::asio::placeholders::error) );
+                boost::bind( &DnsResolver::wait_timer_timeout_handler,
+                             this, boost::asio::placeholders::error) );
     }
 }
 
@@ -366,7 +350,7 @@ void DnsResolver::wait_timer_timeout_handler(
     else
     {
         GlobalLogger.info() << "Done waiting --> re-try resolve";
-        async_resolve();
+        do_resolve();
     }
 }
 
@@ -375,14 +359,17 @@ void DnsResolver::wait_timer_timeout_handler(
 // RETRIEVAL
 //==============================================================================
 
-HostAddress& DnsResolver::get_next_ip()
+HostAddress DnsResolver::get_next_ip()
 {
     // get cached data
-    ResolverBase::get_cached_results();
+    HostAddressVec cached_data = ResolverBase::get_cached_results();
 
     // if no results cached, return default-constructed HostAddress (0.0.0.0)
     if ( cached_data.empty() )
-        return HostAddress;
+    {
+        HostAddress return_value;
+        return return_value;
+    }
 
     // check validity of index (cache may have changed since last call)
     if (NextIpIndex >= cached_data.size())
index 6141d92..4565cb1 100644 (file)
 
 #include "dns_neww/dnsmaster.h"
 
-#include <queue>
 #include <boost/asio/deadline_timer.hpp>
 #include <boost/asio/ip/udp.hpp>
 #include <boost/asio/ip/address.hpp>
 #include <boost/system/error_code.hpp>
 #include <boost/net/network_array.hpp>
 
-#include "host/pinger.h"    // for IoServiceItem
 #include "dns_neww/resolverbase.h"
 #include "dns_neww/dnsmaster.h"
 #include "dns_neww/dnscache.h"
 
-typedef std::list<callback_type> callback_list_type;
-
-typedef std::queue<HostAddress> IpTtlVec;
 
 class DnsResolver : public ResolverBase
 {
@@ -48,27 +43,30 @@ public:
 
 // constructor accessible from friend DnsMaster
 public:
-    friend DnsResolverItem DnsMaster::get_resolver_for(const std::string&);
+    friend ResolverItem& DnsMaster::get_resolver_for(
+                                                   const std::string &hostname);
 private:
-    DnsResolver(const std::string &hostname,
+    DnsResolver(IoServiceItem &io_serv,
+                const std::string &hostname,
                 const DnsCacheItem cache,
-                IoServiceItem &io_serv,
                 const boost::asio::ip::address &name_server);
 
-// only real public functions (called from pingers)
+// only real public function (called from pingers)
 public:
-    void async_resolve(const callback_type &callback);
-    HostAddress& get_next_ip();
+    HostAddress get_next_ip();
+
+// implementation of ResolverBase::async_resolve
+protected:
+    void do_resolve();
 
 private:
     void handle_resolve_timeout(const boost::system::error_code &error);
     void handle_dns_result(const boost::system::error_code &error,
                            const std::size_t bytes_transferred);
-    void handle_unavailable(const boost::system::error_code &error);
-    void handle_ips(const boost::system::error_code &error,
-                    const IpTtlVec &ips);
-    void handle_cname(const boost::system::error_code &error);
-    void cname_resolve_callback(const boost::system::error_code &error,
+    void handle_unavailable();
+    void handle_ips(const HostAddressVec &ips);
+    void handle_cname(const std::string &canonical_name);
+    void cname_resolve_callback(const std::string &canonical_name,
                                 const bool was_success,
                                 const int cname_count);
     void finalize_resolve(const bool success, const int cname_count=0);
@@ -76,15 +74,13 @@ private:
     void wait_timer_timeout_handler(const boost::system::error_code &error);
 
 private:
-    IoServiceItem IoService;
     boost::asio::ip::udp::socket Socket;
-    boost::net::dns_buffer_t ReplyBuffer;
+    boost::net::dns_buffer_t ReceiveBuffer;
     boost::asio::ip::udp::endpoint NameServer;
     boost::asio::deadline_timer ResolveTimeoutTimer;
     boost::asio::deadline_timer PauseBeforeRetryTimer;
     boost::asio::deadline_timer StaleDataLongtermTimer;
-    callback_list_type CallbackList;
-    int NextIpIndex;
+    std::size_t NextIpIndex;
     int RetryCount;
     bool IsResolving;
 };
index 72edf8f..f5fd006 100644 (file)
@@ -23,6 +23,8 @@
 #ifndef IP_PSEUDO_RESOLVER_H
 #define IP_PSEUDO_RESOLVER_H
 
+#include <boost/asio/ip/address.hpp>
+#include "dns/hostaddress.h"
 #include "dns_neww/resolverbase.h"
 #include "dns_neww/dnsmaster.h"
 
@@ -47,22 +49,25 @@ public:
     friend ResolverItem& DnsMaster::get_resolver_for(
                                                    const std::string &hostname);
 private:
-    IpPseudoResolver(const std::string &ip,
+    IpPseudoResolver(const IoServiceItem io_serv,
+                     const std::string &ip_string,
                      const DnsCacheItem &cache )
-        : ResolverBase( ip, cache )
-        , Ip( ip, Config::DefaultTtl )
+        : ResolverBase( io_serv, ip_string, cache )
+        , IpAddress( boost::asio::ip::address::from_string(ip_string),
+                     Config::DefaultTtl )
     {}
 
 private:
-    HostAddress Ip;
+    HostAddress IpAddress;
 
-// only functions, inherited from ResolverBase
+// only real public function
 public:
-    HostAddress& get_next_ip()  { return Ip;  }
-    void async_resolve(const callback_type &callback)
-    {
-        IoService.post( bind(callback, true, 0) );
-    }
+    HostAddress get_next_ip()  { return IpAddress;  }
+
+// implementation of ResolverBase::async_resolve
+protected:
+    void do_resolve()
+    {   ResolverBase::schedule_callbacks(true, 0);   }
 };
 #endif
 
diff --git a/src/dns_neww/resolverbase.cpp b/src/dns_neww/resolverbase.cpp
new file mode 100644 (file)
index 0000000..2dccf4e
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ The software in this package is distributed under the GNU General
+ Public License version 2 (with a special exception described below).
+
+ A copy of GNU General Public License (GPL) is included in this distribution,
+ in the file COPYING.GPL.
+
+ As a special exception, if other files instantiate templates or use macros
+ or inline functions from this file, or you compile this file and link it
+ with other works to produce a work based on this file, this file
+ does not by itself cause the resulting work to be covered
+ by the GNU General Public License.
+
+ However the source code for this file must still be made available
+ in accordance with section (3) of the GNU General Public License.
+
+ This exception does not invalidate any other reasons why a work based
+ on this file might be covered by the GNU General Public License.
+
+ Christian Herdtweck, Intra2net AG 2015
+ */
+
+#include "dns_neww/resolverbase.h"
+#include "dns_neww/dnsmaster.h"
+
+#include <boost/bind.hpp>
+
+ResolverBase::~ResolverBase()
+{
+    DnsMaster::get_instance()->unregister_resolver(Hostname);
+}
+
+/**
+ * callbacks should be of type
+ * void resolve_callback(const bool was_success,
+ *                       const int cname_count)
+ */
+void ResolverBase::async_resolve(const callback_type &callback)
+{
+    // remember callback
+    CallbackList.push(callback);
+
+    // let subclass do the resolving
+    do_resolve();
+}
+
+ResolverBase::ResolverBase(const IoServiceItem &io_serv,
+             const std::string &hostname,
+             const DnsCacheItem &cache )
+    : IoService( io_serv )
+    , Hostname( hostname )
+    , Cache( cache )
+    , CallbackList()
+{}
+
+void ResolverBase::update_cache( const HostAddressVec &new_results ) const
+{   Cache->update( Hostname, new_results );  }
+
+HostAddressVec& ResolverBase::get_cached_results(const std::string host) const
+{
+    if (host.empty())
+        return Cache->get_data( Hostname );
+    else
+        return Cache->get_data( host );
+}
+
+void ResolverBase::schedule_callbacks(const bool was_success,
+                                      const int cname_count)
+{
+    while ( !CallbackList.empty() )
+    {
+        callback_type callback = CallbackList.front();
+        CallbackList.pop();
+        IoService->post( boost::bind( callback,
+                                      was_success, cname_count ) );
+    }
+}
+
+// (created using vim -- the world's best text editor)
+
index 8daab9f..cbd6ae6 100644 (file)
 #define RESOLVER_BASE_H
 
 #include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
 
+#include <queue>
+#include "host/pinger.h"
 #include "dns/hostaddress.h"
 #include "dns_neww/dnscache.h"
-#include "dns_neww/dnsmaster.h"
 
-
-class ResolverBase;
-typedef boost::shared_ptr<ResolverBase> ResolverItem;
-
-typedef void (*callback_type)(const bool, const int);
+typedef boost::function<void(const bool, const int)> callback_type;
+typedef std::queue<callback_type> callback_list_type;
 
 /**
  * @brief: abstract base class for DnsResolver and IpPseudoResolver
@@ -41,39 +40,44 @@ typedef void (*callback_type)(const bool, const int);
 class ResolverBase
 {
 public:
-    virtual HostAddress& get_next_ip() = 0;
-    virtual void async_resolve(const callback_type &callback) = 0;
-    virtual ~ResolverBase()
-    {
-        DnsMaster::get_instance()->unregister(Hostname);
-    }
+    virtual HostAddress get_next_ip() = 0;
+
+    virtual ~ResolverBase();
+
+    /**
+     * callbacks should be of type
+     * void resolve_callback(const bool was_success,
+     *                       const int cname_count)
+     */
+    void async_resolve(const callback_type &callback);
 
 protected:
-    ResolverBase(const std::string &hostname,
-                 const DnsCacheItem &cache )
-        : Hostname( hostname )
-        , Cache( cache )
-    {}
+    ResolverBase(const IoServiceItem &io_serv,
+                 const std::string &hostname,
+                 const DnsCacheItem &cache );
 
 // variables
-private:
+protected:
+    IoServiceItem IoService;
     std::string Hostname;
     DnsCacheItem Cache;
+    callback_list_type CallbackList;
 
 // functions for subclasses
 protected:
-    void update_cache( const HostAddressList &new_results ) const
-    {   Cache->update( Hostname, new_results );  }
-
-    HostAddressList get_cached_results(const std::string host="") const
-    {
-        if (host.empty())
-            return Cache->get_data( Hostname );
-        else
-            return Cache->get_data( host );
-    }
+    virtual void do_resolve() = 0;
+
+    void update_cache( const HostAddressVec &new_results ) const;
+
+    HostAddressVec& get_cached_results(const std::string host="") const;
+
+    void schedule_callbacks(const bool was_success,
+                            const int cname_count);
+
 };
 
+typedef boost::shared_ptr<ResolverBase> ResolverItem;
+
 #endif
 
 // (created using vim -- the world's best text editor)