diff --git a/Makefile b/Makefile index 6084afc9..5446b079 100644 --- a/Makefile +++ b/Makefile @@ -64,7 +64,7 @@ else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS))) DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp include Makefile.bsd else ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS))) - DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32App.cpp Win32/Win32Service.cpp Win32/Win32NetState.cpp + DAEMON_SRC += Win32/Win32App.cpp Win32/Win32Service.cpp Win32/Win32NetState.cpp include Makefile.mingw else # not supported $(error Not supported platform) diff --git a/Makefile.mingw b/Makefile.mingw index a1a861e6..a2523605 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -4,7 +4,7 @@ USE_WIN32_APP := yes WINDRES = windres CXXFLAGS := $(CXX_DEBUG) -fPIC -msse -INCFLAGS = -I$(DAEMON_SRC_DIR) -IWin32 +INCFLAGS = -IWin32 LDFLAGS := ${LD_DEBUG} -static NEEDED_CXXFLAGS += -std=c++17 -DWIN32_LEAN_AND_MEAN diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp index 377e1076..9a535d11 100644 --- a/Win32/Win32App.cpp +++ b/Win32/Win32App.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -18,7 +18,7 @@ #include "Tunnel.h" #include "version.h" #include "resource.h" -#include "Daemon.h" + #include "Win32App.h" #include "Win32NetState.h" @@ -55,13 +55,15 @@ namespace win32 InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About..."); InsertMenu (hPopup, -1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); if(!i2p::context.AcceptsTunnels()) - InsertMenu (hPopup, -1, - i2p::util::DaemonWin32::Instance ().isGraceful ? MF_BYPOSITION | MF_STRING | MF_GRAYED : MF_BYPOSITION | MF_STRING, - ID_ACCEPT_TRANSIT, "Accept &transit"); + if(m_getIsGraceful) + if(m_getIsGraceful()) + InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING | MF_GRAYED, ID_ACCEPT_TRANSIT, "Accept &transit"); + else + InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ACCEPT_TRANSIT, "Accept &transit"); else InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_DECLINE_TRANSIT, "Decline &transit"); InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_RELOAD, "&Reload tunnels config"); - if (!i2p::util::DaemonWin32::Instance ().isGraceful) + if (!m_getIsGraceful) InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_GRACEFUL_SHUTDOWN, "&Graceful shutdown"); else InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_STOP_GRACEFUL_SHUTDOWN, "Stop &graceful shutdown"); @@ -270,7 +272,7 @@ namespace win32 SetTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER, 10*60*1000, nullptr); // 10 minutes SetTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER, 1000, nullptr); // check tunnels every second g_GracefulShutdownEndtime = GetTickCount() + 10*60*1000; - i2p::util::DaemonWin32::Instance ().isGraceful = true; + if (m_setIsGraceful) m_setIsGraceful(true); return 0; } case ID_STOP_GRACEFUL_SHUTDOWN: @@ -279,7 +281,7 @@ namespace win32 KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER); KillTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER); g_GracefulShutdownEndtime = 0; - i2p::util::DaemonWin32::Instance ().isGraceful = false; + if (m_setIsGraceful) m_setIsGraceful(false); return 0; } case ID_RELOAD: diff --git a/Win32/Win32App.h b/Win32/Win32App.h index ebe49efd..30c288c8 100644 --- a/Win32/Win32App.h +++ b/Win32/Win32App.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -22,6 +22,15 @@ namespace win32 int RunWin32App (); bool GracefulShutdown (); bool StopGracefulShutdown (); + + inline typedef std::function DaemonSetIsGraceful; + inline DaemonSetIsGraceful m_setIsGraceful; + inline void SetIsGraceful (const DaemonSetIsGraceful& f) { m_setIsGraceful = f; }; + + inline typedef std::function DaemonGetIsGraceful; + inline DaemonGetIsGraceful m_getIsGraceful; + inline void GetIsGraceful (const DaemonGetIsGraceful& f) { m_getIsGraceful = f; }; + } } #endif // WIN32APP_H__ diff --git a/Win32/Win32Service.cpp b/Win32/Win32Service.cpp index d4ba0d76..526d904a 100644 --- a/Win32/Win32Service.cpp +++ b/Win32/Win32Service.cpp @@ -10,7 +10,6 @@ #include #include -#include "Daemon.h" #include "Log.h" I2PService *I2PService::s_service = NULL; @@ -132,7 +131,13 @@ void I2PService::Start(DWORD dwArgc, PSTR *pszArgv) void I2PService::OnStart(DWORD dwArgc, PSTR *pszArgv) { LogPrint(eLogInfo, "Win32Service: in OnStart (", EVENTLOG_INFORMATION_TYPE, ")"); - Daemon.start(); + if(m_daemonStart) + m_daemonStart(); + else + { + LogPrint(eLogError, "Win32Service: failed to start: Unable to call callback"); + SetServiceStatus(SERVICE_STOPPED); + } _worker = new std::thread(std::bind(&I2PService::WorkerThread, this)); } @@ -171,7 +176,11 @@ void I2PService::OnStop() { // Log a service stop message to the Application log. LogPrint(eLogInfo, "Win32Service: in OnStop (", EVENTLOG_INFORMATION_TYPE, ")"); - Daemon.stop(); + if(m_daemonStop) + m_daemonStop(); + else + LogPrint(eLogError, "Win32Service: failed to stop: Unable to call callback"); + m_fStopping = TRUE; if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0) { diff --git a/Win32/Win32Service.h b/Win32/Win32Service.h index 5cedbed6..f12fe813 100644 --- a/Win32/Win32Service.h +++ b/Win32/Win32Service.h @@ -6,9 +6,10 @@ * See full license text in LICENSE file at top of project tree */ -#ifndef WIN_32_SERVICE_H__ -#define WIN_32_SERVICE_H__ +#ifndef WIN32SERVICE_H__ +#define WIN32SERVICE_H__ +#include #include #include @@ -29,6 +30,13 @@ class I2PService static BOOL Run(I2PService &service); void Stop(); + typedef std::function DaemonStart; + void SetDaemonStart (const DaemonStart& f) { m_daemonStart = f; }; + + typedef std::function DaemonStop; + void SetDaemonStop (const DaemonStop& f) { m_daemonStop = f; }; + + protected: virtual void OnStart(DWORD dwArgc, PSTR *pszArgv); @@ -58,6 +66,11 @@ class I2PService HANDLE m_hStoppedEvent; std::thread* _worker; + + private: + + DaemonStart m_daemonStart; + DaemonStop m_daemonStop; }; -#endif // WIN_32_SERVICE_H__ +#endif // WIN32SERVICE_H__ diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 1dbeba3b..b8cb6677 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -425,7 +425,7 @@ namespace util d.httpServer = std::unique_ptr(new i2p::http::HTTPServer(httpAddr, httpPort)); d.httpServer->SetDaemonStop (std::bind (Daemon_Singleton::stop, this)); #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) - d.httpServer->SetDaemonGracefulTimer (std::bind (Daemon_Singleton::stop, this)); + d.httpServer->SetDaemonGracefulTimer (std::bind (gracefulShutdownInterval, this)); #endif d.httpServer->Start(); } diff --git a/daemon/Daemon.h b/daemon/Daemon.h index 26d4a047..a3553339 100644 --- a/daemon/Daemon.h +++ b/daemon/Daemon.h @@ -75,14 +75,17 @@ namespace util return instance; } - bool init(int argc, char* argv[]); - bool start(); - bool stop(); + bool init (int argc, char* argv[]); + bool start (); + bool stop (); void run (); - bool isGraceful; + void SetIsGraceful (bool state) { m_isGraceful = state; }; + const bool GetIsGraceful () { return m_isGraceful; }; - DaemonWin32 ():isGraceful(false) {} + private: + + bool m_isGraceful; }; #elif (defined(ANDROID) && !defined(ANDROID_BINARY)) #define Daemon i2p::util::DaemonAndroid::Instance() @@ -109,8 +112,8 @@ namespace util return instance; } - bool start(); - bool stop(); + bool start (); + bool stop (); void run (); private: diff --git a/daemon/UnixDaemon.cpp b/daemon/DaemonUnix.cpp similarity index 100% rename from daemon/UnixDaemon.cpp rename to daemon/DaemonUnix.cpp diff --git a/Win32/DaemonWin32.cpp b/daemon/DaemonWin32.cpp similarity index 87% rename from Win32/DaemonWin32.cpp rename to daemon/DaemonWin32.cpp index 0badf802..53178f71 100644 --- a/Win32/DaemonWin32.cpp +++ b/daemon/DaemonWin32.cpp @@ -6,6 +6,8 @@ * See full license text in LICENSE file at top of project tree */ +#ifdef _WIN32 + #include #include #include "Config.h" @@ -13,7 +15,6 @@ #include "util.h" #include "Log.h" -#ifdef _WIN32 #include "Win32Service.h" #ifdef WIN32_APP #include @@ -38,6 +39,9 @@ namespace util } ); + i2p::win32::SetIsGraceful (std::bind (&DaemonWin32::SetIsGraceful, this, std::placeholders::_1)); + i2p::win32::GetIsGraceful (std::bind (&DaemonWin32::GetIsGraceful, this)); + if (!Daemon_Singleton::init(argc, argv)) return false; @@ -45,6 +49,8 @@ namespace util { LogPrint(eLogDebug, "Daemon: running as service"); I2PService service((PSTR)SERVICE_NAME); + service.SetDaemonStart (std::bind (&DaemonWin32::start, this)); + service.SetDaemonStop (std::bind (&DaemonWin32::stop, this)); if (!I2PService::Run(service)) { LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError()); diff --git a/libi2pd_webconsole/HTTPServer.cpp b/libi2pd_webconsole/HTTPServer.cpp index cc5844be..9ab6199d 100644 --- a/libi2pd_webconsole/HTTPServer.cpp +++ b/libi2pd_webconsole/HTTPServer.cpp @@ -31,10 +31,9 @@ #include "ECIESX25519AEADRatchetSession.h" #include "I18N.h" -#ifdef WIN32_APP -#include "Daemon.h" -#include "Win32App.h" -#endif +//#ifdef WIN32_APP +//#include "Win32App.h" +//#endif // Inja template engine #include "inja/inja.hpp" @@ -281,13 +280,13 @@ namespace http { ShowUptime(s, remains); s << "
\r\n"; } -#elif defined(WIN32_APP) +/*#elif defined(WIN32_APP) if (i2p::win32::g_GracefulShutdownEndtime != 0) { uint16_t remains = (i2p::win32::g_GracefulShutdownEndtime - GetTickCount()) / 1000; s << "" << tr("Stopping in") << ": "; ShowUptime(s, remains); s << "
\r\n"; - } + }*/ #endif s << "" << tr("Tunnel creation success rate") << ": " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () << "%
\r\n"; s << "" << tr("Received") << ": "; @@ -714,11 +713,12 @@ namespace http { s << " " << tr("Cancel graceful shutdown") << "
\r\n"; else s << " " << tr("Start graceful shutdown") << "
\r\n"; -#elif defined(WIN32_APP) +/*#elif defined(WIN32_APP) if (i2p::util::DaemonWin32::Instance().isGraceful) s << " " << tr("Cancel graceful shutdown") << "
\r\n"; else s << " " << tr("Start graceful shutdown") << "
\r\n"; +*/ #endif s << " " << tr("Force shutdown") << "

