Implemented determining IP through WEBCHECK URL.
authorBjoern Sikora <bjoern.sikora@intra2net.com>
Thu, 13 Aug 2009 15:57:11 +0000 (17:57 +0200)
committerBjoern Sikora <bjoern.sikora@intra2net.com>
Thu, 13 Aug 2009 15:57:11 +0000 (17:57 +0200)
src/iphelper.cpp
src/iphelper.h
src/logger.cpp
src/logger.h
src/updater.cpp

index 634cc5f..4d81e07 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "iphelper.h"
 #include <boost/asio.hpp>
+#include <boost/regex.hpp>
 
 using namespace std;
 
@@ -120,7 +121,155 @@ string IPHelper::dns_query() const
  */
 string IPHelper::webcheck_ip() const
 {
-    string ip_addr = "127.0.0.1";
+    string ip_addr = "";
+
+    // Init CURL buffers
+    string curl_writedata_buff;
+    char curl_err_buff[CURL_ERROR_SIZE];
+    int curl_err_code=1;
+
+    // Init URL List
+    list<string> url_list;
+    url_list.push_back(WebcheckIpUrl);
+    url_list.push_back(WebcheckIpUrlAlt);
+    string actual_url;
+
+    // Init CURL
+    CURL * curl_easy_handle = init_curl(curl_writedata_buff,curl_err_buff);
+
+    // If perform_curl_operation returns a connection problem indicating return code, try the next ip webcheck url if there is one.
+    while ( (curl_err_code == 1) && (url_list.size() != 0) && (url_list.front() != "") )
+    {
+        // Set URL
+        actual_url = url_list.front();
+        url_list.pop_front();
+        set_curl_url(curl_easy_handle,actual_url);
+
+        // Perform curl operation
+        curl_err_code = perform_curl_operation(curl_easy_handle, curl_err_buff, actual_url);
+    }
+
+    // Cleanup CURL handle
+    curl_easy_cleanup(curl_easy_handle);
+
+    // If curl_err_code is not 0, the ip couldn't be determined through any configured webcheck url.
+    if ( curl_err_code != 0 )
+    {
+        Log->print_webcheck_no_ip();
+        // error handling
+        return ip_addr;
+    }
+
+    Log->print_received_curl_data(curl_writedata_buff);
+
+    ip_addr = parse_ip(curl_writedata_buff);
 
     return ip_addr;
 }
