Block service for a short period of time on too many update errors
[bpdyndnsd] / src / service.cpp
CommitLineData
b1be615b 1/** @file
2bc1878a 2 * @brief The abstract service class. This class represents all services.
b1be615b
BS
3 *
4 *
5 *
6 * @copyright Intra2net AG
7 * @license GPLv2
8*/
9
4de6a9b8 10#include "service.hpp"
3c0cd271 11#include <boost/foreach.hpp>
ca5d6889
BS
12
13using namespace std;
14
0f0908e1
TJ
15/// Number of update errors until a service will be blocked
16const int MaxErrorCount = 3;
17/// Number of seconds a service will be blocked if MaxErrorCount is reached
18const int ErrorBlockServiceSeconds = 15 * 60;
2bc1878a 19
85a0abf9
BS
20/**
21 * Default Constructor
22 */
4545a371 23Service::Service()
9a0aff44 24 : Login("NOT SERIALIZED")
27baf279 25 , Password("NOT SERIALIZED")
025abebb 26 , ActualIP("0.0.0.0")
3c0cd271
BS
27 , UpdateInterval(0)
28 , MaxUpdatesWithinInterval(0)
d5a516ba 29 , DNSCacheTTL(0)
0f0908e1
TJ
30 , ErrorCount(0)
31 , ErrorServiceBlockedUntil(0)
2e956a36 32 , Log(new Logger())
4545a371
BS
33{
34}
35
2bc1878a 36
85a0abf9 37/**
27baf279 38 * Default Destructor needed for deserialization.
85a0abf9 39 */
4545a371
BS
40Service::~Service()
41{
42}
43
44
2bc1878a 45/**
3a89ac31
BS
46 * Setter for member Protocol.
47 * @param _protocol Value to set Protocol to.
48 */
49void 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 */
b38684ce 59string Service::get_protocol() const
3a89ac31
BS
60{
61 return Protocol;
62}
63
64
65/**
66 * Setter for member Hostname.
67 * @param _hostname Value to set Hostname to.
68 */
69void 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 */
b38684ce 79string Service::get_hostname() const
3a89ac31
BS
80{
81 return Hostname;
82}
83
84
85/**
86 * Setter for member Login.
87 * @param _login Value to set Login to.
88 */
89void 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 */
b38684ce 99string Service::get_login() const
3a89ac31
BS
100{
101 return Login;
102}
103
104
105/**
106 * Setter for member Password.
107 * @param _password Value to set Password to.
108 */
109void 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 */
b38684ce 119string Service::get_password() const
3a89ac31
BS
120{
121 return Password;
122}
123
124
d55fbd67 125
88a594e8 126void Service::set_logger(const Logger::Ptr& _log)
3a89ac31
BS
127{
128 Log = _log;
129}
130
131
132/**
133 * Getter for member Log.
134 * @return Shared pointer to Logger object.
135 */
b38684ce 136Logger::Ptr Service::get_logger() const
3a89ac31
BS
137{
138 return Log;
2bc1878a
BS
139}
140
141
62df5f33 142void Service::set_last_updates(std::list<time_t> _last_updates)
2bc1878a 143{
3c0cd271 144 LastUpdates.clear();
62df5f33 145 BOOST_FOREACH( time_t update_time, _last_updates )
3c0cd271
BS
146 {
147 LastUpdates.push_back(update_time);
148 }
2bc1878a
BS
149}
150
151
152/**
153 * Getter for member Lastupdated.
154 * @return Value of member Lastupdated.
155 */
c730deea 156const list<time_t> Service::get_last_updates() const
2bc1878a 157{
c1b8cb79 158 return LastUpdates;
2bc1878a
BS
159}
160
161
162/**
025abebb
BS
163 * Setter for member ActualIP.
164 * @param _actual_ip Value to set ActualIP to.
27baf279
BS
165 */
166void Service::set_actual_ip(const std::string& _actual_ip)
167{
025abebb 168 ActualIP = _actual_ip;
27baf279
BS
169}
170
171
172/**
025abebb
BS
173 * Getter for member ActualIP.
174 * @return Value of member ActualIP.
27baf279 175 */
b38684ce 176std::string Service::get_actual_ip() const
27baf279 177{
025abebb 178 return ActualIP;
27baf279
BS
179}
180
181
182
183/**
3a89ac31
BS
184 * Overloading of comparison operator.
185 * @param other Reference to other Service object.
186 * @return True if they equal, false if not.
2bc1878a 187 */
3a89ac31 188bool Service::operator== (const Service& other) const
2bc1878a 189{
3a89ac31
BS
190 if ( ( this->Protocol == other.Protocol ) && ( this->Hostname == other.Hostname ) )
191 return true;
192 return false;
2bc1878a
BS
193}
194
195
196/**
3a89ac31
BS
197 * Overloading of disparate operator.
198 * @param other Reference to other Service object.
199 * @return True if they differ, false if they are equal.
2bc1878a 200 */
3a89ac31 201bool Service::operator!= (const Service& other) const
2bc1878a 202{
3a89ac31 203 return !(*this == other);
2bc1878a 204}
3c0cd271
BS
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 */
62df5f33 212bool Service::update_allowed(const time_t current_time)
3c0cd271 213{
62df5f33 214 list<time_t>::iterator iter;
3c0cd271
BS
215 int i=0;
216
217 for (iter = LastUpdates.begin(); (iter != LastUpdates.end()) && ( i < MaxUpdatesWithinInterval ); iter++)
218 {
557b6f56 219 if ( (i == (MaxUpdatesWithinInterval-1)) && ( (*iter + ((time_t)UpdateInterval*60)) >= current_time ) )
3c0cd271 220 {
c3dea5dc 221 Log->print_update_not_allowed(current_time,*iter,MaxUpdatesWithinInterval,get_service_name());
3c0cd271
BS
222 return false;
223 }
224 i++;
225 }
226 return true;
227}
228
229
230/**
c3dea5dc
BS
231 * Service update method, common to each service.
232 * @param ip The new ip to set for the hostname.
233 */
62df5f33 234void Service::update(const string& ip, const time_t current_time)
c3dea5dc 235{
0f0908e1
TJ
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);
c3dea5dc
BS
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.
fc613942 253 set_last_update(current_time);
c3dea5dc 254 ActualIP = ip;
0f0908e1
TJ
255 Log->print_update_service_successful(service_name);
256
257 ErrorCount = 0;
258 ErrorServiceBlockedUntil = 0;
c3dea5dc
BS
259 }
260 else
261 {
262 // problem while trying to update service
0f0908e1
TJ
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 }
c3dea5dc
BS
273 }
274 }
275}
276
277
278/**
fc613942
BS
279* Sets the given time into the LastUpdates member and deletes expired entries.
280* @param _timeout Value to set into LastUpdates.
281*/
282void 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/**
3c0cd271
BS
316 * Setter for member Timeout.
317 * @param _timeout Value to set Timeout to.
318 */
319void 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 */
329int 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 */
339void 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 */
349int Service::get_max_updates_within_interval() const
350{
351 return MaxUpdatesWithinInterval;
352}
c3dea5dc
BS
353
354
355/**
356 * Get a unique service identify string
357 * @return A unique service identify string
358 */
359string 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 */
375int 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 */
385void Service::set_dns_cache_ttl(const int _dns_cache_ttl)
386{
387 DNSCacheTTL = _dns_cache_ttl;
388}