* new class for IP utils

* method to check telegram support out of config
* getters in Config.cpp
* lots of reformatings and cdoc
This commit is contained in:
lukas 2020-05-07 14:54:40 +02:00
parent b133ab6961
commit ba4af36df0
16 changed files with 175 additions and 58 deletions

View File

@ -146,7 +146,8 @@ add_library(logger ${LIB_METHOD}
SET(SOURCE SET(SOURCE
src/main.cpp src/main.cpp
src/IPRefresher.cpp src/IPRefresher.cpp
src/Config.cpp) src/Config.cpp
src/IpHelper.cpp)
add_executable(iprefresher ${SOURCE}) add_executable(iprefresher ${SOURCE})

View File

@ -6,22 +6,17 @@
#include <string> #include <string>
/**
* A static class to manage the configuration file, read/write parameters to it.
*/
class Config { class Config {
public: public:
static std::string dynuapikey;
static std::string domainid; //id of the dynu domain
static std::string domainname;
static std::string telegramApiKey;
static std::string chatId;
/** /**
* read configuration out of config file * read configuration out of config file
* *
* @return success of config read * @return success of config read
*/ */
static bool readCredentials(); static bool readConfig();
/** /**
* validate config file * validate config file
@ -30,5 +25,61 @@ public:
*/ */
static bool validateConfig(); static bool validateConfig();
/**
* check if telegram credentials in config are set
* @return is supported?
*/
static bool isTelegramSupported();
/** Getters **/
/**
* encapsulated getter for DynuApiKey
* @return api key
*/
static const std::string &getDynuapikey();
/**
* encapsulated getter for DomainId
* @return DomainId
*/
static const std::string &getDomainid();
/**
* encapsulated getter for Domainname
* @return Domainname
*/
static const std::string &getDomainname();
/**
* encapsulated getter for TelegramApiKey
* @return TelegramApiKey
*/
static const std::string &getTelegramApiKey();
/**
* encapsulated getter for ChatId
* @return ChatId
*/
static const std::string &getChatId();
private: private:
/**
* private constructor --> don't allow instance of this class
*/
Config();
/**
* helper variable for managing telegram Support
*/
static bool telegramSupport;
static std::string dynuapikey;
static std::string domainid; //id of the dynu domain
static std::string domainname;
static std::string telegramApiKey;
static std::string chatId;
}; };

View File

@ -14,7 +14,7 @@ public:
/** /**
* default constructor * default constructor
*/ */
IPRefresher(); IPRefresher() = default;
/** /**
* start the service in loop mode * start the service in loop mode

22
inc/IpHelper.h Normal file
View File

@ -0,0 +1,22 @@
//
// Created by lukas on 07.05.20.
//
#pragma once
#include <string>
/**
* General helper class for IP actions
*/
class IpHelper {
public:
/**
* check if ip is valid
* @param ip ip address to test
* @return validity
*/
static bool isIpValid(std::string ip);
private:
};

View File

@ -25,7 +25,10 @@ public:
* @param headers header fields * @param headers header fields
* @return return string of server * @return return string of server
*/ */
std::string request(std::string myurl, bool post, Hashmap<std::string, std::string> &map, std::vector<std::string> &headers); std::string request(std::string myurl,
bool post,
Hashmap<std::string, std::string> &map,
std::vector<std::string> &headers);
private: private:
static size_t write_data(void *buffer, size_t size, size_t buffersize, FILE *stream); static size_t write_data(void *buffer, size_t size, size_t buffersize, FILE *stream);

View File

@ -6,14 +6,14 @@
#include "API.h" #include "API.h"
class DynuAPI : API{ class DynuAPI : API {
public: public:
/** /**
* refresh the ip of domain on Dynu server * refresh the ip of domain on Dynu server
* @param ip new ip * @param ip new ip
* @return request status * @return request status
*/ */
int refreshIp(std::string ip); bool refreshIp(std::string ip);
/** /**
* init Telegram api with apikey and chatid * init Telegram api with apikey and chatid
@ -21,7 +21,8 @@ public:
* @param domainId ID of domain received by Dynu * @param domainId ID of domain received by Dynu
* @param domainName domainname to refresh * @param domainName domainname to refresh
*/ */
void init(const std::string& dynuApiKey, const std::string& domainId, const std::string& domainName); void init(const std::string &dynuApiKey, const std::string &domainId, const std::string &domainName);
private: private:
std::string dynuapikey; // Dynu API key std::string dynuapikey; // Dynu API key

View File

@ -8,7 +8,7 @@
#include <string> #include <string>
class IPAPI : API{ class IPAPI : API {
public: public:
/** /**
* get global ip of current internet connection * get global ip of current internet connection

View File

@ -14,7 +14,7 @@ public:
* send telegram Message to predefined destination * send telegram Message to predefined destination
* @param text message * @param text message
*/ */
int sendMessage(const std::string& text); int sendMessage(const std::string &text);
/** /**
* init Telegram api with apikey and chatid * init Telegram api with apikey and chatid

View File

@ -18,10 +18,11 @@ std::string Config::domainname;
std::string Config::telegramApiKey; std::string Config::telegramApiKey;
std::string Config::chatId; std::string Config::chatId;
bool Config::readCredentials() { bool Config::telegramSupport;
bool Config::readConfig() {
libconfig::Config cfg; libconfig::Config cfg;
try { try {
// todo make dynamic here
cfg.readFile(Version::ConfigDir.c_str()); cfg.readFile(Version::ConfigDir.c_str());
} }
catch (const libconfig::FileIOException &fioex) { catch (const libconfig::FileIOException &fioex) {
@ -33,7 +34,7 @@ bool Config::readCredentials() {
myfile << Version::SAMPLECONFIG; myfile << Version::SAMPLECONFIG;
myfile.close(); myfile.close();
} else { } else {
std::cout << "error creating file" << std::endl; Logger::error("error creating file");
} }
return false; return false;
@ -52,11 +53,15 @@ bool Config::readCredentials() {
// optional parameters // optional parameters
telegramApiKey = (std::string) cfg.lookup("telegramApiKey"); telegramApiKey = (std::string) cfg.lookup("telegramApiKey");
chatId = (std::string) cfg.lookup("chatId"); chatId = (std::string) cfg.lookup("chatId");
telegramSupport = true;
} }
catch (const libconfig::SettingNotFoundException &nfex) { catch (const libconfig::SettingNotFoundException &nfex) {
// triggered if setting is missing in config // triggered if setting is missing in config
if (!(std::strcmp("telegramApiKey", nfex.getPath()) == 0 || std::strcmp("chatId", nfex.getPath()) == 0)) { if (!(std::strcmp("telegramApiKey", nfex.getPath()) == 0 || std::strcmp("chatId", nfex.getPath()) == 0)) {
std::cerr << "No '" << nfex.getPath() << "' setting in configuration file." << std::endl; std::cerr << "No '" << nfex.getPath() << "' setting in configuration file." << std::endl;
} else {
Logger::message("no Telegram support - fields in config not set");
telegramSupport = false;
} }
} }
// check if needed values aren't empty // check if needed values aren't empty
@ -83,27 +88,57 @@ bool Config::validateConfig() {
try { try {
// needed parameters // needed parameters
if (((std::string) cfg.lookup("dynuapikey")).empty()) { if (((std::string) cfg.lookup("dynuapikey")).empty()) {
Logger::warning("required parameter dynuapikey seems to be empty."); Logger::warning("required parameter \"dynuapikey\" seems to be empty.");
return false; return false;
} }
if (((std::string) cfg.lookup("domainid")).empty()) { if (((std::string) cfg.lookup("domainid")).empty()) {
Logger::warning("required parameter domainid seems to be empty."); Logger::warning("required parameter \"domainid\" seems to be empty.");
return false; return false;
} }
if (((std::string) cfg.lookup("domainname")).empty()) { if (((std::string) cfg.lookup("domainname")).empty()) {
Logger::warning("required parameter domainname seems to be empty."); Logger::warning("required parameter \"domainname\" seems to be empty.");
return false; return false;
} }
// optional parameters // optional parameters
cfg.lookup("telegramApiKey"); cfg.lookup("telegramApiKey");
cfg.lookup("chatId"); cfg.lookup("chatId");
telegramSupport = true;
} }
catch (const libconfig::SettingNotFoundException &nfex) { catch (const libconfig::SettingNotFoundException &nfex) {
// triggered if setting is missing in config // triggered if setting is missing in config
if (!(std::strcmp("telegramApiKey", nfex.getPath()) == 0 || std::strcmp("chatId", nfex.getPath()) == 0)) { if (!(std::strcmp("telegramApiKey", nfex.getPath()) == 0 || std::strcmp("chatId", nfex.getPath()) == 0)) {
std::cerr << "No '" << nfex.getPath() << "' setting in configuration file." << std::endl; std::cerr << "No '" << nfex.getPath() << "' setting in configuration file." << std::endl;
return false; return false;
} else {
Logger::message("no Telegram support - fields in config not set");
telegramSupport = false;
} }
} }
return true; return true;
} }
bool Config::isTelegramSupported() {
return telegramSupport;
}
const std::string &Config::getDynuapikey() {
return dynuapikey;
}
const std::string &Config::getDomainid() {
return domainid;
}
const std::string &Config::getDomainname() {
return domainname;
}
const std::string &Config::getTelegramApiKey() {
return telegramApiKey;
}
const std::string &Config::getChatId() {
return chatId;
}
Config::Config() = default;

View File

@ -3,10 +3,10 @@
// //
#include "FileLogger.h" #include "FileLogger.h"
#include "IpHelper.h"
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <climits>
void FileLogger::safeip(std::string ip) { void FileLogger::safeip(std::string ip) {
std::ofstream out; std::ofstream out;
@ -25,8 +25,8 @@ std::string FileLogger::readip() {
in >> ip; in >> ip;
// when received ip has no : return 0.0.0.0 // when received ip has no . return 0.0.0.0
if (ip.find(':') == ULONG_MAX) if (!IpHelper::isIpValid(ip))
return "0.0.0.0"; return "0.0.0.0";
else else
return ip; return ip;

View File

@ -9,12 +9,11 @@
#include "api/TelegramAPI.h" #include "api/TelegramAPI.h"
#include "Config.h" #include "Config.h"
#include "Version.h" #include "Version.h"
#include "IpHelper.h"
#include <string>
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <Logger.h> #include <Logger.h>
#include <climits>
void IPRefresher::checkIPAdress(bool force) { void IPRefresher::checkIPAdress(bool force) {
FileLogger logger; FileLogger logger;
@ -25,7 +24,7 @@ void IPRefresher::checkIPAdress(bool force) {
if (ip.empty()) { if (ip.empty()) {
//no internet connection (or other error) //no internet connection (or other error)
Logger::warning("no internet connection"); Logger::warning("no internet connection");
} else if (ip.find(':') == ULONG_MAX) { } else if (!IpHelper::isIpValid(ip)) {
// error when ip doesn't contain a : // error when ip doesn't contain a :
Logger::warning("an error occured when getting the global ip"); Logger::warning("an error occured when getting the global ip");
} else { } else {
@ -37,13 +36,15 @@ void IPRefresher::checkIPAdress(bool force) {
Logger::message("ip changed! -- from :" + oldip + "to: " + ip); Logger::message("ip changed! -- from :" + oldip + "to: " + ip);
DynuAPI dynu; DynuAPI dynu;
dynu.init(Config::dynuapikey, Config::domainid, Config::domainname); dynu.init(Config::getDynuapikey(), Config::getDomainid(), Config::getDomainname());
// actual refresh of IP in api - here
bool result = dynu.refreshIp(ip);
if (dynu.refreshIp(ip)) { if (result && Config::isTelegramSupported()) {
TelegramAPI tele; TelegramAPI tele;
tele.init(Config::telegramApiKey, Config::chatId); tele.init(Config::getTelegramApiKey(), Config::getChatId());
tele.sendMessage(oldip + " moved to " + ip); tele.sendMessage(oldip + " moved to " + ip);
} else { } else if (!result) {
//error //error
Logger::error("failed to write ip to dynu api!"); Logger::error("failed to write ip to dynu api!");
} }
@ -53,13 +54,11 @@ void IPRefresher::checkIPAdress(bool force) {
} }
} }
IPRefresher::IPRefresher() = default;
IPRefresher::IPRefresher(bool loop) { IPRefresher::IPRefresher(bool loop) {
if (loop) { if (loop) {
Logger::message("startup of service"); Logger::message("startup of service");
Logger::message("Version: " + Version::VERSION); Logger::message("Version: " + Version::VERSION);
if (Config::readCredentials()) { if (Config::readConfig()) {
while (true) { while (true) {
Logger::message("starting check"); Logger::message("starting check");
checkIPAdress(false); checkIPAdress(false);

11
src/IpHelper.cpp Normal file
View File

@ -0,0 +1,11 @@
//
// Created by lukas on 07.05.20.
//
#include "IpHelper.h"
#include <climits>
bool IpHelper::isIpValid(std::string ip) {
return (ip.find('.') != ULONG_MAX);
}

View File

@ -4,7 +4,7 @@
#include "api/DynuAPI.h" #include "api/DynuAPI.h"
int DynuAPI::refreshIp(std:: string ip) { bool DynuAPI::refreshIp(std::string ip) {
Hashmap<std::string, std::string> args; Hashmap<std::string, std::string> args;
args.add("name", domainname); args.add("name", domainname);
args.add("ipv4Address", ip); args.add("ipv4Address", ip);
@ -16,15 +16,11 @@ int DynuAPI::refreshIp(std:: string ip) {
const std::string dynurepl = request("https://api.dynu.com/v2/dns/" + domainid, true, args, headers); const std::string dynurepl = request("https://api.dynu.com/v2/dns/" + domainid, true, args, headers);
if (dynurepl != "{\"statusCode\":200}") { return (dynurepl == "{\"statusCode\":200}");
return -1;
} else {
return 1;
}
} }
void DynuAPI::init(const std::string& dynuApiKey, const std::string& domainId, const std::string& domainName) { void DynuAPI::init(const std::string &dynuApiKey, const std::string &domainId, const std::string &domainName) {
this->dynuapikey=dynuApiKey; this->dynuapikey = dynuApiKey;
this->domainid=domainId; this->domainid = domainId;
this->domainname=domainName; this->domainname = domainName;
} }

View File

@ -6,4 +6,4 @@
std::string IPAPI::getGlobalIp() { std::string IPAPI::getGlobalIp() {
return request("https://api.ipify.org"); return request("https://api.ipify.org");
} }

View File

@ -7,7 +7,7 @@
#include <climits> #include <climits>
int TelegramAPI::sendMessage(const std::string& text) { int TelegramAPI::sendMessage(const std::string &text) {
Hashmap<std::string, std::string> args; Hashmap<std::string, std::string> args;
args.add("chat_id", chatid); args.add("chat_id", chatid);
args.add("text", text); args.add("text", text);

View File

@ -8,8 +8,6 @@
#include "Config.h" #include "Config.h"
#include "api/IPAPI.h" #include "api/IPAPI.h"
#include <iostream>
/** /**
* application entry point * application entry point
*/ */
@ -28,7 +26,7 @@ int main(int argc, char *argv[]) {
std::cout << "Version " << Version::VERSION << std::endl; std::cout << "Version " << Version::VERSION << std::endl;
} else if (firstarg == "-f" || firstarg == "--force") { } else if (firstarg == "-f" || firstarg == "--force") {
IPRefresher ipr; IPRefresher ipr;
if (Config::readCredentials()) { if (Config::readConfig()) {
ipr.checkIPAdress(true); ipr.checkIPAdress(true);
} else { } else {
std::cout << "incorrect credentials!" << std::endl; std::cout << "incorrect credentials!" << std::endl;
@ -40,7 +38,7 @@ int main(int argc, char *argv[]) {
if (Config::validateConfig()) { if (Config::validateConfig()) {
Logger::message("Config file is OK"); Logger::message("Config file is OK");
} else { } else {
Logger::warning("There are errors in config file!"); Logger::error("There are errors in config file!");
return -1; return -1;
} }
} else if (firstarg == "-ip" || firstarg == "--currentip") { } else if (firstarg == "-ip" || firstarg == "--currentip") {
@ -52,7 +50,7 @@ int main(int argc, char *argv[]) {
} else { } else {
IPRefresher ipr; IPRefresher ipr;
Logger::message("starting check"); Logger::message("starting check");
if (Config::readCredentials()) { if (Config::readConfig()) {
ipr.checkIPAdress(false); ipr.checkIPAdress(false);
} else { } else {
std::cout << "incorrect credentials!" << std::endl; std::cout << "incorrect credentials!" << std::endl;