+
+
+/**
+ * Tries to find a valid IPv4 Address in dottet format in a given string and returns the IP-Address found.
+ * @param data The string data to search in for a valid IPv4-Address.
+ * @return The IP Address found or an empty string.
+ */
+string IPHelper::parse_ip(const string& data) const
+{
+    string ip = "";
+
+    // regex for valid ip address
+    boost::regex expr("([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})");
+
+    boost::smatch matches;
+
+    if ( boost::regex_search(data,matches,expr) )
+    {
+        ip = matches[1];
+        Log->print_regex_found_ip(ip);
+    }
+    else
+    {
+        Log->print_regex_ip_not_found(data);
+    }
+
+    return ip;
+}
+
+
+/**
+ * Performs the curl operation.
+ * @param curl_easy_handle The initialized and configured curl handle.
+ * @param curl_err_buff The pointer to the curl error buffer to get error messages from.
+ * @param actual_url The actual configured URL.
+ * @return 0 if all is fine, 1 if an connection problem to the configured url occurs, -1 on other errors.
+ */
+int IPHelper::perform_curl_operation(CURL * curl_easy_handle, char* curl_err_buff, const string& actual_url) const
+{
+    int curl_err_code;
+    if ( (curl_err_code = curl_easy_perform(curl_easy_handle) ) != 0 )
+    {
+        // CURL error occured
+        if ( (curl_err_code == CURLE_COULDNT_CONNECT) || (curl_err_code == CURLE_OPERATION_TIMEOUTED) || (curl_err_code == CURLE_COULDNT_RESOLVE_HOST) )
+        {
+            // In case of connection problems we should return 1, that the fallback url will be used.
+            Log->print_webcheck_url_connection_problem(curl_err_buff, actual_url);
+            return 1;
+        }
+        else
+        {
+            // other error
+            Log->print_webcheck_error(curl_err_buff, actual_url);
+            return -1;
+        }
+    }
+    // Operation performed without any problems
+    return 0;
+}
+
+
+/**
+ * Sets a url to the easy curl handle
+ * @param curl_easy_handle The easy curl handle to set the url for.
+ * @param url The url to set.
+ */
+void IPHelper::set_curl_url(CURL * curl_easy_handle, const string& url) const
+{
+    curl_easy_setopt(curl_easy_handle,CURLOPT_URL,url.c_str());
+}
+
+
+/**
+ * Initialized curl easy handle with a few options.
+ * @param curl_writedata_buff Reference to a string wich will be filled with the curl result
+ * @param curl_err_buff A pointer to an char array which will be filled with error message.
+ * @return A pointer to the easy curl handle.
+ */
+CURL * IPHelper::init_curl(string& curl_writedata_buff,char* curl_err_buff) const
+{
+    CURL *curl_easy_handle = curl_easy_init();
+
+    curl_easy_setopt(curl_easy_handle,CURLOPT_NOPROGRESS,1);
+    curl_easy_setopt(curl_easy_handle,CURLOPT_CONNECTTIMEOUT,5);
+    curl_easy_setopt(curl_easy_handle,CURLOPT_TIMEOUT,10);
+    curl_easy_setopt(curl_easy_handle,CURLOPT_BUFFERSIZE,1024);
+    curl_easy_setopt(curl_easy_handle,CURLOPT_ERRORBUFFER,curl_err_buff);
+    curl_easy_setopt(curl_easy_handle,CURLOPT_WRITEFUNCTION,http_receive);
+    curl_easy_setopt(curl_easy_handle,CURLOPT_WRITEDATA,&curl_writedata_buff);
+
+    return curl_easy_handle;
+}
+
+
+/**
+ * Callback Function is called every time CURL is receiving data from HTTPS-Server and will copy all received Data to the given stream pointer
+ * @param inBuffer Pointer to input.
+ * @param size How many mem blocks are received
+ * @param nmemb size of each memblock
+ * @param outBuffer Pointer to output stream.
+ * @return The size received.
+ */
+int IPHelper::http_receive( char *inBuffer, size_t size, size_t nmemb, string *outBuffer )
+{
+    outBuffer->append(inBuffer);
+    return (size*nmemb);
+}
index 0cf4787..98622fd 100644 (file)
@@ -13,6 +13,7 @@
 #include "logger.h"
 
 #include <boost/shared_ptr.hpp>
+#include <curl/curl.h>
 
 /**
        @author Bjoern Sikora <bjoern.sikora@intra2net.com>
@@ -43,6 +44,17 @@ public:
     std::string dns_query() const;
 
     std::string webcheck_ip() const;
+
+    // libcurl is a C library, so we have to make the callback member function static :-(
+    static int http_receive( char *, size_t, size_t, std::string* );
+
+    CURL * init_curl(std::string&, char*) const;
+
+    void set_curl_url(CURL *, const std::string&) const;
+
+    int perform_curl_operation(CURL *, char*, const std::string&) const;
+
+    std::string parse_ip(const std::string&) const;
 };
 
 #endif
index cab7b5e..93f8ed2 100644 (file)
@@ -749,7 +749,7 @@ void Logger::print_own_ipv6(const std::string& ip_addr_v6) const
  * @param exception The exception caught.
  * @param hostname The hostname.
  */
