Resolved Issues #10 and #11

This commit is contained in:
Naim A 2016-01-23 18:11:51 +02:00
parent bc97b747ad
commit edaa44bfc7
13 changed files with 178 additions and 168 deletions

View file

@ -23,9 +23,8 @@ namespace UDPT
{
namespace Data
{
DatabaseDriver::DatabaseDriver(Settings::SettingClass *sc, bool isDynamic)
DatabaseDriver::DatabaseDriver(const boost::program_options::variables_map& conf, bool isDynamic) : m_conf(conf)
{
this->dClass = sc;
this->is_dynamic = isDynamic;
}

View file

@ -21,6 +21,7 @@
#define DATABASE_HPP_
#include "../settings.hpp"
#include <boost/program_options.hpp>
namespace UDPT
{
@ -35,10 +36,10 @@ namespace UDPT
E_CONNECTION_FAILURE = 2
};
DatabaseException ();
DatabaseException (EType);
EType getErrorType ();
const char* getErrorMessage ();
DatabaseException();
DatabaseException(EType);
EType getErrorType();
const char* getErrorMessage();
private:
EType errorNum;
};
@ -68,34 +69,34 @@ namespace UDPT
* Opens the DB's connection
* @param dClass Settings class ('database' class).
*/
DatabaseDriver (Settings::SettingClass *dClass, bool isDynamic = false);
DatabaseDriver(const boost::program_options::variables_map& conf, bool isDynamic = false);
/**
* Adds a torrent to the Database. automatically done if in dynamic mode.
* @param hash The info_hash of the torrent.
* @return true on success. false on failure.
*/
virtual bool addTorrent (uint8_t hash[20]);
virtual bool addTorrent(uint8_t hash[20]);
/**
* Removes a torrent from the database. should be used only for non-dynamic trackers or by cleanup.
* @param hash The info_hash to drop.
* @return true if torrent's database was dropped or no longer exists. otherwise false (shouldn't happen - critical)
*/
virtual bool removeTorrent (uint8_t hash[20]);
virtual bool removeTorrent(uint8_t hash[20]);
/**
* Checks if the Database is acting as a dynamic tracker DB.
* @return true if dynamic. otherwise false.
*/
bool isDynamic ();
bool isDynamic();
/**
* Checks if the torrent can be used in the tracker.
* @param info_hash The torrent's info_hash.
* @return true if allowed. otherwise false.
*/
virtual bool isTorrentAllowed (uint8_t info_hash [20]);
virtual bool isTorrentAllowed(uint8_t info_hash [20]);
/**
* Generate a Connection ID for the peer.
@ -104,9 +105,9 @@ namespace UDPT
* @param port The peer's IP (remote port if tracker accepts)
* @return
*/
virtual bool genConnectionId (uint64_t *connectionId, uint32_t ip, uint16_t port);
virtual bool genConnectionId(uint64_t *connectionId, uint32_t ip, uint16_t port);
virtual bool verifyConnectionId (uint64_t connectionId, uint32_t ip, uint16_t port);
virtual bool verifyConnectionId(uint64_t connectionId, uint32_t ip, uint16_t port);
/**
* Updates/Adds a peer to/in the database.
@ -119,7 +120,7 @@ namespace UDPT
* @param uploaded total bytes uploaded
* @return true on success, false on failure.
*/
virtual bool updatePeer (uint8_t peer_id [20], uint8_t info_hash [20],
virtual bool updatePeer(uint8_t peer_id [20], uint8_t info_hash [20],
uint32_t ip, uint16_t port,
int64_t downloaded, int64_t left, int64_t uploaded,
enum TrackerEvents event);
@ -132,14 +133,14 @@ namespace UDPT
* @param port The TCP port (remote port if tracker accepts)
* @return true on success. false on failure (shouldn't happen - critical)
*/
virtual bool removePeer (uint8_t peer_id [20], uint8_t info_hash [20], uint32_t ip, uint16_t port);
virtual bool removePeer(uint8_t peer_id [20], uint8_t info_hash [20], uint32_t ip, uint16_t port);
/**
* Gets stats on a torrent
* @param e TorrentEntry, only this info_hash has to be set
* @return true on success, false on failure.
*/
virtual bool getTorrentInfo (TorrentEntry *e);
virtual bool getTorrentInfo(TorrentEntry *e);
/**
* Gets a list of peers from the database.
@ -148,21 +149,21 @@ namespace UDPT
* @param pe The list of peers. Must be pre-allocated to the size of max_count.
* @return true on success, otherwise false (shouldn't happen).
*/
virtual bool getPeers (uint8_t info_hash [20], int *max_count, PeerEntry *pe);
virtual bool getPeers(uint8_t info_hash [20], int *max_count, PeerEntry *pe);
/**
* Cleanup the database.
* Other actions may be locked when using this depending on the driver.
*/
virtual void cleanup ();
virtual void cleanup();
/**
* Closes the connections, and releases all other resources.
*/
virtual ~DatabaseDriver ();
virtual ~DatabaseDriver();
protected:
Settings::SettingClass *dClass;
const boost::program_options::variables_map& m_conf;
private:
bool is_dynamic;
};

View file

@ -69,13 +69,13 @@ namespace UDPT
return data;
}
SQLite3Driver::SQLite3Driver (Settings::SettingClass *sc, bool isDyn) : DatabaseDriver(sc, isDyn)
SQLite3Driver::SQLite3Driver(const boost::program_options::variables_map& conf, bool isDyn) : DatabaseDriver(conf, isDyn)
{
int r;
bool doSetup;
fstream fCheck;
string filename = sc->get("file");
string filename = m_conf["db.param"].as<std::string>();
fCheck.open(filename.c_str(), ios::binary | ios::in);
if (fCheck.is_open())

View file

@ -31,23 +31,23 @@ namespace UDPT
class SQLite3Driver : public DatabaseDriver
{
public:
SQLite3Driver (Settings::SettingClass *sc, bool isDyn = false);
bool addTorrent (uint8_t info_hash[20]);
bool removeTorrent (uint8_t info_hash[20]);
bool genConnectionId (uint64_t *connId, uint32_t ip, uint16_t port);
bool verifyConnectionId (uint64_t connId, uint32_t ip, uint16_t port);
bool updatePeer (uint8_t peer_id [20], uint8_t info_hash [20], uint32_t ip, uint16_t port, int64_t downloaded, int64_t left, int64_t uploaded, enum TrackerEvents event);
bool removePeer (uint8_t peer_id [20], uint8_t info_hash [20], uint32_t ip, uint16_t port);
bool getTorrentInfo (TorrentEntry *e);
bool isTorrentAllowed (uint8_t info_hash[20]);
bool getPeers (uint8_t info_hash [20], int *max_count, PeerEntry *pe);
void cleanup ();
SQLite3Driver(const boost::program_options::variables_map& conf, bool isDyn = false);
bool addTorrent(uint8_t info_hash[20]);
bool removeTorrent(uint8_t info_hash[20]);
bool genConnectionId(uint64_t *connId, uint32_t ip, uint16_t port);
bool verifyConnectionId(uint64_t connId, uint32_t ip, uint16_t port);
bool updatePeer(uint8_t peer_id [20], uint8_t info_hash [20], uint32_t ip, uint16_t port, int64_t downloaded, int64_t left, int64_t uploaded, enum TrackerEvents event);
bool removePeer(uint8_t peer_id [20], uint8_t info_hash [20], uint32_t ip, uint16_t port);
bool getTorrentInfo(TorrentEntry *e);
bool isTorrentAllowed(uint8_t info_hash[20]);
bool getPeers(uint8_t info_hash [20], int *max_count, PeerEntry *pe);
void cleanup();
virtual ~SQLite3Driver ();
virtual ~SQLite3Driver();
private:
sqlite3 *db;
void doSetup ();
void doSetup();
};
};
};

