From dd4f066e95c7120595cc393130865d62a057d4eb Mon Sep 17 00:00:00 2001
From: R4SAS
Date: Wed, 27 Sep 2017 23:28:58 +0300
Subject: [PATCH] add graceful shutdown in webconsole for windows add stop
graceful shutdown menu item add reload menu item
---
Win32/DaemonWin32.cpp | 140 ++++++++++++++---------------
Win32/Win32App.cpp | 40 ++++++++-
Win32/Win32App.h | 9 +-
daemon/Daemon.h | 70 +++++++--------
daemon/HTTPServer.cpp | 199 +++++++++++++++++++++---------------------
5 files changed, 248 insertions(+), 210 deletions(-)
diff --git a/Win32/DaemonWin32.cpp b/Win32/DaemonWin32.cpp
index 698cf390..d36949c3 100644
--- a/Win32/DaemonWin32.cpp
+++ b/Win32/DaemonWin32.cpp
@@ -14,99 +14,99 @@
namespace i2p
{
- namespace util
+namespace util
+{
+ bool DaemonWin32::init(int argc, char* argv[])
{
- bool DaemonWin32::init(int argc, char* argv[])
- {
- setlocale(LC_CTYPE, "");
- SetConsoleCP(1251);
- SetConsoleOutputCP(1251);
- setlocale(LC_ALL, "Russian");
+ setlocale(LC_CTYPE, "");
+ SetConsoleCP(1251);
+ SetConsoleOutputCP(1251);
+ setlocale(LC_ALL, "Russian");
- if (!Daemon_Singleton::init(argc, argv))
- return false;
+ if (!Daemon_Singleton::init(argc, argv))
+ return false;
- std::string serviceControl; i2p::config::GetOption("svcctl", serviceControl);
- if (serviceControl == "install")
- {
- LogPrint(eLogInfo, "WinSVC: installing ", SERVICE_NAME, " as service");
- 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
- );
- return false;
- }
- else if (serviceControl == "remove")
- {
- LogPrint(eLogInfo, "WinSVC: uninstalling ", SERVICE_NAME, " service");
- UninstallService(SERVICE_NAME);
- return false;
- }
+ std::string serviceControl; i2p::config::GetOption("svcctl", serviceControl);
+ if (serviceControl == "install")
+ {
+ LogPrint(eLogInfo, "WinSVC: installing ", SERVICE_NAME, " as service");
+ 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
+ );
+ return false;
+ }
+ else if (serviceControl == "remove")
+ {
+ LogPrint(eLogInfo, "WinSVC: uninstalling ", SERVICE_NAME, " service");
+ UninstallService(SERVICE_NAME);
+ return false;
+ }
- if (isDaemon)
+ if (isDaemon)
+ {
+ LogPrint(eLogDebug, "Daemon: running as service");
+ I2PService service(SERVICE_NAME);
+ if (!I2PService::Run(service))
{
- LogPrint(eLogDebug, "Daemon: running as service");
- I2PService service(SERVICE_NAME);
- if (!I2PService::Run(service))
- {
- LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
- return false;
- }
+ LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
return false;
}
- else
- LogPrint(eLogDebug, "Daemon: running as user");
- return true;
+ return false;
}
+ else
+ LogPrint(eLogDebug, "Daemon: running as user");
+ return true;
+ }
- bool DaemonWin32::start()
- {
- setlocale(LC_CTYPE, "");
- SetConsoleCP(1251);
- SetConsoleOutputCP(1251);
- setlocale(LC_ALL, "Russian");
+ bool DaemonWin32::start()
+ {
+ setlocale(LC_CTYPE, "");
+ SetConsoleCP(1251);
+ SetConsoleOutputCP(1251);
+ setlocale(LC_ALL, "Russian");
#ifdef WIN32_APP
- if (!i2p::win32::StartWin32App ()) return false;
+ if (!i2p::win32::StartWin32App ()) return false;
- // override log
- i2p::config::SetOption("log", std::string ("file"));
+ // override log
+ i2p::config::SetOption("log", std::string ("file"));
#endif
- bool ret = Daemon_Singleton::start();
- if (ret && i2p::log::Logger().GetLogType() == eLogFile)
- {
- // TODO: find out where this garbage to console comes from
- SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE);
- SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE);
- }
- bool insomnia; i2p::config::GetOption("insomnia", insomnia);
- if (insomnia)
- SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
- return ret;
+ bool ret = Daemon_Singleton::start();
+ if (ret && i2p::log::Logger().GetLogType() == eLogFile)
+ {
+ // TODO: find out where this garbage to console comes from
+ SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE);
+ SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE);
}
+ bool insomnia; i2p::config::GetOption("insomnia", insomnia);
+ if (insomnia)
+ SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
+ return ret;
+ }
- bool DaemonWin32::stop()
- {
+ bool DaemonWin32::stop()
+ {
#ifdef WIN32_APP
- i2p::win32::StopWin32App ();
+ i2p::win32::StopWin32App ();
#endif
- return Daemon_Singleton::stop();
- }
+ return Daemon_Singleton::stop();
+ }
- void DaemonWin32::run ()
- {
+ void DaemonWin32::run ()
+ {
#ifdef WIN32_APP
- i2p::win32::RunWin32App ();
+ i2p::win32::RunWin32App ();
#else
- while (running)
+ while (running)
{
std::this_thread::sleep_for (std::chrono::seconds(1));
}
#endif
- }
}
}
+}
#endif
diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp
index e66b5f08..4c7eae03 100644
--- a/Win32/Win32App.cpp
+++ b/Win32/Win32App.cpp
@@ -9,6 +9,7 @@
#include "Tunnel.h"
#include "version.h"
#include "resource.h"
+#include "Daemon.h"
#include "Win32App.h"
#include
@@ -21,6 +22,8 @@
#define ID_CONSOLE 2002
#define ID_APP 2003
#define ID_GRACEFUL_SHUTDOWN 2004
+#define ID_STOP_GRACEFUL_SHUTDOWN 2005
+#define ID_RELOAD 2006
#define ID_TRAY_ICON 2050
#define WM_TRAYICON (WM_USER + 1)
@@ -39,7 +42,11 @@ namespace win32
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_APP, "Show app");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About...");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
- InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_GRACEFUL_SHUTDOWN, "&Graceful shutdown");
+ InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_RELOAD, "&Reload configs");
+ if (!i2p::util::DaemonWin32::Instance ().isGraceful)
+ 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");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_EXIT, "E&xit");
SetMenuDefaultItem (hPopup, ID_CONSOLE, FALSE);
SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0);
@@ -68,7 +75,7 @@ namespace win32
nid.uCallbackMessage = WM_TRAYICON;
nid.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE (MAINICON));
strcpy (nid.szTip, "i2pd");
- strcpy (nid.szInfo, "i2pd is running");
+ strcpy (nid.szInfo, "i2pd is starting");
Shell_NotifyIcon(NIM_ADD, &nid );
}
@@ -120,6 +127,7 @@ namespace win32
static void PrintMainWindowText (std::stringstream& s)
{
+ s << "\n";
s << "Status: ";
switch (i2p::context.GetStatus())
{
@@ -153,6 +161,7 @@ namespace win32
s << "In: " << i2p::tunnel::tunnels.CountInboundTunnels() << "; ";
s << "Out: " << i2p::tunnel::tunnels.CountOutboundTunnels() << "; ";
s << "Transit: " << i2p::tunnel::tunnels.CountTransitTunnels() << "\n";
+ s << "\n";
}
static LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
@@ -192,6 +201,22 @@ namespace win32
{
i2p::context.SetAcceptsTunnels (false);
SetTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER, 10*60*1000, nullptr); // 10 minutes
+ i2p::util::DaemonWin32::Instance ().isGraceful = true;
+ return 0;
+ }
+ case ID_STOP_GRACEFUL_SHUTDOWN:
+ {
+ i2p::context.SetAcceptsTunnels (true);
+ KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER);
+ i2p::util::DaemonWin32::Instance ().isGraceful = false;
+ return 0;
+ }
+ case ID_RELOAD:
+ {
+ i2p::client::context.ReloadConfig();
+ std::stringstream text;
+ text << "I2Pd reloading configs...";
+ MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK );
return 0;
}
case ID_CONSOLE:
@@ -322,7 +347,7 @@ namespace win32
wclx.lpszClassName = I2PD_WIN32_CLASSNAME;
RegisterClassEx (&wclx);
// create new window
- if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 100, 100, 350, 180, NULL, NULL, hInst, NULL))
+ if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 100, 100, 350, 210, NULL, NULL, hInst, NULL))
{
MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
return false;
@@ -353,5 +378,14 @@ namespace win32
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_GRACEFUL_SHUTDOWN, 0), 0);
return hWnd;
}
+
+ bool StopGracefulShutdown ()
+ {
+ HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
+ if (hWnd)
+ PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_STOP_GRACEFUL_SHUTDOWN, 0), 0);
+ return hWnd;
+ }
+
}
}
diff --git a/Win32/Win32App.h b/Win32/Win32App.h
index 3babffa9..b230eb06 100644
--- a/Win32/Win32App.h
+++ b/Win32/Win32App.h
@@ -7,10 +7,11 @@ namespace i2p
{
namespace win32
{
- bool StartWin32App ();
- void StopWin32App ();
- int RunWin32App ();
- bool GracefulShutdown ();
+ bool StartWin32App ();
+ void StopWin32App ();
+ int RunWin32App ();
+ bool GracefulShutdown ();
+ bool StopGracefulShutdown ();
}
}
#endif // WIN32APP_H__
diff --git a/daemon/Daemon.h b/daemon/Daemon.h
index 2bc05462..48301e73 100644
--- a/daemon/Daemon.h
+++ b/daemon/Daemon.h
@@ -6,11 +6,11 @@
namespace i2p
{
- namespace util
+namespace util
+{
+ class Daemon_Singleton_Private;
+ class Daemon_Singleton
{
- class Daemon_Singleton_Private;
- class Daemon_Singleton
- {
public:
virtual bool init(int argc, char* argv[]);
virtual bool start();
@@ -29,40 +29,38 @@ namespace i2p
// d-pointer for httpServer, httpProxy, etc.
class Daemon_Singleton_Private;
Daemon_Singleton_Private &d;
- };
+ };
#if defined(QT_GUI_LIB) // check if QT
#define Daemon i2p::util::DaemonQT::Instance()
- // dummy, invoked from RunQT
- class DaemonQT: public i2p::util::Daemon_Singleton
+ // dummy, invoked from RunQT
+ class DaemonQT: public i2p::util::Daemon_Singleton
{
public:
-
static DaemonQT& Instance()
{
static DaemonQT instance;
return instance;
}
- };
+ };
#elif defined(ANDROID)
#define Daemon i2p::util::DaemonAndroid::Instance()
// dummy, invoked from android/jni/DaemonAndroid.*
- class DaemonAndroid: public i2p::util::Daemon_Singleton
+ class DaemonAndroid: public i2p::util::Daemon_Singleton
{
public:
-
static DaemonAndroid& Instance()
{
static DaemonAndroid instance;
return instance;
}
- };
+ };
#elif defined(_WIN32)
#define Daemon i2p::util::DaemonWin32::Instance()
- class DaemonWin32 : public Daemon_Singleton
- {
+ class DaemonWin32 : public Daemon_Singleton
+ {
public:
static DaemonWin32& Instance()
{
@@ -74,34 +72,36 @@ namespace i2p
bool start();
bool stop();
void run ();
- };
-#else
-#define Daemon i2p::util::DaemonLinux::Instance()
- class DaemonLinux : public Daemon_Singleton
- {
- public:
- static DaemonLinux& Instance()
- {
- static DaemonLinux instance;
- return instance;
- }
- bool start();
- bool stop();
- void run ();
+ bool isGraceful;
- private:
+ DaemonWin32 ():isGraceful(false) {}
+ };
- std::string pidfile;
- int pidFH;
+#else
+#define Daemon i2p::util::DaemonLinux::Instance()
+ class DaemonLinux : public Daemon_Singleton
+ {
+ public:
+ static DaemonLinux& Instance()
+ {
+ static DaemonLinux instance;
+ return instance;
+ }
- public:
+ bool start();
+ bool stop();
+ void run ();
- int gracefulShutdownInterval; // in seconds
+ private:
+ std::string pidfile;
+ int pidFH;
- };
+ public:
+ int gracefulShutdownInterval; // in seconds
+ };
#endif
- }
+}
}
#endif // DAEMON_H__
diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp
index f3f9bb74..d6a358cf 100644
--- a/daemon/HTTPServer.cpp
+++ b/daemon/HTTPServer.cpp
@@ -58,9 +58,9 @@ namespace http {
" .left { float: left; position: absolute; }\r\n"
" .right { float: left; font-size: 1em; margin-left: 13em; max-width: 46em; overflow: auto; }\r\n"
" .tunnel.established { color: #56B734; }\r\n"
- " .tunnel.expiring { color: #D3AE3F; }\r\n"
- " .tunnel.failed { color: #D33F3F; }\r\n"
- " .tunnel.another { color: #434343; }\r\n"
+ " .tunnel.expiring { color: #D3AE3F; }\r\n"
+ " .tunnel.failed { color: #D33F3F; }\r\n"
+ " .tunnel.another { color: #434343; }\r\n"
" caption { font-size: 1.5em; text-align: center; color: #894C84; }\r\n"
" table { width: 100%; border-collapse: collapse; text-align: center; }\r\n"
" .private { background: black; color: black; } .private:hover { background: black; color: white } \r\n"
@@ -89,7 +89,7 @@ namespace http {
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
const char HTTP_PARAM_ADDRESS[] = "address";
- static void ShowUptime (std::stringstream& s, int seconds)
+ static void ShowUptime (std::stringstream& s, int seconds)
{
int num;
@@ -125,11 +125,11 @@ namespace http {
std::string state;
switch (eState) {
case i2p::tunnel::eTunnelStateBuildReplyReceived :
- case i2p::tunnel::eTunnelStatePending : state = "building"; break;
+ case i2p::tunnel::eTunnelStatePending : state = "building"; break;
case i2p::tunnel::eTunnelStateBuildFailed :
case i2p::tunnel::eTunnelStateTestFailed :
- case i2p::tunnel::eTunnelStateFailed : state = "failed"; break;
- case i2p::tunnel::eTunnelStateExpiring : state = "expiring"; break;
+ case i2p::tunnel::eTunnelStateFailed : state = "failed"; break;
+ case i2p::tunnel::eTunnelStateExpiring : state = "expiring"; break;
case i2p::tunnel::eTunnelStateEstablished : state = "established"; break;
default: state = "unknown"; break;
}
@@ -185,7 +185,7 @@ namespace http {
s << "ERROR: " << string << "
\r\n";
}
- void ShowStatus (std::stringstream& s, bool includeHiddenContent)
+ void ShowStatus (std::stringstream& s, bool includeHiddenContent)
{
s << "Uptime: ";
ShowUptime(s, i2p::context.GetUptime ());
@@ -195,21 +195,21 @@ namespace http {
{
case eRouterStatusOK: s << "OK"; break;
case eRouterStatusTesting: s << "Testing"; break;
- case eRouterStatusFirewalled: s << "Firewalled"; break;
- case eRouterStatusError:
- {
- s << "Error";
+ case eRouterStatusFirewalled: s << "Firewalled"; break;
+ case eRouterStatusError:
+ {
+ s << "Error";
switch (i2p::context.GetError ())
{
case eRouterErrorClockSkew:
- s << "
Clock skew";
+ s << "
Clock skew";
break;
- default: ;
- }
+ default: ;
+ }
break;
- }
+ }
default: s << "Unknown";
- }
+ }
s << "
\r\n";
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
if (auto remains = Daemon.gracefulShutdownInterval) {
@@ -230,38 +230,38 @@ namespace http {
s << " (" << (double) i2p::transport::transports.GetOutBandwidth () / 1024 << " KiB/s)
\r\n";
s << "Transit: ";
ShowTraffic (s, i2p::transport::transports.GetTotalTransitTransmittedBytes ());
- s << " (" << (double) i2p::transport::transports.GetTransitBandwidth () / 1024 << " KiB/s)
\r\n";
+ s << " (" << (double) i2p::transport::transports.GetTransitBandwidth () / 1024 << " KiB/s)
\r\n";
s << "Data path: " << i2p::fs::GetDataDir() << "
\r\n";
s << "\r\n
\r\n
\r\n";
- if(includeHiddenContent) {
- s << "Router Ident: " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "
\r\n";
- s << "Router Family: " << i2p::context.GetRouterInfo().GetProperty("family") << "
\r\n";
- s << "Router Caps: " << i2p::context.GetRouterInfo().GetProperty("caps") << "
\r\n";
- s << "Our external address:" << "
\r\n" ;
- for (const auto& address : i2p::context.GetRouterInfo().GetAddresses())
- {
- switch (address->transportStyle)
- {
- case i2p::data::RouterInfo::eTransportNTCP:
- if (address->host.is_v6 ())
- s << "NTCP6 ";
- else
- s << "NTCP ";
- break;
- case i2p::data::RouterInfo::eTransportSSU:
- if (address->host.is_v6 ())
- s << "SSU6 ";
- else
- s << "SSU ";
- break;
- default:
- s << "Unknown ";
- }
- s << address->host.to_string() << ":" << address->port << "
\r\n";
- }
- }
- s << "
\r\n
\r\n";
- s << "Routers: " << i2p::data::netdb.GetNumRouters () << " ";
+ if(includeHiddenContent) {
+ s << "Router Ident: " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "
\r\n";
+ s << "Router Family: " << i2p::context.GetRouterInfo().GetProperty("family") << "
\r\n";
+ s << "Router Caps: " << i2p::context.GetRouterInfo().GetProperty("caps") << "
\r\n";
+ s << "Our external address:" << "
\r\n" ;
+ for (const auto& address : i2p::context.GetRouterInfo().GetAddresses())
+ {
+ switch (address->transportStyle)
+ {
+ case i2p::data::RouterInfo::eTransportNTCP:
+ if (address->host.is_v6 ())
+ s << "NTCP6 ";
+ else
+ s << "NTCP ";
+ break;
+ case i2p::data::RouterInfo::eTransportSSU:
+ if (address->host.is_v6 ())
+ s << "SSU6 ";
+ else
+ s << "SSU ";
+ break;
+ default:
+ s << "Unknown ";
+ }
+ s << address->host.to_string() << ":" << address->port << "
\r\n";
+ }
+ }
+ s << "
\r\n\r\n";
+ s << "Routers: " << i2p::data::netdb.GetNumRouters () << " ";
s << "Floodfills: " << i2p::data::netdb.GetNumFloodfills () << " ";
s << "LeaseSets: " << i2p::data::netdb.GetNumLeaseSets () << "
\r\n";
@@ -273,13 +273,13 @@ namespace http {
s << "Transit Tunnels: " << std::to_string(transitTunnelCount) << "
\r\n";
}
- void ShowLocalDestinations (std::stringstream& s)
+ void ShowLocalDestinations (std::stringstream& s)
{
s << "Local Destinations:
\r\n
\r\n";
for (auto& it: i2p::client::context.GetDestinations ())
{
- auto ident = it.second->GetIdentHash ();
- s << "";
+ auto ident = it.second->GetIdentHash ();
+ s << "";
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "
\r\n" << std::endl;
}
@@ -291,11 +291,11 @@ namespace http {
{
auto dest = it.second->GetDestination ();
if (dest)
- {
- auto ident = dest->GetIdentHash ();
- s << "";
+ {
+ auto ident = dest->GetIdentHash ();
+ s << "";
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "
\r\n" << std::endl;
- }
+ }
}
}
}
@@ -341,7 +341,7 @@ namespace http {
s << "
" << std::endl;
}
- void ShowLocalDestination (std::stringstream& s, const std::string& b32)
+ void ShowLocalDestination (std::stringstream& s, const std::string& b32)
{
s << "Local Destination:
\r\n
\r\n";
i2p::data::IdentHash ident;
@@ -349,7 +349,7 @@ namespace http {
auto dest = i2p::client::context.FindLocalDestination (ident);
if (dest)
{
- ShowLeaseSetDestination (s, dest);
+ ShowLeaseSetDestination (s, dest);
// show streams
s << "
\r\nStreams";
s << "StreamID | ";
@@ -377,35 +377,35 @@ namespace http {
s << "" << it->GetRTT () << " | ";
s << "" << it->GetWindowSize () << " | ";
s << "" << (int)it->GetStatus () << " | ";
- s << "
\r\n" << std::endl;
- }
+ s << "
\r\n" << std::endl;
+ }
s << "
";
}
}
- static void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id)
+ static void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id)
{
auto i2cpServer = i2p::client::context.GetI2CPServer ();
if (i2cpServer)
{
s << "I2CP Local Destination:
\r\n
\r\n";
- auto it = i2cpServer->GetSessions ().find (std::stoi (id));
+ auto it = i2cpServer->GetSessions ().find (std::stoi (id));
if (it != i2cpServer->GetSessions ().end ())
ShowLeaseSetDestination (s, it->second->GetDestination ());
else
- ShowError(s, "I2CP session not found");
+ ShowError(s, "I2CP session not found");
}
else
ShowError(s, "I2CP is not enabled");
}
- void ShowLeasesSets(std::stringstream& s)
+ void ShowLeasesSets(std::stringstream& s)
{
s << "LeaseSets (click on to show info):
\r\n";
int counter = 1;
// for each lease set
i2p::data::netdb.VisitLeaseSets(
- [&s, &counter](const i2p::data::IdentHash dest, std::shared_ptr leaseSet)
+ [&s, &counter](const i2p::data::IdentHash dest, std::shared_ptr leaseSet)
{
// create copy of lease set so we extract leases
i2p::data::LeaseSet ls(leaseSet->GetBuffer(), leaseSet->GetBufferLen());
@@ -432,7 +432,7 @@ namespace http {
// end for each lease set
}
- void ShowTunnels (std::stringstream& s)
+ void ShowTunnels (std::stringstream& s)
{
s << "Queue size: " << i2p::tunnel::tunnels.GetQueueSize () << "
\r\n";
@@ -454,7 +454,7 @@ namespace http {
s << "
\r\n";
}
- static void ShowCommands (std::stringstream& s, uint32_t token)
+ static void ShowCommands (std::stringstream& s, uint32_t token)
{
/* commands */
s << "Router Commands
\r\n";
@@ -465,18 +465,20 @@ namespace http {
else
s << " Accept transit tunnels
\r\n";
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
- if (Daemon.gracefulShutdownInterval)
+ if (Daemon.gracefulShutdownInterval)
s << " Cancel graceful shutdown
";
- else
+ else
s << " Start graceful shutdown
\r\n";
-#endif
-#ifdef WIN32_APP
- s << " Graceful shutdown
\r\n";
+#elif defined(WIN32_APP)
+ if (i2p::util::DaemonWin32::Instance().isGraceful)
+ s << " Cancel graceful shutdown
";
+ else
+ s << " Graceful shutdown
\r\n";
#endif
s << " Force shutdown
\r\n";
}
- void ShowTransitTunnels (std::stringstream& s)
+ void ShowTransitTunnels (std::stringstream& s)
{
s << "Transit tunnels:
\r\n
\r\n";
for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ())
@@ -491,10 +493,10 @@ namespace http {
}
}
- void ShowTransports (std::stringstream& s)
+ void ShowTransports (std::stringstream& s)
{
s << "Transports:
\r\n
\r\n";
- auto ntcpServer = i2p::transport::transports.GetNTCPServer ();
+ auto ntcpServer = i2p::transport::transports.GetNTCPServer ();
if (ntcpServer)
{
auto sessions = ntcpServer->GetNTCPSessions ();
@@ -577,7 +579,7 @@ namespace http {
}
}
- void ShowSAMSessions (std::stringstream& s)
+ void ShowSAMSessions (std::stringstream& s)
{
auto sam = i2p::client::context.GetSAMBridge ();
if (!sam) {
@@ -624,13 +626,13 @@ namespace http {
}
}
- void ShowI2PTunnels (std::stringstream& s)
+ void ShowI2PTunnels (std::stringstream& s)
{
s << "Client Tunnels:
\r\n
\r\n";
for (auto& it: i2p::client::context.GetClientTunnels ())
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
- s << "";
+ s << "";
s << it.second->GetName () << " ⇐ ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "
\r\n"<< std::endl;
@@ -639,16 +641,16 @@ namespace http {
if (httpProxy)
{
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
- s << "";
+ s << "";
s << "HTTP Proxy" << " ⇐ ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "
\r\n"<< std::endl;
- }
+ }
auto socksProxy = i2p::client::context.GetSocksProxy ();
if (socksProxy)
{
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
- s << "";
+ s << "";
s << "SOCKS Proxy" << " ⇐ ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "
\r\n"<< std::endl;
@@ -659,7 +661,7 @@ namespace http {
for (auto& it: serverTunnels)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
- s << "";
+ s << "";
s << it.second->GetName () << " ⇒ ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << ":" << it.second->GetLocalPort ();
@@ -673,7 +675,7 @@ namespace http {
for (auto& it: clientForwards)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
- s << "";
+ s << "";
s << it.second->GetName () << " ⇐ ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "
\r\n"<< std::endl;
@@ -686,7 +688,7 @@ namespace http {
for (auto& it: serverForwards)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
- s << "";
+ s << "";
s << it.second->GetName () << " ⇐ ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "
\r\n"<< std::endl;
@@ -756,10 +758,10 @@ namespace http {
}
/* method #2: 'Authorization' header sent */
auto provided = req.GetHeader ("Authorization");
- if (provided.length () > 0)
- {
+ if (provided.length () > 0)
+ {
bool result = false;
-
+
std::string expected = user + ":" + pass;
size_t b64_sz = i2p::data::Base64EncodingBufferSize(expected.length()) + 1;
char * b64_creds = new char[b64_sz];
@@ -802,7 +804,7 @@ namespace http {
} else if (req.uri.find("cmd=") != std::string::npos) {
HandleCommand (req, res, s);
} else {
- ShowStatus (s, true);
+ ShowStatus (s, true);
res.add_header("Refresh", "10");
}
ShowPageTail (s);
@@ -814,7 +816,7 @@ namespace http {
std::map HTTPConnection::m_Tokens;
void HTTPConnection::HandlePage (const HTTPReq& req, HTTPRes& res, std::stringstream& s)
- {
+ {
std::map params;
std::string page("");
URL url;
@@ -840,13 +842,13 @@ namespace http {
else
++it;
}
- m_Tokens[token] = ts;
+ m_Tokens[token] = ts;
ShowCommands (s, token);
}
else if (page == HTTP_PAGE_TRANSIT_TUNNELS)
ShowTransitTunnels (s);
else if (page == HTTP_PAGE_LOCAL_DESTINATIONS)
- ShowLocalDestinations (s);
+ ShowLocalDestinations (s);
else if (page == HTTP_PAGE_LOCAL_DESTINATION)
ShowLocalDestination (s, params["b32"]);
else if (page == HTTP_PAGE_I2CP_LOCAL_DESTINATION)
@@ -864,7 +866,7 @@ namespace http {
ShowError(s, "Unknown page: " + page);
return;
}
- }
+ }
void HTTPConnection::HandleCommand (const HTTPReq& req, HTTPRes& res, std::stringstream& s)
{
@@ -881,7 +883,7 @@ namespace http {
return;
}
- std::string cmd = params["cmd"];
+ std::string cmd = params["cmd"];
if (cmd == HTTP_COMMAND_RUN_PEER_TEST)
i2p::transport::transports.PeerTest ();
else if (cmd == HTTP_COMMAND_RELOAD_CONFIG)
@@ -894,14 +896,15 @@ namespace http {
i2p::context.SetAcceptsTunnels (false);
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
Daemon.gracefulShutdownInterval = 10*60;
-#endif
-#ifdef WIN32_APP
+#elif defined(WIN32_APP)
i2p::win32::GracefulShutdown ();
#endif
} else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) {
i2p::context.SetAcceptsTunnels (true);
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
Daemon.gracefulShutdownInterval = 0;
+#elif defined(WIN32_APP)
+ i2p::win32::StopGracefulShutdown ();
#endif
} else if (cmd == HTTP_COMMAND_SHUTDOWN_NOW) {
Daemon.running = false;
@@ -940,7 +943,7 @@ namespace http {
void HTTPServer::Start ()
{
- bool needAuth; i2p::config::GetOption("http.auth", needAuth);
+ bool needAuth; i2p::config::GetOption("http.auth", needAuth);
std::string user; i2p::config::GetOption("http.user", user);
std::string pass; i2p::config::GetOption("http.pass", pass);
/* generate pass if needed */
@@ -968,7 +971,7 @@ namespace http {
m_IsRunning = false;
m_Acceptor.close();
m_Service.stop ();
- if (m_Thread)
+ if (m_Thread)
{
m_Thread->join ();
m_Thread = nullptr;
@@ -986,7 +989,7 @@ namespace http {
catch (std::exception& ex)
{
LogPrint (eLogError, "HTTPServer: runtime exception: ", ex.what ());
- }
+ }
}
}
@@ -997,7 +1000,7 @@ namespace http {
boost::asio::placeholders::error, newSocket));
}
- void HTTPServer::HandleAccept(const boost::system::error_code& ecode,
+ void HTTPServer::HandleAccept(const boost::system::error_code& ecode,
std::shared_ptr newSocket)
{
if (ecode)
@@ -1005,7 +1008,7 @@ namespace http {
if(newSocket) newSocket->close();
LogPrint(eLogError, "HTTP Server: error handling accept ", ecode.message());
if(ecode != boost::asio::error::operation_aborted)
- Accept();
+ Accept();
return;
}
CreateConnection(newSocket);