Fixed unused variable.
[bpdyndnsd] / src / service.cpp
1 /** @file
2  * @brief The abstract service class. This class represents all services.
3  *
4  *
5  *
6  * @copyright Intra2net AG
7  * @license GPLv2
8 */
9
10 #include "service.hpp"
11 #include <boost/foreach.hpp>
12
13 using namespace std;
14
15 /// Number of update errors until a service will be blocked
16 const int MaxErrorCount = 3;
17 /// Number of seconds a service will be blocked if MaxErrorCount is reached
18 const int ErrorBlockServiceSeconds = 15 * 60;
19
20 /**
21  * Default Constructor
22  */
23 Service::Service()
24     : Login("NOT SERIALIZED")
25     , Password("NOT SERIALIZED")
26     , ActualIP("0.0.0.0")
27     , UpdateInterval(15)
28     , MaxUpdatesWithinInterval(3)
29     , MaxEqualUpdatesInSuccession(2)
30     , DNSCacheTTL(0)
31     , ErrorCount(0)
32     , ErrorServiceBlockedUntil(0)
33     , Log(new Logger())
34 {
35 }
36
37
38 /**
39  * Default Destructor needed for deserialization.
40  */
41 Service::~Service()
42 {
43 }
44
45
46 /**
47  * Setter for member Protocol.
48  * @param _protocol Value to set Protocol to.
49  */
50 void Service::set_protocol(const string& _protocol)
51 {
52     Protocol = _protocol;
53 }
54
55
56 /**
57  * Getter for memeber Protocol.
58  * @return Value of member Protocol.
59  */
60 string Service::get_protocol() const
61 {
62     return Protocol;
63 }
64
65
66 /**
67  * Setter for member Hostname.
68  * @param _hostname Value to set Hostname to.
69  */
70 void Service::set_hostname(const string& _hostname)
71 {
72     Hostname = _hostname;
73 }
74
75
76 /**
77  * Getter for member Hostname.
78  * @return Value of member Hostname.
79  */
80 string Service::get_hostname() const
81 {
82     return Hostname;
83 }
84
85
86 /**
87  * Setter for member Login.
88  * @param _login Value to set Login to.
89  */
90 void Service::set_login(const string& _login)
91 {
92     Login = _login;
93 }
94
95
96 /**
97  * Getter for member Login.
98  * @return Value of member Login.
99  */
100 string Service::get_login() const
101 {
102     return Login;
103 }
104
105
106 /**
107  * Setter for member Password.
108  * @param _password Value to set Password to.
109  */
110 void Service::set_password(const string& _password)
111 {
112     Password = _password;
113 }
114
115
116 /**
117  * Getter for member Password.
118  * @return Value of member Password.
119  */
120 string Service::get_password() const
121 {
122     return Password;
123 }
124
125
126
127 void Service::set_logger(const Logger::Ptr& _log)
128 {
129     Log = _log;
130 }
131
132
133 /**
134  * Getter for member Log.
135  * @return Shared pointer to Logger object.
136  */
137 Logger::Ptr Service::get_logger() const
138 {
139     return Log;
140 }
141
142
143 /**
144  * Setter for member LastUpdates.
145  * @param _last_updates Value to set LastUpdates to.
146  */
147 void Service::set_last_updates(std::map<time_t,std::string> _last_updates)
148 {
149     LastUpdates.clear();
150     for ( std::map<time_t,std::string>::iterator iter = _last_updates.begin(); iter != _last_updates.end(); iter++ )
151     {
152         LastUpdates.insert(make_pair(iter->first,iter->second));
153     }
154 }
155
156
157 /**
158  * Getter for member LastUpdates.
159  * @return Value of member LastUpdates.
160  */
161 const std::map<time_t,std::string> Service::get_last_updates() const
162 {
163     return LastUpdates;
164 }
165
166
167 /**
168  * Setter for member ActualIP.
169  * @param _actual_ip Value to set ActualIP to.
170  */
171 void Service::set_actual_ip(const std::string& _actual_ip)
172 {
173     ActualIP = _actual_ip;
174 }
175
176
177 /**
178  * Getter for member ActualIP.
179  * @return Value of member ActualIP.
180  */
181 std::string Service::get_actual_ip() const
182 {
183     return ActualIP;
184 }
185
186
187 /**
188  * Overloading of comparison operator.
189  * @param other Reference to other Service object.
190  * @return True if they equal, false if not.
191  */
192 bool Service::operator== (const Service& other) const
193 {
194     if ( ( this->Protocol == other.Protocol ) && ( this->Hostname == other.Hostname ) )
195         return true;
196     return false;
197 }
198
199
200 /**
201  * Overloading of disparate operator.
202  * @param other Reference to other Service object.
203  * @return True if they differ, false if they are equal.
204  */
205 bool Service::operator!= (const Service& other) const
206 {
207     return !(*this == other);
208 }
209
210
211 /**
212  * Checks if update will exceed max update interval.
213  * @param current_time Current time.
214  * @param changed_to_online True if we just changed to online, false if we were already online
215  * @return True if update is allowed, false if update would exceed max update interval.
216  */
217 bool Service::update_allowed(const time_t current_time, bool changed_to_online)
218 {
219     int i = 0;
220     for ( std::map<time_t,std::string>::reverse_iterator r_iter = LastUpdates.rbegin(); (r_iter != LastUpdates.rend()) && ( i < MaxUpdatesWithinInterval ); r_iter++)
221     {
222         if ( (i == (MaxUpdatesWithinInterval-1)) && ( (r_iter->first + ((time_t)UpdateInterval*60)) >= current_time ) )
223         {
224             Log->print_update_not_allowed(changed_to_online,current_time,r_iter->first,MaxUpdatesWithinInterval,get_service_name());
225             return false;
226         }
227         i++;
228     }
229     return true;
230 }
231
232
233 /**
234  * Service update method, common to each service.
235  * @param ip The new ip to set for the hostname.
236  * @param current_time Current time
237  * @param changed_to_online True if we just changed to online, false if we were already online
238  */
239 void Service::update(const string& ip, const time_t current_time, bool changed_to_online)
240 {
241     const std::string service_name = get_service_name();
242
243     // Check if service is blocked for a short period of time (because of update errors)
244     if (ErrorServiceBlockedUntil && current_time < ErrorServiceBlockedUntil)
245     {
246         Log->print_update_service_is_blocked(service_name, ErrorServiceBlockedUntil - current_time);
247         return;
248     }
249
250     // test if update is permitted by UpdateInterval Status
251     if ( update_allowed(current_time, changed_to_online) )
252     {
253         Log->print_update_service(service_name);
254
255         if ( perform_update(ip) == 0 )
256         {
257             // if update was successful, we need to set the Lastupdated and ActualIP base member.
258             set_last_update(current_time,ip);
259             ActualIP = ip;
260             Log->print_update_service_successful(service_name);
261
262             ErrorCount = 0;
263             ErrorServiceBlockedUntil = 0;
264         }
265         else
266         {
267             // problem while trying to update service
268             Log->print_update_service_failure(service_name);
269
270             ++ErrorCount;
271             if (ErrorCount >= MaxErrorCount)
272             {
273                 Log->print_block_service(service_name, ErrorBlockServiceSeconds);
274
275                 ErrorServiceBlockedUntil = time(NULL) + ErrorBlockServiceSeconds;
276                 ErrorCount = 0;
277             }
278         }
279     }
280 }
281
282
283 /**
284 * Sets the given time into the LastUpdates member and deletes expired entries.
285 * @param _timeout Value to set into LastUpdates.
286 */
287 void Service::set_last_update(const time_t current_time, const string& ip)
288 {
289     // Insert value into the list.
290     LastUpdates.insert(make_pair(current_time,ip));
291
292     // Get the maximum of MaxUpdatesWithinInterval and MaxEqualUpdatesInSuccession
293     int maximum = max(MaxUpdatesWithinInterval,MaxEqualUpdatesInSuccession);
294
295     // Check for expired entries:
296
297     // MaxUpdatesWithinInterval given in service config, then use this to check for expired entries.
298     if ( maximum > 0 )
299     {
300         // Delete the oldest entry if there are more than max(MaxUpdatesWithinInterval,MaxEqualUpdatesInSuccession)+1 entries in the list.
301         if ( LastUpdates.size() > (size_t)(maximum+1) )
302             LastUpdates.erase(LastUpdates.upper_bound(0));
303         return;
304     }
305     // UpdateInterval given in service config, then use this to check for expired entries.
306     else if ( UpdateInterval > 0 )
307     {
308         // Delete the oldest entry if it's older than current_time - UpdateInterval(minutes) + 1.
309         if ( (current_time - ((time_t)UpdateInterval*60) + 1) > LastUpdates.upper_bound(0)->first )
310             LastUpdates.erase(LastUpdates.upper_bound(0));
311         return;
312     }
313     // Neither MaxUpdatesWithinInterval nor UpdateInterval are given, so keep fix number of 10 entries.
314     else
315     {
316         if ( LastUpdates.size() > 10 )
317             LastUpdates.erase(LastUpdates.upper_bound(0));
318         return;
319     }
320 }
321
322
323 /**
324  * Getter the last updated time.
325  * @return Value of the last update as time_t.
326  */
327 time_t Service::get_last_update_time( )
328 {
329     time_t last_update = 0;
330     if ( !LastUpdates.empty() )
331     {
332         std::map<time_t,std::string>::reverse_iterator r_iter = LastUpdates.rbegin();
333         if ( r_iter != LastUpdates.rend() )
334             last_update = r_iter->first;
335     }
336     return last_update;
337 }
338
339
340 /**
341  * Setter for member Timeout.
342  * @param _timeout Value to set Timeout to.
343  */
344 void Service::set_update_interval(const int _update_interval)
345 {
346     UpdateInterval = _update_interval;
347 }
348
349
350 /**
351  * Getter for member Timeout.
352  * @return Value of Timeout.
353  */
354 int Service::get_update_interval() const
355 {
356     return UpdateInterval;
357 }
358
359
360 /**
361  * Setter for member Max_updates_per_timeout.
362  * @param  _max_updates_per_timeout Value to set Max_updates_per_timeout to.
363  */
364 void Service::set_max_updates_within_interval(const int _max_updates_within_interval)
365 {
366     MaxUpdatesWithinInterval = _max_updates_within_interval;
367 }
368
369
370 /**
371  * Getter for member Max_updates_per_timeout.
372  * @return Value of Max_updates_per_timeout.
373  */
374 int Service::get_max_updates_within_interval() const
375 {
376     return MaxUpdatesWithinInterval;
377 }
378
379
380 /**
381  * Setter for member MaxEqualUpdatesInSuccession.
382  * @param  _max_equal_updates_in_succession Value to set MaxEqualUpdatesInSuccession to.
383  */
384 void Service::set_max_equal_updates_in_succession(const int _max_equal_updates_in_succession)
385 {
386     MaxEqualUpdatesInSuccession = _max_equal_updates_in_succession;
387 }
388
389
390 /**
391  * Getter for member MaxEqualUpdatesInSuccession.
392  * @return Value of MaxEqualUpdatesInSuccession.
393  */
394 int Service::get_max_equal_updates_in_succession() const
395 {
396     return MaxEqualUpdatesInSuccession;
397 }
398
399
400 /**
401  * Get a unique service identify string
402  * @return A unique service identify string
403  */
404 string Service::get_service_name() const
405 {
406     string service_name;
407
408     service_name.append(Protocol);
409     service_name.append(" ");
410     service_name.append(Hostname);
411
412     return service_name;
413 }
414
415
416 /**
417  * Get member DNSCacheTTL
418  * @return DNSCacheTTL
419  */
420 int Service::get_dns_cache_ttl() const
421 {
422     return DNSCacheTTL;
423 }
424
425
426 /**
427  * Set member DNSCacheTTL
428  * @param _dns_cache_ttl DNSCacheTTL
429  */
430 void Service::set_dns_cache_ttl(const int _dns_cache_ttl)
431 {
432     DNSCacheTTL = _dns_cache_ttl;
433 }