View file

@ -23,6 +23,7 @@
#include <cstring>
#include <map>
#include "httpserver.hpp"
#include <boost/program_options.hpp>
using namespace std;
@ -43,22 +44,14 @@ namespace UDPT
this->init(sa, threads);
}
HTTPServer::HTTPServer(Settings *s)
HTTPServer::HTTPServer(const boost::program_options::variables_map& conf)
{
Settings::SettingClass *sc = s->getClass("apiserver");
list<SOCKADDR_IN> localEndpoints;
uint16_t port;
int threads;
port = 6969;
threads = 1;
if (sc != NULL)
{
port = sc->getInt("port", 6969);
threads = sc->getInt("threads", 1);
sc->getIPs("bind", localEndpoints);
}
port = conf["apiserver.port"].as<unsigned short>();
threads = conf["apiserver.threads"].as<unsigned short>();
if (threads <= 0)
threads = 1;
@ -85,16 +78,16 @@ namespace UDPT
this->rootNode.callback = NULL;
this->srv = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
this->srv = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (this->srv == INVALID_SOCKET)
{
throw ServerException (1, "Failed to create Socket");
}
r = bind (this->srv, (SOCKADDR*)&localEndpoint, sizeof(localEndpoint));
r = ::bind(this->srv, (SOCKADDR*)&localEndpoint, sizeof(localEndpoint));
if (r == SOCKET_ERROR)
{
throw ServerException (2, "Failed to bind socket");
throw ServerException(2, "Failed to bind socket");
}
this->isRunning = true;
@ -118,7 +111,7 @@ namespace UDPT
doSrv:
try {
HTTPServer::handleConnections (s);
} catch (ServerException &se)
} catch (const ServerException &se)
{
cerr << "SRV ERR #" << se.getErrorCode() << ": " << se.getErrorMsg () << endl;
goto doSrv;
@ -139,13 +132,13 @@ doSrv:
while (server->isRunning)
{
r = listen (server->srv, 50);
r = ::listen(server->srv, 50);
if (r == SOCKET_ERROR)
{
#ifdef WIN32
Sleep (500);
::Sleep(500);
#else
sleep (1);
::sleep(1);
#endif
continue;
}

View file

@ -24,8 +24,8 @@
#include <string>
#include <sstream>
#include <list>
#include <boost/program_options.hpp>
#include "../multiplatform.h"
#include "../settings.hpp"
using namespace std;
#define REQUEST_BUFFER_SIZE 2048
@ -131,7 +131,7 @@ namespace UDPT
typedef void (reqCallback)(HTTPServer*,Request*,Response*);
HTTPServer (uint16_t port, int threads);
HTTPServer (Settings *s);
HTTPServer(const boost::program_options::variables_map& conf);
void addApp (list<string> *path, reqCallback *);

View file

@ -97,11 +97,11 @@ namespace UDPT
return true;
}
WebApp::WebApp(HTTPServer *srv, DatabaseDriver *db, Settings *settings)
WebApp::WebApp(HTTPServer *srv, DatabaseDriver *db, const boost::program_options::variables_map& conf) : m_conf(conf)
{
this->instance = srv;
this->db = db;
this->sc_api = settings->getClass("api");
/* this->sc_api = settings->getClass("api");
Settings::SettingClass *apiKeys = settings->getClass("api.keys");
if (apiKeys != NULL)
@ -124,7 +124,7 @@ namespace UDPT
this->ip_whitelist.insert(pair<string, list<uint32_t> >(key, ips));
}
}
} */
srv->setData("webapp", this);
}

View file

@ -25,6 +25,7 @@
#include <stdint.h>
#include <map>
#include <string>
#include <boost/program_options.hpp>
using namespace std;
using namespace UDPT;
@ -37,15 +38,15 @@ namespace UDPT
class WebApp
{
public:
WebApp (HTTPServer *, DatabaseDriver *, Settings *);
~WebApp ();
WebApp(HTTPServer *, DatabaseDriver *, const boost::program_options::variables_map& conf);
~WebApp();
void deploy ();
private:
HTTPServer *instance;
UDPT::Data::DatabaseDriver *db;
Settings::SettingClass *sc_api;
const boost::program_options::variables_map& m_conf;
std::map<std::string, list<uint32_t> > ip_whitelist;
static void handleRoot (HTTPServer*,HTTPServer::Request*, HTTPServer::Response*);

View file

@ -26,30 +26,14 @@ using namespace std;
namespace UDPT {
Logger::Logger(Settings *s)
Logger::Logger(const boost::program_options::variables_map& s)
: logfile (&std::cout)
{
Settings::SettingClass *sc;
string filename = "stdout";
string level = "error";
const string& filename = s["logging.filename"].as<std::string>();
const string& level = s["logging.level"].as<std::string>();
closeStreamOnDestroy = false;
sc = s->getClass("logging");
if (sc != NULL)
{
string::size_type i;
filename = sc->get("filename");
level = sc->get("level");
for (i = 0;i < level.length(); i++)
{
if (level[i] >= 'A' && level[i] <= 'Z')
level[i] = 'a' + (level[i] - 'A');
}
}
if (level == "debug" || level == "d")
this->loglevel = LL_DEBUG;
else if (level == "warning" || level == "w")
@ -73,7 +57,7 @@ namespace UDPT {
}
}
Logger::Logger(Settings *s, ostream &os)
Logger::Logger(const boost::program_options::variables_map& s, ostream &os)
: logfile (&os), loglevel (LL_ERROR)
{
closeStreamOnDestroy = false;

View file

@ -25,10 +25,12 @@
#include <iostream>
#include <queue>
#include <time.h>
#include <boost/program_options.hpp>
namespace UDPT {
using namespace std;
class Logger {
class Logger
{
public:
enum LogLevel {
@ -38,19 +40,19 @@ namespace UDPT {
LL_DEBUG = 3
};
Logger (Settings *s);
Logger(const boost::program_options::variables_map& s);
Logger (Settings *s, ostream &os);
Logger(const boost::program_options::variables_map& s, ostream &os);
virtual ~Logger ();
virtual ~Logger();
void log (enum LogLevel, string msg);
void log(enum LogLevel, string msg);
private:
ostream *logfile;
enum LogLevel loglevel;
bool closeStreamOnDestroy;
static void setStream (Logger *logger, ostream &s);
static void setStream(Logger *logger, ostream &s);
};
};

View file

@ -28,6 +28,8 @@
#include <cstdlib> // atoi
#include <csignal> // signal
#include <cstring> // strlen
#include <memory.h>
#include <boost/program_options.hpp>
using namespace std;
using namespace UDPT;
@ -41,32 +43,28 @@ static struct {
HTTPServer *httpserver;
} Instance;
static void _print_usage ()
{
cout << "Usage: udpt [<configuration file>]" << endl;
}
static void _doAPIStart (Settings *settings, WebApp **wa, HTTPServer **srv, DatabaseDriver *drvr)
static void _doAPIStart (const boost::program_options::variables_map& settings, WebApp **wa, HTTPServer **srv, DatabaseDriver *drvr)
{
if (settings == NULL)
return;
Settings::SettingClass *sc = settings->getClass("apiserver");
if (sc == NULL)
return; // no settings set!
if (!sc->getBool("enable", false))
if (!settings["apiserver.enable"].as<bool>())
{
cerr << "API Server not enabled." << endl;
return;
}
try {
*srv = Instance.httpserver = new HTTPServer (settings);
*wa = Instance.wa = new WebApp (*srv, drvr, settings);
(*wa)->deploy();
} catch (ServerException &e)
try
{
cerr << "ServerException #" << e.getErrorCode() << ": " << e.getErrorMsg() << endl;
*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;
}
}
@ -137,9 +135,7 @@ static void _signal_handler (int sig)
int main(int argc, char *argv[])
{
Settings *settings;
UDPTracker *usi;
string config_file;
int r;
#ifdef WIN32
@ -147,11 +143,81 @@ int main(int argc, char *argv[])
WSAStartup(MAKEWORD(2, 2), &wsadata);
#endif
cout << "UDP Tracker (UDPT) " << VERSION << " (" << PLATFORM << ")" << endl;
cout << "Copyright 2012,2013 Naim Abda <naim94a@gmail.com>\n\tReleased under the GPLv3 License." << endl;
cout << "Build Date: " << __DATE__ << endl << endl;
boost::program_options::options_description commandLine("Command line options");
commandLine.add_options()
("help,h", "produce help message")
("all-help", "displays all help")
("test,t", "test configuration file")
("config,c", boost::program_options::value<std::string>()->default_value("/etc/udpt.conf"), "configuration file to use")
;
boost::program_options::options_description configOptions("Configuration options");
configOptions.add_options()
("db.driver", boost::program_options::value<std::string>()->default_value("sqlite3"), "database driver to use")
("db.param", boost::program_options::value<std::string>()->default_value("/var/lib/udpt.db"), "database connection parameters")
("tracker.is_dynamic", boost::program_options::value<bool>()->default_value(true), "Sets if the tracker is dynamic")
("tracker.port", boost::program_options::value<unsigned short>()->default_value(6969), "UDP port to listen on")
("tracker.threads", boost::program_options::value<unsigned>()->default_value(5), "threads to run (UDP only)")
("tracker.allow_remotes", boost::program_options::value<bool>()->default_value(true), "allows clients to report remote IPs")
("tracker.allow_iana_ips", boost::program_options::value<bool>()->default_value(false), "allows IANA reserved IPs to connect (useful for debugging)")
("tracker.announce_interval", boost::program_options::value<unsigned>()->default_value(1800), "announce interval")
("tracker.cleanup_interval", boost::program_options::value<unsigned>()->default_value(120), "sets database cleanup interval")
("apiserver.enable", boost::program_options::value<bool>()->default_value(0), "Enable API server?")
("apiserver.threads", boost::program_options::value<unsigned>()->default_value(1), "threads for API server")
("apiserver.port", boost::program_options::value<unsigned short>()->default_value(6969), "TCP port to listen on")
("logging.filename", boost::program_options::value<std::string>()->default_value("stdout"), "file to write logs to")
("logging.level", boost::program_options::value<std::string>()->default_value("warning"), "log level (error/warning/info/debug)")
;
boost::program_options::variables_map var_map;
boost::program_options::store(boost::program_options::parse_command_line(argc, argv, commandLine), var_map);
boost::program_options::notify(var_map);
if (var_map.count("help"))
{
std::cout << "UDP Tracker (UDPT) " << VERSION << " (" << PLATFORM << ")" << std::endl
<< "Copyright 2012-2016 Naim A. <naim94a@gmail.com>" << std::endl
<< "Build Date: " << __DATE__ << std::endl << std::endl;
std::cout << commandLine << std::endl;
return 0;
}
if (var_map.count("all-help"))
{
std::cout << commandLine << std::endl;
std::cout << configOptions << std::endl;
return 0;
}
std::string config_filename(var_map["config"].as<std::string>());
bool isTest = var_map.count("test");
if (var_map.count("config"))
{
try
{
boost::program_options::basic_parsed_options<wchar_t> parsed_options = boost::program_options::parse_config_file<wchar_t>(config_filename.c_str(), configOptions);
boost::program_options::store(
parsed_options,
var_map);
}
catch (const boost::program_options::error& ex)
{
std::cerr << "ERROR: " << ex.what() << std::endl;
return -1;
}
if (isTest)
{
std::cout << "Config OK" << std::endl;
return 0;
}
}
config_file = "udpt.conf";
memset(&Instance, 0, sizeof(Instance));
#ifdef SIGBREAK
@ -167,48 +233,17 @@ int main(int argc, char *argv[])
signal(SIGINT, &_signal_handler);
#endif
if (argc <= 1)
try
{
// set current directory when no filename is present.
_setCWD(argv[0]);
_print_usage ();
logger = new Logger(var_map);
}
else if (argc >= 2)
catch (const std::exception& ex)
{
config_file = argv[1]; // reported in issue #5.
std::cerr << "Failed to initialize logger: " << ex.what() << std::endl;
return -1;
}
settings = Instance.settings = new Settings (config_file);
if (!settings->load())
{
const char strDATABASE[] = "database";
const char strTRACKER[] = "tracker";
const char strAPISRV [] = "apiserver";
// set default settings:
settings->set (strDATABASE, "driver", "sqlite3");
settings->set (strDATABASE, "file", "tracker.db");
settings->set (strTRACKER, "is_dynamic", "0");
settings->set (strTRACKER, "port", "6969"); // UDP PORT
settings->set (strTRACKER, "threads", "5");
settings->set (strTRACKER, "allow_remotes", "1");
settings->set (strTRACKER, "allow_iana_ips", "1");
settings->set (strTRACKER, "announce_interval", "1800");
settings->set (strTRACKER, "cleanup_interval", "120");
settings->set (strAPISRV, "enable", "1");
settings->set (strAPISRV, "threads", "1");
settings->set (strAPISRV, "port", "6969"); // TCP PORT
settings->save();
cerr << "Failed to read from '" << config_file.c_str() << "'. Using default settings." << endl;
}
logger = new Logger (settings);
usi = Instance.usi = new UDPTracker (settings);
usi = Instance.usi = new UDPTracker(var_map);
HTTPServer *apiSrv = NULL;
WebApp *wa = NULL;
@ -232,7 +267,7 @@ int main(int argc, char *argv[])
goto cleanup;
}
_doAPIStart(settings, &wa, &apiSrv, usi->conn);
_doAPIStart(var_map, &wa, &apiSrv, usi->conn);
cout << "Hit Control-C to exit." << endl;

View file

@ -36,23 +36,19 @@ using namespace UDPT::Data;
namespace UDPT
{
UDPTracker::UDPTracker (Settings *settings)
UDPTracker::UDPTracker(const boost::program_options::variables_map& conf) : m_conf(conf)
{
Settings::SettingClass *sc_tracker;
sc_tracker = settings->getClass("tracker");
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->allowRemotes = sc_tracker->getBool("allow_remotes", true);
this->allowIANA_IPs = sc_tracker->getBool("allow_iana_ips", false);
this->isDynamic = sc_tracker->getBool("is_dynamic", true);
this->announce_interval = sc_tracker->getInt("announce_interval", 1800);
this->cleanup_interval = sc_tracker->getInt("cleanup_interval", 120);
this->port = sc_tracker->getInt("port", 6969);
this->thread_count = abs (sc_tracker->getInt("threads", 5)) + 1;
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;
list<SOCKADDR_IN> addrs;
sc_tracker->getIPs("bind", addrs);
if (addrs.empty())
{
@ -69,7 +65,6 @@ namespace UDPT
this->isRunning = false;
this->conn = NULL;
this->o_settings = settings;
}
UDPTracker::~UDPTracker ()
@ -130,15 +125,15 @@ namespace UDPT
yup; // just to set TRUE
string dbname;// saves the Database name.
sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
sock = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == INVALID_SOCKET)
return START_ESOCKET_FAILED;
yup = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&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));
r = ::bind(sock, (SOCKADDR*)&this->localEndpoint, sizeof(SOCKADDR_IN));
if (r == SOCKET_ERROR)
{
@ -152,8 +147,7 @@ namespace UDPT
this->sock = sock;
this->conn = new Data::SQLite3Driver (this->o_settings->getClass("database"),
this->isDynamic);
this->conn = new Data::SQLite3Driver(m_conf, this->isDynamic);
this->isRunning = true;

View file

@ -25,6 +25,7 @@
#include "multiplatform.h"
#include "db/driver_sqlite.hpp"
#include "settings.hpp"
#include <boost/program_options.hpp>
#include <string>
using namespace std;
@ -117,7 +118,7 @@ namespace UDPT
* Initializes the UDP Tracker.
* @param settings Settings to start server with
*/
UDPTracker (Settings *);
UDPTracker(const boost::program_options::variables_map& conf);
/**
* Starts the Initialized instance.
@ -150,7 +151,7 @@ namespace UDPT
uint32_t announce_interval;
uint32_t cleanup_interval;
Settings *o_settings;
const boost::program_options::variables_map& m_conf;
#ifdef WIN32
static DWORD _thread_start (LPVOID arg);