-void Logger::print_error_hostname_to_ip(const std::string& exception, const std::string& hostname) const
+void Logger::print_error_hostname_to_ip(const string& exception, const string& hostname) const
 {
     if ( 1 <= Loglevel )
     {
@@ -760,12 +760,107 @@ void Logger::print_error_hostname_to_ip(const std::string& exception, const std:
 }
 
 
-void Logger::print_update_service_successful(const std::string& service)
+/**
+ * The update of the given service was successful.
+ * @param service The service.
+ */
+void Logger::print_update_service_successful(const string& service) const
 {
     if ( 0 <= Loglevel )
     {
         ostringstream msg;
         msg << "Updated service successful: " << service << endl;
+        log_notice(msg.str());
+    }
+}
+
+
+/**
+ * No ip could be determined through webcheck
+ */
+void Logger::print_webcheck_no_ip() const
+{
+    if ( 0 <= Loglevel )
+    {
+        ostringstream msg;
+        msg << "This hosts' IP could not be determined through any configured webcheck url." << endl;
+        log_error(msg.str());
+    }
+}
+
+
+/**
+ * Connection problem while trying to get ip through webcheck url
+ * @param curl_err_buff Curl error message
+ * @param url the url
+ */
+void Logger::print_webcheck_url_connection_problem(const char * curl_err_buff, const string& url) const
+{
+    if ( 1 <= Loglevel )
+    {
+        ostringstream msg;
+        msg << "There was a problem while trying to connect to following URL: " << url << " CURL error: " << curl_err_buff << endl;
+        log_warning(msg.str());
+    }
+}
+
+
+/**
+ * Prints out curl error.
+ * @param curl_err_buff Curl error message.
+ * @param url URL
+ */
+void Logger::print_webcheck_error(const char * curl_err_buff, const string& url) const
+{
+    if ( 0 <= Loglevel )
+    {
+        ostringstream msg;
+        msg << "There was an error while trying to connect to following URL: " << url << " CURL error: " << curl_err_buff << endl;
         log_error(msg.str());
     }
 }
+
+
+/**
+ * Prints out the received data through curl.
+ * @param curl_data Data string
+ */
+void Logger::print_received_curl_data(const string& curl_data) const
+{
+    if ( 1 <= Loglevel )
+    {
+        ostringstream msg;
+        msg << "Received CURL data: " << curl_data << endl;
+        log_notice(msg.str());
+    }
+}
+
+
+/**
+ * IP was foudn through regex
+ * @param ip The IP found.
+ */
+void Logger::print_regex_found_ip(const string& ip) const
+{
+    if ( 1 <= Loglevel )
+    {
+        ostringstream msg;
+        msg << "Found IP-Address via regex: " << ip << endl;
+        log_notice(msg.str());
+    }
+}
+
+
+/**
+ * No IP was found through regex.
+ * @param data The data string which should contain a valid IP.s
+ */
+void Logger::print_regex_ip_not_found(const string& data) const
+{
+    if ( 0 <= Loglevel )
+    {
+        ostringstream msg;
+        msg << "Could not extract an IP-Address via regex from following data:\n" << data << endl;
+        log_warning(msg.str());
+    }
+}
index a7fd2df..b2a584f 100644 (file)
@@ -133,7 +133,19 @@ public:
 
     void print_error_hostname_to_ip(const std::string&, const std::string&) const;
 
-    void print_update_service_successful(const std::string&);
+    void print_update_service_successful(const std::string&) const;
+
+    void print_webcheck_no_ip() const;
+
+    void print_webcheck_url_connection_problem(const char *, const std::string&) const;
+
+    void print_webcheck_error(const char *, const std::string&) const;
+
+    void print_received_curl_data(const std::string&) const;
+
+    void print_regex_found_ip(const std::string&) const;
+
+    void print_regex_ip_not_found(const std::string&) const;
 };
 
 #endif
index bc46127..17ed7da 100644 (file)
@@ -163,7 +163,7 @@ void Updater::update_services()
 
     BOOST_FOREACH(Service::Ptr &service, services )
     {
-        // TODO: only update if IP differs.
+        // TODO: only update if IP differs and is_valid and is_not_empty.
         service->update(ip);
     }
 }