Refactored (#31)

* Build system changed to CMake
* Converted tabs to spaces
* Removed all usages of boost::log
* Replaced boost::thread with std::thread
* Update copyright year
* Added a tiny bit of unit tests
* Added a simple message queue
* Added basic independent logging
* Added CONTRIBUTING
This commit is contained in:
Naim A 2017-09-27 04:33:21 +03:00 committed by Naim A
parent 7193f945a9
commit f34fcdbd04
No known key found for this signature in database
GPG key ID: FD7948915D9EF8B9
29 changed files with 3243 additions and 3091 deletions

44
.github/CONTRIBUTING.md vendored Normal file
View file

@ -0,0 +1,44 @@
# Contributing
Thank you for looking into [UDPT](https://github.com/naim94a/udpt)!
This document lists various ways to contribute to UDPT. If you can, please do.
## Bug Reports
Bug reports are always welcome, they help us maintain a quality product.
Before submitting a bug report, please first check that the issue does not already exist and that the effected version
is the most recent one.
* If a similar (or same) issue already exists, please upvote, comment, elaborate on the existing issue.
* If you found a new issue, please attach the used configuration and how to cause the bug to appear.
* Core dumps are always welcome
Bugs should be reported at [UDPT's issue tracker](https://github.com/naim94a/udpt) on GitHub.
## Suggesting new features
New features are welcome, it doesn't mean they will enter immediately.
Suggestions should be filed as issues along with bug reports, just add the "enhancement" label to the created issue.
## Donations
Please show us your appreciation by donating BitCoin at bitcoin:1KMeZvcgnmWdHitu51yEFWBNcSTXL1eBk3.
![bitcoin:1KMeZvcgnmWdHitu51yEFWBNcSTXL1eBk3](bitcoin-qr.png)
## Pull requests
Before submitting a pull request, please check that the changes don't effect other platforms or have any unwanted
side-effects.
Pull Requests should address open issue(s), where the project owner and contributors can discuss how the issue should be
addressed.
Pull requests that add new features should be first mentioned in issues in order to verify that the project owner will
allow such changes to the project.
Code in pull requests should meet the following requirements:
* Class names should be CamelCase, and the first letter should be capital.
* Functions should be camelCase, and the first letter should be lower-case.
* Class members should be prefixed with `m_`, for example: `bool m_isRunning`
* All variables, classes, functions and class members should have an indicative name.
* Adding external libraries is allowed, but frowned upon

BIN
.github/bitcoin-qr.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View file

@ -1,15 +1,24 @@
project(udpt)
cmake_minimum_required(VERSION 3.6)
cmake_minimum_required(VERSION 3.2)
enable_testing()
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_definitions(-DBOOST_LOG_DYN_LINK)
file(GLOB src_files "src/*.c"
"src/*.cpp"
"src/db/*.cpp"
"src/http/*.cpp")
LIST(APPEND LIBS "pthread" "sqlite3" "boost_program_options" "boost_system")
add_executable(udpt ${src_files})
target_link_libraries(udpt pthread sqlite3 boost_log boost_program_options boost_thread boost_system)
target_link_libraries(udpt ${LIBS})
add_executable(udpt_tests tests/main.cpp ${src_files})
target_compile_definitions(udpt_tests PRIVATE TEST=1)
target_link_libraries(udpt_tests gtest ${LIBS})
add_test(NAME udpt_tests COMMAND udpt_tests)

64
src/MessageQueue.hpp Normal file
View file

@ -0,0 +1,64 @@
/*
* Copyright © 2012-2017 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 <queue>
#include <mutex>
namespace UDPT
{
namespace Utils {
template<class T>
class MessageQueue {
public:
MessageQueue() {}
virtual ~MessageQueue() {}
bool IsEmpty() const {
return m_queue.empty();
}
T Pop() {
m_queueMutex.lock();
T val = m_queue.front();
m_queue.pop();
m_queueMutex.unlock();
return val;
}
void Push(T obj) {
m_queueMutex.lock();
m_queue.push(obj);
m_queueMutex.unlock();
}
size_t Count() const {
return m_queue.size();
}
private:
std::queue<T> m_queue;
std::mutex m_queueMutex;
};
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2012-2016 Naim A.
* Copyright © 2012-2017 Naim A.
*
* This file is part of UDPT.
*

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2012-2016 Naim A.
* Copyright © 2012-2017 Naim A.
*
* This file is part of UDPT.
*
@ -21,8 +21,6 @@
#define DATABASE_HPP_
#include <boost/program_options.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/sources/severity_channel_logger.hpp>
namespace UDPT
{

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2012-2016 Naim A.
* Copyright © 2012-2017 Naim A.
*
* This file is part of UDPT.
*
@ -26,6 +26,7 @@
#include <cassert>
#include <cstring> // memcpy
#include "../multiplatform.h"
#include "../logging.hpp"
using namespace std;
@ -66,7 +67,7 @@ namespace UDPT
return data;
}
SQLite3Driver::SQLite3Driver(const boost::program_options::variables_map& conf, bool isDyn) : DatabaseDriver(conf, isDyn), m_logger(boost::log::keywords::channel="SQLite3")
SQLite3Driver::SQLite3Driver(const boost::program_options::variables_map& conf, bool isDyn) : DatabaseDriver(conf, isDyn)
{
int r;
bool doSetup;
@ -86,6 +87,7 @@ namespace UDPT
r = sqlite3_open(filename.c_str(), &this->db);
if (r != SQLITE_OK)
{
LOG_FATAL("db-sqlite", "Failed to connect DB. sqlite returned " << r);
sqlite3_close(this->db);
throw DatabaseException (DatabaseException::E_CONNECTION_FAILURE);
}
@ -97,6 +99,7 @@ namespace UDPT
void SQLite3Driver::doSetup()
{
char *eMsg = NULL;
LOG_INFO("db-sqlite", "Setting up database...");
// for quicker stats.
sqlite3_exec(this->db, "CREATE TABLE stats ("
"info_hash blob(20) UNIQUE,"
@ -177,8 +180,6 @@ namespace UDPT
}
}
BOOST_LOG_SEV(m_logger, boost::log::trivial::debug) << "Retrieved " << i << " peers";
sqlite3_finalize(stmt);
*max_count = i;
@ -259,12 +260,10 @@ namespace UDPT
if (SQLITE_OK == r)
{
BOOST_LOG_SEV(m_logger, boost::log::trivial::info) << "Added torrent";
return true;
}
else
{
BOOST_LOG_SEV(m_logger, boost::log::trivial::error) << "Failed to add torrent: SQLite3 error code = " << r;
return false;
}
}
@ -286,17 +285,26 @@ namespace UDPT
void SQLite3Driver::cleanup()
{
LOG_INFO("db-sqlite", "Cleaning up...");
int exp = time (NULL) - 7200; // 2 hours, expired.
int r = 0;
// drop all peers with no activity for 2 hours.
sqlite3_stmt *getTables;
// torrent table names: t<hex-of-sha-1>
sqlite3_prepare(this->db, "SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 't________________________________________'", -1, &getTables, NULL);
r = sqlite3_prepare(this->db, "SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 't________________________________________'", -1, &getTables, NULL);
if (r != SQLITE_OK) {
LOG_ERR("db-sqlite", "Failed fetch tables from DB for cleanup.");
return;
}
uint8_t buff [20];
sqlite3_stmt *updateStats;
assert (sqlite3_prepare(this->db, "REPLACE INTO stats (info_hash,seeders,leechers,last_mod) VALUES (?,?,?,?)", -1, &updateStats, NULL) == SQLITE_OK);
r = sqlite3_prepare(this->db, "REPLACE INTO stats (info_hash,seeders,leechers,last_mod) VALUES (?,?,?,?)", -1, &updateStats, NULL);
if (r != SQLITE_OK) {
LOG_ERR("db-sqlite", "Failed to prepare update stats query.");
return;
}
while (sqlite3_step(getTables) == SQLITE_ROW)
{
@ -304,18 +312,23 @@ namespace UDPT
stringstream sStr;
sStr << "DELETE FROM " << tblN << " WHERE last_seen<" << exp;
assert (sqlite3_exec(this->db, sStr.str().c_str(), NULL, NULL, NULL) == SQLITE_OK);
r = sqlite3_exec(this->db, sStr.str().c_str(), NULL, NULL, NULL);
if (r != SQLITE_OK) {
LOG_ERR("db-sqlite", "Failed to execute cleanup for table '" << tblN << "'.");
continue;
}
sStr.str (string());
sStr << "SELECT left,COUNT(*) FROM " << tblN << " GROUP BY left==0";
sqlite3_stmt *collectStats;
sqlite3_prepare(this->db, sStr.str().c_str(), sStr.str().length(), &collectStats, NULL);
r = sqlite3_prepare(this->db, sStr.str().c_str(), sStr.str().length(), &collectStats, NULL);
if (sqlite3_errcode(this->db) != SQLITE_OK)
if (r != SQLITE_OK)
{
// TODO: Log this error
LOG_ERR("db-sqlite", "Failed while trying to prepare stats query for '" << tblN << "', sqlite returned " << r);
continue;
}
int seeders = 0, leechers = 0;
@ -340,8 +353,7 @@ namespace UDPT
sqlite3_finalize(getTables);
}
bool SQLite3Driver::removeTorrent(uint8_t info_hash[20])
{
bool SQLite3Driver::removeTorrent(uint8_t info_hash[20]) {
// if non-dynamic, remove from table
sqlite3_stmt *stmt;
sqlite3_prepare(this->db, "DELETE FROM torrents WHERE info_hash=?", -1, &stmt, NULL);
@ -368,13 +380,10 @@ namespace UDPT
sqlite3_exec(this->db, str.c_str(), NULL, NULL, NULL);
BOOST_LOG_SEV(m_logger, boost::log::trivial::info) << "Torrent removed.";
return true;
}
bool SQLite3Driver::removePeer(uint8_t peer_id [20], uint8_t info_hash [20], uint32_t ip, uint16_t port)
{
bool SQLite3Driver::removePeer(uint8_t peer_id [20], uint8_t info_hash [20], uint32_t ip, uint16_t port) {
string sql;
char xHash [50];
sqlite3_stmt *stmt;
@ -398,8 +407,7 @@ namespace UDPT
return true;
}
static uint64_t _genCiD (uint32_t ip, uint16_t port)
{
static uint64_t _genCiD (uint32_t ip, uint16_t port) {
uint64_t x;
x = (time(NULL) / 3600) * port; // x will probably overload.
x = (ip ^ port);
@ -408,23 +416,19 @@ namespace UDPT
return x;
}
bool SQLite3Driver::genConnectionId (uint64_t *connectionId, uint32_t ip, uint16_t port)
{
bool SQLite3Driver::genConnectionId (uint64_t *connectionId, uint32_t ip, uint16_t port) {
*connectionId = _genCiD(ip, port);
return true;
}
bool SQLite3Driver::verifyConnectionId(uint64_t cId, uint32_t ip, uint16_t port)
{
bool SQLite3Driver::verifyConnectionId(uint64_t cId, uint32_t ip, uint16_t port) {
if (cId == _genCiD(ip, port))
return true;
else
return false;
}
SQLite3Driver::~SQLite3Driver()
{
BOOST_LOG_SEV(m_logger, boost::log::trivial::info) << "Closing SQLite";
SQLite3Driver::~SQLite3Driver() {
sqlite3_close(this->db);
}
};

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2012-2016 Naim A.
* Copyright © 2012-2017 Naim A.
*
* This file is part of UDPT.
*
@ -46,7 +46,6 @@ namespace UDPT
virtual ~SQLite3Driver();
private:
sqlite3 *db;
boost::log::sources::severity_channel_logger_mt<> m_logger;
void doSetup();
};

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2013-2016 Naim A.
* Copyright © 2013-2017 Naim A.
*
* This file is part of UDPT.
*

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2013-2016 Naim A.
* Copyright © 2013-2017 Naim A.
*
* This file is part of UDPT.
*

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2013-2016 Naim A.
* Copyright © 2013-2017 Naim A.
*
* This file is part of UDPT.
*

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2013-2016 Naim A.
* Copyright © 2013-2017 Naim A.
*
* This file is part of UDPT.
*

140
src/logging.cpp Normal file
View file

@ -0,0 +1,140 @@
/*
* Copyright © 2012-2017 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 "logging.hpp"
#include <sstream>
#include <chrono>
#include <cstring>
#include <iostream>
namespace UDPT {
namespace Logging {
Logger::Logger() : m_cleaningUp(false), m_workerThread(Logger::worker, this), m_minLogLevel(Severity::FATAL) {
}
Logger::~Logger() {
try {
// prevent new log messages from entering queue.
m_cleaningUp = true;
// tell thread to exit
m_runningCondition.notify_one();
// wait for worker to terminate
m_workerThread.join();
// flush any remaining logs
flush();
// flush iostreams
for (std::vector<std::pair<std::ostream*, Severity>>::const_iterator it = m_outputStreams.begin(); it != m_outputStreams.end(); ++it) {
it->first->flush();
}
} catch (...) {
// can't do much here... this is a logging class...
}
}
Logger& Logger::getLogger() {
static Logger instance;
return instance;
}
void Logger::log(Severity severity, const std::string& channel, const std::string& message) {
if (severity < m_minLogLevel) {
return;
}
m_queue.Push(LogEntry{
.when=std::chrono::system_clock::now(),
.severity=severity,
.channel=channel,
.message=message
});
}
void Logger::addStream(std::ostream *stream, Severity severity) {
m_minLogLevel = m_minLogLevel > severity ? severity : m_minLogLevel;
m_outputStreams.push_back(std::pair<std::ostream*, Severity>(stream, severity));
}
void Logger::flush() {
while (!m_queue.IsEmpty()) {
LogEntry entry = m_queue.Pop();
std::stringstream sstream;
//TODO: Write the log time in a more elegant manner.
time_t timestamp = std::chrono::system_clock::to_time_t(entry.when);
char* time_buffer = ctime(&timestamp);
time_buffer[strlen(time_buffer) - 1] = '\0';
sstream << time_buffer << "\t";
switch (entry.severity) {
case Severity::DEBUG:
sstream << "DEBUG";
break;
case Severity::INFO:
sstream << "INFO ";
break;
case Severity::WARNING:
sstream << "WARN ";
break;
case Severity::ERROR:
sstream << "ERROR";
break;
case Severity::FATAL:
sstream << "FATAL";
break;
}
sstream << " [" << entry.channel << "]\t" << entry.message;
const std::string& result_log = sstream.str();
for (std::vector<std::pair<std::ostream*, Severity>>::const_iterator it = m_outputStreams.begin(); it != m_outputStreams.end(); ++it) {
if (entry.severity < it->second) {
// message severity isn't high enough for this logger.
continue;
}
std::ostream& current_stream = *(it->first);
// catch an exception in case we get a broken pipe or something...
try {
current_stream << result_log << std::endl;
} catch (...) {
// do nothing.
}
}
}
}
void Logger::worker(Logger *me) {
std::unique_lock<std::mutex> lk (me->m_runningMutex);
while (true) {
me->flush();
if (std::cv_status::no_timeout == me->m_runningCondition.wait_for(lk, std::chrono::seconds(5))) {
break;
}
}
}
}
}

83
src/logging.hpp Normal file
View file

@ -0,0 +1,83 @@
/*
* Copyright © 2012-2017 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 <string>
#include <ostream>
#include <thread>
#include <atomic>
#include <condition_variable>
#include "MessageQueue.hpp"
#define LOG(severity, channel, message) \
{\
std::stringstream __sstream; \
__sstream << message; \
UDPT::Logging::Logger::getLogger().log(severity, channel, __sstream.str()); \
}
#define LOG_INFO(channel, message) LOG(UDPT::Logging::Severity::INFO, channel, message)
#define LOG_DEBUG(channel, message) LOG(UDPT::Logging::Severity::DEBUG, channel, message)
#define LOG_WARN(channel, message) LOG(UDPT::Logging::Severity::WARNING, channel, message)
#define LOG_ERR(channel, message) LOG(UDPT::Logging::Severity::ERROR, channel, message)
#define LOG_FATAL(channel, message) LOG(UDPT::Logging::Severity::FATAL, channel, message)
namespace UDPT {
namespace Logging {
enum Severity {
UNSET = 0,
DEBUG = 10,
INFO = 20,
WARNING = 30,
ERROR = 40,
FATAL = 50
};
struct LogEntry {
const std::chrono::time_point<std::chrono::system_clock> when;
Severity severity;
const std::string channel;
const std::string message;
};
class Logger {
public:
static Logger& getLogger();
void log(Severity severity, const std::string& channel, const std::string& message);
void addStream(std::ostream *, Severity minSeverity=INFO);
private:
Logger();
virtual ~Logger();
static void worker(Logger*);
void flush();
std::vector<std::pair<std::ostream*, UDPT::Logging::Severity>> m_outputStreams;
UDPT::Utils::MessageQueue<struct LogEntry> m_queue;
std::thread m_workerThread;
std::atomic_bool m_cleaningUp;
std::mutex m_runningMutex;
std::condition_variable m_runningCondition;
Severity m_minLogLevel;
};
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2012-2016 Naim A.
* Copyright © 2012-2017 Naim A.
*
* This file is part of UDPT.
*
@ -25,8 +25,6 @@
#include <memory>
#include <algorithm>
#include <boost/program_options.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/sources/severity_channel_logger.hpp>
#include "multiplatform.h"
#include "udpTracker.hpp"
@ -34,16 +32,20 @@
#include "http/webapp.hpp"
#include "tracker.hpp"
#include "service.hpp"
#include "logging.hpp"
static void _signal_handler(int sig)
{
switch (sig)
extern "C" void _signal_handler(int sig)
{
switch (sig) {
case SIGTERM:
case SIGQUIT:
case SIGINT: {
LOG_INFO("core", "Received signal " << sig << ", requesting to stop tracker");
UDPT::Tracker::getInstance().stop();
break;
}
}
}
#ifdef linux
static void daemonize(const boost::program_options::variables_map& conf)
@ -74,7 +76,11 @@ void _close_wsa()
}
#endif
#ifdef TEST
int real_main(int argc, char *argv[])
#else
int main(int argc, char *argv[])
#endif
{
#ifdef WIN32
WSADATA wsadata;
@ -145,15 +151,13 @@ int main(int argc, char *argv[])
}
}
boost::log::sources::severity_channel_logger_mt<> logger(boost::log::keywords::channel = "main");
Tracker::setupLogging(var_map, logger);
#ifdef linux
if (!var_map.count("interactive"))
{
daemonize(var_map);
}
::signal(SIGTERM, _signal_handler);
::signal(SIGINT, _signal_handler);
#endif
#ifdef WIN32
UDPT::Service svc(var_map);
@ -220,9 +224,11 @@ int main(int argc, char *argv[])
}
catch (const UDPT::UDPTException& ex)
{
BOOST_LOG_SEV(logger, boost::log::trivial::fatal) << "UDPT exception: (" << ex.getErrorCode() << "): " << ex.what();
std::cerr << "UDPT exception: (" << ex.getErrorCode() << "): " << ex.what();
return -1;
}
LOG_INFO("core", "UDPT terminated.");
return 0;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2012-2016 Naim A.
* Copyright © 2012-2017 Naim A.
*
* This file is part of UDPT.
*

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2012-2016 Naim A.
* Copyright © 2012-2017 Naim A.
*
* This file is part of UDPT.
*

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2012-2016 Naim A.
* Copyright © 2012-2017 Naim A.
*
* This file is part of UDPT.
*

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2012-2016 Naim A.
* Copyright © 2012-2017 Naim A.
*
* This file is part of UDPT.
*

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2012-2016 Naim A.
* Copyright © 2012-2017 Naim A.
*
* This file is part of UDPT.
*

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2012-2016 Naim A.
* Copyright © 2012-2017 Naim A.
*
* This file is part of UDPT.
*
@ -16,52 +16,60 @@
* You should have received a copy of the GNU General Public License
* along with UDPT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <fstream>
#include "tracker.hpp"
#include "logging.hpp"
namespace UDPT
{
Tracker::Tracker() : m_logger(boost::log::keywords::channel = "TRACKER")
Tracker::Tracker() : m_logStream(nullptr)
{
BOOST_LOG_SEV(m_logger, boost::log::trivial::debug) << "Initialized Tracker";
}
Tracker::~Tracker()
{
BOOST_LOG_SEV(m_logger, boost::log::trivial::debug) << "Destroying Tracker...";
try {
if (nullptr != m_logStream) {
m_logStream->flush();
delete m_logStream;
m_logStream = nullptr;
}
} catch (...) {
}
}
void Tracker::stop()
{
BOOST_LOG_SEV(m_logger, boost::log::trivial::info) << "Requesting Tracker to terminate.";
LOG_INFO("tracker", "Requesting components to terminate...");
m_udpTracker->stop();
wait();
// cause other components to destruct.
m_apiSrv = nullptr;
m_webApp = nullptr;
m_udpTracker = nullptr;
}
void Tracker::wait()
{
m_udpTracker->wait();
BOOST_LOG_SEV(m_logger, boost::log::trivial::info) << "Tracker terminated.";
}
void Tracker::start(const boost::program_options::variables_map& conf)
{
BOOST_LOG_SEV(m_logger, boost::log::trivial::debug) << "Starting Tracker...";
setupLogging(conf);
LOG_INFO("core", "Initializing...");
m_udpTracker = std::shared_ptr<UDPTracker>(new UDPTracker(conf));
if (conf["apiserver.enable"].as<bool>())
{
BOOST_LOG_SEV(m_logger, boost::log::trivial::info) << "Initializing and deploying WebAPI...";
m_apiSrv = std::shared_ptr<UDPT::Server::HTTPServer>(new UDPT::Server::HTTPServer(conf));
m_webApp = std::shared_ptr<UDPT::Server::WebApp>(new UDPT::Server::WebApp(m_apiSrv, m_udpTracker->m_conn.get(), conf));
m_webApp->deploy();
}
m_udpTracker->start();
BOOST_LOG_SEV(m_logger, boost::log::trivial::info) << "Tracker started.";
}
Tracker& Tracker::getInstance()
@ -91,7 +99,7 @@ namespace UDPT
("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("/var/log/udpt.log"), "file to write logs to")
("logging.level", boost::program_options::value<std::string>()->default_value("warning"), "log level (fatal/error/warning/info/debug/trace)")
("logging.level", boost::program_options::value<std::string>()->default_value("warning"), "log level (fatal/error/warning/info/debug)")
#ifdef linux
("daemon.chdir", boost::program_options::value<std::string>()->default_value("/"), "home directory for daemon")
@ -104,42 +112,40 @@ namespace UDPT
return configOptions;
}
void Tracker::setupLogging(const boost::program_options::variables_map& config, boost::log::sources::severity_channel_logger_mt<>& logger)
{
boost::log::add_common_attributes();
boost::shared_ptr<boost::log::sinks::text_file_backend> logBackend = boost::make_shared<boost::log::sinks::text_file_backend>(
boost::log::keywords::file_name = config["logging.filename"].as<std::string>(),
boost::log::keywords::auto_flush = true,
boost::log::keywords::open_mode = std::ios::out | std::ios::app
);
typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::text_file_backend> udptSink_t;
boost::shared_ptr<udptSink_t> async_sink(new udptSink_t(logBackend));
async_sink->set_formatter(
boost::log::expressions::stream
<< boost::log::expressions::format_date_time<boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d %H:%M:%S") << " "
<< boost::log::expressions::attr<int>("Severity")
<< " [" << boost::log::expressions::attr<std::string>("Channel") << "] \t"
<< boost::log::expressions::smessage
);
auto loggingCore = boost::log::core::get();
loggingCore->add_sink(async_sink);
void Tracker::setupLogging(const boost::program_options::variables_map& va_map) {
Logging::Logger& logger = Logging::Logger::getLogger();
std::string severity = config["logging.level"].as<std::string>();
std::transform(severity.begin(), severity.end(), severity.begin(), ::tolower);
int severityVal = boost::log::trivial::warning;
if ("fatal" == severity) severityVal = boost::log::trivial::fatal;
else if ("error" == severity) severityVal = boost::log::trivial::error;
else if ("warning" == severity) severityVal = boost::log::trivial::warning;
else if ("info" == severity) severityVal = boost::log::trivial::info;
else if ("debug" == severity) severityVal = boost::log::trivial::debug;
else if ("trace" == severity) severityVal = boost::log::trivial::trace;
else
{
BOOST_LOG_SEV(logger, boost::log::trivial::warning) << "Unknown debug level \"" << severity << "\" defaulting to warning";
logger.addStream(&std::cerr, Logging::Severity::FATAL);
Logging::Severity severity;
std::string severity_text = va_map["logging.level"].as<std::string>();
std::transform(severity_text.begin(), severity_text.end(), severity_text.begin(), ::tolower);
if (severity_text == "fatal") {
severity = Logging::Severity::FATAL;
} else if (severity_text == "error") {
severity = Logging::Severity::ERROR;
} else if (severity_text == "warning") {
severity = Logging::Severity::WARNING;
} else if (severity_text == "info") {
severity = Logging::Severity::INFO;
} else if (severity_text == "debug") {
severity = Logging::Severity::DEBUG;
} else {
severity = Logging::Severity::UNSET;
}
loggingCore->set_filter(
boost::log::trivial::severity >= severityVal
);
const std::string& logFileName = va_map["logging.filename"].as<std::string>();
Logging::Severity real_severity = (severity == Logging::Severity::UNSET ? Logging::Severity::INFO : severity);
if (logFileName.length() == 0 || logFileName == "--") {
logger.addStream(&std::cerr, real_severity);
} else {
m_logStream = new ofstream(logFileName, std::ios::app | std::ios::out);
logger.addStream(m_logStream, real_severity);
}
if (severity != real_severity) {
LOG_WARN("core", "'" << severity_text << "' is invalid, log level set to " << real_severity);
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2012-2016 Naim A.
* Copyright © 2012-2017 Naim A.
*
* This file is part of UDPT.
*
@ -21,16 +21,7 @@
#include <memory>
#include <boost/program_options.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/sources/severity_channel_logger.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/sinks/async_frontend.hpp>
#include <boost/log/keywords/format.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include "multiplatform.h"
#include "udpTracker.hpp"
@ -55,14 +46,14 @@ namespace UDPT
static boost::program_options::options_description getConfigOptions();
static void setupLogging(const boost::program_options::variables_map& config, boost::log::sources::severity_channel_logger_mt<>& logger);
private:
std::shared_ptr<UDPT::UDPTracker> m_udpTracker;
std::shared_ptr<UDPT::Server::HTTPServer> m_apiSrv;
std::shared_ptr<UDPT::Server::WebApp> m_webApp;
boost::log::sources::severity_channel_logger_mt<> m_logger;
Tracker();
void setupLogging(const boost::program_options::variables_map& va_map);
std::ostream *m_logStream;
};
}

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2012-2016 Naim A.
* Copyright © 2012-2017 Naim A.
*
* This file is part of UDPT.
*
@ -18,6 +18,7 @@
*/
#include "udpTracker.hpp"
#include "logging.hpp"
using namespace UDPT::Data;
@ -26,8 +27,7 @@ using namespace UDPT::Data;
namespace UDPT
{
UDPTracker::UDPTracker(const boost::program_options::variables_map& conf) : m_conf(conf), m_logger(boost::log::keywords::channel = "UDPTracker")
{
UDPTracker::UDPTracker(const boost::program_options::variables_map& conf) : m_conf(conf) {
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>();
@ -37,28 +37,17 @@ namespace UDPT
this->m_port = conf["tracker.port"].as<unsigned short>();
this->m_threadCount = conf["tracker.threads"].as<unsigned>() + 1;
std::list<SOCKADDR_IN> addrs;
if (addrs.empty())
{
SOCKADDR_IN sa;
sa.sin_port = m_hton16(m_port);
sa.sin_addr.s_addr = 0L;
addrs.push_back(sa);
}
this->m_localEndpoint = addrs.front();
this->m_localEndpoint.sin_family = AF_INET;
this->m_localEndpoint.sin_port = m_hton16(m_port);
this->m_localEndpoint.sin_addr.s_addr = 0L;
this->m_conn = std::shared_ptr<DatabaseDriver>(new Data::SQLite3Driver(m_conf, this->m_isDynamic));
}
UDPTracker::~UDPTracker()
{
stop();
UDPTracker::~UDPTracker() {
}
void UDPTracker::start()
{
void UDPTracker::start() {
SOCKET sock;
int r, // saves results
i, // loop index
@ -68,6 +57,7 @@ namespace UDPT
sock = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == INVALID_SOCKET)
{
LOG_FATAL("udp-tracker", "Failed to create socket. error=" << errno);
throw UDPT::UDPTException("Failed to create socket");
}
@ -92,6 +82,8 @@ namespace UDPT
if (r == SOCKET_ERROR)
{
LOG_FATAL("udp-tracker", "Failed to bind socket. error=" << errno);
#ifdef WIN32
::closesocket(sock);
#elif defined (linux)
@ -100,52 +92,52 @@ namespace UDPT
throw UDPT::UDPTException("Failed to bind socket.");
}
{
char buff[INET_ADDRSTRLEN];
BOOST_LOG_SEV(m_logger, boost::log::trivial::info) << "UDP tracker bound on " << ::inet_ntop(AF_INET, reinterpret_cast<LPVOID>(&m_localEndpoint.sin_addr), buff, sizeof(buff)) << ":" << htons(m_localEndpoint.sin_port);
}
this->m_sock = sock;
LOG_INFO("udp-tracker", "Tracker bound to " << inet_ntoa(this->m_localEndpoint.sin_addr));
// create maintainer thread.
m_threads.push_back(std::thread(UDPTracker::_maintainance_start, this));
LOG_INFO("udp-tracker", "Started maintenance thread @" << m_threads.back().get_id());
m_threads.push_back(boost::thread(UDPTracker::_maintainance_start, this));
m_shouldRun = true;
for (i = 1;i < this->m_threadCount; i++)
{
m_threads.push_back(boost::thread(UDPTracker::_thread_start, this));
m_threads.push_back(std::thread(UDPTracker::_thread_start, this));
LOG_INFO("udp-tracker", "Started worker thread @" << m_threads.back().get_id());
}
}
void UDPTracker::stop()
void UDPTracker::stop() {
// tell workers to stop running...
m_shouldRun = false;
// stop maintenance thread's sleep...
m_maintenanceCondition.notify_one();
}
/**
* @brief blocks until all threads die.
* @note This method should be called only once, preferably by the main thread.
* **/
void UDPTracker::wait() {
LOG_INFO("udp-tracker", "Waiting for threads to terminate...");
for (std::vector<std::thread>::iterator it = m_threads.begin(); it != m_threads.end(); ++it)
{
it->join();
}
LOG_INFO("udp-tracker", "UDP Tracker terminated");
#ifdef linux
::close(m_sock);
#elif defined (WIN32)
::closesocket(m_sock);
#endif
BOOST_LOG_SEV(m_logger, boost::log::trivial::warning) << "Interrupting workers...";
for (std::vector<boost::thread>::iterator it = m_threads.begin(); it != m_threads.end(); ++it)
{
it->interrupt();
}
wait();
}
void UDPTracker::wait()
{
BOOST_LOG_SEV(m_logger, boost::log::trivial::warning) << "Waiting for threads to terminate...";
for (std::vector<boost::thread>::iterator it = m_threads.begin(); it != m_threads.end(); ++it)
{
it->join();
}
}
int UDPTracker::sendError(UDPTracker* usi, SOCKADDR_IN* remote, uint32_t transactionID, const std::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.
i; // copy loop
@ -169,11 +161,12 @@ namespace UDPT
::sendto(usi->m_sock, buff, msg_sz, 0, reinterpret_cast<SOCKADDR*>(remote), sizeof(*remote));
LOG_DEBUG("udp-tracker", "Error sent to " << inet_ntoa(remote->sin_addr) << ", '" << msg << "' (len=" << msg_sz << ")");
return 0;
}
int UDPTracker::handleConnection(UDPTracker *usi, SOCKADDR_IN *remote, char *data)
{
int UDPTracker::handleConnection(UDPTracker *usi, SOCKADDR_IN *remote, char *data) {
ConnectionRequest *req = reinterpret_cast<ConnectionRequest*>(data);
ConnectionResponse resp;
@ -189,17 +182,10 @@ namespace UDPT
::sendto(usi->m_sock, (char*)&resp, sizeof(ConnectionResponse), 0, (SOCKADDR*)remote, sizeof(SOCKADDR_IN));
{
char buffer[INET_ADDRSTRLEN];
BOOST_LOG_SEV(usi->m_logger, boost::log::trivial::debug) << "Connection Request from " << ::inet_ntop(AF_INET, &remote->sin_addr, buffer, sizeof(buffer)) << "; cId=" << resp.connection_id << "; tId=" << resp.transaction_id;
}
return 0;
}
int UDPTracker::handleAnnounce(UDPTracker *usi, SOCKADDR_IN *remote, char *data)
{
int UDPTracker::handleAnnounce(UDPTracker *usi, SOCKADDR_IN *remote, char *data) {
AnnounceRequest *req;
AnnounceResponse *resp;
int q, // peer counts
@ -303,6 +289,7 @@ namespace UDPT
}
}
::sendto(usi->m_sock, (char*)buff, bSize, 0, (SOCKADDR*)remote, sizeof(SOCKADDR_IN));
LOG_DEBUG("udp-tracker", "Announce request from " << inet_ntoa(remote->sin_addr) << " (event=" << event << "), Sent " << q << " peers");
// update DB.
uint32_t ip;
@ -316,8 +303,7 @@ 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 = reinterpret_cast<ScrapeRequest*>(data);
int v, // validation helper
c, // torrent counter
@ -339,6 +325,7 @@ namespace UDPT
m_hton32(remote->sin_addr.s_addr),
m_hton16(remote->sin_port)))
{
LOG_DEBUG("udp-tracker", "Bad connection id from " << inet_ntoa(remote->sin_addr));
return 1;
}
@ -376,20 +363,19 @@ namespace UDPT
}
::sendto(usi->m_sock, reinterpret_cast<const char*>(buffer), sizeof(buffer), 0, reinterpret_cast<SOCKADDR*>(remote), sizeof(SOCKADDR_IN));
LOG_DEBUG("udp-tracker", "Scrape request from " << inet_ntoa(remote->sin_addr) << ", Sent " << c << " torrents");
return 0;
}
int UDPTracker::isIANAIP(uint32_t ip)
{
int UDPTracker::isIANAIP(uint32_t ip) {
uint8_t x = (ip % 256);
if (x == 0 || x == 10 || x == 127 || x >= 224)
return 1;
return 0;
}
int UDPTracker::resolveRequest(UDPTracker *usi, SOCKADDR_IN *remote, char *data, int r)
{
int UDPTracker::resolveRequest(UDPTracker *usi, SOCKADDR_IN *remote, char *data, int r) {
ConnectionRequest* cR = reinterpret_cast<ConnectionRequest*>(data);
uint32_t action;
@ -399,18 +385,11 @@ namespace UDPT
{
if (isIANAIP(remote->sin_addr.s_addr))
{
char buffer[INET_ADDRSTRLEN];
BOOST_LOG_SEV(usi->m_logger, boost::log::trivial::warning) << "Client ignored (IANA IP): " << ::inet_ntop(AF_INET, &remote->sin_addr, buffer, sizeof(buffer));
LOG_DEBUG("udp-tracker", "Request from IANA reserved IP rejected (" << inet_ntoa(remote->sin_addr) << ")");
return 0; // Access Denied: IANA reserved IP.
}
}
{
char buffer[INET_ADDRSTRLEN];
BOOST_LOG_SEV(usi->m_logger, boost::log::trivial::debug) << "Client request from " << ::inet_ntop(AF_INET, &remote->sin_addr, buffer, sizeof(buffer));
}
if (action == 0 && r >= 16)
return UDPTracker::handleConnection(usi, remote, data);
else if (action == 1 && r >= 98)
@ -422,13 +401,9 @@ namespace UDPT
UDPTracker::sendError(usi, remote, cR->transaction_id, "Tracker couldn't understand Client's request.");
return -1;
}
return 0;
}
void UDPTracker::_thread_start(UDPTracker *usi)
{
BOOST_LOG_SEV(usi->m_logger, boost::log::trivial::info) << "Worker thread started with PID=" << boost::this_thread::get_id() << ".";
void UDPTracker::_thread_start(UDPTracker *usi) {
SOCKADDR_IN remoteAddr;
char tmpBuff[UDP_BUFFER_SIZE];
@ -440,38 +415,36 @@ namespace UDPT
addrSz = sizeof(SOCKADDR_IN);
while (true)
while (usi->m_shouldRun)
{
// peek into the first 12 bytes of data; determine if connection request or announce request.
int r = ::recvfrom(usi->m_sock, (char*)tmpBuff, UDP_BUFFER_SIZE, 0, (SOCKADDR*)&remoteAddr, &addrSz);
if (r <= 0)
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
std::this_thread::yield();
continue;
}
{
boost::this_thread::disable_interruption di;
UDPTracker::resolveRequest(usi, &remoteAddr, tmpBuff, r);
}
}
LOG_INFO("udp-tracker", "worker " << std::this_thread::get_id() << " exited.");
}
void UDPTracker::_maintainance_start(UDPTracker* usi)
{
BOOST_LOG_SEV(usi->m_logger, boost::log::trivial::info) << "Maintenance thread started with PID=" << boost::this_thread::get_id() << ".";
void UDPTracker::_maintainance_start(UDPTracker* usi) {
std::unique_lock<std::mutex> lk (usi->m_maintenanceMutex);
while (true)
{
{
boost::this_thread::disable_interruption di;
BOOST_LOG_SEV(usi->m_logger, boost::log::trivial::info) << "Running cleanup...";
if (std::cv_status::no_timeout == usi->m_maintenanceCondition.wait_for(lk, std::chrono::seconds(usi->m_cleanupInterval))) {
break;
}
LOG_INFO("udp-tracker", "Maintenance running...");
usi->m_conn->cleanup();
}
boost::this_thread::sleep_for(boost::chrono::seconds(usi->m_cleanupInterval));
lk.unlock();
LOG_INFO("udp-tracker", "Maintenance thread " << std::this_thread::get_id() << " existed.");
}
}
};

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2012-2016 Naim A.
* Copyright © 2012-2017 Naim A.
*
* This file is part of UDPT.
*
@ -29,10 +29,10 @@
#include <list>
#include <ctime>
#include <boost/thread.hpp>
#include <thread>
#include <boost/program_options.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/sources/severity_channel_logger.hpp>
#include <mutex>
#include <condition_variable>
#include "tools.h"
#include "exceptions.h"
@ -160,10 +160,13 @@ namespace UDPT
bool m_isDynamic;
bool m_allowRemotes;
bool m_allowIANA_IPs;
std::vector<boost::thread> m_threads;
std::vector<std::thread> m_threads;
uint32_t m_announceInterval;
uint32_t m_cleanupInterval;
boost::log::sources::severity_channel_logger_mt<> m_logger;
std::atomic_bool m_shouldRun;
std::mutex m_maintenanceMutex;
std::condition_variable m_maintenanceCondition;
const boost::program_options::variables_map& m_conf;

55
tests/main.cpp Normal file
View file

@ -0,0 +1,55 @@
#include <gtest/gtest.h>
#include "../src/tools.h"
#include "../src/db/driver_sqlite.hpp"
TEST(Utility, SanityCheck) {
const uint32_t MAGIC = 0xDEADBEEF;
const unsigned char MAGIC_BYTES[4] = {0xEF, 0xBE, 0xAD, 0xDE};
ASSERT_TRUE(memcmp(&MAGIC, MAGIC_BYTES, 4) == 0);
}
TEST(Utility, CheckMTON) {
EXPECT_EQ(m_hton16(0xDEAD), 0xADDE);
EXPECT_EQ(m_hton32(0xDEADBEEF), 0xEFBEADDE);
EXPECT_EQ(m_hton64(0xDEADBEEFA1B2C3E4), 0xE4C3B2A1EFBEADDE);
}
TEST(Utility, HashToHexStr) {
const char EXPECTED_OUTPUT[] = "c670606edd22fd0e3b432c977559a687cc5d9bd2";
const unsigned char DATA[20] = {198, 112, 96, 110, 221, 34, 253, 14, 59, 67, 44, 151, 117, 89, 166, 135, 204, 93, 155, 210};
char OUTPUT_BUFFER[41] = {0};
to_hex_str(DATA, OUTPUT_BUFFER);
ASSERT_EQ(std::string(EXPECTED_OUTPUT), OUTPUT_BUFFER);
}
class SQLiteDriverTest:
public ::testing::Test {
protected:
SQLiteDriverTest(): va_map(), driver(nullptr) {
va_map.insert(std::pair<std::string, boost::program_options::variable_value>("db.param", boost::program_options::variable_value(std::string(":memory:"), true)));
}
virtual void SetUp() {
if (nullptr == driver) {
driver = new UDPT::Data::SQLite3Driver(va_map, false);
}
}
virtual void TearDown() {
if (nullptr != driver) {
delete driver;
driver = nullptr;
}
}
UDPT::Data::SQLite3Driver *driver;
boost::program_options::variables_map va_map;
};
int main(int argc, char *argv[]) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View file

@ -1,22 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UDPT", "UDPT\UDPT.vcxproj", "{9F399AF8-861E-4E50-A94C-1388089E3FA0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9F399AF8-861E-4E50-A94C-1388089E3FA0}.Debug|Win32.ActiveCfg = Debug|Win32
{9F399AF8-861E-4E50-A94C-1388089E3FA0}.Debug|Win32.Build.0 = Debug|Win32
{9F399AF8-861E-4E50-A94C-1388089E3FA0}.Release|Win32.ActiveCfg = Release|Win32
{9F399AF8-861E-4E50-A94C-1388089E3FA0}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -1,111 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9F399AF8-861E-4E50-A94C-1388089E3FA0}</ProjectGuid>
<RootNamespace>UDPT</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);D:\libs\sqlite3;D:\libs\boost\boost_1_59_0</IncludePath>
<LibraryPath>D:\libs\boost\boost_1_59_0\stage\lib;D:\libs\sqlite3\Release;$(LibraryPath)</LibraryPath>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);D:\libs\sqlite3;D:\libs\boost\boost_1_59_0</IncludePath>
<LibraryPath>D:\libs\boost\boost_1_59_0\stage\lib;D:\libs\sqlite3\Release;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<ExceptionHandling>Async</ExceptionHandling>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;sqlite3.lib;advapi32.lib;shell32.lib</AdditionalDependencies>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<ExceptionHandling>Async</ExceptionHandling>
</ClCompile>
<Link>
<EnableCOMDATFolding>
</EnableCOMDATFolding>
<OptimizeReferences>
</OptimizeReferences>
<AdditionalDependencies>ws2_32.lib;sqlite3.lib;advapi32.lib;shell32.lib</AdditionalDependencies>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\db\database.cpp" />
<ClCompile Include="..\..\src\db\driver_sqlite.cpp" />
<ClCompile Include="..\..\src\http\httpserver.cpp" />
<ClCompile Include="..\..\src\http\webapp.cpp" />
<ClCompile Include="..\..\src\main.cpp" />
<ClCompile Include="..\..\src\service.cpp" />
<ClCompile Include="..\..\src\tools.c" />
<ClCompile Include="..\..\src\tracker.cpp" />
<ClCompile Include="..\..\src\udpTracker.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\db\database.hpp" />
<ClInclude Include="..\..\src\db\driver_sqlite.hpp" />
<ClInclude Include="..\..\src\exceptions.h" />
<ClInclude Include="..\..\src\http\httpserver.hpp" />
<ClInclude Include="..\..\src\http\webapp.hpp" />
<ClInclude Include="..\..\src\multiplatform.h" />
<ClInclude Include="..\..\src\service.hpp" />
<ClInclude Include="..\..\src\tools.h" />
<ClInclude Include="..\..\src\tracker.hpp" />
<ClInclude Include="..\..\src\udpTracker.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -1,90 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Header Files\db">
<UniqueIdentifier>{f5a85f67-2777-4fa5-828e-9c79af9f4b13}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\db">
<UniqueIdentifier>{643f664e-8751-4440-8b90-fe95b15e0aac}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\http">
<UniqueIdentifier>{bcb1fa9f-c9ec-4398-97f9-544baf69f2a9}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\http">
<UniqueIdentifier>{f65a2e69-6a71-4cd0-ad64-36a73c6c94c4}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\tools.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\udpTracker.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\db\database.cpp">
<Filter>Source Files\db</Filter>
</ClCompile>
<ClCompile Include="..\..\src\db\driver_sqlite.cpp">
<Filter>Source Files\db</Filter>
</ClCompile>
<ClCompile Include="..\..\src\http\httpserver.cpp">
<Filter>Source Files\http</Filter>
</ClCompile>
<ClCompile Include="..\..\src\http\webapp.cpp">
<Filter>Source Files\http</Filter>
</ClCompile>
<ClCompile Include="..\..\src\tracker.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\service.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\multiplatform.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\tools.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\udpTracker.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\db\database.hpp">
<Filter>Header Files\db</Filter>
</ClInclude>
<ClInclude Include="..\..\src\db\driver_sqlite.hpp">
<Filter>Header Files\db</Filter>
</ClInclude>
<ClInclude Include="..\..\src\http\httpserver.hpp">
<Filter>Header Files\http</Filter>
</ClInclude>
<ClInclude Include="..\..\src\http\webapp.hpp">
<Filter>Header Files\http</Filter>
</ClInclude>
<ClInclude Include="..\..\src\exceptions.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\tracker.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\service.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>