From 0b210ee99d9784cfd33d9db9a6a46c235b8f6559 Mon Sep 17 00:00:00 2001 From: chertov Date: Sun, 20 Apr 2014 05:54:34 +0400 Subject: [PATCH] Add simple Linux, Win32 daemons --- Daemon.cpp | 83 ++++++++++++++++ Daemon.h | 63 ++++++++++++ DaemonLinux.cpp | 109 +++++++++++++++++++++ DaemonWin32.cpp | 31 ++++++ Win32/i2pd.vcxproj | 4 + Win32/i2pd.vcxproj.filters | 12 +++ i2p.cpp | 196 +++---------------------------------- 7 files changed, 315 insertions(+), 183 deletions(-) create mode 100644 Daemon.cpp create mode 100644 Daemon.h create mode 100644 DaemonLinux.cpp create mode 100644 DaemonWin32.cpp diff --git a/Daemon.cpp b/Daemon.cpp new file mode 100644 index 00000000..f6c0668b --- /dev/null +++ b/Daemon.cpp @@ -0,0 +1,83 @@ +#ifdef _WIN32 +#define _CRT_SECURE_NO_WARNINGS // to use freopen +#endif + +#include "Daemon.h" + +#include "Log.h" +#include "base64.h" +#include "Transports.h" +#include "NTCPSession.h" +#include "RouterInfo.h" +#include "RouterContext.h" +#include "Tunnel.h" +#include "NetDb.h" +#include "Garlic.h" +#include "util.h" +#include "Streaming.h" + +namespace i2p +{ + namespace util + { + bool Daemon_Singleton::start() + { + isDaemon = i2p::util::config::GetArg("-daemon", 0); + isLogging = i2p::util::config::GetArg("-log", 0); + + //TODO: This is an ugly workaround. fix it. + //TODO: Autodetect public IP. + i2p::context.OverrideNTCPAddress(i2p::util::config::GetCharArg("-host", "127.0.0.1"), + i2p::util::config::GetArg("-port", 17070)); + + if (isLogging == 1) + { + std::string logfile = i2p::util::filesystem::GetDataDir().string(); +#ifndef _WIN32 + logfile.append("/debug.log"); +#else + logfile.append("\\debug.log"); +#endif + freopen(logfile.c_str(), "a", stdout); + LogPrint("Logging to file enabled."); + } + + httpServer = new i2p::util::HTTPServer(i2p::util::config::GetArg("-httpport", 7070)); + httpServer->Start(); + + i2p::data::netdb.Start(); + i2p::transports.Start(); + i2p::tunnel::tunnels.Start(); + i2p::garlic::routing.Start(); + i2p::stream::StartStreaming(); + + httpProxy = new i2p::proxy::HTTPProxy(i2p::util::config::GetArg("-httpproxyport", 4446)); + httpProxy->Start(); + + return true; + } + + bool Daemon_Singleton::stop() + { + LogPrint("Shutdown started."); + + httpProxy->Stop(); + i2p::stream::StopStreaming(); + i2p::garlic::routing.Stop(); + i2p::tunnel::tunnels.Stop(); + i2p::transports.Stop(); + i2p::data::netdb.Stop(); + httpServer->Stop(); + + delete httpProxy; httpProxy = NULL; + delete httpServer; httpServer = NULL; + + if (isLogging == 1) + { + fclose(stdout); + } + + return true; + } + } +} \ No newline at end of file diff --git a/Daemon.h b/Daemon.h new file mode 100644 index 00000000..d7fdc82a --- /dev/null +++ b/Daemon.h @@ -0,0 +1,63 @@ +#pragma once + +#include "HTTPServer.h" +#include "HTTPProxy.h" + +namespace i2p +{ + namespace util + { + class Daemon_Singleton + { + public: + virtual bool start(); + virtual bool stop(); + + int isLogging; + int isDaemon; + + int running = 1; + + private: + i2p::util::HTTPServer *httpServer; + i2p::proxy::HTTPProxy *httpProxy; + + protected: + Daemon_Singleton() : running(1) {}; + virtual ~Daemon_Singleton() { + delete httpServer; + delete httpProxy; + }; + }; + +#ifdef _WIN32 + #define Daemon i2p::util::DaemonWin32::Instance() + class DaemonWin32 : public Daemon_Singleton + { + public: + static DaemonWin32& Instance() + { + static DaemonWin32 instance; + return instance; + } + + virtual bool start(); + virtual bool stop(); + }; +#else + #define Daemon i2p::util::DaemonLinux::Instance() + class DaemonLinux : public Daemon_Singleton + { + public: + static DaemonLinux& Instance() + { + static DaemonLinux instance; + return instance; + } + + virtual bool start(); + virtual bool stop(); + }; +#endif + } +} \ No newline at end of file diff --git a/DaemonLinux.cpp b/DaemonLinux.cpp new file mode 100644 index 00000000..116e0ae6 --- /dev/null +++ b/DaemonLinux.cpp @@ -0,0 +1,109 @@ +#include "Daemon.h" + +#ifndef _WIN32 + +#include +#include +#include + +void handle_signal(int sig) +{ + switch (sig) + { + case SIGHUP: + if (i2p::util::config::GetArg("daemon", 0) == 1) + { + static bool first=true; + if (first) + { + first=false; + return; + } + } + LogPrint("Reloading config."); + i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs); + break; + case SIGABRT: + case SIGTERM: + case SIGINT: + running = 0; // Exit loop + break; + } +} + + +namespace i2p +{ + namespace util + { + bool DaemonLinux::start() + { + if (isDaemon == 1) + { + pid_t pid; + pid = fork(); + if (pid > 0) + { + g_Log.Stop(); + return 0; + } + if (pid < 0) + { + return -1; + } + + umask(0); + int sid = setsid(); + if (sid < 0) + { + LogPrint("Error, could not create process group."); + return -1; + } + chdir(i2p::util::filesystem::GetDataDir().string().c_str()); + } + + // Pidfile + std::string pidfile = i2p::util::filesystem::GetDataDir().string(); + pidfile.append("/i2pd.pid"); + int pidFilehandle = open(pidfile.c_str(), O_RDWR | O_CREAT, 0600); + if (pidFilehandle == -1) + { + LogPrint("Error, could not create pid file (", pidfile, ")\nIs an instance already running?"); + return -1; + } + if (lockf(pidFilehandle, F_TLOCK, 0) == -1) + { + LogPrint("Error, could not lock pid file (", pidfile, ")\nIs an instance already running?"); + return -1; + } + char pid[10]; + sprintf(pid, "%d\n", getpid()); + write(pidFilehandle, pid, strlen(pid)); + + // Signal handler + struct sigaction sa; + sa.sa_handler = handle_signal; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sigaction(SIGHUP, &sa, 0); + sigaction(SIGABRT, &sa, 0); + sigaction(SIGTERM, &sa, 0); + sigaction(SIGINT, &sa, 0); + + retunrn Daemon_Singleton::start(); + } + + bool DaemonLinux::stop() + { + Daemon_Singleton::stop(); + + close(pidFilehandle); + unlink(pidfile.c_str()); + + return true; + } + + } +} + +#endif \ No newline at end of file diff --git a/DaemonWin32.cpp b/DaemonWin32.cpp new file mode 100644 index 00000000..f27ba9c7 --- /dev/null +++ b/DaemonWin32.cpp @@ -0,0 +1,31 @@ +#include "Daemon.h" + +#ifdef _WIN32 + +#include "./Win32/Win32Service.h" + + +namespace i2p +{ + namespace util + { + bool DaemonWin32::start() + { + setlocale(LC_CTYPE, ""); + SetConsoleCP(1251); + SetConsoleOutputCP(1251); + setlocale(LC_ALL, "Russian"); + + service_control(isDaemon); + + return Daemon_Singleton::start(); + } + + bool DaemonWin32::stop() + { + return Daemon_Singleton::stop(); + } + } +} + +#endif \ No newline at end of file diff --git a/Win32/i2pd.vcxproj b/Win32/i2pd.vcxproj index 64f9f574..612c3de2 100644 --- a/Win32/i2pd.vcxproj +++ b/Win32/i2pd.vcxproj @@ -13,6 +13,9 @@ + + + @@ -43,6 +46,7 @@ + diff --git a/Win32/i2pd.vcxproj.filters b/Win32/i2pd.vcxproj.filters index 38e0e9e0..091e4acf 100644 --- a/Win32/i2pd.vcxproj.filters +++ b/Win32/i2pd.vcxproj.filters @@ -99,6 +99,15 @@ Win32 + + Source Files + + + Source Files + + + Source Files + @@ -200,5 +209,8 @@ Win32 + + Header Files + \ No newline at end of file diff --git a/i2p.cpp b/i2p.cpp index ddb0d219..3d8ef13b 100644 --- a/i2p.cpp +++ b/i2p.cpp @@ -1,193 +1,23 @@ -#ifdef _WIN32 -#define _CRT_SECURE_NO_WARNINGS // to use freopen -#endif - -#include -#include -#include #include -#ifndef _WIN32 -#include -#include -#include -#else -#include "./Win32/Win32Service.h" -#endif - -#include "Log.h" -#include "base64.h" -#include "Transports.h" -#include "NTCPSession.h" -#include "RouterInfo.h" -#include "RouterContext.h" -#include "Tunnel.h" -#include "NetDb.h" -#include "HTTPServer.h" -#include "HTTPProxy.h" -#include "Garlic.h" #include "util.h" -#include "Streaming.h" - - -// Global -volatile int running = 1; -volatile int isDaemon; - -#ifndef _WIN32 -void handle_signal(int sig) -{ - switch (sig) - { - case SIGHUP: - if (i2p::util::config::GetArg("daemon", 0) == 1) - { - static bool first=true; - if (first) - { - first=false; - return; - } - } - LogPrint("Reloading config."); - i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs); - break; - case SIGABRT: - case SIGTERM: - case SIGINT: - running = 0; // Exit loop - break; - } -} -#endif - +#include "Daemon.h" int main( int argc, char* argv[] ) { - i2p::util::config::OptionParser(argc,argv); - volatile int isDaemon = i2p::util::config::GetArg("-daemon", 0); -#ifdef _WIN32 - setlocale(LC_CTYPE, ""); - SetConsoleCP(1251); - SetConsoleOutputCP(1251); - setlocale(LC_ALL, "Russian"); -#endif - -#ifdef _WIN32 - service_control(isDaemon); -#endif - - 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); - - volatile int isLogging = i2p::util::config::GetArg("-log", 0); - if (isLogging == 1) - { - std::string logfile = i2p::util::filesystem::GetDataDir().string(); -#ifndef _WIN32 - logfile.append("/debug.log"); -#else - logfile.append("\\debug.log"); -#endif - freopen(logfile.c_str(),"a",stdout); - LogPrint("Logging to file enabled."); - } - - -#ifndef _WIN32 - if (isDaemon == 1) - { - pid_t pid; - pid = fork(); - if (pid > 0) - { - g_Log.Stop(); - return 0; - } - if (pid < 0) - { - return -1; - } - - umask(0); - int sid = setsid(); - if (sid < 0) - { - LogPrint("Error, could not create process group."); - return -1; - } - chdir(i2p::util::filesystem::GetDataDir().string().c_str()); - } - - // Pidfile - std::string pidfile = i2p::util::filesystem::GetDataDir().string(); - pidfile.append("/i2pd.pid"); - int pidFilehandle = open(pidfile.c_str(), O_RDWR|O_CREAT, 0600); - if (pidFilehandle == -1 ) - { - LogPrint("Error, could not create pid file (", pidfile, ")\nIs an instance already running?"); - return -1; - } - if (lockf(pidFilehandle,F_TLOCK,0) == -1) - { - LogPrint("Error, could not lock pid file (", pidfile, ")\nIs an instance already running?"); - return -1; - } - char pid[10]; - sprintf(pid,"%d\n",getpid()); - write(pidFilehandle, pid, strlen(pid)); - - // Signal handler - struct sigaction sa; - sa.sa_handler = handle_signal; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - sigaction(SIGHUP,&sa,0); - sigaction(SIGABRT,&sa,0); - sigaction(SIGTERM,&sa,0); - sigaction(SIGINT,&sa,0); -#endif - - //TODO: This is an ugly workaround. fix it. - //TODO: Autodetect public IP. - i2p::context.OverrideNTCPAddress(i2p::util::config::GetCharArg("-host", "127.0.0.1"), - i2p::util::config::GetArg("-port", 17070)); - - i2p::util::HTTPServer httpServer (i2p::util::config::GetArg("-httpport", 7070)); - - httpServer.Start (); - i2p::data::netdb.Start (); - i2p::transports.Start (); - i2p::tunnel::tunnels.Start (); - i2p::garlic::routing.Start (); - i2p::stream::StartStreaming (); - - i2p::proxy::HTTPProxy httpProxy (i2p::util::config::GetArg("-httpproxyport", 4446)); - httpProxy.Start(); + i2p::util::config::OptionParser(argc, argv); - while (running) - { - //TODO Meeh: Find something better to do here. - std::this_thread::sleep_for (std::chrono::seconds(1)); - } - LogPrint("Shutdown started."); + 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); - httpProxy.Stop (); - i2p::stream::StopStreaming (); - i2p::garlic::routing.Stop (); - i2p::tunnel::tunnels.Stop (); - i2p::transports.Stop (); - i2p::data::netdb.Stop (); - httpServer.Stop (); + Daemon.start(); + while (Daemon.running) + { + //TODO Meeh: Find something better to do here. + std::this_thread::sleep_for (std::chrono::seconds(1)); + } + Daemon.start(); - if (isLogging == 1) - { - fclose (stdout); - } -#ifndef _WIN32 - close(pidFilehandle); - unlink(pidfile.c_str()); -#endif - return 0; + return 0; }