Implemented curl error handling. Improved httphelper. Enhanced dhs protocol handling.
authorBjoern Sikora <bjoern.sikora@intra2net.com>
Thu, 3 Sep 2009 08:35:10 +0000 (10:35 +0200)
committerBjoern Sikora <bjoern.sikora@intra2net.com>
Thu, 3 Sep 2009 08:35:10 +0000 (10:35 +0200)
src/config.cpp
src/dhs.cpp
src/httphelper.cpp
src/httphelper.h
src/logger.cpp
src/logger.h
src/service.cpp
src/serviceholder.cpp
src/updater.cpp

index f46a562..a4fa6bf 100644 (file)
@@ -163,7 +163,7 @@ int Config::parse_cmd_line(int argc, char *argv[])
             if ( service )
             {
                 ServiceHolder->add_service(service);
-                Log->print_service_object("New Service object from command line options:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password(), service->get_update_interval(), service->get_max_updates_within_interval(), service->get_actual_ip(), service->get_last_updates());
+                Log->print_service_object("New Service object from command line options:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password(), service->get_update_interval(), service->get_max_updates_within_interval(), service->get_dns_cache_ttl() , service->get_actual_ip(), service->get_last_updates());
             }
             else
                 return -1;
@@ -314,7 +314,7 @@ int Config::load_service_config_file(const string& full_filename)
                 if ( service )
                 {
                     ServiceHolder->add_service(service);
-                    Log->print_service_object("New Service object from config:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password(), service->get_update_interval(), service->get_max_updates_within_interval(), service->get_actual_ip(), service->get_last_updates());
+                    Log->print_service_object("New Service object from config:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password(), service->get_update_interval(), service->get_max_updates_within_interval(), service->get_dns_cache_ttl() , service->get_actual_ip(), service->get_last_updates());
                 }
                 else
                     return -1;
index dd3fc80..cbefaae 100644 (file)
@@ -173,17 +173,30 @@ list<string> DHS::split(const string& str,const string& delimiters) const
  */
 int DHS::perform_update(const std::string& ip)
 {
-    BaseUrl.append(ip);
+    int ret_val = 0;
 
-    cout << "BASE URL: " << BaseUrl << endl;
+    BaseUrl.append(ip);
 
-    string output = HTTPHelp->http_get(BaseUrl);
+    long output = HTTPHelp->http_get(BaseUrl);
 
-    cout << "OUTPUT: " << output << endl;
+    get_logger()->print_http_status_code(BaseUrl,output);
 
-    // TODO: check output for failure, we have to parse html :-(
+    if ( output == 200 )
+    {
+        ret_val = 0;
+    }
+    else if ( output == -1 )
+    {
+        ret_val = -1;
+    }
+    else if ( output == 401 )
+    {
+        get_logger()->print_http_not_authorized(BaseUrl,get_login(),get_password());
+        // not authorized
+        ret_val = -1;
+    }
 
-    return 0;
+    return ret_val;
 }
 
 
index 2b4b3ac..036051e 100644 (file)
@@ -9,6 +9,9 @@
 
 #include "httphelper.h"
 
+/**
+ * Default Constructor
+ */
 HTTPHelper::HTTPHelper()
     : Proxy("")
     , ProxyPort(0)
@@ -16,6 +19,15 @@ HTTPHelper::HTTPHelper()
 {
 }
 
+
+/**
+ * Constructor
+ * @param _log Logger Object 
+ * @param _proxy Proxy to use
+ * @param _proxy_port Proxy Port
+ * @param _username Username
+ * @param _password Password
+ */
 HTTPHelper::HTTPHelper(Logger::Ptr _log, const string& _proxy, const int _proxy_port, const string& _username, const string& _password)
 {
     Log = _log;
@@ -27,6 +39,9 @@ HTTPHelper::HTTPHelper(Logger::Ptr _log, const string& _proxy, const int _proxy_
 }
 
 
+/**
+ * Destructor
+ */
 HTTPHelper::~HTTPHelper()
 {
 }
@@ -35,21 +50,30 @@ HTTPHelper::~HTTPHelper()
 /**
  * Perform a HTTP GET operation
  * @param url URL for HTTP GET operation
- * @return The data GET from the URL
+ * @return The status code from the http operation or -1 if an curl error occurs
  */
-string HTTPHelper::http_get(const string& url)
+long HTTPHelper::http_get(const string& url)
 {
     int curl_err_code;
+    long curl_info;
 
     set_curl_url(url);
 
     if ( (curl_err_code = curl_easy_perform(CurlEasyHandle) ) != 0 )
     {
-        // TODO: Logging errors
-        return "";
+        Log->print_curl_error(url,curl_err_code,CurlErrBuff);
+        return -1;
+    }
+    if ( (curl_err_code = curl_easy_getinfo(CurlEasyHandle,CURLINFO_RESPONSE_CODE,&curl_info)) != 0 )
+    {
+         Log->print_curl_error(url,curl_err_code);
+        return -1;
     }
-    // Operation performed without any problems so we can return the CurlWritedataBuff
-    return CurlWritedataBuff;
+
+    Log->print_curl_data(CurlWritedataBuff);
+
+    // Operation performed without any problems so we can return the curl_info
+    return curl_info;
 }
 
 
index b5cb9d2..b63e45c 100644 (file)
@@ -44,7 +44,7 @@ public:
 
     CURL* init_curl(std::string& curl_writedata_buff, char* curl_err_buff) const;
 
-    std::string http_get(const std::string& ip);
+    long http_get(const std::string& ip);
 
     // libcurl is a C library, so we have to make the callback member function static :-(
     static int http_receive(char *inBuffer, size_t size, size_t nmemb, std::string *outBuffer);
index d0ad8d2..9fe824f 100644 (file)
@@ -672,7 +672,7 @@ void Logger::print_deserialized_objects_success() const
  * @param actual_ip Service's actual_ip.
  * @param lastupdated Service's lastupdated.
  */
-void Logger::print_service_object(const string& message, const string& protocol, const string& hostname, const string& login, const string& password, const int update_interval, const int max_updates_within_interval, const string& actual_ip, list<int>* lastupdated) const
+void Logger::print_service_object(const string& message, const string& protocol, const string& hostname, const string& login, const string& password, const int update_interval, const int max_updates_within_interval, const int dns_cache_ttl , const string& actual_ip, list<int>* lastupdated) const
 {
     int level = 1;
     if ( (level <= Loglevel) || ((level <= ExternalWarningLevel) && (!ExternalWarningLog.empty())) )
@@ -685,6 +685,7 @@ void Logger::print_service_object(const string& message, const string& protocol,
         msg << "\t" << "Password:         " << password << endl;
         msg << "\t" << "Update Interval:  " << update_interval << endl;
         msg << "\t" << "Max Updates:      " << max_updates_within_interval << endl;
+        msg << "\t" << "DNS Cache TTL:    " << dns_cache_ttl << endl;
         msg << "\t" << "Actual_IP:        " << actual_ip << endl;
         BOOST_FOREACH( int update_time, *lastupdated)
         {
@@ -1077,7 +1078,7 @@ void Logger::print_recheck_dns_entry(const string& hostname, const int lastupdat
     if ( (level <= Loglevel) || ((level <= ExternalWarningLevel) && (!ExternalWarningLog.empty())) )
     {
         ostringstream msg;
-        msg << "DNS cache record for host <" << hostname << "> expired: Lastupdated: " << lastupdated << " DNS cache ttl: " << dns_cache_ttl << " Current time: " << current_time << " Checking current DNS cache status." << endl;
+        msg << "DNS cache record for host <" << hostname << "> expired or host will be updated for the first time: Lastupdated: " << lastupdated << " DNS cache ttl: " << dns_cache_ttl << " Current time: " << current_time << " Checking current DNS cache status." << endl;
         log_notice(msg.str(),level);
     }
 }
@@ -1169,7 +1170,7 @@ void Logger::print_missing_conf_proxy_option(const string& main_conf_filename) c
  * There is no domain part in the given hostname
  * @param hostname The hostname with no domain part in it.
  */
-void Logger::print_no_domain_part(const std::string& hostname) const
+void Logger::print_no_domain_part(const string& hostname) const
 {
     int level = 0;
     if ( (level <= Loglevel) || ((level <= ExternalWarningLevel) && (!ExternalWarningLog.empty())) )
@@ -1179,3 +1180,111 @@ void Logger::print_no_domain_part(const std::string& hostname) const
         log_notice(msg.str(),level);
     }
 }
+
+
+/**
+ * An curl error occured.
+ * @param url The url requested by the curl operation
+ * @param curl_err_code The resulting curl error code
+ */
+void Logger::print_curl_error(const string& url, const int curl_err_code) const
+{
+    string curl_err = "";
+
+    if ( curl_err_code == 3 )
+        curl_err = "CURLE_URL_MALFORMAT";
+    else if ( curl_err_code == 6 )
+        curl_err = "CURLE_COULDNT_RESOLVE_HOST";
+    else if ( curl_err_code == 7 )
+        curl_err = "CURLE_COULDNT_CONNECT";
+    else
+        curl_err = "UNKNOWN";
+
+    int level = 0;
+    if ( (level <= Loglevel) || ((level <= ExternalWarningLevel) && (!ExternalWarningLog.empty())) )
+    {
+        ostringstream msg;
+        msg << "Curl error while requesting following url: " << url << " Curl error code: " << curl_err_code << " "<< curl_err << endl;
+        log_warning(msg.str(),level);
+    }
+}
+
+
+/**
+ * An curl error occured.
+ * @param url The url requested by the curl operation
+ * @param curl_err_code The resulting curl error code
+ * @param curl_err_buff The curl error buffer
+ */
+void Logger::print_curl_error(const string& url, const int curl_err_code, const char * curl_err_buff) const
+{
+    string curl_err = "";
+
+    if ( curl_err_code == 3 )
+        curl_err = "CURLE_URL_MALFORMAT";
+    else if ( curl_err_code == 6 )
+        curl_err = "CURLE_COULDNT_RESOLVE_HOST";
+    else if ( curl_err_code == 7 )
+        curl_err = "CURLE_COULDNT_CONNECT";
+    else
+        curl_err = "UNKNOWN";
+
+    int level = 0;
+    if ( (level <= Loglevel) || ((level <= ExternalWarningLevel) && (!ExternalWarningLog.empty())) )
+    {
+        ostringstream msg;
+        msg << "Curl error while requesting following url: " << url << " Curl error code: " << curl_err_code << " "<< curl_err << " " << curl_err_buff << endl;
+        log_warning(msg.str(),level);
+    }
+}
+
+
+/**
+ * Prints out the data received by curl operation
+ * @param CurlWritedataBuff 
+ */
+void Logger::print_curl_data(const string& curl_writedata_buff) const
+{
+    int level = 1;
+    if ( (level <= Loglevel) || ((level <= ExternalWarningLevel) && (!ExternalWarningLog.empty())) )
+    {
+        ostringstream msg;
+        msg << "Data received by curl:\n" << curl_writedata_buff << endl;
+        log_notice(msg.str(),level);
+    }
+}
+
+
+/**
+ * Not authorized to perform requested http operation
+ * @param url The requested url
+ * @param username Username
+ * @param password Password
+ */
+void Logger::print_http_not_authorized(const string& url, const string& username, const string& password) const
+{
+    int level = 0;
+    if ( (level <= Loglevel) || ((level <= ExternalWarningLevel) && (!ExternalWarningLog.empty())) )
+    {
+        ostringstream msg;
+        msg << "Not authorized to perform update operation on url: " << url << "\n Please check username and password: " << username << ":" << password << endl;
+        log_warning(msg.str(),level);
+    }
+}
+
+
+/**
+ * Prints out the http status code
+ * @param url Url
+ * @param output HTTP status code
+ */
+void Logger::print_http_status_code(const std::string& url, const long http_code) const
+{
+    int level = 1;
+    if ( (level <= Loglevel) || ((level <= ExternalWarningLevel) && (!ExternalWarningLog.empty())) )
+    {
+        ostringstream msg;
+        msg << "Requested URL: " << url << " Received HTTP status code: " << http_code << endl;
+        log_notice(msg.str(),level);
+    }
+}
index 69284b9..710be11 100644 (file)
@@ -118,7 +118,7 @@ public:
 
     void print_deserialized_objects_success() const;
 
-    void print_service_object(const std::string& message, const std::string& protocol, const std::string& hostname, const std::string& login, const std::string& password, const int update_interval, const int max_updates_within_interval, const std::string& actual_ip, std::list<int>* lastupdated) const;
+    void print_service_object(const std::string& message, const std::string& protocol, const std::string& hostname, const std::string& login, const std::string& password, const int update_interval, const int max_updates_within_interval, const int dns_cache_ttl , const std::string& actual_ip, std::list<int>* lastupdated) const;
 
     void print_exception_serialize(const std::string& exception) const;
 
@@ -179,6 +179,16 @@ public:
     void print_missing_conf_proxy_option(const std::string& main_conf_filename) const;
 
     void print_no_domain_part(const std::string& hostname) const;
+
+    void print_curl_error(const std::string& url, const int curl_err_code) const;
+
+    void print_curl_error(const std::string& url, const int curl_err_code, const char * curl_err_buff) const;
+
+    void print_curl_data(const std::string& curl_writedata_buff) const;
+
+    void print_http_not_authorized(const std::string& url, const std::string& username, const std::string& password) const;
+
+    void print_http_status_code(const std::string& url, const long http_code) const;
 };
 
 #endif
index 704da13..1319aee 100644 (file)
@@ -22,6 +22,7 @@ Service::Service()
     , ActualIP("0.0.0.0")
     , UpdateInterval(0)
     , MaxUpdatesWithinInterval(0)
+    , DNSCacheTTL(0)
     , Log(new Logger())
 {
 }
@@ -51,6 +52,7 @@ void Service::serialize(Archive & ar, const unsigned int version)
     ar & ActualIP;
     ar & UpdateInterval;
     ar & MaxUpdatesWithinInterval;
+    ar & DNSCacheTTL;
 }
 
 
index d45b211..7e33214 100644 (file)
@@ -134,14 +134,14 @@ int Serviceholder::deserialize_services()
         BOOST_FOREACH(Service::Ptr &old_service, _old_services)
         {
             OldServices.push_back(old_service);
-            Log->print_service_object("Deserialized following Service object:", old_service->get_protocol(), old_service->get_hostname(), old_service->get_login() ,old_service->get_password(), old_service->get_update_interval(), old_service->get_max_updates_within_interval(), old_service->get_actual_ip(), old_service->get_last_updates());
+            Log->print_service_object("Deserialized following Service object:", old_service->get_protocol(), old_service->get_hostname(), old_service->get_login() ,old_service->get_password(), old_service->get_update_interval(), old_service->get_max_updates_within_interval(), old_service->get_dns_cache_ttl() , old_service->get_actual_ip(), old_service->get_last_updates());
             BOOST_FOREACH(Service::Ptr &service, Services)
             {
                 if ( *service == *old_service )
                 {
                     service->set_last_updates(old_service->get_last_updates());
                     service->set_actual_ip(old_service->get_actual_ip());
-                    Log->print_service_object("New Service object with adopted values:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password(), service->get_update_interval(), service->get_max_updates_within_interval(), service->get_actual_ip(), service->get_last_updates());
+                    Log->print_service_object("New Service object with adopted values:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password(), service->get_update_interval(), service->get_max_updates_within_interval(), service->get_dns_cache_ttl() , service->get_actual_ip(), service->get_last_updates());
                     // We have adopted the values of the old_service. Just set lastupdated and timeout to 0, so this old_service wont be serialized.
                     old_service->set_update_interval(0);
                 }
index 1c82dbe..d966d14 100644 (file)
@@ -230,8 +230,8 @@ void Updater::update_services()
             if ( service->get_last_updates()->size() > 0 )
                 lastupdated = service->get_last_updates()->front();
 
-            // If the dns cache ttl is expired, then get the actual ip of the dns record (this should be the IP in the last update)
-            if ( (lastupdated != 0) && ((lastupdated + service->get_dns_cache_ttl()) < current_time) )
+            // If the dns cache ttl is expired or the service is updated for the first time, then get the actual ip of the dns record (this should be the IP in the last update)
+            if ( ((lastupdated != 0) && ((lastupdated + service->get_dns_cache_ttl()) < current_time)) || (lastupdated == 0) )
             {
                 Log->print_recheck_dns_entry(service->get_hostname(),lastupdated,service->get_dns_cache_ttl(),current_time);
                 string _dns_recheck_ip = IPHelp->dns_query(service->get_hostname());
@@ -243,8 +243,11 @@ void Updater::update_services()
             // In case the local hosts IP (ip) differ from the IP set in the last update (actual_ip) or
             // the IP of the dns record (dns_recheck_ip) differs from the IP of the local host (ip)
             // then perform an update. This implies that the update is not performed if actual_ip == dns_recheck_ip.
-            if ( (service->get_actual_ip() != ip) || (dns_recheck_ip != ip)  )
+            // Special case when latupdated == 0 then only perform the update if dns_rechek_ip differs from ip
+            if ( ((service->get_actual_ip() != ip) && (lastupdated != 0)) || (dns_recheck_ip != ip)  )
                 service->update(ip,current_time);
+            else if ( (service->get_actual_ip() != ip) && (lastupdated == 0)  )
+                service->set_actual_ip(ip);
         }
     }
 }