Browse Source

Merge pull request #68 from chertov/master

Add simple Linux, Win32 daemons
pull/70/head
orignal 11 years ago
parent
commit
4bd8195e99
  1. 83
      Daemon.cpp
  2. 67
      Daemon.h
  3. 113
      DaemonLinux.cpp
  4. 31
      DaemonWin32.cpp
  5. 3
      Makefile
  6. 4
      Win32/i2pd.vcxproj
  7. 12
      Win32/i2pd.vcxproj.filters
  8. 196
      i2p.cpp

83
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;
}
}
}

67
Daemon.h

@ -0,0 +1,67 @@
#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;
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();
private:
std::string pidfile;
int pidFilehandle;
};
#endif
}
}

113
DaemonLinux.cpp

@ -0,0 +1,113 @@
#include "Daemon.h"
#ifndef _WIN32
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
//#include <boost/filesystem.hpp>
#include "util.h"
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:
Daemon.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
pidfile = i2p::util::filesystem::GetDataDir().string();
pidfile.append("/i2pd.pid");
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);
return Daemon_Singleton::start();
}
bool DaemonLinux::stop()
{
Daemon_Singleton::stop();
close(pidFilehandle);
unlink(pidfile.c_str());
return true;
}
}
}
#endif

31
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

3
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/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/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/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 = INCFLAGS =
LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
LIBS = LIBS =

4
Win32/i2pd.vcxproj

@ -13,6 +13,9 @@
<ItemGroup> <ItemGroup>
<ClCompile Include="..\AddressBook.cpp" /> <ClCompile Include="..\AddressBook.cpp" />
<ClCompile Include="..\base64.cpp" /> <ClCompile Include="..\base64.cpp" />
<ClCompile Include="..\Daemon.cpp" />
<ClCompile Include="..\DaemonLinux.cpp" />
<ClCompile Include="..\DaemonWin32.cpp" />
<ClCompile Include="..\Garlic.cpp" /> <ClCompile Include="..\Garlic.cpp" />
<ClCompile Include="..\HTTPProxy.cpp" /> <ClCompile Include="..\HTTPProxy.cpp" />
<ClCompile Include="..\HTTPServer.cpp" /> <ClCompile Include="..\HTTPServer.cpp" />
@ -43,6 +46,7 @@
<ClInclude Include="..\AddressBook.h" /> <ClInclude Include="..\AddressBook.h" />
<ClInclude Include="..\base64.h" /> <ClInclude Include="..\base64.h" />
<ClInclude Include="..\CryptoConst.h" /> <ClInclude Include="..\CryptoConst.h" />
<ClInclude Include="..\Daemon.h" />
<ClInclude Include="..\ElGamal.h" /> <ClInclude Include="..\ElGamal.h" />
<ClInclude Include="..\Garlic.h" /> <ClInclude Include="..\Garlic.h" />
<ClInclude Include="..\HTTPProxy.h" /> <ClInclude Include="..\HTTPProxy.h" />

12
Win32/i2pd.vcxproj.filters

@ -99,6 +99,15 @@
<ClCompile Include="Win32Service.cpp"> <ClCompile Include="Win32Service.cpp">
<Filter>Win32</Filter> <Filter>Win32</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Daemon.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\DaemonLinux.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\DaemonWin32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\Identity.h"> <ClInclude Include="..\Identity.h">
@ -200,5 +209,8 @@
<ClInclude Include="Win32Service.h"> <ClInclude Include="Win32Service.h">
<Filter>Win32</Filter> <Filter>Win32</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\Daemon.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

196
i2p.cpp

@ -1,193 +1,23 @@
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS // to use freopen
#endif
#include <iostream>
#include <thread>
#include <cryptopp/integer.h>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#ifndef _WIN32
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#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 "util.h"
#include "Streaming.h" #include "Daemon.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
int main( int argc, char* argv[] ) int main( int argc, char* argv[] )
{ {
i2p::util::config::OptionParser(argc,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();
while (running) LogPrint("\n\n\n\ni2pd starting\n");
{ LogPrint("data directory: ", i2p::util::filesystem::GetDataDir().string());
//TODO Meeh: Find something better to do here. i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs);
std::this_thread::sleep_for (std::chrono::seconds(1));
}
LogPrint("Shutdown started.");
httpProxy.Stop (); Daemon.start();
i2p::stream::StopStreaming (); while (Daemon.running)
i2p::garlic::routing.Stop (); {
i2p::tunnel::tunnels.Stop (); //TODO Meeh: Find something better to do here.
i2p::transports.Stop (); std::this_thread::sleep_for (std::chrono::seconds(1));
i2p::data::netdb.Stop (); }
httpServer.Stop (); Daemon.stop();
if (isLogging == 1) return 0;
{
fclose (stdout);
}
#ifndef _WIN32
close(pidFilehandle);
unlink(pidfile.c_str());
#endif
return 0;
} }

Loading…
Cancel
Save