Code cleanup (WIP)
This commit is contained in:
parent
edaa44bfc7
commit
1db33eb0b6
|
@ -20,7 +20,6 @@
|
|||
#ifndef DATABASE_HPP_
|
||||
#define DATABASE_HPP_
|
||||
|
||||
#include "../settings.hpp"
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
namespace UDPT
|
||||
|
|
33
src/exceptions.h
Normal file
33
src/exceptions.h
Normal file
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -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<HTTPServer> 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<string, string>* aK = apiKeys->getMap();
|
||||
map<string, string>::iterator it, end;
|
||||
end = aK->end();
|
||||
for (it = aK->begin();it != end;it++)
|
||||
{
|
||||
string key = it->first;
|
||||
list<uint32_t> 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<string, list<uint32_t> >(key, ips));
|
||||
}
|
||||
|
||||
} */
|
||||
|
||||
srv->setData("webapp", this);
|
||||
m_server->setData("webapp", this);
|
||||
}
|
||||
|
||||
WebApp::~WebApp()
|
||||
|
@ -136,17 +112,17 @@ namespace UDPT
|
|||
void WebApp::deploy()
|
||||
{
|
||||
list<string> 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("<html>"
|
||||
|
@ -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")
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
|
||||
#include "httpserver.hpp"
|
||||
#include "../db/database.hpp"
|
||||
#include "../settings.hpp"
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <boost/program_options.hpp>
|
||||
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<HTTPServer> , DatabaseDriver *, const boost::program_options::variables_map& conf);
|
||||
virtual ~WebApp();
|
||||
void deploy ();
|
||||
|
||||
|
||||
private:
|
||||
HTTPServer *instance;
|
||||
std::shared_ptr<HTTPServer> m_server;
|
||||
UDPT::Data::DatabaseDriver *db;
|
||||
const boost::program_options::variables_map& m_conf;
|
||||
std::map<std::string, list<uint32_t> > ip_whitelist;
|
||||
|
|
|
@ -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<std::string>();
|
||||
const string& level = s["logging.level"].as<std::string>();
|
||||
const std::string& filename = s["logging.filename"].as<std::string>();
|
||||
const std::string& level = s["logging.level"].as<std::string>();
|
||||
|
||||
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";
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#ifndef LOGGING_H_
|
||||
#define LOGGING_H_
|
||||
|
||||
#include "settings.hpp"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
|
@ -28,7 +27,6 @@
|
|||
#include <boost/program_options.hpp>
|
||||
|
||||
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);
|
||||
};
|
||||
};
|
||||
|
||||
|
|
168
src/main.cpp
168
src/main.cpp
|
@ -19,128 +19,35 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
#include "logging.h"
|
||||
#include "multiplatform.h"
|
||||
#include "udpTracker.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "http/httpserver.hpp"
|
||||
#include "http/webapp.hpp"
|
||||
#include <cstdlib> // atoi
|
||||
#include <csignal> // signal
|
||||
#include <cstring> // strlen
|
||||
#include <memory.h>
|
||||
#include <memory>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
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 [<configuration file>]" << endl;
|
||||
}
|
||||
|
||||
static void _doAPIStart (const boost::program_options::variables_map& settings, WebApp **wa, HTTPServer **srv, DatabaseDriver *drvr)
|
||||
{
|
||||
if (!settings["apiserver.enable"].as<bool>())
|
||||
{
|
||||
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<std::string>());
|
||||
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<UDPTracker> tracker;
|
||||
std::shared_ptr<UDPT::Server::HTTPServer> apiSrv;
|
||||
std::shared_ptr<UDPT::Server::WebApp> webApp;
|
||||
|
||||
HTTPServer *apiSrv = NULL;
|
||||
WebApp *wa = NULL;
|
||||
try
|
||||
{
|
||||
tracker = std::shared_ptr<UDPTracker>(new UDPTracker(var_map));
|
||||
tracker->start();
|
||||
|
||||
r = usi->start();
|
||||
if (r != UDPTracker::START_OK)
|
||||
if (var_map["apiserver.enable"].as<bool>())
|
||||
{
|
||||
cerr << "Error While trying to start server." << endl;
|
||||
switch (r)
|
||||
try
|
||||
{
|
||||
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;
|
||||
apiSrv = std::shared_ptr<UDPT::Server::HTTPServer>(new UDPT::Server::HTTPServer(var_map));
|
||||
webApp = std::shared_ptr<UDPT::Server::WebApp>(new UDPT::Server::WebApp(apiSrv, tracker->conn, var_map));
|
||||
webApp->deploy();
|
||||
}
|
||||
goto cleanup;
|
||||
catch (const UDPT::Server::ServerException &e)
|
||||
{
|
||||
std::cerr << "ServerException #" << e.getErrorCode() << ": " << e.getErrorMsg() << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#define linux
|
||||
#endif
|
||||
|
||||
#define VERSION "1.0.0-beta"
|
||||
#define VERSION "1.0.2-dev"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
|
|
449
src/settings.cpp
449
src/settings.cpp
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "settings.hpp"
|
||||
#include <string.h> // still primitive - need for strlen()
|
||||
#include <ctype.h> // need for isspace()
|
||||
#include <exception>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "tools.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace UDPT
|
||||
{
|
||||
Settings::SettingClass* Settings::getClass(const string classname)
|
||||
{
|
||||
if (classname == "")
|
||||
return NULL;
|
||||
|
||||
map<string, SettingClass*>::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<string, SettingClass*>::iterator it;
|
||||
for (it = this->classes.begin();it != this->classes.end();it++)
|
||||
{
|
||||
sclass = it->second;
|
||||
cfg << "[" << it->first.c_str() << "]\n";
|
||||
|
||||
map<string, string>::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<string, SettingClass*>::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<string, SettingClass*>(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<SOCKADDR_IN> &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<string, string>* Settings::SettingClass::getMap()
|
||||
{
|
||||
return &this->entries;
|
||||
}
|
||||
|
||||
bool Settings::SettingClass::set (const string name, const string value)
|
||||
{
|
||||
pair<map<string, string>::iterator, bool> r;
|
||||
r = this->entries.insert(pair<string, string>(name, value));
|
||||
if (!r.second)
|
||||
{
|
||||
r.first->second = value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
121
src/settings.hpp
121
src/settings.hpp
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#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<string, string>* getMap ();
|
||||
void getIPs (const string& key, list<SOCKADDR_IN> &ip);
|
||||
private:
|
||||
friend class Settings;
|
||||
string className;
|
||||
map<string, string> 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<string, SettingClass*> classes;
|
||||
|
||||
void parseSettings (char *data, int len);
|
||||
};
|
||||
};
|
|
@ -17,19 +17,19 @@
|
|||
* along with UDPT. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "udpTracker.hpp"
|
||||
#include "tools.h"
|
||||
#include <cstdlib> // atoi
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <list>
|
||||
#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<bool>();
|
||||
this->allowIANA_IPs = conf["tracker.allow_iana_ips"].as<bool>();
|
||||
this->isDynamic = conf["tracker.is_dynamic"].as<bool>();
|
||||
this->m_allowRemotes = conf["tracker.allow_remotes"].as<bool>();
|
||||
this->m_allowIANA_IPs = conf["tracker.allow_iana_ips"].as<bool>();
|
||||
this->m_isDynamic = conf["tracker.is_dynamic"].as<bool>();
|
||||
|
||||
this->announce_interval = conf["tracker.announce_interval"].as<unsigned>();
|
||||
this->cleanup_interval = conf["tracker.cleanup_interval"].as<unsigned>();
|
||||
this->port = conf["tracker.port"].as<unsigned short>();
|
||||
this->thread_count = conf["tracker.threads"].as<unsigned>() + 1;
|
||||
this->m_announceInterval = conf["tracker.announce_interval"].as<unsigned>();
|
||||
this->m_cleanupInterval = conf["tracker.cleanup_interval"].as<unsigned>();
|
||||
this->m_port = conf["tracker.port"].as<unsigned short>();
|
||||
this->m_threadCount = conf["tracker.threads"].as<unsigned>() + 1;
|
||||
|
||||
list<SOCKADDR_IN> addrs;
|
||||
std::list<SOCKADDR_IN> 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<SOCKADDR*>(&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<LPTHREAD_START_ROUTINE>(_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<LPTHREAD_START_ROUTINE>(_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<SOCKADDR*>(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<ConnectionRequest*>(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<ScrapeRequest*>(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<ScrapeResponse*>(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<const char*>(buffer), sizeof(buffer), 0, reinterpret_cast<SOCKADDR*>(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<ConnectionRequest*>(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<UDPTracker*>(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<UDPTracker*>(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
|
||||
|
|
|
@ -22,18 +22,16 @@
|
|||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <string>
|
||||
#include "exceptions.h"
|
||||
#include "multiplatform.h"
|
||||
#include "db/driver_sqlite.hpp"
|
||||
#include "settings.hpp"
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <string>
|
||||
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 &);
|
||||
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue