diff --git a/Daemon.cpp b/Daemon.cpp index f6c0668b..c587bfa9 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -2,6 +2,8 @@ #define _CRT_SECURE_NO_WARNINGS // to use freopen #endif +#include + #include "Daemon.h" #include "Log.h" @@ -15,15 +17,42 @@ #include "Garlic.h" #include "util.h" #include "Streaming.h" +#include "HTTPServer.h" +#include "HTTPProxy.h" namespace i2p { namespace util { - bool Daemon_Singleton::start() + class Daemon_Singleton::Daemon_Singleton_Private { + public: + Daemon_Singleton_Private() : httpServer(nullptr), httpProxy(nullptr) { }; + ~Daemon_Singleton_Private() { + delete httpServer; + delete httpProxy; + }; + + i2p::util::HTTPServer *httpServer; + i2p::proxy::HTTPProxy *httpProxy; + }; + + Daemon_Singleton::Daemon_Singleton() : d(*new Daemon_Singleton_Private()), running(1) {}; + Daemon_Singleton::~Daemon_Singleton() { + delete &d; + }; + + + bool Daemon_Singleton::init(int argc, char* argv[]) + { + i2p::util::config::OptionParser(argc, argv); + + LogPrint("\n\n\n\ni2pd starting\n"); + LogPrint("data directory: ", i2p::util::filesystem::GetDataDir().string()); + i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs); + isDaemon = i2p::util::config::GetArg("-daemon", 0); - isLogging = i2p::util::config::GetArg("-log", 0); + isLogging = i2p::util::config::GetArg("-log", 1); //TODO: This is an ugly workaround. fix it. //TODO: Autodetect public IP. @@ -32,27 +61,51 @@ namespace i2p if (isLogging == 1) { - std::string logfile = i2p::util::filesystem::GetDataDir().string(); + std::string logfile_path = i2p::util::filesystem::GetDataDir().string(); #ifndef _WIN32 - logfile.append("/debug.log"); + logfile_path.append("/debug.log"); #else - logfile.append("\\debug.log"); + logfile_path.append("\\debug.log"); #endif - freopen(logfile.c_str(), "a", stdout); + logfile.open(logfile_path, std::ofstream::out | std::ofstream::binary | std::ofstream::trunc); + //logfile = freopen(logfile_path.c_str(), "a", stdout); + if (!logfile.is_open()) + { + exit(-17); + } + + //std::streambuf * old = std::cout.rdbuf(logfile.rdbuf()); + LogPrint("Logging to file enabled."); - } - httpServer = new i2p::util::HTTPServer(i2p::util::config::GetArg("-httpport", 7070)); - httpServer->Start(); + LogPrint("CMD parameters:"); + for (int i = 0; i < argc; ++i) + LogPrint(i, " ", argv[i]); + + } + return true; + } + + bool Daemon_Singleton::start() + { + d.httpServer = new i2p::util::HTTPServer(i2p::util::config::GetArg("-httpport", 7070)); + d.httpServer->Start(); + LogPrint("HTTPServer started", EVENTLOG_INFORMATION_TYPE); i2p::data::netdb.Start(); + LogPrint("NetDB started", EVENTLOG_INFORMATION_TYPE); i2p::transports.Start(); + LogPrint("Transports started", EVENTLOG_INFORMATION_TYPE); i2p::tunnel::tunnels.Start(); + LogPrint("Tunnels started", EVENTLOG_INFORMATION_TYPE); i2p::garlic::routing.Start(); + LogPrint("Routing started", EVENTLOG_INFORMATION_TYPE); i2p::stream::StartStreaming(); + LogPrint("Streaming started", EVENTLOG_INFORMATION_TYPE); - httpProxy = new i2p::proxy::HTTPProxy(i2p::util::config::GetArg("-httpproxyport", 4446)); - httpProxy->Start(); + d.httpProxy = new i2p::proxy::HTTPProxy(i2p::util::config::GetArg("-httpproxyport", 4446)); + d.httpProxy->Start(); + LogPrint("Proxy started", EVENTLOG_INFORMATION_TYPE); return true; } @@ -61,16 +114,23 @@ namespace i2p { LogPrint("Shutdown started."); - httpProxy->Stop(); + d.httpProxy->Stop(); + LogPrint("HTTPProxy stoped", EVENTLOG_INFORMATION_TYPE); i2p::stream::StopStreaming(); + LogPrint("Streaming stoped", EVENTLOG_INFORMATION_TYPE); i2p::garlic::routing.Stop(); + LogPrint("Routing stoped", EVENTLOG_INFORMATION_TYPE); i2p::tunnel::tunnels.Stop(); + LogPrint("Tunnels stoped", EVENTLOG_INFORMATION_TYPE); i2p::transports.Stop(); + LogPrint("Transports stoped", EVENTLOG_INFORMATION_TYPE); i2p::data::netdb.Stop(); - httpServer->Stop(); + LogPrint("NetDB stoped", EVENTLOG_INFORMATION_TYPE); + d.httpServer->Stop(); + LogPrint("HTTPServer stoped", EVENTLOG_INFORMATION_TYPE); - delete httpProxy; httpProxy = NULL; - delete httpServer; httpServer = NULL; + delete d.httpProxy; d.httpProxy = nullptr; + delete d.httpServer; d.httpServer = nullptr; if (isLogging == 1) { diff --git a/Daemon.h b/Daemon.h index 9ac00a48..4e27d108 100644 --- a/Daemon.h +++ b/Daemon.h @@ -1,15 +1,21 @@ #pragma once +#include -#include "HTTPServer.h" -#include "HTTPProxy.h" +#ifdef _WIN32 +#define Daemon i2p::util::DaemonWin32::Instance() +#else +#define Daemon i2p::util::DaemonLinux::Instance() +#endif namespace i2p { namespace util { + class Daemon_Singleton_Private; class Daemon_Singleton { public: + virtual bool init(int argc, char* argv[]); virtual bool start(); virtual bool stop(); @@ -18,20 +24,18 @@ namespace i2p int running; - private: - i2p::util::HTTPServer *httpServer; - i2p::proxy::HTTPProxy *httpProxy; + std::ofstream logfile; protected: - Daemon_Singleton() : running(1) {}; - virtual ~Daemon_Singleton() { - delete httpServer; - delete httpProxy; - }; + Daemon_Singleton(); + virtual ~Daemon_Singleton(); + + // d-pointer for httpServer, httpProxy, etc. + class Daemon_Singleton_Private; + Daemon_Singleton_Private &d; }; #ifdef _WIN32 - #define Daemon i2p::util::DaemonWin32::Instance() class DaemonWin32 : public Daemon_Singleton { public: @@ -41,11 +45,11 @@ namespace i2p return instance; } + virtual bool init(int argc, char* argv[]); virtual bool start(); virtual bool stop(); }; #else - #define Daemon i2p::util::DaemonLinux::Instance() class DaemonLinux : public Daemon_Singleton { public: diff --git a/DaemonWin32.cpp b/DaemonWin32.cpp index f27ba9c7..96b28076 100644 --- a/DaemonWin32.cpp +++ b/DaemonWin32.cpp @@ -1,22 +1,74 @@ #include "Daemon.h" +#include "util.h" +#include "Log.h" #ifdef _WIN32 #include "./Win32/Win32Service.h" - namespace i2p { namespace util { - bool DaemonWin32::start() + bool DaemonWin32::init(int argc, char* argv[]) { setlocale(LC_CTYPE, ""); SetConsoleCP(1251); SetConsoleOutputCP(1251); setlocale(LC_ALL, "Russian"); - service_control(isDaemon); + if (!Daemon_Singleton::init(argc, argv)) return false; + if (I2PService::isService()) + isDaemon = 1; + else + isDaemon = 0; + + std::string serviceControl = i2p::util::config::GetArg("-service", "none"); + if (serviceControl == "install") + { + InstallService( + SERVICE_NAME, // Name of service + SERVICE_DISPLAY_NAME, // Name to display + SERVICE_START_TYPE, // Service start type + SERVICE_DEPENDENCIES, // Dependencies + SERVICE_ACCOUNT, // Service running account + SERVICE_PASSWORD // Password of the account + ); + exit(0); + } + else if (serviceControl == "remove") + { + UninstallService(SERVICE_NAME); + exit(0); + } + else if (serviceControl != "none") + { + printf(" --service=install to install the service.\n"); + printf(" --service=remove to remove the service.\n"); + } + + if (isDaemon == 1) + { + LogPrint("Service session"); + I2PService service(SERVICE_NAME); + if (!I2PService::Run(service)) + { + LogPrint("Service failed to run w/err 0x%08lx\n", GetLastError()); + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); + } + else + LogPrint("User session"); + + return true; + } + bool DaemonWin32::start() + { + setlocale(LC_CTYPE, ""); + SetConsoleCP(1251); + SetConsoleOutputCP(1251); + setlocale(LC_ALL, "Russian"); return Daemon_Singleton::start(); }