Implemented logic for ability to activate webcheck through signals.
[bpdyndnsd] / src / updater.cpp
CommitLineData
b1be615b
BS
1/** @file
2 * @brief The updater class implementation. This class implements the updater logic.
3 *
4 *
5 *
6 * @copyright Intra2net AG
7 * @license GPLv2
8*/
9
4545a371
BS
10#include "updater.h"
11
e0080b78 12#include "serviceholder.h"
e0080b78 13
e0080b78 14
ca5d6889
BS
15#include <boost/foreach.hpp>
16#include <boost/serialization/export.hpp>
b30f392d 17
e0080b78 18
8bca3c5d 19using namespace std;
527536b3 20
ca5d6889 21
b1be615b
BS
22/**
23 * Default constructor which initializes the member Conf.
24 */
4545a371 25Updater::Updater()
ad0e5016 26 : IPAddrHelp(new IPAddrHelper)
4545a371 27{
2e956a36 28 // Initialize program wide Logger, at this point we don't know where to log and with which loglevel.
c3c84086 29 Log = Logger::Ptr(new Logger);
4545a371 30
e0080b78 31 // initialize Serviceholder
c3c84086 32 ServiceHolder = Serviceholder::Ptr(new Serviceholder(Log));
e0080b78 33
254bbf53 34 // initialize Config
c3c84086 35 Conf = Config::Ptr(new Config(Log,ServiceHolder));
4545a371
BS
36}
37
527536b3 38
b1be615b
BS
39/**
40 * Default destructor.
41 */
4545a371
BS
42Updater::~Updater()
43{
44}
45
527536b3 46
efbde536
BS
47
48/**
49 * Load config and initialize helper classes.
50 * @param argc Number of arguments in array
51 * @param argv Array with cmd options
52 */
53int Updater::load_config(int argc, char *argv[])
54{
55 // load the cmd options
56 if ( init_config_from_cmd(argc,argv) != 0 )
57 return -1;
58
59 // load the config and service files
60 if ( init_config_from_files() != 0 )
61 return -1;
62
63 // init all helper classes
64 if ( init_helper_classes() != 0 )
65 return -1;
66
67 return 0;
68}
69
70
71/**
72 * Reloading the config. Delete all Service objects and then init new Service objects from config files.
73 */
74int Updater::reload_config()
75{
76 // serialize all service objects
77 if ( ServiceHolder->serialize_services() != 0 )
78 return -1;
79
80 // delete all service objects
81 ServiceHolder->delete_services();
82
83 // delete the actual Variables_map, perhaps with old cmd options which would overwrite new config file options.
84 Conf->delete_variables_map();
85
86 // load only config files
87 if ( init_config_from_files() != 0 )
88 return -1;
89
90 // init all helper classes
91 if ( init_helper_classes() != 0 )
92 return -1;
93
94 return 0;
95}
96
97
b1be615b 98/**
254bbf53
BS
99 * Parse the command line arguments and initialize corresponding options.
100 * @param argc Number command line arguments.
101 * @param argv[] Array with arguments.
102 * @return 0 if cmd options successfully parsed, 1 if usage or version.
38060291 103 */
08a5a621 104int Updater::init_config_from_cmd(int argc, char *argv[]) const
38060291
BS
105{
106 // Load the command line parameters
e95a6634 107 if( Conf->parse_cmd_line( argc, argv) != 0)
667c672c 108 return -1;
38060291 109
59c8d63c
BS
110 // If we have loaded the cmd options we need to init the log facility immediately in case debugging is enabled from cmd.
111 init_log_facility();
112
254bbf53
BS
113 // successful parsed
114 Log->print_cmd_parsed();
38060291
BS
115 return 0;
116}
117
118
119/**
254bbf53
BS
120 * Load the main config and the service definition files in config path.
121 * @return 0 if all is fine,
b1be615b 122 */
08a5a621 123int Updater::init_config_from_files() const
4545a371 124{
254bbf53 125 // Load the main and service config files in config path
e95a6634 126 if ( Conf->load_config_from_files() != 0 )
667c672c 127 return -1;
4545a371 128
59c8d63c
BS
129 // Re-init log facility, perhaps new config file options for logger are set.
130 // These config file options will only overwrite the cmd options if the SIGHUP (reload config) is caught.
131 init_log_facility();
132
27baf279 133 // Here we are. All Service Objects should be initialized, so it is time to deserialize the old service objects and compare them.
e0080b78 134 if ( ServiceHolder->deserialize_services() != 0 )
667c672c 135 return -1;
27baf279 136
254bbf53 137 // successful loaded
667c672c 138 Log->print_conf_files_parsed();
254bbf53 139 return 0;
4545a371
BS
140}
141
527536b3 142
b1be615b 143/**
efbde536
BS
144 * Init all Helper classes
145 * @return
3434b35f 146 */
efbde536 147int Updater::init_helper_classes()
3434b35f 148{
efbde536
BS
149 // Initialize IPHelper
150 if ( init_ip_helper() != 0 )
151 return -1;
3434b35f 152
efbde536 153 return 0;
3434b35f
BS
154}
155
156
157/**
0665b239
BS
158 * Init the IPHelp member with needed values.
159 * @return 0 if all is fine, -1 otherwise.
160 */
161int Updater::init_ip_helper()
162{
20399847
BS
163 // Try to get deserialized IPAddrHelper from ServiceHolder
164 IPAddrHelper::Ptr _ip_addr_help = ServiceHolder->get_ip_addr_helper();
165 if ( _ip_addr_help.use_count() != 0 )
166 {
167 // Initialize IPHelper
c3c84086 168 IPAddrHelp = IPAddrHelper::Ptr( new IPAddrHelper( Log, Conf->get_webcheck_ip_url(), Conf->get_webcheck_ip_url_alt(), Conf->get_webcheck_interval(), _ip_addr_help->get_last_webcheck(), Conf->get_enable_ipv6(), Conf->get_proxy(), Conf->get_proxy_port() ) );
20399847
BS
169 }
170 else
171 {
172 // IPAddrHelper from ServiceHolder was not declared, so init oen with LastWebcheck 0
08a5a621 173 IPAddrHelp = IPAddrHelper::Ptr( new IPAddrHelper( Log, Conf->get_webcheck_ip_url(), Conf->get_webcheck_ip_url_alt(), Conf->get_webcheck_interval(), (size_t)0, Conf->get_enable_ipv6(), Conf->get_proxy(), Conf->get_proxy_port() ) );
20399847
BS
174 }
175
176 // Put the IPAddrHelper into ServiceHolder, so the LastWebcheck state will be serialized too.
177 ServiceHolder->set_ip_addr_helper(IPAddrHelp);
0665b239
BS
178
179 return 0;
180}
181
182
183/**
efbde536
BS
184 * Getter for member Config.
185 * @return Member Config.
186 */
187Config::Ptr Updater::get_config() const
188{
189 return Conf;
190}
667c672c 191
efbde536
BS
192
193/**
194 * Getter for member Logger.
195 * @return Member Logger.
196 */
197Logger::Ptr Updater::get_logger() const
198{
199 return Log;
8bca3c5d
BS
200}
201
202
2bc1878a
BS
203/**
204 * Initialize the logging facility with loglevel and syslog.
205 */
c730deea 206void Updater::init_log_facility() const
8bca3c5d 207{
cbbdeb6c 208 Log->set_log_facility(Conf->get_loglevel(),Conf->get_syslog(),Conf->get_external_warning_log(),Conf->get_external_warning_level());
8bca3c5d 209 Log->print_init_log_facility();
c5675c01
BS
210}
211
212
213/**
b1be615b
BS
214 * Update all configured services.
215 */
c730deea 216void Updater::update_services() const
4545a371 217{
1af7c124 218 // Get all services from the ServiceHolder.
e0080b78 219 list<Service::Ptr> services = ServiceHolder->get_services();
4545a371 220
1af7c124 221 // Get the actual IP of this host.
46fffdd6 222 string ip_host = IPAddrHelp->get_actual_ip(Conf->get_webcheck_enabled());
4545a371 223
1af7c124 224 if ( !ip_host.empty() )
4545a371 225 {
3c0cd271
BS
226 BOOST_FOREACH(Service::Ptr &service, services )
227 {
1af7c124
BS
228 string ip_last_update = service->get_actual_ip();
229 string hostname = service->get_hostname();
c730deea
BS
230 time_t lastupdated = 0;
231 time_t current_time = time(NULL);
c3dea5dc 232
1af7c124 233 // Try to get the lastupdated time of the actual service if there is one.
c1b8cb79 234 if ( service->get_last_updates().size() > 0 )
08a5a621 235 lastupdated = service->get_last_updates().front(); /*lint !e1793 */
c3dea5dc 236
1af7c124
BS
237 Log->print_check_service_update(hostname, current_time, lastupdated);
238
239 // Do a DNS Query for the dynamic hostname.
240 string ip_dns_recheck = IPAddrHelp->dns_query(hostname);
241
242 Log->print_cached_dns_entry(hostname, ip_dns_recheck, ip_last_update, ip_host);
243
a7c1e271
BS
244 // Test if the DNS-Record could not be found.
245 if ( ip_dns_recheck.empty() )
246 {
247 // Next in BOOST_FOREACH
248 }
1af7c124 249 // Test if the actual DNS-Record differs from the host's IP.
a7c1e271 250 else if ( ip_host != ip_dns_recheck )
0541cd71 251 {
1af7c124
BS
252 // Check if the service will be updated for the first time.
253 if ( lastupdated == 0 )
254 {
255 // Update for the firt time.
256 Log->print_update_service_firttime(hostname, ip_dns_recheck, ip_host);
257 service->update(ip_host,current_time);
258 }
259 else
260 {
261 // We already have updated, check if the IP set in last update differs from the actual host's ip.
262 if ( ip_last_update != ip_host )
263 {
264 // Update
265 Log->print_update_service(hostname, ip_dns_recheck, ip_last_update, ip_host, lastupdated);
266 service->update(ip_host,current_time);
267 }
268 else
269 {
270 int dns_cache_ttl = service->get_dns_cache_ttl();
271 // Check if DNS Cache TTL is expired, if so, then update the same IP again.
272 if ( (lastupdated + dns_cache_ttl) < current_time )
273 {
274 // Update
275 Log->print_update_service_ttl_expired(hostname, ip_dns_recheck, ip_last_update, ip_host, lastupdated, dns_cache_ttl, current_time);
276 service->update(ip_host,current_time);
277 }
278 else
279 {
280 // DNS cache TTL isn't expired
281 Log->print_update_service_ttl_not_expired(hostname, ip_dns_recheck, ip_last_update, ip_host, lastupdated, dns_cache_ttl, current_time);
282 }
283 }
284 }
285 }
286 else
287 {
288 Log->print_no_update_needed(hostname, ip_dns_recheck, ip_last_update, ip_host, lastupdated);
0541cd71 289 }
3c0cd271 290 }
4545a371 291 }
1d2e2f56
BS
292 else
293 {
294 Log->print_no_wan_ip();
295 }
b1be615b 296}
e0080b78
BS
297
298
299/**
300 * Getter for member ServiceHolder.
301 * @return ServiceHolder
302 */
303Serviceholder::Ptr Updater::get_service_holder() const
304{
305 return ServiceHolder;
306}