dcc7fa1d76195bb4eb39bfbdd008a2e1e4dac818
[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(0)
28     , MaxUpdatesWithinInterval(0)
29     , DNSCacheTTL(0)
30     , ErrorCount(0)
31     , ErrorServiceBlockedUntil(0)
32     , Log(new Logger())
33 {
34 }
35
36
37 /**
38  * Default Destructor needed for deserialization.
39  */
40 Service::~Service()
41 {
42 }
43
44
45 /**
46  * Setter for member Protocol.
47  * @param _protocol Value to set Protocol to.
48  */
49 void Service::set_protocol(const string& _protocol)
50 {
51     Protocol = _protocol;
52 }
53
54
55 /**
56  * Getter for memeber Protocol.
57  * @return Value of member Protocol.
58  */
59 string Service::get_protocol() const
60 {
61     return Protocol;
62 }
63
64
65 /**
66  * Setter for member Hostname.
67  * @param _hostname Value to set Hostname to.
68  */
69 void Service::set_hostname(const string& _hostname)
70 {
71     Hostname = _hostname;
72 }
73
74
75 /**
76  * Getter for member Hostname.
77  * @return Value of member Hostname.
78  */
79 string Service::get_hostname() const
80 {
81     return Hostname;
82 }
83
84
85 /**
86  * Setter for member Login.
87  * @param _login Value to set Login to.
88  */
89 void Service::set_login(const string& _login)
90 {
91     Login = _login;
92 }
93
94
95 /**
96  * Getter for member Login.
97  * @return Value of member Login.
98  */
99 string Service::get_login() const
100 {
101     return Login;
102 }
103
104
105 /**
106  * Setter for member Password.
107  * @param _password Value to set Password to.
108  */
109 void Service::set_password(const string& _password)
110 {
111     Password = _password;
112 }
113
114
115 /**
116  * Getter for member Password.
117  * @return Value of member Password.
118  */
119 string Service::get_password() const
120 {
121     return Password;
122 }
123
124
125
126 void Service::set_logger(const Logger::Ptr& _log)
127 {
128     Log = _log;
129 }
130
131
132 /**
133  * Getter for member Log.
134  * @return Shared pointer to Logger object.
135  */
136 Logger::Ptr Service::get_logger() const
137 {
138     return Log;
139 }
140
141
142 void Service::set_last_updates(std::list<time_t> _last_updates)
143 {
144     LastUpdates.clear();
145     BOOST_FOREACH( time_t update_time, _last_updates )
146     {
147         LastUpdates.push_back(update_time);
148     }
149 }
150
151
152 /**
153  * Getter for member Lastupdated.
154  * @return Value of member Lastupdated.
155  */
156 const list<time_t> Service::get_last_updates() const
157 {
158     return LastUpdates;
159 }
160
161
162 /**
163  * Setter for member ActualIP.
164  * @param _actual_ip Value to set ActualIP to.
165  */
166 void Service::set_actual_ip(const std::string& _actual_ip)
167 {
168     ActualIP = _actual_ip;
169 }
170
171
172 /**
173  * Getter for member ActualIP.
174  * @return Value of member ActualIP.
175  */
176 std::string Service::get_actual_ip() const
177 {
178     return ActualIP;
179 }
180
181
182
183 /**
184  * Overloading of comparison operator.
185  * @param other Reference to other Service object.
186  * @return True if they equal, false if not.
187  */
188 bool Service::operator== (const Service& other) const
189 {
190     if ( ( this->Protocol == other.Protocol ) && ( this->Hostname == other.Hostname ) )
191         return true;
192     return false;
193 }
194
195
196 /**
197  * Overloading of disparate operator.
198  * @param other Reference to other Service object.
199  * @return True if they differ, false if they are equal.
200  */
201 bool Service::operator!= (const Service& other) const
202 {
203     return !(*this == other);
204 }
205
206
207 /**
208  * Checks if update will exceed max update interval.
209  * @param current_time Current time.
210  * @return True if update is allowed, false if update would exceed max update interval.
211  */
212 bool Service::update_allowed(const time_t current_time)
213 {
214     list<time_t>::iterator iter;
215     int i=0;
216
217     for (iter = LastUpdates.begin(); (iter != LastUpdates.end()) && ( i < MaxUpdatesWithinInterval ); iter++)
218     {
219         if ( (i == (MaxUpdatesWithinInterval-1)) && ( (*iter + ((time_t)UpdateInterval*60)) >= current_time ) )
220         {
221             Log->print_update_not_allowed(current_time,*iter,MaxUpdatesWithinInterval,get_service_name());
222             return false;
223         }
224         i++;
225     }
226     return true;
227 }
228
229
230 /**
231  * Service update method, common to each service.
232  * @param ip The new ip to set for the hostname.
233  */
234 void Service::update(const string& ip, const time_t current_time)
235 {
236     const std::string service_name = get_service_name();
237
238     // Check if service is blocked for a short period of time (because of update errors)
239     if (ErrorServiceBlockedUntil && current_time < ErrorServiceBlockedUntil)
240     {
241         Log->print_update_service_is_blocked(service_name, ErrorServiceBlockedUntil - current_time);
242         return;
243     }
244
245     Log->print_update_service(service_name);
246
247     // test if update is permitted by UpdateInterval Status
248     if ( update_allowed(current_time) )
249     {
250         if ( perform_update(ip) == 0 )
251         {
252             // if update was successful, we need to set the Lastupdated and ActualIP base member.
253             set_last_update(current_time);
254             ActualIP = ip;
255             Log->print_update_service_successful(service_name);
256
257             ErrorCount = 0;
258             ErrorServiceBlockedUntil = 0;
259         }
260         else
261         {
262             // problem while trying to update service
263             Log->print_update_service_failure(service_name);
264
265             ++ErrorCount;
266             if (ErrorCount >= MaxErrorCount)
267             {
268                 Log->print_block_service(service_name, ErrorBlockServiceSeconds);
269
270                 ErrorServiceBlockedUntil = time(NULL) + ErrorBlockServiceSeconds;
271                 ErrorCount = 0;
272             }
273         }
274     }
275 }
276
277
278 /**
279 * Sets the given time into the LastUpdates member and deletes expired entries.
280 * @param _timeout Value to set into LastUpdates.
281 */
282 void Service::set_last_update(const time_t current_time)
283 {
284     // Insert value into the list.
285     LastUpdates.push_front(current_time);
286
287     // Check for expired entries:
288
289     // MaxUpdatesWithinInterval given in service config, then use this to check for expired entries.
290     if ( MaxUpdatesWithinInterval > 0 )
291     {
292         // Delete the oldest entry if there are more than MaxUpdatesWithinInterval+1 entries in the list.
293         if (LastUpdates.size() > (MaxUpdatesWithinInterval+1))
294             LastUpdates.pop_back();
295         return;
296     }
297     // UpdateInterval given in service config, then use this to check for expired entries.
298     else if ( UpdateInterval > 0 )
299     {
300         // Delete the oldest entry if it's older than current_time - UpdateInterval(minutes) + 1.
301         if ( (current_time - ((time_t)UpdateInterval*60) + 1) > LastUpdates.back() )
302             LastUpdates.pop_back();
303         return;
304     }
305     // Neither MaxUpdatesWithinInterval nor UpdateInterval are given, so keep fix number of 10 entries.
306     else
307     {
308         if ( LastUpdates.size() > 10 )
309             LastUpdates.pop_back();
310         return;
311     }
312 }
313
314
315 /**
316  * Setter for member Timeout.
317  * @param _timeout Value to set Timeout to.
318  */
319 void Service::set_update_interval(const int _update_interval)
320 {
321     UpdateInterval = _update_interval;
322 }
323
324
325 /**
326  * Getter for member Timeout.
327  * @return Value of Timeout.
328  */
329 int Service::get_update_interval() const
330 {
331     return UpdateInterval;
332 }
333
334
335 /**
336  * Setter for member Max_updates_per_timeout.
337  * @param  _max_updates_per_timeout Value to set Max_updates_per_timeout to.
338  */
339 void Service::set_max_updates_within_interval(const int _max_updates_within_interval)
340 {
341     MaxUpdatesWithinInterval = _max_updates_within_interval;
342 }
343
344
345 /**
346  * Getter for member Max_updates_per_timeout.
347  * @return Value of Max_updates_per_timeout.
348  */
349 int Service::get_max_updates_within_interval() const
350 {
351     return MaxUpdatesWithinInterval;
352 }
353
354
355 /**
356  * Get a unique service identify string
357  * @return A unique service identify string
358  */
359 string Service::get_service_name() const
360 {
361     string service_name;
362
363     service_name.append(Protocol);
364     service_name.append(" ");
365     service_name.append(Hostname);
366
367     return service_name;
368 }
369
370
371 /**
372  * Get member DNSCacheTTL
373  * @return DNSCacheTTL
374  */
375 int Service::get_dns_cache_ttl() const
376 {
377     return DNSCacheTTL;
378 }
379
380
381 /**
382  * Set member DNSCacheTTL
383  * @param _dns_cache_ttl DNSCacheTTL
384  */
385 void Service::set_dns_cache_ttl(const int _dns_cache_ttl)
386 {
387     DNSCacheTTL = _dns_cache_ttl;
388 }