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