diff --git a/src/db/database.hpp b/src/db/database.hpp index 535ef17..878da73 100644 --- a/src/db/database.hpp +++ b/src/db/database.hpp @@ -20,7 +20,6 @@ #ifndef DATABASE_HPP_ #define DATABASE_HPP_ -#include "../settings.hpp" #include namespace UDPT diff --git a/src/exceptions.h b/src/exceptions.h new file mode 100644 index 0000000..43e14b4 --- /dev/null +++ b/src/exceptions.h @@ -0,0 +1,33 @@ +#pragma once + + +namespace UDPT +{ + class UDPTException + { + public: + UDPTException(const char* errorMsg = "", int errorCode = 0) : m_error(errorMsg), m_errorCode(errorCode) + { + + } + + virtual const char* what() const + { + return m_error; + } + + virtual int getErrorCode() const + { + return m_errorCode; + } + + virtual ~UDPTException() + { + + } + + protected: + const char* m_error; + const int m_errorCode; + }; +} diff --git a/src/http/webapp.cpp b/src/http/webapp.cpp index 297fce0..3ab1c03 100644 --- a/src/http/webapp.cpp +++ b/src/http/webapp.cpp @@ -97,36 +97,12 @@ namespace UDPT return true; } - WebApp::WebApp(HTTPServer *srv, DatabaseDriver *db, const boost::program_options::variables_map& conf) : m_conf(conf) + WebApp::WebApp(std::shared_ptr srv, DatabaseDriver *db, const boost::program_options::variables_map& conf) : m_conf(conf), m_server(srv) { - this->instance = srv; this->db = db; - /* this->sc_api = settings->getClass("api"); + // TODO: Implement authentication by keys - Settings::SettingClass *apiKeys = settings->getClass("api.keys"); - if (apiKeys != NULL) - { - map* aK = apiKeys->getMap(); - map::iterator it, end; - end = aK->end(); - for (it = aK->begin();it != end;it++) - { - string key = it->first; - list ips; - - string::size_type strp = 0; - uint32_t ip; - while ((ip = _getNextIPv4(strp, it->second)) != 0) - { - ips.push_back( m_hton32(ip) ); - } - - this->ip_whitelist.insert(pair >(key, ips)); - } - - } */ - - srv->setData("webapp", this); + m_server->setData("webapp", this); } WebApp::~WebApp() @@ -136,17 +112,17 @@ namespace UDPT void WebApp::deploy() { list path; - this->instance->addApp(&path, &WebApp::handleRoot); + m_server->addApp(&path, &WebApp::handleRoot); path.push_back("api"); - this->instance->addApp(&path, &WebApp::handleAPI); // "/api" + m_server->addApp(&path, &WebApp::handleAPI); // "/api" path.pop_back(); path.push_back("announce"); - this->instance->addApp(&path, &WebApp::handleAnnounce); + m_server->addApp(&path, &WebApp::handleAnnounce); } - void WebApp::handleRoot (HTTPServer *srv, HTTPServer::Request *req, HTTPServer::Response *resp) + void WebApp::handleRoot(HTTPServer *srv, HTTPServer::Request *req, HTTPServer::Response *resp) { // It would be very appreciated to keep this in the code. resp->write("" @@ -201,7 +177,7 @@ namespace UDPT void WebApp::doAddTorrent (HTTPServer::Request *req, HTTPServer::Response *resp) { - string strHash = req->getParam("hash"); + std::string strHash = req->getParam("hash"); if (strHash.length() != 40) { resp->write("{\"error\":\"Hash length must be 40 characters.\"}"); @@ -232,7 +208,7 @@ namespace UDPT throw ServerException (0, "IPv4 supported Only."); } - string key = req->getParam("auth"); + std::string key = req->getParam("auth"); if (key.length() <= 0) throw ServerException (0, "Bad Authentication Key"); @@ -247,7 +223,7 @@ namespace UDPT return; } - string action = req->getParam("action"); + std::string action = req->getParam("action"); if (action == "add") app->doAddTorrent(req, resp); else if (action == "remove") diff --git a/src/http/webapp.hpp b/src/http/webapp.hpp index fdb37c4..dc4bafb 100644 --- a/src/http/webapp.hpp +++ b/src/http/webapp.hpp @@ -21,10 +21,10 @@ #include "httpserver.hpp" #include "../db/database.hpp" -#include "../settings.hpp" #include #include #include +#include #include using namespace std; @@ -38,13 +38,13 @@ namespace UDPT class WebApp { public: - WebApp(HTTPServer *, DatabaseDriver *, const boost::program_options::variables_map& conf); - ~WebApp(); + WebApp(std::shared_ptr , DatabaseDriver *, const boost::program_options::variables_map& conf); + virtual ~WebApp(); void deploy (); private: - HTTPServer *instance; + std::shared_ptr m_server; UDPT::Data::DatabaseDriver *db; const boost::program_options::variables_map& m_conf; std::map > ip_whitelist; diff --git a/src/logging.cpp b/src/logging.cpp index 5fcf3dc..4266c73 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -27,10 +27,10 @@ using namespace std; namespace UDPT { Logger::Logger(const boost::program_options::variables_map& s) - : logfile (&std::cout) + : m_logfile (std::cout) { - const string& filename = s["logging.filename"].as(); - const string& level = s["logging.level"].as(); + const std::string& filename = s["logging.filename"].as(); + const std::string& level = s["logging.level"].as(); closeStreamOnDestroy = false; @@ -42,35 +42,10 @@ namespace UDPT { this->loglevel = LL_INFO; else this->loglevel = LL_ERROR; - - if (filename.compare("stdout") != 0 && filename.length() > 0) - { - fstream fs; - fs.open(filename.c_str(), ios::binary | ios::out | ios::app); - if (!fs.is_open()) - { - this->log(LL_ERROR, "Failed to open log file."); - return; - } - this->logfile = &fs; - closeStreamOnDestroy = true; - } - } - - Logger::Logger(const boost::program_options::variables_map& s, ostream &os) - : logfile (&os), loglevel (LL_ERROR) - { - closeStreamOnDestroy = false; } Logger::~Logger() { - fstream *f = (fstream*)this->logfile; - f->flush(); - if (closeStreamOnDestroy) - { - f->close(); - } } void Logger::log(enum LogLevel lvl, string msg) @@ -78,7 +53,7 @@ namespace UDPT { const char letters[] = "EWID"; if (lvl <= this->loglevel) { - (*logfile) << time (NULL) << ": (" + m_logfile << time (NULL) << ": (" << ((char)letters[lvl]) << "): " << msg << "\n"; } diff --git a/src/logging.h b/src/logging.h index a9c4af6..4ca37a9 100644 --- a/src/logging.h +++ b/src/logging.h @@ -20,7 +20,6 @@ #ifndef LOGGING_H_ #define LOGGING_H_ -#include "settings.hpp" #include #include #include @@ -28,7 +27,6 @@ #include namespace UDPT { - using namespace std; class Logger { @@ -42,17 +40,15 @@ namespace UDPT { Logger(const boost::program_options::variables_map& s); - Logger(const boost::program_options::variables_map& s, ostream &os); - virtual ~Logger(); - void log(enum LogLevel, string msg); + void log(enum LogLevel, std::string msg); private: - ostream *logfile; + std::ostream& m_logfile; enum LogLevel loglevel; bool closeStreamOnDestroy; - static void setStream(Logger *logger, ostream &s); + static void setStream(Logger *logger, std::ostream &s); }; }; diff --git a/src/main.cpp b/src/main.cpp index 4e466f7..a78fe2c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,128 +19,35 @@ #include -#include "logging.h" -#include "multiplatform.h" -#include "udpTracker.hpp" -#include "settings.hpp" -#include "http/httpserver.hpp" -#include "http/webapp.hpp" #include // atoi #include // signal #include // strlen -#include +#include #include -using namespace std; -using namespace UDPT; -using namespace UDPT::Server; +#include "logging.h" +#include "multiplatform.h" +#include "udpTracker.hpp" +#include "http/httpserver.hpp" +#include "http/webapp.hpp" -Logger *logger; -static struct { - Settings *settings; - UDPTracker *usi; - WebApp *wa; - HTTPServer *httpserver; -} Instance; +UDPT::Logger *logger; -static void _print_usage () -{ - cout << "Usage: udpt []" << endl; -} - -static void _doAPIStart (const boost::program_options::variables_map& settings, WebApp **wa, HTTPServer **srv, DatabaseDriver *drvr) -{ - if (!settings["apiserver.enable"].as()) - { - return; - } - - try - { - *srv = Instance.httpserver = new HTTPServer(settings); - *wa = Instance.wa = new WebApp(*srv, drvr, settings); - (*wa)->deploy(); - } - catch (const ServerException &e) - { - std::cerr << "ServerException #" << e.getErrorCode() << ": " << e.getErrorMsg() << endl; - } -} - -/** - * Sets current working directory to executables directory. - */ -static void _setCWD (char *argv0) -{ -#ifdef WIN32 - wchar_t strFileName [MAX_PATH]; - DWORD r, i; - r = GetModuleFileNameW(NULL, strFileName, MAX_PATH); - for (i = r;i >= 0;i--) - { - if (strFileName[i] == '\\') - { - strFileName[i] = '\0'; - break; - } - } - SetCurrentDirectoryW(strFileName); - -#elif defined(linux) - int len, i; - char *strFN; - if (argv0 != NULL) - { - len = strlen (argv0); - strFN = new char [len + 1]; - - for (i = len;i >= 0;i--) - { - if (strFN[i] == '/') - { - strFN = '\0'; - break; - } - } - chdir (strFN); - delete [] strFN; - } -#endif - -} - -/** - * Releases resources before exit. - */ -static void _doCleanup () -{ - delete Instance.wa; - delete Instance.httpserver; - delete Instance.usi; - delete Instance.settings; - delete logger; - - memset (&Instance, 0, sizeof(Instance)); - logger = NULL; -} - static void _signal_handler (int sig) { - stringstream ss; - ss << "Signal " << sig << " raised. Terminating..."; + std::stringstream ss; + ss << "Signal " << sig << " raised. "; logger->log(Logger::LL_INFO, ss.str()); - _doCleanup(); } int main(int argc, char *argv[]) { - UDPTracker *usi; int r; #ifdef WIN32 WSADATA wsadata; - WSAStartup(MAKEWORD(2, 2), &wsadata); + ::WSAStartup(MAKEWORD(2, 2), &wsadata); #endif boost::program_options::options_description commandLine("Command line options"); @@ -194,7 +101,7 @@ int main(int argc, char *argv[]) } std::string config_filename(var_map["config"].as()); - bool isTest = var_map.count("test"); + bool isTest = (0 != var_map.count("test")); if (var_map.count("config")) { @@ -218,8 +125,6 @@ int main(int argc, char *argv[]) } } - memset(&Instance, 0, sizeof(Instance)); - #ifdef SIGBREAK signal(SIGBREAK, &_signal_handler); #endif @@ -235,7 +140,7 @@ int main(int argc, char *argv[]) try { - logger = new Logger(var_map); + logger = new UDPT::Logger(var_map); } catch (const std::exception& ex) { @@ -243,41 +148,42 @@ int main(int argc, char *argv[]) return -1; } - usi = Instance.usi = new UDPTracker(var_map); + std::shared_ptr tracker; + std::shared_ptr apiSrv; + std::shared_ptr webApp; - HTTPServer *apiSrv = NULL; - WebApp *wa = NULL; - - r = usi->start(); - if (r != UDPTracker::START_OK) + try { - cerr << "Error While trying to start server." << endl; - switch (r) + tracker = std::shared_ptr(new UDPTracker(var_map)); + tracker->start(); + + if (var_map["apiserver.enable"].as()) { - case UDPTracker::START_ESOCKET_FAILED: - cerr << "Failed to create socket." << endl; - break; - case UDPTracker::START_EBIND_FAILED: - cerr << "Failed to bind socket." << endl; - break; - default: - cerr << "Unknown Error" << endl; - break; + try + { + apiSrv = std::shared_ptr(new UDPT::Server::HTTPServer(var_map)); + webApp = std::shared_ptr(new UDPT::Server::WebApp(apiSrv, tracker->conn, var_map)); + webApp->deploy(); + } + catch (const UDPT::Server::ServerException &e) + { + std::cerr << "ServerException #" << e.getErrorCode() << ": " << e.getErrorMsg() << endl; + } } - goto cleanup; + } + catch (const UDPT::UDPTException& ex) + { + std::cerr << "UDPTException: " << ex.what() << std::endl; } - _doAPIStart(var_map, &wa, &apiSrv, usi->conn); + std::cout << "Hit Control-C to exit." << endl; - cout << "Hit Control-C to exit." << endl; + tracker->wait(); - usi->wait(); - -cleanup: - cout << endl << "Goodbye." << endl; + std::cout << endl << "Goodbye." << endl; #ifdef WIN32 - WSACleanup(); + ::WSACleanup(); #endif return 0; diff --git a/src/multiplatform.h b/src/multiplatform.h index 5ff6d1c..6dc3a33 100644 --- a/src/multiplatform.h +++ b/src/multiplatform.h @@ -28,7 +28,7 @@ #define linux #endif -#define VERSION "1.0.0-beta" +#define VERSION "1.0.2-dev" #ifdef WIN32 #include diff --git a/src/settings.cpp b/src/settings.cpp deleted file mode 100644 index 4da755e..0000000 --- a/src/settings.cpp +++ /dev/null @@ -1,449 +0,0 @@ -/* - * - * Copyright © 2012-2016 Naim A. - * - * This file is part of UDPT. - * - * UDPT is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * UDPT is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with UDPT. If not, see . - */ - -#include "settings.hpp" -#include // still primitive - need for strlen() -#include // need for isspace() -#include -#include -#include -#include -#include "tools.h" - -using namespace std; - -namespace UDPT -{ - Settings::SettingClass* Settings::getClass(const string classname) - { - if (classname == "") - return NULL; - - map::iterator it; - it = this->classes.find(classname); - - if (it == this->classes.end()) - return NULL; - else - return it->second; - - return NULL; - } - - Settings::Settings (const string filename) - { - this->filename = filename; - this->classes.clear(); - } - -static -void _settings_clean_string (char **str) -{ - int len, - i, - offset; - - len = strlen(*str); - - //strip leading whitespaces. - offset = 0; - for (i = 0;i < len;i++) - { - if (isspace(*str[i]) == 0) - break; - offset++; - } - - (*str) += offset; - len -= offset; - - for (i = len - 1;i >= 0;i--) - { - if (isspace( (*str)[i] ) != 0) - { - (*str)[i] = '\0'; - } - else - break; - } -} - - void Settings::parseSettings (char *data, int len) - { - char *className, *key, *value; - int i, - cil; // cil = Chars in line. - char c; - - className = key = value = NULL; - cil = 0; - - for (i = 0;i < len;i++) - { - c = data[i]; - if (c == '\n') - { - cil = 0; - continue; - } - if (cil == 0 && (c == ';' || c == '#')) - { - while (i < len) - { - if (data[i] == '\n') - break; - i++; - } - continue; - } - if (isspace(c) != 0 && cil == 0) - { - continue; - } - if (cil == 0 && c == '[') - { - className = (char*)(i + data + 1); - while (i < len) - { - if (data[i] != ']') - { - i++; - continue; - } - data[i] = '\0'; - break; - } - continue; - } - - if (isgraph(c) != 0 && cil == 0) // must be a key. - { - key = (char*)(i + data); - while (i < len) - { - if (data[i] == '\n') - { - key = NULL; - break; - } - if (data[i] == '=') - { - data[i] = '\0'; - value = (char*)(data + i + 1); - while (i < len) - { - if (data[i] == '\n') - { - data[i] = '\0'; - - _settings_clean_string(&key); - _settings_clean_string(&value); - - // add to settings... - this->set (className, key, value); - - cil = 0; - break; - } - i++; - } - break; - } - i++; - } - continue; - } - - if (isgraph(c) != 0) - { - cil++; - } - } - } - - bool Settings::load() - { - int len; - char *buffer; - - fstream cfg; - cfg.open(this->filename.c_str(), ios::in | ios::binary); - - if (!cfg.is_open()) - return false; - - cfg.seekg(0, ios::end); - len = cfg.tellg(); - cfg.seekg(0, ios::beg); - - buffer = new char [len]; - cfg.read(buffer, len); - cfg.close(); - - this->parseSettings(buffer, len); - - delete[] buffer; - - return true; - } - - bool Settings::save () - { - SettingClass *sclass; - - fstream cfg (this->filename.c_str(), ios::binary | ios::out); - if (!cfg.is_open()) - return false; - - cfg << "; udpt Settings File - Created Automatically.\n"; - - map::iterator it; - for (it = this->classes.begin();it != this->classes.end();it++) - { - sclass = it->second; - cfg << "[" << it->first.c_str() << "]\n"; - - map::iterator rec; - for (rec = sclass->entries.begin();rec != sclass->entries.end();rec++) - { - cfg << rec->first.c_str() << "=" << rec->second.c_str() << "\n"; - } - - cfg << "\n"; - } - cfg.close(); - - return 0; - } - - Settings::~Settings() - { - map::iterator it; - for (it = this->classes.begin();it != this->classes.end();it++) - { - SettingClass *sc = it->second; - delete sc; - } - this->classes.clear(); - } - - string Settings::get (const string classN, const string name) - { - SettingClass *c; - - c = this->getClass(classN); - if (c == NULL) - return ""; - return c->get(name); - } - - bool Settings::set (const string classN, const string name, const string value) - { - SettingClass *c; - - if (classN == "" || name == "" || value == "") - return false; - - c = this->getClass (classN); - - if (c == NULL) - { - c = new SettingClass(classN); - this->classes.insert(pair(classN, c)); - } - - return c->set (name, value); - } - - Settings::SettingClass::SettingClass(const string cn) - { - this->className = cn; - } - - string Settings::SettingClass::get (const string& name) - { - if (this->entries.find(name) == this->entries.end()) - return ""; - return this->entries[name]; - } - - inline static int _isTrue (string str) - { - int i, // loop index - len; // string's length - - if (str == "") - return -1; - len = str.length(); - for (i = 0;i < len;i++) - { - if (str[i] >= 'A' && str[i] <= 'Z') - { - str[i] = (str[i] - 'A' + 'a'); - } - } - if (str.compare ("yes") == 0) - return 1; - if (str.compare ("no") == 0) - return 0; - if (str.compare("true") == 0) - return 1; - if (str.compare ("false") == 0) - return 0; - if (str.compare("1") == 0) - return 1; - if (str.compare ("0") == 0) - return 0; - return -1; - } - - bool Settings::SettingClass::getBool(const string& name) - { - string v = this->get(name); - int r = _isTrue(v); - if (r == 0 || r == 1) - return (bool)r; - throw SettingsException("Invalid boolean value."); - } - - bool Settings::SettingClass::getBool (const string& key, bool defaultValue) - { - try { - return this->getBool(key); - } catch (SettingsException &e) - { } - - return defaultValue; - } - - void Settings::SettingClass::getIPs (const string& key, list &ip) - { - string v = this->get(key) + " "; // add padding for last entry. - // expect a.b.c.d[:port], IPv4 only supported with BEP-15. - - string::size_type s, e; - s = e = 0; - char c; - for (string::size_type i = 0;i < v.length();i++) - { - c = v[i]; - if (isspace(c) != 0 || c == ';' || c == ',') - { - if (s == e) - s = e = i; - else - { - string addr = v.substr(s, (e - s) + 1); - SOCKADDR_IN saddr; - memset(&saddr, 0, sizeof (SOCKADDR_IN)); - saddr.sin_family = AF_INET; - saddr.sin_addr.s_addr = 0L; - saddr.sin_port = (6969); - - { - uint8_t b; // temporary container for IP byte - uint16_t port; - uint32_t ip; - unsigned i, // loop index - stage; // 0,1,2,3=IP[a.b.c.d], 4=port - - ip = 0; - b = 0; - stage = 0; - for (i = 0;i < addr.length();i++) - { - if (addr[i] >= '0' && addr[i] <= '9') - { - if (stage <= 3) - { - b *= 10; - b += (addr[i] - '0'); - } - else if (stage == 4) - { - port *= 10; - port += (addr[i] - '0'); - } - } - else if (addr[i] == '.' && stage < 3) - { - stage ++; - ip *= 256; - ip += b; - b = 0; - } - else if (addr[i] == ':') - { - stage++; - port = 0; - - ip *= 256; - ip += b; - } - } - - if (stage == 3) // port not provided. - { - port = 6969; - // add last byte. - ip *= 256; - ip += b; - } - saddr.sin_addr.s_addr = m_hton32(ip); - saddr.sin_port = m_hton16(port); - } - - ip.push_back(saddr); - - s = e = i + 1; - } - } - else - { - e = i; - } - } - } - - int Settings::SettingClass::getInt (const string& key, int def) - { - string v = this->get (key); - if (v.length() == 0) - return def; - return std::atoi(v.c_str()); - } - - map* Settings::SettingClass::getMap() - { - return &this->entries; - } - - bool Settings::SettingClass::set (const string name, const string value) - { - pair::iterator, bool> r; - r = this->entries.insert(pair(name, value)); - if (!r.second) - { - r.first->second = value; - } - - return true; - } -}; diff --git a/src/settings.hpp b/src/settings.hpp deleted file mode 100644 index dcec64a..0000000 --- a/src/settings.hpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * - * Copyright © 2012-2016 Naim A. - * - * This file is part of UDPT. - * - * UDPT is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * UDPT is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with UDPT. If not, see . - */ - -#pragma once - -#include -#include -#include -#include -#include "multiplatform.h" -using namespace std; - -namespace UDPT -{ - class Settings - { - public: - class SettingsException : public std::exception - { - public: - SettingsException (const char *str) - { - this->str = str; - } - - const char * what () - { - return str; - } - - private: - const char *str; - }; - - class SettingClass - { - public: - SettingClass (const string className); - bool set (const string key, const string value); - string get (const string& key); - bool getBool (const string& key); - bool getBool (const string& key, bool defaultValue); - int getInt (const string& key, int def = -1); - map* getMap (); - void getIPs (const string& key, list &ip); - private: - friend class Settings; - string className; - map entries; - }; - - /** - * Initializes the settings type. - * @param filename the settings filename. - */ - Settings (const string filename); - - /** - * Gets a setting from a Settings type. - * @param class The class of the requested setting. - * @param name The name of the requested setting. - * @return The value for the requested setting, NULL if not available. - */ - SettingClass* getClass (const string name); - - /** - * Loads settings from file - * @return true on success, otherwise false. - */ - bool load (); - - /** - * Saves settings to file. - * @return true on success; otherwise false. - */ - bool save (); - - /** - * Sets a setting in a settings type. - * @param className The class of the setting. - * @param key The name of the setting. - * @param value The value to set for the setting. - * @return true on success, otherwise false. - */ - bool set (const string className, const string key, const string value); - - /** - * Gets the requested SettingClass. - * @param classname The name of the class to find (case sensitive). - * @return a pointer to the found class, or NULL if not found. - */ - string get (const string className, const string key); - - /** - * Destroys the settings "object" - */ - virtual ~Settings (); - private: - string filename; - map classes; - - void parseSettings (char *data, int len); - }; -}; diff --git a/src/udpTracker.cpp b/src/udpTracker.cpp index aa31e29..26632e3 100644 --- a/src/udpTracker.cpp +++ b/src/udpTracker.cpp @@ -17,19 +17,19 @@ * along with UDPT. If not, see . */ -#include "udpTracker.hpp" -#include "tools.h" #include // atoi #include #include #include #include +#include +#include "udpTracker.hpp" +#include "tools.h" #include "multiplatform.h" #include "logging.h" extern UDPT::Logger *logger; -using namespace std; using namespace UDPT::Data; #define UDP_BUFFER_SIZE 2048 @@ -39,146 +39,146 @@ namespace UDPT UDPTracker::UDPTracker(const boost::program_options::variables_map& conf) : m_conf(conf) { - this->allowRemotes = conf["tracker.allow_remotes"].as(); - this->allowIANA_IPs = conf["tracker.allow_iana_ips"].as(); - this->isDynamic = conf["tracker.is_dynamic"].as(); + this->m_allowRemotes = conf["tracker.allow_remotes"].as(); + this->m_allowIANA_IPs = conf["tracker.allow_iana_ips"].as(); + this->m_isDynamic = conf["tracker.is_dynamic"].as(); - this->announce_interval = conf["tracker.announce_interval"].as(); - this->cleanup_interval = conf["tracker.cleanup_interval"].as(); - this->port = conf["tracker.port"].as(); - this->thread_count = conf["tracker.threads"].as() + 1; + this->m_announceInterval = conf["tracker.announce_interval"].as(); + this->m_cleanupInterval = conf["tracker.cleanup_interval"].as(); + this->m_port = conf["tracker.port"].as(); + this->m_threadCount = conf["tracker.threads"].as() + 1; - list addrs; + std::list addrs; if (addrs.empty()) { SOCKADDR_IN sa; - sa.sin_port = m_hton16(port); + sa.sin_port = m_hton16(m_port); sa.sin_addr.s_addr = 0L; addrs.push_back(sa); } - this->localEndpoint = addrs.front(); + this->m_localEndpoint = addrs.front(); - this->threads = new HANDLE[this->thread_count]; + this->m_threads = new HANDLE[this->m_threadCount]; - this->isRunning = false; - this->conn = NULL; + this->m_isRunning = false; + this->conn = nullptr; } - UDPTracker::~UDPTracker () + UDPTracker::~UDPTracker() { int i; // loop index - this->isRunning = false; + this->m_isRunning = false; // drop listener connection to continue thread loops. // wait for request to finish (1 second max; allot of time for a computer!). #ifdef linux - close (this->sock); + ::close(this->m_sock); - sleep (1); + ::sleep(1); #elif defined (WIN32) - closesocket (this->sock); + ::closesocket(this->m_sock); - Sleep (1000); + ::Sleep(1000); #endif - for (i = 0;i < this->thread_count;i++) + for (i = 0;i < this->m_threadCount;i++) { #ifdef WIN32 - TerminateThread (this->threads[i], 0x00); + ::TerminateThread(this->m_threads[i], 0x00); #elif defined (linux) - pthread_detach (this->threads[i]); - pthread_cancel (this->threads[i]); + ::pthread_detach(this->m_threads[i]); + ::pthread_cancel(this->m_threads[i]); #endif - stringstream str; - str << "Thread (" << (i + 1) << "/" << ((int)this->thread_count) << ") terminated."; + std::stringstream str; + str << "Thread (" << (i + 1) << "/" << ((int)this->m_threadCount) << ") terminated."; logger->log(Logger::LL_INFO, str.str()); } if (this->conn != NULL) delete this->conn; - delete[] this->threads; + delete[] this->m_threads; } void UDPTracker::wait() { #ifdef WIN32 - WaitForMultipleObjects(this->thread_count, this->threads, TRUE, INFINITE); + WaitForMultipleObjects(this->m_threadCount, this->m_threads, TRUE, INFINITE); #else int i; - for (i = 0;i < this->thread_count; i++) + for (i = 0;i < this->m_threadCount; i++) { - pthread_join (this->threads[i], NULL); + pthread_join (this->m_threads[i], NULL); } #endif } - enum UDPTracker::StartStatus UDPTracker::start () + void UDPTracker::start() { - stringstream ss; + std::stringstream ss; SOCKET sock; int r, // saves results i, // loop index yup; // just to set TRUE - string dbname;// saves the Database name. + std::string dbname;// saves the Database name. sock = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock == INVALID_SOCKET) - return START_ESOCKET_FAILED; + { + throw UDPT::UDPTException("Failed to create socket"); + } yup = 1; ::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&yup, 1); - this->localEndpoint.sin_family = AF_INET; - r = ::bind(sock, (SOCKADDR*)&this->localEndpoint, sizeof(SOCKADDR_IN)); + this->m_localEndpoint.sin_family = AF_INET; + r = ::bind(sock, reinterpret_cast(&this->m_localEndpoint), sizeof(SOCKADDR_IN)); if (r == SOCKET_ERROR) { #ifdef WIN32 - closesocket (sock); + ::closesocket(sock); #elif defined (linux) - close (sock); + ::close(sock); #endif - return START_EBIND_FAILED; + throw UDPT::UDPTException("Failed to bind socket."); } - this->sock = sock; + this->m_sock = sock; - this->conn = new Data::SQLite3Driver(m_conf, this->isDynamic); + this->conn = new Data::SQLite3Driver(m_conf, this->m_isDynamic); - this->isRunning = true; + this->m_isRunning = true; ss.str(""); - ss << "Starting maintenance thread (1/" << ((int)this->thread_count) << ")"; + ss << "Starting maintenance thread (1/" << ((int)this->m_threadCount) << ")"; logger->log(Logger::LL_INFO, ss.str()); // create maintainer thread. #ifdef WIN32 - this->threads[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)_maintainance_start, (LPVOID)this, 0, NULL); + this->m_threads[0] = ::CreateThread(NULL, 0, reinterpret_cast(_maintainance_start), (LPVOID)this, 0, NULL); #elif defined (linux) - pthread_create (&this->threads[0], NULL, _maintainance_start, (void*)this); + ::pthread_create (&this->m_threads[0], NULL, _maintainance_start, (void*)this); #endif - for (i = 1;i < this->thread_count; i++) + for (i = 1;i < this->m_threadCount; i++) { ss.str(""); - ss << "Starting thread (" << (i + 1) << "/" << ((int)this->thread_count) << ")"; + ss << "Starting thread (" << (i + 1) << "/" << ((int)this->m_threadCount) << ")"; logger->log(Logger::LL_INFO, ss.str()); #ifdef WIN32 - this->threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)_thread_start, (LPVOID)this, 0, NULL); + this->m_threads[i] = ::CreateThread(NULL, 0, reinterpret_cast(_thread_start), (LPVOID)this, 0, NULL); #elif defined (linux) - pthread_create (&(this->threads[i]), NULL, _thread_start, (void*)this); + ::pthread_create (&(this->m_threads[i]), NULL, _thread_start, (void*)this); #endif } - - return START_OK; } - int UDPTracker::sendError (UDPTracker *usi, SOCKADDR_IN *remote, uint32_t transactionID, const string &msg) + int UDPTracker::sendError(UDPTracker* usi, SOCKADDR_IN* remote, uint32_t transactionID, const std::string &msg) { struct udp_error_response error; int msg_sz, // message size to send. @@ -195,24 +195,22 @@ namespace UDPT if (msg_sz > 1024) return -1; - memcpy(buff, &error, 8); + ::memcpy(buff, &error, 8); for (i = 8;i <= msg_sz;i++) { buff[i] = msg[i - 8]; } - sendto(usi->sock, buff, msg_sz, 0, (SOCKADDR*)remote, sizeof(*remote)); + ::sendto(usi->m_sock, buff, msg_sz, 0, reinterpret_cast(remote), sizeof(*remote)); return 0; } - int UDPTracker::handleConnection (UDPTracker *usi, SOCKADDR_IN *remote, char *data) + int UDPTracker::handleConnection(UDPTracker *usi, SOCKADDR_IN *remote, char *data) { - ConnectionRequest *req; + ConnectionRequest *req = reinterpret_cast(data); ConnectionResponse resp; - req = (ConnectionRequest*)data; - resp.action = m_hton32(0); resp.transaction_id = req->transaction_id; @@ -223,7 +221,7 @@ namespace UDPT return 1; } - sendto(usi->sock, (char*)&resp, sizeof(ConnectionResponse), 0, (SOCKADDR*)remote, sizeof(SOCKADDR_IN)); + ::sendto(usi->m_sock, (char*)&resp, sizeof(ConnectionResponse), 0, (SOCKADDR*)remote, sizeof(SOCKADDR_IN)); return 0; } @@ -258,7 +256,7 @@ namespace UDPT req->num_want = m_hton32 (req->num_want); req->left = m_hton64 (req->left); - if (!usi->allowRemotes && req->ip_address != 0) + if (!usi->m_allowRemotes && req->ip_address != 0) { UDPTracker::sendError (usi, remote, req->transaction_id, "Tracker doesn't allow remote IP's; Request ignored."); return 0; @@ -309,7 +307,7 @@ namespace UDPT resp = (AnnounceResponse*)buff; resp->action = m_hton32(1); - resp->interval = m_hton32 ( usi->announce_interval ); + resp->interval = m_hton32 ( usi->m_announceInterval ); resp->leechers = m_hton32(tE.leechers); resp->seeders = m_hton32 (tE.seeders); resp->transaction_id = req->transaction_id; @@ -331,7 +329,7 @@ namespace UDPT } delete[] peers; - sendto(usi->sock, (char*)buff, bSize, 0, (SOCKADDR*)remote, sizeof(SOCKADDR_IN)); + ::sendto(usi->m_sock, (char*)buff, bSize, 0, (SOCKADDR*)remote, sizeof(SOCKADDR_IN)); // update DB. uint32_t ip; @@ -345,9 +343,9 @@ namespace UDPT return 0; } - int UDPTracker::handleScrape (UDPTracker *usi, SOCKADDR_IN *remote, char *data, int len) + int UDPTracker::handleScrape(UDPTracker *usi, SOCKADDR_IN *remote, char *data, int len) { - ScrapeRequest *sR; + ScrapeRequest *sR = reinterpret_cast(data); int v, // validation helper c, // torrent counter i, // loop counter @@ -356,14 +354,11 @@ namespace UDPT ScrapeResponse *resp; uint8_t buffer [1024]; // up to 74 torrents can be scraped at once (17*74+8) < 1024 - - sR = (ScrapeRequest*)data; - // validate request length: v = len - 16; if (v < 0 || v % 20 != 0) { - UDPTracker::sendError (usi, remote, sR->transaction_id, "Bad scrape request."); + UDPTracker::sendError(usi, remote, sR->transaction_id, "Bad scrape request."); return 0; } @@ -377,8 +372,8 @@ namespace UDPT // get torrent count. c = v / 20; - resp = (ScrapeResponse*)buffer; - resp->action = m_hton32 (2); + resp = reinterpret_cast(buffer); + resp->action = m_hton32(2); resp->transaction_id = sR->transaction_id; for (i = 0;i < c;i++) @@ -402,12 +397,12 @@ namespace UDPT return 0; } - *seeders = m_hton32 (tE.seeders); - *completed = m_hton32 (tE.completed); - *leechers = m_hton32 (tE.leechers); + *seeders = m_hton32(tE.seeders); + *completed = m_hton32(tE.completed); + *leechers = m_hton32(tE.leechers); } - sendto (usi->sock, (const char*)buffer, sizeof(buffer), 0, (SOCKADDR*)remote, sizeof(SOCKADDR_IN)); + ::sendto(usi->m_sock, reinterpret_cast(buffer), sizeof(buffer), 0, reinterpret_cast(remote), sizeof(SOCKADDR_IN)); return 0; } @@ -422,14 +417,12 @@ static int _isIANA_IP (uint32_t ip) int UDPTracker::resolveRequest (UDPTracker *usi, SOCKADDR_IN *remote, char *data, int r) { - ConnectionRequest *cR; + ConnectionRequest* cR = reinterpret_cast(data); uint32_t action; - cR = (ConnectionRequest*)data; - action = m_hton32(cR->action); - if (!usi->allowIANA_IPs) + if (!usi->m_allowIANA_IPs) { if (_isIANA_IP (remote->sin_addr.s_addr)) { @@ -438,14 +431,14 @@ static int _isIANA_IP (uint32_t ip) } if (action == 0 && r >= 16) - return UDPTracker::handleConnection (usi, remote, data); + return UDPTracker::handleConnection(usi, remote, data); else if (action == 1 && r >= 98) - return UDPTracker::handleAnnounce (usi, remote, data); + return UDPTracker::handleAnnounce(usi, remote, data); else if (action == 2) - return UDPTracker::handleScrape (usi, remote, data, r); + return UDPTracker::handleScrape(usi, remote, data, r); else { - UDPTracker::sendError (usi, remote, cR->transaction_id, "Tracker couldn't understand Client's request."); + UDPTracker::sendError(usi, remote, cR->transaction_id, "Tracker couldn't understand Client's request."); return -1; } @@ -468,47 +461,44 @@ static int _isIANA_IP (uint32_t ip) #endif int r; - char tmpBuff [UDP_BUFFER_SIZE]; + char tmpBuff[UDP_BUFFER_SIZE]; - usi = (UDPTracker*)arg; + usi = reinterpret_cast(arg); - addrSz = sizeof (SOCKADDR_IN); + addrSz = sizeof(SOCKADDR_IN); - while (usi->isRunning) + while (usi->m_isRunning) { - cout.flush(); // peek into the first 12 bytes of data; determine if connection request or announce request. - r = recvfrom(usi->sock, (char*)tmpBuff, UDP_BUFFER_SIZE, 0, (SOCKADDR*)&remoteAddr, &addrSz); + r = ::recvfrom(usi->m_sock, (char*)tmpBuff, UDP_BUFFER_SIZE, 0, (SOCKADDR*)&remoteAddr, &addrSz); if (r <= 0) continue; // bad request... - r = UDPTracker::resolveRequest (usi, &remoteAddr, tmpBuff, r); + r = UDPTracker::resolveRequest(usi, &remoteAddr, tmpBuff, r); } #ifdef linux - pthread_exit (NULL); + ::pthread_exit (NULL); #endif return 0; } #ifdef WIN32 - DWORD UDPTracker::_maintainance_start (LPVOID arg) + DWORD UDPTracker::_maintainance_start(LPVOID arg) #elif defined (linux) - void* UDPTracker::_maintainance_start (void *arg) + void* UDPTracker::_maintainance_start(void *arg) #endif { - UDPTracker *usi; + UDPTracker* usi = reinterpret_cast(arg); - usi = (UDPTracker *)arg; - - while (usi->isRunning) + while (usi->m_isRunning) { usi->conn->cleanup(); #ifdef WIN32 - Sleep (usi->cleanup_interval * 1000); + ::Sleep(usi->m_cleanupInterval * 1000); #elif defined (linux) - sleep (usi->cleanup_interval); + ::sleep(usi->m_cleanupInterval); #else #error Unsupported OS. #endif diff --git a/src/udpTracker.hpp b/src/udpTracker.hpp index 175fcfa..084a52b 100644 --- a/src/udpTracker.hpp +++ b/src/udpTracker.hpp @@ -22,18 +22,16 @@ #include +#include +#include +#include "exceptions.h" #include "multiplatform.h" #include "db/driver_sqlite.hpp" -#include "settings.hpp" -#include -#include -using namespace std; - -#define UDPT_DYNAMIC 0x01 // Track Any info_hash? -#define UDPT_ALLOW_REMOTE_IP 0x02 // Allow client's to send other IPs? -#define UDPT_ALLOW_IANA_IP 0x04 // allow IP's like 127.0.0.1 or other IANA reserved IPs? -#define UDPT_VALIDATE_CLIENT 0x08 // validate client before adding to Database? (check if connection is open?) +#define UDPT_DYNAMIC (0x01) // Track Any info_hash? +#define UDPT_ALLOW_REMOTE_IP (0x02) // Allow client's to send other IPs? +#define UDPT_ALLOW_IANA_IP (0x04) // allow IP's like 127.0.0.1 or other IANA reserved IPs? +#define UDPT_VALIDATE_CLIENT (0x08) // validate client before adding to Database? (check if connection is open?) namespace UDPT @@ -122,52 +120,51 @@ namespace UDPT /** * Starts the Initialized instance. - * @return 0 on success, otherwise non-zero. */ - enum StartStatus start (); + void start(); /** * Joins all threads, and waits for all of them to terminate. */ - void wait (); + void wait(); /** * Destroys resources that were created by constructor * @param usi Instance to destroy. */ - virtual ~UDPTracker (); + virtual ~UDPTracker(); Data::DatabaseDriver *conn; private: - SOCKET sock; - SOCKADDR_IN localEndpoint; - uint16_t port; - uint8_t thread_count; - bool isRunning; - bool isDynamic; - bool allowRemotes; - bool allowIANA_IPs; - HANDLE *threads; - uint32_t announce_interval; - uint32_t cleanup_interval; + SOCKET m_sock; + SOCKADDR_IN m_localEndpoint; + uint16_t m_port; + uint8_t m_threadCount; + bool m_isRunning; + bool m_isDynamic; + bool m_allowRemotes; + bool m_allowIANA_IPs; + HANDLE *m_threads; + uint32_t m_announceInterval; + uint32_t m_cleanupInterval; const boost::program_options::variables_map& m_conf; #ifdef WIN32 - static DWORD _thread_start (LPVOID arg); - static DWORD _maintainance_start (LPVOID arg); + static DWORD _thread_start(LPVOID arg); + static DWORD _maintainance_start(LPVOID arg); #elif defined (linux) - static void* _thread_start (void *arg); - static void* _maintainance_start (void *arg); + static void* _thread_start(void *arg); + static void* _maintainance_start(void *arg); #endif - static int resolveRequest (UDPTracker *usi, SOCKADDR_IN *remote, char *data, int r); + static int resolveRequest(UDPTracker *usi, SOCKADDR_IN *remote, char *data, int r); - static int handleConnection (UDPTracker *usi, SOCKADDR_IN *remote, char *data); - static int handleAnnounce (UDPTracker *usi, SOCKADDR_IN *remote, char *data); - static int handleScrape (UDPTracker *usi, SOCKADDR_IN *remote, char *data, int len); + static int handleConnection(UDPTracker *usi, SOCKADDR_IN *remote, char *data); + static int handleAnnounce(UDPTracker *usi, SOCKADDR_IN *remote, char *data); + static int handleScrape(UDPTracker *usi, SOCKADDR_IN *remote, char *data, int len); - static int sendError (UDPTracker *, SOCKADDR_IN *remote, uint32_t transId, const string &); + static int sendError(UDPTracker *, SOCKADDR_IN *remote, uint32_t transId, const std::string &); }; };