/** @file * @brief The abstract service class. This class represents all services. * * * * @copyright Intra2net AG * @license GPLv2 */ #include "service.hpp" #include using namespace std; /// Number of update errors until a service will be blocked const int MaxErrorCount = 3; /// Number of seconds a service will be blocked if MaxErrorCount is reached const int ErrorBlockServiceSeconds = 15 * 60; /** * Default Constructor */ Service::Service() : Login("NOT SERIALIZED") , Password("NOT SERIALIZED") , ActualIP("0.0.0.0") , UpdateInterval(15) , MaxUpdatesWithinInterval(3) , MaxEqualUpdatesInSuccession(2) , DNSCacheTTL(0) , ErrorCount(0) , ErrorServiceBlockedUntil(0) , Log(new Logger()) { } /** * Default Destructor needed for deserialization. */ Service::~Service() { } /** * Setter for member Protocol. * @param _protocol Value to set Protocol to. */ void Service::set_protocol(const string& _protocol) { Protocol = _protocol; } /** * Getter for memeber Protocol. * @return Value of member Protocol. */ string Service::get_protocol() const { return Protocol; } /** * Setter for member Hostname. * @param _hostname Value to set Hostname to. */ void Service::set_hostname(const string& _hostname) { Hostname = _hostname; } /** * Getter for member Hostname. * @return Value of member Hostname. */ string Service::get_hostname() const { return Hostname; } /** * Setter for member Login. * @param _login Value to set Login to. */ void Service::set_login(const string& _login) { Login = _login; } /** * Getter for member Login. * @return Value of member Login. */ string Service::get_login() const { return Login; } /** * Setter for member Password. * @param _password Value to set Password to. */ void Service::set_password(const string& _password) { Password = _password; } /** * Getter for member Password. * @return Value of member Password. */ string Service::get_password() const { return Password; } void Service::set_logger(const Logger::Ptr& _log) { Log = _log; } /** * Getter for member Log. * @return Shared pointer to Logger object. */ Logger::Ptr Service::get_logger() const { return Log; } /** * Setter for member LastUpdates. * @param _last_updates Value to set LastUpdates to. */ void Service::set_last_updates(std::map _last_updates) { LastUpdates.clear(); for ( std::map::iterator iter = _last_updates.begin(); iter != _last_updates.end(); iter++ ) { LastUpdates.insert(make_pair(iter->first,iter->second)); } } /** * Getter for member LastUpdates. * @return Value of member LastUpdates. */ const std::map Service::get_last_updates() const { return LastUpdates; } /** * Setter for member ActualIP. * @param _actual_ip Value to set ActualIP to. */ void Service::set_actual_ip(const std::string& _actual_ip) { ActualIP = _actual_ip; } /** * Getter for member ActualIP. * @return Value of member ActualIP. */ std::string Service::get_actual_ip() const { return ActualIP; } /** * Overloading of comparison operator. * @param other Reference to other Service object. * @return True if they equal, false if not. */ bool Service::operator== (const Service& other) const { if ( ( this->Protocol == other.Protocol ) && ( this->Hostname == other.Hostname ) ) return true; return false; } /** * Overloading of disparate operator. * @param other Reference to other Service object. * @return True if they differ, false if they are equal. */ bool Service::operator!= (const Service& other) const { return !(*this == other); } /** * Checks if update will exceed max update interval. * @param current_time Current time. * @param changed_to_online True if we just changed to online, false if we were already online * @return True if update is allowed, false if update would exceed max update interval. */ bool Service::update_allowed(const time_t current_time, bool changed_to_online) { int i = 0; for ( std::map::reverse_iterator r_iter = LastUpdates.rbegin(); (r_iter != LastUpdates.rend()) && ( i < MaxUpdatesWithinInterval ); r_iter++) { if ( (i == (MaxUpdatesWithinInterval-1)) && ( (r_iter->first + ((time_t)UpdateInterval*60)) >= current_time ) ) { Log->print_update_not_allowed(changed_to_online,current_time,r_iter->first,MaxUpdatesWithinInterval,get_service_name()); return false; } i++; } return true; } /** * Service update method, common to each service. * @param ip The new ip to set for the hostname. * @param current_time Current time * @param changed_to_online True if we just changed to online, false if we were already online */ void Service::update(const string& ip, const time_t current_time, bool changed_to_online) { const std::string service_name = get_service_name(); // Check if service is blocked for a short period of time (because of update errors) if (ErrorServiceBlockedUntil && current_time < ErrorServiceBlockedUntil) { Log->print_update_service_is_blocked(service_name, ErrorServiceBlockedUntil - current_time); return; } // test if update is permitted by UpdateInterval Status if ( update_allowed(current_time, changed_to_online) ) { Log->print_update_service(service_name); if ( perform_update(ip) == 0 ) { // if update was successful, we need to set the Lastupdated and ActualIP base member. set_last_update(current_time,ip); ActualIP = ip; Log->print_update_service_successful(service_name); ErrorCount = 0; ErrorServiceBlockedUntil = 0; } else { // problem while trying to update service Log->print_update_service_failure(service_name); ++ErrorCount; if (ErrorCount >= MaxErrorCount) { Log->print_block_service(service_name, ErrorBlockServiceSeconds); ErrorServiceBlockedUntil = time(NULL) + ErrorBlockServiceSeconds; ErrorCount = 0; } } } } /** * 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, const string& ip) { // Insert value into the list. 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 ( maximum > 0 ) { // 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.upper_bound(0)->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.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::reverse_iterator r_iter = LastUpdates.rbegin(); return r_iter->first; } /** * Setter for member Timeout. * @param _timeout Value to set Timeout to. */ void Service::set_update_interval(const int _update_interval) { UpdateInterval = _update_interval; } /** * Getter for member Timeout. * @return Value of Timeout. */ int Service::get_update_interval() const { return UpdateInterval; } /** * Setter for member Max_updates_per_timeout. * @param _max_updates_per_timeout Value to set Max_updates_per_timeout to. */ void Service::set_max_updates_within_interval(const int _max_updates_within_interval) { MaxUpdatesWithinInterval = _max_updates_within_interval; } /** * Getter for member Max_updates_per_timeout. * @return Value of Max_updates_per_timeout. */ int Service::get_max_updates_within_interval() const { return MaxUpdatesWithinInterval; } /** * 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 */ string Service::get_service_name() const { string service_name; service_name.append(Protocol); service_name.append(" "); service_name.append(Hostname); return service_name; } /** * Get member DNSCacheTTL * @return DNSCacheTTL */ int Service::get_dns_cache_ttl() const { return DNSCacheTTL; } /** * Set member DNSCacheTTL * @param _dns_cache_ttl DNSCacheTTL */ void Service::set_dns_cache_ttl(const int _dns_cache_ttl) { DNSCacheTTL = _dns_cache_ttl; }