From 0b210ee99d9784cfd33d9db9a6a46c235b8f6559 Mon Sep 17 00:00:00 2001 From: chertov Date: Sun, 20 Apr 2014 05:54:34 +0400 Subject: [PATCH 1/4] 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; } From e674014efc82acf8a12bbec9ae1c6a66d4772cc3 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 22 Apr 2014 06:15:07 +0200 Subject: [PATCH 2/4] fix Linux Daemon --- Daemon.h | 6 +++++- DaemonLinux.cpp | 14 +++++++++----- Makefile | 3 ++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Daemon.h b/Daemon.h index d7fdc82a..86971d29 100644 --- a/Daemon.h +++ b/Daemon.h @@ -57,7 +57,11 @@ namespace i2p virtual bool start(); virtual bool stop(); + private: + std::string pidfile; + int pidFilehandle; + }; #endif } -} \ No newline at end of file +} diff --git a/DaemonLinux.cpp b/DaemonLinux.cpp index 116e0ae6..4cfd51ce 100644 --- a/DaemonLinux.cpp +++ b/DaemonLinux.cpp @@ -6,6 +6,10 @@ #include #include +//#include +#include "util.h" + + void handle_signal(int sig) { switch (sig) @@ -26,7 +30,7 @@ void handle_signal(int sig) case SIGABRT: case SIGTERM: case SIGINT: - running = 0; // Exit loop + Daemon.running = 0; // Exit loop break; } } @@ -63,9 +67,9 @@ namespace i2p } // Pidfile - std::string pidfile = i2p::util::filesystem::GetDataDir().string(); + pidfile = i2p::util::filesystem::GetDataDir().string(); pidfile.append("/i2pd.pid"); - int pidFilehandle = open(pidfile.c_str(), O_RDWR | O_CREAT, 0600); + 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?"); @@ -90,7 +94,7 @@ namespace i2p sigaction(SIGTERM, &sa, 0); sigaction(SIGINT, &sa, 0); - retunrn Daemon_Singleton::start(); + return Daemon_Singleton::start(); } bool DaemonLinux::stop() @@ -106,4 +110,4 @@ namespace i2p } } -#endif \ No newline at end of file +#endif diff --git a/Makefile b/Makefile index fec4f79d..2d30a01c 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,8 @@ OBJECTS = obj/i2p.o obj/base64.o obj/NTCPSession.o obj/RouterInfo.o obj/Transpor obj/RouterContext.o obj/NetDb.o obj/LeaseSet.o obj/Tunnel.o obj/TunnelEndpoint.o \ obj/TunnelGateway.o obj/TransitTunnel.o obj/I2NPProtocol.o obj/Log.o obj/Garlic.o \ obj/HTTPServer.o obj/Streaming.o obj/Identity.o obj/SSU.o obj/util.o obj/Reseed.o \ - obj/UPnP.o obj/TunnelPool.o obj/HTTPProxy.o obj/AddressBook.o + obj/UPnP.o obj/TunnelPool.o obj/HTTPProxy.o obj/AddressBook.o \ + obj/Daemon.o obj/DaemonLinux.o INCFLAGS = LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread LIBS = From edafc3dabf1d7ca364cd113862f2b54456307049 Mon Sep 17 00:00:00 2001 From: chertov Date: Tue, 22 Apr 2014 08:25:19 +0400 Subject: [PATCH 3/4] fix i2p.cpp --- i2p.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i2p.cpp b/i2p.cpp index 3d8ef13b..3c5f3637 100644 --- a/i2p.cpp +++ b/i2p.cpp @@ -17,7 +17,7 @@ int main( int argc, char* argv[] ) //TODO Meeh: Find something better to do here. std::this_thread::sleep_for (std::chrono::seconds(1)); } - Daemon.start(); + Daemon.stop(); return 0; } From 6516b64960502fc271100bb5d88d2bbce9418433 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 22 Apr 2014 07:13:35 +0200 Subject: [PATCH 4/4] fix daemon --- Daemon.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Daemon.h b/Daemon.h index 86971d29..9ac00a48 100644 --- a/Daemon.h +++ b/Daemon.h @@ -16,7 +16,7 @@ namespace i2p int isLogging; int isDaemon; - int running = 1; + int running; private: i2p::util::HTTPServer *httpServer;