finished self-implementation of DNS resolver recursion; will now remove all that!
[pingcheck] / src / dns / dnscache.cpp
index f065223..e87c039 100644 (file)
@@ -36,6 +36,8 @@
 #include <boost/archive/xml_oarchive.hpp>
 #include <boost/archive/xml_iarchive.hpp>
 
+#include "dns/dnsmaster.h"
+
 using boost::bind;
 using boost::posix_time::seconds;
 using I2n::Logger::GlobalLogger;
@@ -43,10 +45,9 @@ using I2n::Logger::GlobalLogger;
 namespace Config
 {
     int SaveTimerSeconds = 60;
+    int MaxRetrievalRecursions = 10;
 }
 
-
-
 DnsCache::DnsCache(const IoServiceItem &io_serv,
                    const std::string &cache_file)
     : IpCache()
@@ -182,16 +183,16 @@ void DnsCache::update(const std::string &hostname,
 
 
 void DnsCache::update(const std::string &hostname,
-                      const std::string &cname)
+                      const Cname &cname)
 {
     GlobalLogger.info() << "DnsCache: update CNAME for " << hostname
-                        << " to " << cname;
+                        << " to " << cname.first;
     CnameCache[hostname] = cname;
     HasChanged = true;
 }
 
 
-void DnsCache::update_ttl(const std::string &hostname,
+void DnsCache::update(const std::string &hostname,
                           const uint32_t new_ttl)
 {
     GlobalLogger.info() << "DnsCache: ensure TTL for IPs for " << hostname
@@ -212,31 +213,72 @@ void DnsCache::update_ttl(const std::string &hostname,
 }
 
 
-HostAddressVec& DnsCache::get_ips(const std::string &hostname)
+HostAddressVec DnsCache::get_ips(const std::string &hostname,
+                                 const bool check_up_to_date)
 {
+    HostAddressVec result = IpCache[hostname];
+    if (check_up_to_date)
+    {
+        HostAddressVec result_up_to_date;
+        int threshold = DnsMaster::get_instance()
+                        ->get_resolved_ip_ttl_threshold();
+        BOOST_FOREACH( const HostAddress &addr, result )
+        {
+            if (addr.get_ttl().get_updated_value() > threshold)
+                result_up_to_date.push_back(addr);
+        }
+        GlobalLogger.debug() << "DnsCache: From cached list of size "
+             << result.size() << " return " << result_up_to_date.size()
+             << " since rest out of date";
+        result = result_up_to_date;
+    }
     GlobalLogger.info() << "DnsCache: request IPs for " << hostname
-                        << " --> " << IpCache[hostname].size() << "-list";
-    return IpCache[hostname];
+                        << " --> " << result.size() << "-list";
+    return result;
 }
 
-std::string& DnsCache::get_cname(const std::string &hostname)
+std::string DnsCache::get_cname(const std::string &hostname,
+                                 const bool check_up_to_date)
 {
+    Cname result_obj = CnameCache[hostname];
     GlobalLogger.info() << "DnsCache: request CNAME for " << hostname
-                        << " --> \"" << CnameCache[hostname] << "\"";
-    return CnameCache[hostname];
+                        << " --> \"" << result_obj.first << "\"";
+    if (check_up_to_date)
+    {
+        if (result_obj.second.get_updated_value() > DnsMaster::get_instance()
+                                              ->get_resolved_ip_ttl_threshold())
+            return result_obj.first;
+        else
+        {
+            GlobalLogger.debug() << "DnsCache: Cname is out of date";
+            return "";
+        }
+    }
+    else
+        return result_obj.first;
 }
 
-HostAddressVec& DnsCache::get_ips_recursive(const std::string &hostname)
+// underlying assumption in this function: for a hostname, the cache has either
+// a list of IPs saved or a cname saved, but never both
+HostAddressVec DnsCache::get_ips_recursive(const std::string &hostname,
+                                           const bool check_up_to_date)
 {
     std::string current_host = hostname;
-    HostAddressVec& result = get_ips(current_host);
+    HostAddressVec result = get_ips(current_host);
+    int n_recursions = 0;
     while ( result.empty() )
     {
-        current_host = get_cname(current_host);
+        current_host = get_cname(current_host, check_up_to_date);
         if (current_host.empty())
             break;
+        else if (++n_recursions >= Config::MaxRetrievalRecursions)
+        {
+            GlobalLogger.warning() << "DnsCache: reached recursion limit of "
+                << n_recursions << " in recursive IP retrieval!";
+            break;
+        }
         else
-            result = get_ips(current_host);
+            result = get_ips(current_host, check_up_to_date);
     }
     return result;
 }