Commit | Line | Data |
---|---|---|
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 | |
13 | using namespace std; | |
14 | ||
0f0908e1 TJ |
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; | |
2bc1878a | 19 | |
85a0abf9 BS |
20 | /** |
21 | * Default Constructor | |
22 | */ | |
4545a371 | 23 | Service::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 |
40 | Service::~Service() |
41 | { | |
42 | } | |
43 | ||
44 | ||
2bc1878a | 45 | /** |
3a89ac31 BS |
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 | */ | |
b38684ce | 59 | string 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 | */ | |
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 | */ | |
b38684ce | 79 | string 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 | */ | |
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 | */ | |
b38684ce | 99 | string 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 | */ | |
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 | */ | |
b38684ce | 119 | string Service::get_password() const |
3a89ac31 BS |
120 | { |
121 | return Password; | |
122 | } | |
123 | ||
124 | ||
d55fbd67 | 125 | |
88a594e8 | 126 | void 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 | 136 | Logger::Ptr Service::get_logger() const |
3a89ac31 BS |
137 | { |
138 | return Log; | |
2bc1878a BS |
139 | } |
140 | ||
141 | ||
62df5f33 | 142 | void 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 | 156 | const 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 | */ |
166 | void 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 | 176 | std::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 | 188 | bool 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 | 201 | bool 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 | 212 | bool 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 | 234 | void 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 | */ | |
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 | /** | |
3c0cd271 BS |
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 | } | |
c3dea5dc BS |
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 | } |