\r\n"; @@ -1023,8 +1023,8 @@ namespace http { } } - HTTPConnection::HTTPConnection (std::string hostname, std::shared_ptr socket): - m_Socket (socket), m_BufferLen (0), expected_host(hostname) + HTTPConnection::HTTPConnection (std::string hostname, std::shared_ptr socket, HTTPServer& server): + m_Socket (socket), m_Server (server), m_BufferLen (0), expected_host(hostname) { /* cache options */ i2p::config::GetOption("http.auth", needAuth); @@ -1248,8 +1248,9 @@ namespace http { // TODO: rewrite timer access #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) if (m_DaemonGracefulTimer) m_DaemonGracefulTimer = 10 * 60; -#elif defined(WIN32_APP) +/*#elif defined(WIN32_APP) i2p::win32::GracefulShutdown (); +*/ #endif } else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) @@ -1258,18 +1259,19 @@ namespace http { // TODO: rewrite timer access #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) if (m_DaemonGracefulTimer) m_DaemonGracefulTimer = 0; -#elif defined(WIN32_APP) +/*#elif defined(WIN32_APP) i2p::win32::StopGracefulShutdown (); +*/ #endif } else if (cmd == HTTP_COMMAND_SHUTDOWN_NOW) { // TODO: rewrite stop command access -#ifndef WIN32_APP - if (m_DaemonStop) m_DaemonStop(); -#else - i2p::win32::StopWin32App (); -#endif +//#ifndef WIN32_APP + m_Server.GetDaemonStop(); +//#else +// i2p::win32::StopWin32App (); +//#endif } else if (cmd == HTTP_COMMAND_LOGLEVEL) { @@ -1503,7 +1505,7 @@ namespace http { void HTTPServer::CreateConnection(std::shared_ptr newSocket) { - auto conn = std::make_shared (m_Hostname, newSocket); + auto conn = std::make_shared (m_Hostname, newSocket, *this); conn->Receive (); } } // http diff --git a/libi2pd_webconsole/HTTPServer.h b/libi2pd_webconsole/HTTPServer.h index 8f85421d..f06468bc 100644 --- a/libi2pd_webconsole/HTTPServer.h +++ b/libi2pd_webconsole/HTTPServer.h @@ -25,11 +25,13 @@ namespace http const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192; const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds + class HTTPServer; + class HTTPConnection: public std::enable_shared_from_this { public: - HTTPConnection (std::string serverhost, std::shared_ptr socket); + HTTPConnection (std::string serverhost, std::shared_ptr socket, HTTPServer& server); void Receive (); private: @@ -48,6 +50,7 @@ namespace http private: std::shared_ptr m_Socket; + HTTPServer& m_Server; char m_Buffer[HTTP_CONNECTION_BUFFER_SIZE + 1]; size_t m_BufferLen; std::string m_SendBuffer; @@ -70,9 +73,11 @@ namespace http void Stop (); typedef std::function DaemonStop; - typedef int DaemonGracefulTimer; void SetDaemonStop (const DaemonStop& f) { m_DaemonStop = f; }; - void SetDaemonGracefulTimer (const DaemonGracefulTimer& f) { m_DaemonGracefulTimer = f; }; + DaemonStop GetDaemonStop () { return m_DaemonStop; }; + + void SetDaemonGracefulTimer (const int& f) { m_DaemonGracefulTimer = f; }; + int GetDaemonGracefulTimer () { return m_DaemonGracefulTimer; }; private: @@ -94,7 +99,7 @@ namespace http private: DaemonStop m_DaemonStop; - DaemonGracefulTimer m_DaemonGracefulTimer; + int m_DaemonGracefulTimer; }; //all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml