Improve logging when IP update is not allowed (log once on log level 0 if we changed...
[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.
0ebcd4ef 210 * @param changed_to_online True if we just changed to online, false if we were already online
3c0cd271
BS
211 * @return True if update is allowed, false if update would exceed max update interval.
212 */
0ebcd4ef 213bool Service::update_allowed(const time_t current_time, bool changed_to_online)
3c0cd271 214{
62df5f33 215 list<time_t>::iterator iter;
3c0cd271
BS
216 int i=0;
217
218 for (iter = LastUpdates.begin(); (iter != LastUpdates.end()) && ( i < MaxUpdatesWithinInterval ); iter++)
219 {
557b6f56 220 if ( (i == (MaxUpdatesWithinInterval-1)) && ( (*iter + ((time_t)UpdateInterval*60)) >= current_time ) )
3c0cd271 221 {
0ebcd4ef 222 Log->print_update_not_allowed(changed_to_online, current_time,*iter,MaxUpdatesWithinInterval,get_service_name());
3c0cd271
BS
223 return false;
224 }
225 i++;
226 }
227 return true;
228}
229
230
231/**
c3dea5dc
BS
232 * Service update method, common to each service.
233 * @param ip The new ip to set for the hostname.
0ebcd4ef
TJ
234 * @param current_time Current time
235 * @param changed_to_online True if we just changed to online, false if we were already online
c3dea5dc 236 */
0ebcd4ef 237void Service::update(const string& ip, const time_t current_time, bool changed_to_online)
c3dea5dc 238{
0f0908e1
TJ
239 const std::string service_name = get_service_name();
240
241 // Check if service is blocked for a short period of time (because of update errors)
242 if (ErrorServiceBlockedUntil && current_time < ErrorServiceBlockedUntil)
243 {
244 Log->print_update_service_is_blocked(service_name, ErrorServiceBlockedUntil - current_time);
245 return;
246 }
247
c3dea5dc 248 // test if update is permitted by UpdateInterval Status
0ebcd4ef 249 if ( update_allowed(current_time, changed_to_online) )
c3dea5dc 250 {
0ebcd4ef
TJ
251 Log->print_update_service(service_name);
252
c3dea5dc
BS
253 if ( perform_update(ip) == 0 )
254 {
255 // if update was successful, we need to set the Lastupdated and ActualIP base member.
fc613942 256 set_last_update(current_time);
c3dea5dc 257 ActualIP = ip;
0f0908e1
TJ
258 Log->print_update_service_successful(service_name);
259
260 ErrorCount = 0;
261 ErrorServiceBlockedUntil = 0;
c3dea5dc
BS
262 }
263 else
264 {
265 // problem while trying to update service
0f0908e1
TJ
266 Log->print_update_service_failure(service_name);
267
268 ++ErrorCount;
269 if (ErrorCount >= MaxErrorCount)
270 {
271 Log->print_block_service(service_name, ErrorBlockServiceSeconds);
272
273 ErrorServiceBlockedUntil = time(NULL) + ErrorBlockServiceSeconds;
274 ErrorCount = 0;
275 }
c3dea5dc
BS
276 }
277 }
278}
279
280
281/**
fc613942
BS
282* Sets the given time into the LastUpdates member and deletes expired entries.
283* @param _timeout Value to set into LastUpdates.
284*/
285void Service::set_last_update(const time_t current_time)
286{
287 // Insert value into the list.
288 LastUpdates.push_front(current_time);
289
290 // Check for expired entries:
291
292 // MaxUpdatesWithinInterval given in service config, then use this to check for expired entries.
293 if ( MaxUpdatesWithinInterval > 0 )
294 {
295 // Delete the oldest entry if there are more than MaxUpdatesWithinInterval+1 entries in the list.
296 if (LastUpdates.size() > (MaxUpdatesWithinInterval+1))
297 LastUpdates.pop_back();
298 return;
299 }
300 // UpdateInterval given in service config, then use this to check for expired entries.
301 else if ( UpdateInterval > 0 )
302 {
303 // Delete the oldest entry if it's older than current_time - UpdateInterval(minutes) + 1.
304 if ( (current_time - ((time_t)UpdateInterval*60) + 1) > LastUpdates.back() )
305 LastUpdates.pop_back();
306 return;
307 }
308 // Neither MaxUpdatesWithinInterval nor UpdateInterval are given, so keep fix number of 10 entries.
309 else
310 {
311 if ( LastUpdates.size() > 10 )
312 LastUpdates.pop_back();
313 return;
314 }
315}
316
317
318/**
3c0cd271
BS
319 * Setter for member Timeout.
320 * @param _timeout Value to set Timeout to.
321 */
322void Service::set_update_interval(const int _update_interval)
323{
324 UpdateInterval = _update_interval;
325}
326
327
328/**
329 * Getter for member Timeout.
330 * @return Value of Timeout.
331 */
332int Service::get_update_interval() const
333{
334 return UpdateInterval;
335}
336
337
338/**
339 * Setter for member Max_updates_per_timeout.
340 * @param _max_updates_per_timeout Value to set Max_updates_per_timeout to.
341 */
342void Service::set_max_updates_within_interval(const int _max_updates_within_interval)
343{
344 MaxUpdatesWithinInterval = _max_updates_within_interval;
345}
346
347
348/**
349 * Getter for member Max_updates_per_timeout.
350 * @return Value of Max_updates_per_timeout.
351 */
352int Service::get_max_updates_within_interval() const
353{
354 return MaxUpdatesWithinInterval;
355}
c3dea5dc
BS
356
357
358/**
359 * Get a unique service identify string
360 * @return A unique service identify string
361 */
362string Service::get_service_name() const
363{
364 string service_name;
365
366 service_name.append(Protocol);
367 service_name.append(" ");
368 service_name.append(Hostname);
369
370 return service_name;
371}
372
373
374/**
375 * Get member DNSCacheTTL
376 * @return DNSCacheTTL
377 */
378int Service::get_dns_cache_ttl() const
379{
380 return DNSCacheTTL;
381}
382
383
384/**
385 * Set member DNSCacheTTL
386 * @param _dns_cache_ttl DNSCacheTTL
387 */
388void Service::set_dns_cache_ttl(const int _dns_cache_ttl)
389{
390 DNSCacheTTL = _dns_cache_ttl;
391}