Skip to content
This repository has been archived by the owner on Sep 1, 2022. It is now read-only.

App/Client/Core: lib + instance work for prelim API #742

Merged
merged 12 commits into from
Nov 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ include_directories("../")

set(APP_SRC
"main.cc"
"config.cc"
"daemon.cc"
"instance.cc")
"daemon.cc")

# Linux/OSX/BSD/DragonFly
if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows")
Expand Down
168 changes: 77 additions & 91 deletions src/app/daemon.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,123 +32,109 @@

#include "app/daemon.h"

#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/ptree.hpp>

#include <thread>
#include <exception>
#include <memory>
#include <vector>

#include "client/context.h"

#include "core/router/net_db/impl.h"
#include "core/router/transports/impl.h"
#include "core/router/tunnel/impl.h"

namespace kovri {
namespace app {
#include "client/instance.h"

namespace kovri
{
namespace app
{
DaemonSingleton::DaemonSingleton()
: m_IsDaemon(false),
m_IsRunning(true),
m_Instance(nullptr) {}
: m_Exception(__func__), m_IsDaemon(false), m_IsRunning(true)
{
}

DaemonSingleton::~DaemonSingleton() {}

bool DaemonSingleton::Config(
const std::vector<std::string>& args) {
// TODO(unassigned): ideally, all instance configuration, etc., happens outside of singleton
m_Instance = std::make_unique<Instance>(args);
try {
m_Instance->Configure();
} catch (const std::exception& ex) {
LOG(error) << "DaemonSingleton: " << ex.what();
return false;
} catch (...) {
LOG(error) << "DaemonSingleton: unknown exception when configuring";
return false;
}
// Set daemon mode (if applicable)
m_IsDaemon = m_Instance->GetConfig().GetParsedKovriConfig().at("daemon").as<bool>();
// Note: we'd love Instance RAII but singleton needs to be daemonized (if applicable) before initialization

bool DaemonSingleton::Configure(const std::vector<std::string>& args)
{
try
{
// TODO(anonimal): we currently want to limit core interaction through client only for all apps and most API users.
// A member function getter can return the object which will (should) change mutable data via the core API.
// In essence, the core and client Instance objects are essentially a preliminary API.

// Create/configure core instance
auto core = std::make_unique<core::Instance>(args);

// Set daemon mode (if applicable)
m_IsDaemon = core->GetConfig().GetMap().at("daemon").as<bool>();
#ifdef _WIN32
m_Service = m_Instance->GetConfig().GetParsedKovriConfig().at("service").as<std::string>();
m_Service = core->GetConfig().GetMap().at("service").as<std::string>();
#endif
// Create/configure client instance
m_Client = std::make_unique<client::Instance>(std::move(core));
}
catch (...)
{
m_Exception.Dispatch(__func__);
return false;
}

LOG(info) << "DaemonSingleton: configured";
return true;
}

bool DaemonSingleton::Init() {
bool DaemonSingleton::Initialize()
{
// We must initialize contexts here (in child process, if in daemon mode)
try {
m_Instance->Initialize();
} catch (const std::exception& ex) {
LOG(error) << "DaemonSingleton: exception during initialization: " << ex.what();
// TODO(anonimal): Instance and RAII refactoring
Stop();
return false;
} catch (...) {
LOG(error) << "DaemonSingleton: unknown exception during initialization";
return false;
}
try
{
m_Client->Initialize();
}
catch (...)
{
m_Exception.Dispatch(__func__);
Stop();
return false;
}

LOG(info) << "DaemonSingleton: initialized";
return true;
}

// TODO(anonimal): when refactoring TODO's for singleton, have instance Start
bool DaemonSingleton::Start() {
try {
LOG(debug) << "DaemonSingleton: starting NetDb";
if (!kovri::core::netdb.Start()) {
LOG(error) << "DaemonSingleton: NetDb failed to start";
return false;
bool DaemonSingleton::Start()
{
try
{
m_Client->Start();
}
if (core::netdb.GetNumRouters() < core::NetDb::Size::MinRequiredRouters) {
LOG(debug) << "DaemonSingleton: reseeding NetDb";
kovri::client::Reseed reseed;
if (!reseed.Start()) {
LOG(error) << "DaemonSingleton: reseed failed";
return false;
}
catch (...)
{
m_Exception.Dispatch(__func__);
return false;
}
LOG(debug) << "DaemonSingleton: starting transports";
kovri::core::transports.Start();
LOG(debug) << "DaemonSingleton: starting tunnels";
kovri::core::tunnels.Start();
LOG(debug) << "DaemonSingleton: starting client";
kovri::client::context.Start();
} catch (const std::exception& ex) {
LOG(error) << "DaemonSingleton: start exception: " << ex.what();
return false;
} catch (...) {
LOG(error) << "DaemonSingleton: unknown exception when starting";
return false;
}

LOG(info) << "DaemonSingleton: successfully started";
return true;
}

void DaemonSingleton::Reload() {
void DaemonSingleton::Reload()
{
// TODO(unassigned): reload complete instance?
// TODO(unassigned): do we want to add locking?
LOG(info) << "DaemonSingleton: reloading configuration";
// Reload tunnels configuration
m_Instance->Reload();
// Reload client configuration
m_Client->Reload();
}

// TODO(anonimal): when refactoring TODO's for singleton, have instance Stop
bool DaemonSingleton::Stop() {
try {
LOG(debug) << "DaemonSingleton: stopping client";
kovri::client::context.Stop();
LOG(debug) << "DaemonSingleton: stopping tunnels";
kovri::core::tunnels.Stop();
LOG(debug) << "DaemonSingleton: stopping transports";
kovri::core::transports.Stop();
LOG(debug) << "DaemonSingleton: stopping NetDb";
kovri::core::netdb.Stop();
} catch (const std::exception& ex) {
LOG(error) << "DaemonSingleton: stop exception: " << ex.what();
return false;
} catch (...) {
LOG(error) << "DaemonSingleton: unknown exception when stopping";
return false;
}
bool DaemonSingleton::Stop()
{
try
{
m_Client->Stop();
}
catch (...)
{
m_Exception.Dispatch(__func__);
return false;
}

LOG(info) << "DaemonSingleton: successfully stopped";
LOG(info) << "Goodbye!";
return true;
Expand Down
56 changes: 31 additions & 25 deletions src/app/daemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,28 @@
#define Daemon kovri::app::DaemonLinux::Instance()
#endif

#include "app/instance.h"
#include "client/instance.h"

#include "core/instance.h"

#include "core/util/exception.h"
#include "core/util/filesystem.h"
#include "core/util/log.h"

namespace kovri {
namespace app {

class DaemonSingleton {
namespace kovri
{
namespace app
{
class DaemonSingleton
{
public:
/// @brief Get/Set configuration options before initialization/forking
/// @param args Reference to string vector of command line args
virtual bool Config(
const std::vector<std::string>& args);
virtual bool Configure(const std::vector<std::string>& args);

/// @brief Forks process if daemon mode is set, initializes contexts
/// @warning Child *must* fork *before* contexts are initialized
virtual bool Init();
virtual bool Initialize();

/// @brief Start client/router
virtual bool Start();
Expand All @@ -70,49 +74,51 @@ class DaemonSingleton {
/// @brief Reload tunnels
virtual void Reload();

bool m_IsDaemon, m_IsRunning;

#ifdef _WIN32
std::string m_Service;
#endif

/// @var m_Instance
/// @brief Unique pointer to instance object (client/router)
std::unique_ptr<Instance> m_Instance;
/// @brief Client instance
std::unique_ptr<client::Instance> m_Client;

/// @brief Exception dispatcher
core::Exception m_Exception;

bool m_IsDaemon, m_IsRunning;

protected:
DaemonSingleton();
virtual ~DaemonSingleton();
};

#ifdef _WIN32
class DaemonWin32 : public DaemonSingleton {
class DaemonWin32 : public DaemonSingleton
{
public:
static DaemonWin32& Instance() {
static DaemonWin32& Instance()
{
static DaemonWin32 instance;
return instance;
}
virtual bool Config(
const std::vector<std::string>& args);
virtual bool Configure(const std::vector<std::string>& args);
virtual bool Initialize();

virtual bool Init();
virtual bool Start();
virtual bool Stop();
};
#else
class DaemonLinux : public DaemonSingleton {
class DaemonLinux : public DaemonSingleton
{
public:
DaemonLinux() : m_PIDFileHandle()
DaemonLinux() : m_PIDFileHandle() {}
static DaemonLinux& Instance()
{
}
static DaemonLinux& Instance() {
static DaemonLinux instance;
return instance;
}
virtual bool Config(
const std::vector<std::string>& args);
virtual bool Configure(const std::vector<std::string>& args);
virtual bool Initialize();

virtual bool Init();
virtual bool Start();
virtual bool Stop();
void Reload();
Expand Down
8 changes: 4 additions & 4 deletions src/app/daemon_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@ void handle_signal(int sig) {
namespace kovri {
namespace app {

bool DaemonLinux::Config(
bool DaemonLinux::Configure(
const std::vector<std::string>& args) {
return DaemonSingleton::Config(args);
return DaemonSingleton::Configure(args);
}

bool DaemonLinux::Init() {
bool DaemonLinux::Initialize() {
m_PIDPath = kovri::core::GetDataPath().string();
m_PIDFile = (kovri::core::GetDataPath() / "kovri.pid").string();

Expand Down Expand Up @@ -155,7 +155,7 @@ bool DaemonLinux::Init() {
sigaction(SIGABRT, &sa, 0);
sigaction(SIGTERM, &sa, 0);
sigaction(SIGINT, &sa, 0);
return DaemonSingleton::Init();
return DaemonSingleton::Initialize();
}

bool DaemonLinux::Start() {
Expand Down
10 changes: 5 additions & 5 deletions src/app/daemon_win32.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

#include "daemon.h"

#include "app/config.h"
#include "client/util/config.h"

#include "core/util/log.h"

Expand All @@ -45,12 +45,12 @@
namespace kovri {
namespace app {

bool DaemonWin32::Config(
bool DaemonWin32::Configure(
const std::vector<std::string>& args) {
return DaemonSingleton::Config(args);
return DaemonSingleton::Configure(args);
}

bool DaemonWin32::Init() {
bool DaemonWin32::Initialize() {
// TODO(unassigned): use Boost.Locale
setlocale(LC_CTYPE, ""); // "" uses environment's default locale
SetConsoleCP(65001); // UTF-8
Expand Down Expand Up @@ -85,7 +85,7 @@ bool DaemonWin32::Init() {
} else {
LOG(info) << "DaemonWin32: user session";
}
return DaemonSingleton::Init();
return DaemonSingleton::Initialize();
}

bool DaemonWin32::Start() {
Expand Down
Loading