From b30f392dfa55d0fdb0834407561a91f78fac472d Mon Sep 17 00:00:00 2001 From: Bjoern Sikora Date: Thu, 3 Sep 2009 16:41:11 +0200 Subject: [PATCH] Added implementation of dyns service. --- dyns.conf | 7 ++ src/config.cpp | 6 ++ src/dyndns.cpp | 2 +- src/dyns.cpp | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/dyns.h | 54 +++++++++++++++ src/httphelper.cpp | 4 +- src/httphelper.h | 4 +- src/iphelper.cpp | 6 +- src/iphelper.h | 7 +- src/main.cpp | 7 +- src/updater.cpp | 4 + 11 files changed, 271 insertions(+), 16 deletions(-) create mode 100644 dyns.conf create mode 100644 src/dyns.cpp create mode 100644 src/dyns.h diff --git a/dyns.conf b/dyns.conf new file mode 100644 index 0000000..ac68498 --- /dev/null +++ b/dyns.conf @@ -0,0 +1,7 @@ +protocol=dyns +host=ddnstest.dyns.net +login=testclient +password=open +update_interval=0 +max_updates_within_interval=0 +dns_cache_ttl=300 diff --git a/src/config.cpp b/src/config.cpp index 8aaa873..7b7d184 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -12,6 +12,7 @@ #include "dhs.h" #include "ods.h" #include "dyndns.h" +#include "dyns.h" #include #include @@ -262,6 +263,11 @@ Service::Ptr Config::create_service(const string &protocol,const string &hostnam Service::Ptr service_dyndns(new DYNDNS(protocol,hostname,login,password,Log,update_interval,max_updates_within_interval,dns_cache_ttl,Proxy,ProxyPort)); return service_dyndns; } + else if(protocol == "dyns") + { + Service::Ptr service_dyns(new DYNS(protocol,hostname,login,password,Log,update_interval,max_updates_within_interval,dns_cache_ttl,Proxy,ProxyPort)); + return service_dyns; + } else { Log->print_unknown_protocol(protocol); diff --git a/src/dyndns.cpp b/src/dyndns.cpp index c8eacda..22923c6 100644 --- a/src/dyndns.cpp +++ b/src/dyndns.cpp @@ -70,7 +70,7 @@ DYNDNS::~DYNDNS() /** - * Assemble the dhs update url from the given fqhn + * Assemble the dyndns update url from the given fqhn * @param hostname The fqhn hostname to update IP for. * @return The assembled update url without IP. */ diff --git a/src/dyns.cpp b/src/dyns.cpp new file mode 100644 index 0000000..7a2229d --- /dev/null +++ b/src/dyns.cpp @@ -0,0 +1,186 @@ +/** @file + * @brief DYNS Service class implementation. This class represents the DYNS service. + * + * + * + * @copyright Intra2net AG + * @license GPLv2 +*/ + +#include "dyns.h" + +#include +#include + +using namespace std; + + +/** + * Default Constructor, needed for object serialization. + */ +DYNS::DYNS() +{ +} + + +/** + * Constructor. + * @param _hostname The hostname to update + * @param _login The login name. + * @param _password The corresponding password. + */ +DYNS::DYNS(const string& _protocol, const string& _hostname, const string& _login, const string& _password, const Logger::Ptr& _logger, const int _update_interval, const int _max_updates_within_interval, const int _dns_cache_ttl, const string& _proxy, const int _proxy_port) +{ + if ( _update_interval == -1 ) // If _update_interval is default po::option_desc (not specified via config) + set_update_interval(5); // use default protocol value + else + set_update_interval(_update_interval); + + if ( _max_updates_within_interval == -1 ) + set_max_updates_within_interval(1); + else + set_max_updates_within_interval(_max_updates_within_interval); + + if ( _dns_cache_ttl == -1 ) + set_dns_cache_ttl(300); + else + set_dns_cache_ttl(_dns_cache_ttl); + + set_protocol(_protocol); + set_hostname(_hostname); + set_login(_login); + set_password(_password); + set_logger(_logger); + + // create http helper class + HTTPHelper::Ptr _http_help(new HTTPHelper(_logger,_proxy,_proxy_port)); + HTTPHelp = _http_help; + _http_help.reset(); + + BaseUrl = assemble_base_url(get_hostname(),get_login(),get_password()); +} + + +/** + * Default destructor + */ +DYNS::~DYNS() +{ +} + + +/** + * Assemble the dyns update url from the given fqhn + * @param hostname The fqhn hostname to update IP for. + * @param username The username to use. + * @param hostname The password to use. + * @return The assembled update url without IP. + */ +string DYNS::assemble_base_url(const string& fqhn, const string& username, const string& password) const +{ + string base_url; + + base_url = "http://www.dyns.net"; + base_url.append("/postscript011.php?username="); + base_url.append(username); + base_url.append("&password="); + base_url.append(password); + base_url.append("&host="); + base_url.append(fqhn); + base_url.append("&ip="); + + return base_url; +} + + +/** + * Performs the Service update. + * @param ip IP Address to set. + * @return 0 if all is fine, -1 otherwise. + */ +int DYNS::perform_update(const std::string& ip) +{ + int ret_val = -1; + + string url = BaseUrl; + url.append(ip); + + long http_status_code = HTTPHelp->http_get(url); + + get_logger()->print_http_status_code(url,http_status_code); + + // HTTP operation completed successful, now we have to parse the data received by curl cause http status code is not significant for dyns update errors + if ( http_status_code == 200 ) + { + string curl_data = HTTPHelp->get_curl_data(); + string status_code = parse_status_code(curl_data); + + if ( status_code == "200" ) + { + ret_val = 0; + } + else if ( status_code == "401" ) + { + // badauth + get_logger()->print_http_not_authorized(url,get_login(),get_password()); + } + else + { + // generic + get_logger()->print_update_failure(url,curl_data); + } + } + + return ret_val; +} + + +/** + * Get the status code from the returned http data + * @param data The returned http data. + * @return The status code. + */ +string DYNS::parse_status_code(const string& data) const +{ + list tokens = split(data," "); + return tokens.front(); +} + + +/** + * Splitts a string into single tokens useing given delimiters + * @param str String to split + * @param delimiters Deliminters to use + * @return A list with the single tokens + */ +list DYNS::split(const string& str,const string& delimiters) const +{ + list tokens; + // Skip delimiters at beginning. + string::size_type lastPos = str.find_first_not_of(delimiters, 0); + // Find first "non-delimiter". + string::size_type pos = str.find_first_of(delimiters, lastPos); + + while (string::npos != pos || string::npos != lastPos) + { + // Found a token, add it to the list. + tokens.push_back(str.substr(lastPos, pos - lastPos)); + // Skip delimiters. Note the "not_of" + lastPos = str.find_first_not_of(delimiters, pos); + // Find next "non-delimiter" + pos = str.find_first_of(delimiters, lastPos); + } + return tokens; +} + + +/** + * Serialize function needed by boost/serialization to define which members should be stored as the object state. + * @param ar Archive + * @param version Version + */ +template +void DYNS::serialize(Archive & ar, const unsigned int version) +{ + ar & boost::serialization::base_object(*this); +} diff --git a/src/dyns.h b/src/dyns.h new file mode 100644 index 0000000..1650f80 --- /dev/null +++ b/src/dyns.h @@ -0,0 +1,54 @@ +/** @file + * @brief DYNS Service class header. This class represents the DYNS service. + * + * + * + * @copyright Intra2net AG + * @license GPLv2 +*/ + +#ifndef DYNS_H +#define DYNS_H + +#include + +#include "service.h" +#include "logger.h" + +#include +#include +#include + +class DYNS : public Service +{ + +private: + + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version); + + std::string BaseUrl; + + HTTPHelper::Ptr HTTPHelp; + + std::string assemble_base_url(const std::string& fqhn, const std::string& username, const std::string& password) const; + + std::string parse_status_code(const std::string& data) const; + + std::list split(const std::string& str,const std::string& delimiters) const; + +public: + + typedef boost::shared_ptr Ptr; + + DYNS(); + + DYNS(const std::string& _protocol, const std::string& _hostname, const std::string& _login, const std::string& _password, const Logger::Ptr& _logger, const int _update_interval, const int _max_updates_within_interval, const int dns_cache_ttl, const std::string& proxy, const int proxy_port); + + ~DYNS(); + + int perform_update(const std::string& ip); +}; + +#endif diff --git a/src/httphelper.cpp b/src/httphelper.cpp index b1dbbbf..5b24702 100644 --- a/src/httphelper.cpp +++ b/src/httphelper.cpp @@ -13,8 +13,8 @@ * Default Constructor */ HTTPHelper::HTTPHelper() - : ProxyPort(0) - , Log(new Logger) + : Log(new Logger) + , ProxyPort(0) { } diff --git a/src/httphelper.h b/src/httphelper.h index bb1b7c3..d8c982a 100644 --- a/src/httphelper.h +++ b/src/httphelper.h @@ -20,16 +20,14 @@ class HTTPHelper { private: + Logger::Ptr Log; std::string Proxy; int ProxyPort; CURL* CurlEasyHandle; std::string CurlWritedataBuff; char* CurlErrBuff; - Logger::Ptr Log; - void set_curl_url(const std::string& url); - void set_curl_auth(const std::string& username, const std::string& password); public: diff --git a/src/iphelper.cpp b/src/iphelper.cpp index 446193e..a5ed2e5 100644 --- a/src/iphelper.cpp +++ b/src/iphelper.cpp @@ -19,9 +19,9 @@ namespace net = boost::asio; * Default constructor. */ IPHelper::IPHelper() - : ProxyPort(0) + : Log(new Logger) + , ProxyPort(0) , UseIPv6(false) - , Log(new Logger) { } @@ -32,7 +32,7 @@ IPHelper::IPHelper() IPHelper::IPHelper(const Logger::Ptr _log, const string& _webcheck_url, const string& _webcheck_url_alt, const bool _use_ipv6, const string& _proxy, const int _proxy_port) : Log(_log) , WebcheckIpUrl(_webcheck_url) - , WebcheckIpUrlAl(_webcheck_url_alt) + , WebcheckIpUrlAlt(_webcheck_url_alt) , Proxy(_proxy) , ProxyPort(_proxy_port) , UseIPv6(_use_ipv6) diff --git a/src/iphelper.h b/src/iphelper.h index 9cc74fa..439268c 100644 --- a/src/iphelper.h +++ b/src/iphelper.h @@ -19,15 +19,14 @@ class IPHelper { private: - std::string Hostname; + + Logger::Ptr Log; std::string WebcheckIpUrl; std::string WebcheckIpUrlAlt; std::string Proxy; int ProxyPort; - bool UseIPv6; - - Logger::Ptr Log; + std::string Hostname; public: diff --git a/src/main.cpp b/src/main.cpp index 55ab56d..4653c69 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,17 +29,18 @@ #include "updater.h" #include "config.cpp" -#include "dhs.cpp" #include "logger.cpp" -#include "ods.cpp" #include "service.cpp" #include "serviceholder.cpp" #include "updater.cpp" #include "iphelper.cpp" #include "httphelper.cpp" #include "serializeservicecontainer.cpp" -#include "dyndns.cpp" +#include "dyndns.cpp" +#include "dyns.cpp" +#include "ods.cpp" +#include "dhs.cpp" using namespace std; diff --git a/src/updater.cpp b/src/updater.cpp index e1fa1ae..7650f67 100644 --- a/src/updater.cpp +++ b/src/updater.cpp @@ -12,6 +12,8 @@ #include "serviceholder.h" #include "dhs.h" #include "ods.h" +#include "dyndns.h" +#include "dyns.h" #include @@ -19,8 +21,10 @@ // Following boost macros are needed for serialization of derived classes through a base class pointer (Service *). BOOST_CLASS_EXPORT_GUID(ODS, "ODS") BOOST_CLASS_EXPORT_GUID(DHS, "DHS") +BOOST_CLASS_EXPORT_GUID(DYNS, "DYNS") BOOST_CLASS_EXPORT_GUID(DYNDNS, "DYNDNS") + namespace fs = boost::filesystem; using namespace std; -- 1.7.1