Don't update the same IP more than 2 times in success.
[bpdyndnsd] / src / service.cpp
index 492425f..fa80fd9 100644 (file)
@@ -26,6 +26,7 @@ Service::Service()
     , ActualIP("0.0.0.0")
     , UpdateInterval(15)
     , MaxUpdatesWithinInterval(3)
+    , MaxEqualUpdatesInSuccession(2)
     , DNSCacheTTL(0)
     , ErrorCount(0)
     , ErrorServiceBlockedUntil(0)
@@ -139,21 +140,25 @@ Logger::Ptr Service::get_logger() const
 }
 
 
-void Service::set_last_updates(std::list<time_t> _last_updates)
+/**
+ * Setter for member LastUpdates.
+ * @param _last_updates Value to set LastUpdates to.
+ */
+void Service::set_last_updates(std::map<time_t,std::string> _last_updates)
 {
     LastUpdates.clear();
-    BOOST_FOREACH( time_t update_time, _last_updates )
+    for ( std::map<time_t,std::string>::iterator iter = _last_updates.begin(); iter != _last_updates.end(); iter++ )
     {
-        LastUpdates.push_back(update_time);
+        LastUpdates.insert(make_pair(iter->first,iter->second));
     }
 }
 
 
 /**
- * Getter for member Lastupdated.
- * @return Value of member Lastupdated.
+ * Getter for member LastUpdates.
+ * @return Value of member LastUpdates.
  */
-const list<time_t> Service::get_last_updates() const
+const std::map<time_t,std::string> Service::get_last_updates() const
 {
     return LastUpdates;
 }
@@ -179,7 +184,6 @@ std::string Service::get_actual_ip() const
 }
 
 
-
 /**
  * Overloading of comparison operator.
  * @param other Reference to other Service object.
@@ -212,14 +216,12 @@ bool Service::operator!= (const Service& other) const
  */
 bool Service::update_allowed(const time_t current_time, bool changed_to_online)
 {
-    list<time_t>::iterator iter;
-    int i=0;
-
-    for (iter = LastUpdates.begin(); (iter != LastUpdates.end()) && ( i < MaxUpdatesWithinInterval ); iter++)
+    int i = 0;
+    for ( std::map<time_t,std::string>::reverse_iterator r_iter = LastUpdates.rbegin(); (r_iter != LastUpdates.rend()) && ( i < MaxUpdatesWithinInterval ); r_iter++)
     {
-        if ( (i == (MaxUpdatesWithinInterval-1)) && ( (*iter + ((time_t)UpdateInterval*60)) >= current_time ) )
+        if ( (i == (MaxUpdatesWithinInterval-1)) && ( (r_iter->first + ((time_t)UpdateInterval*60)) >= current_time ) )
         {
-            Log->print_update_not_allowed(changed_to_online, current_time,*iter,MaxUpdatesWithinInterval,get_service_name());
+            Log->print_update_not_allowed(changed_to_online,current_time,r_iter->first,MaxUpdatesWithinInterval,get_service_name());
             return false;
         }
         i++;
@@ -253,7 +255,7 @@ void Service::update(const string& ip, const time_t current_time, bool changed_t
         if ( perform_update(ip) == 0 )
         {
             // if update was successful, we need to set the Lastupdated and ActualIP base member.
-            set_last_update(current_time);
+            set_last_update(current_time,ip);
             ActualIP = ip;
             Log->print_update_service_successful(service_name);
 
@@ -282,40 +284,54 @@ void Service::update(const string& ip, const time_t current_time, bool changed_t
 * Sets the given time into the LastUpdates member and deletes expired entries.
 * @param _timeout Value to set into LastUpdates.
 */
-void Service::set_last_update(const time_t current_time)
+void Service::set_last_update(const time_t current_time, const string& ip)
 {
     // Insert value into the list.
-    LastUpdates.push_front(current_time);
+    LastUpdates.insert(make_pair(current_time,ip));
+
+    // Get the maximum of MaxUpdatesWithinInterval and MaxEqualUpdatesInSuccession
+    int maximum = max(MaxUpdatesWithinInterval,MaxEqualUpdatesInSuccession);
 
     // Check for expired entries:
 
     // MaxUpdatesWithinInterval given in service config, then use this to check for expired entries.
-    if ( MaxUpdatesWithinInterval > 0 )
+    if ( maximum > 0 )
     {
-        // Delete the oldest entry if there are more than MaxUpdatesWithinInterval+1 entries in the list.
-        if (LastUpdates.size() > (MaxUpdatesWithinInterval+1))
-            LastUpdates.pop_back();
+        // Delete the oldest entry if there are more than max(MaxUpdatesWithinInterval,MaxEqualUpdatesInSuccession)+1 entries in the list.
+        if ( LastUpdates.size() > (size_t)(maximum+1) )
+            LastUpdates.erase(LastUpdates.upper_bound(0));
         return;
     }
     // UpdateInterval given in service config, then use this to check for expired entries.
     else if ( UpdateInterval > 0 )
     {
         // Delete the oldest entry if it's older than current_time - UpdateInterval(minutes) + 1.
-        if ( (current_time - ((time_t)UpdateInterval*60) + 1) > LastUpdates.back() )
-            LastUpdates.pop_back();
+        if ( (current_time - ((time_t)UpdateInterval*60) + 1) > LastUpdates.upper_bound(zero)->first )
+            LastUpdates.erase(LastUpdates.upper_bound(0));
         return;
     }
     // Neither MaxUpdatesWithinInterval nor UpdateInterval are given, so keep fix number of 10 entries.
     else
     {
         if ( LastUpdates.size() > 10 )
-            LastUpdates.pop_back();
+            LastUpdates.erase(LastUpdates.upper_bound(0));
         return;
     }
 }
 
 
 /**
+ * Getter the last updated time.
+ * @return Value of the last update as time_t.
+ */
+time_t Service::get_last_update_time( )
+{
+    std::map<time_t,std::string>::reverse_iterator r_iter = LastUpdates.rbegin();
+    return r_iter->first;
+}
+
+
+/**
  * Setter for member Timeout.
  * @param _timeout Value to set Timeout to.
  */
@@ -356,6 +372,26 @@ int Service::get_max_updates_within_interval() const
 
 
 /**
+ * Setter for member MaxEqualUpdatesInSuccession.
+ * @param  _max_equal_updates_in_succession Value to set MaxEqualUpdatesInSuccession to.
+ */
+void Service::set_max_equal_updates_in_succession(const int _max_equal_updates_in_succession)
+{
+    MaxEqualUpdatesInSuccession = _max_equal_updates_in_succession;
+}
+
+
+/**
+ * Getter for member MaxEqualUpdatesInSuccession.
+ * @return Value of MaxEqualUpdatesInSuccession.
+ */
+int Service::get_max_equal_updates_in_succession() const
+{
+    return MaxEqualUpdatesInSuccession;
+}
+
+
+/**
  * Get a unique service identify string
  * @return A unique service identify string
  */