Merge pull request #986 from PurpleI2P/openssl

recent changes
This commit is contained in:
orignal 2017-11-02 14:45:47 -04:00 committed by GitHub
commit 42483b6f32
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
71 changed files with 6849 additions and 4347 deletions

2
.gitignore vendored
View file

@ -262,3 +262,5 @@ qt/i2pd_qt/*.ui.autosave
qt/i2pd_qt/*.ui.bk* qt/i2pd_qt/*.ui.bk*
qt/i2pd_qt/*.ui_* qt/i2pd_qt/*.ui_*
#unknown android stuff
android/libs/

View file

@ -89,14 +89,14 @@ $(SHLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
$(CXX) $(LDFLAGS) $(LDLIBS) -shared -o $@ $^ $(CXX) $(LDFLAGS) $(LDLIBS) -shared -o $@ $^
$(ARLIB): $(patsubst %.cpp,obj/%.o,$(LIB_SRC)) $(ARLIB): $(patsubst %.cpp,obj/%.o,$(LIB_SRC))
ar -r $@ $^ $(AR) -r $@ $^
$(ARLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC)) $(ARLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
ar -r $@ $^ $(AR) -r $@ $^
clean: clean:
rm -rf obj $(RM) -r obj
rm -rf docs/generated $(RM) -r docs/generated
$(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) $(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT)
strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB) strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB)

View file

@ -1,17 +1,29 @@
# root directory holding homebrew # root directory holding homebrew
BREWROOT = /usr/local/ BREWROOT = /usr/local
BOOSTROOT = ${BREWROOT}/opt/boost BOOSTROOT = ${BREWROOT}/opt/boost
SSLROOT = ${BREWROOT}/opt/libressl SSLROOT = ${BREWROOT}/opt/libressl
UPNPROOT = ${BREWROOT}/opt/miniupnpc
CXX = clang++ CXX = clang++
CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX -Wno-overloaded-virtual
INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include
ifeq ($(USE_STATIC),yes)
LDLIBS = -lz ${SSLROOT}/lib/libcrypto.a ${SSLROOT}/lib/libssl.a ${BOOSTROOT}/lib/libboost_system.a ${BOOSTROOT}/lib/libboost_date_time.a ${BOOSTROOT}/lib/libboost_filesystem.a ${BOOSTROOT}/lib/libboost_program_options.a -lpthread
else
LDFLAGS = -L${SSLROOT}/lib -L${BOOSTROOT}/lib LDFLAGS = -L${SSLROOT}/lib -L${BOOSTROOT}/lib
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
endif
ifeq ($(USE_UPNP),yes) ifeq ($(USE_UPNP),yes)
LDFLAGS += -ldl LDFLAGS += -ldl
CXXFLAGS += -DUSE_UPNP CXXFLAGS += -DUSE_UPNP
LDLIBS += -lminiupnpc INCFLAGS += -I${UPNPROOT}/include
ifeq ($(USE_STATIC),yes)
LDLIBS += ${UPNPROOT}/lib/libminiupnpc.a
else
LDFLAGS += -L${UPNPROOT}/lib
LDLIBS += -lminiupnpc
endif
endif endif
# OSX Notes # OSX Notes

View file

@ -47,8 +47,7 @@ ifeq ($(USE_AVX),1)
endif endif
ifeq ($(USE_ASLR),yes) ifeq ($(USE_ASLR),yes)
LDFLAGS += -Wl,--nxcompat -Wl,--high-entropy-va \ LDFLAGS += -Wl,--nxcompat -Wl,--high-entropy-va -Wl,--dynamicbase,--export-all-symbols
-Wl,--dynamicbase,--export-all-symbols
endif endif
obj/%.o : %.rc obj/%.o : %.rc

View file

@ -6,7 +6,6 @@
#include "Log.h" #include "Log.h"
#ifdef _WIN32 #ifdef _WIN32
#include "Win32/Win32Service.h" #include "Win32/Win32Service.h"
#ifdef WIN32_APP #ifdef WIN32_APP
#include "Win32/Win32App.h" #include "Win32/Win32App.h"
@ -14,99 +13,99 @@
namespace i2p 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");
if (!Daemon_Singleton::init(argc, argv))
return false;
std::string serviceControl; i2p::config::GetOption("svcctl", serviceControl);
if (serviceControl == "install")
{ {
setlocale(LC_CTYPE, ""); LogPrint(eLogInfo, "WinSVC: installing ", SERVICE_NAME, " as service");
SetConsoleCP(1251); InstallService(
SetConsoleOutputCP(1251); SERVICE_NAME, // Name of service
setlocale(LC_ALL, "Russian"); SERVICE_DISPLAY_NAME, // Name to display
SERVICE_START_TYPE, // Service start type
if (!Daemon_Singleton::init(argc, argv)) SERVICE_DEPENDENCIES, // Dependencies
return false; SERVICE_ACCOUNT, // Service running account
SERVICE_PASSWORD // Password of the account
std::string serviceControl; i2p::config::GetOption("svcctl", serviceControl); );
if (serviceControl == "install") return false;
{ }
LogPrint(eLogInfo, "WinSVC: installing ", SERVICE_NAME, " as service"); else if (serviceControl == "remove")
InstallService( {
SERVICE_NAME, // Name of service LogPrint(eLogInfo, "WinSVC: uninstalling ", SERVICE_NAME, " service");
SERVICE_DISPLAY_NAME, // Name to display UninstallService(SERVICE_NAME);
SERVICE_START_TYPE, // Service start type return false;
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)
{
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;
}
return false;
}
else
LogPrint(eLogDebug, "Daemon: running as user");
return true;
} }
bool DaemonWin32::start() if (isDaemon)
{ {
setlocale(LC_CTYPE, ""); LogPrint(eLogDebug, "Daemon: running as service");
SetConsoleCP(1251); I2PService service(SERVICE_NAME);
SetConsoleOutputCP(1251); if (!I2PService::Run(service))
setlocale(LC_ALL, "Russian"); {
#ifdef WIN32_APP LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
if (!i2p::win32::StartWin32App ()) return false; return false;
}
return false;
}
else
LogPrint(eLogDebug, "Daemon: running as user");
return true;
}
// override log bool DaemonWin32::start()
i2p::config::SetOption("log", std::string ("file")); {
setlocale(LC_CTYPE, "");
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
setlocale(LC_ALL, "Russian");
#ifdef WIN32_APP
if (!i2p::win32::StartWin32App ()) return false;
// override log
i2p::config::SetOption("log", std::string ("file"));
#endif #endif
bool ret = Daemon_Singleton::start(); bool ret = Daemon_Singleton::start();
if (ret && i2p::log::Logger().GetLogType() == eLogFile) 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()
{ {
// 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()
{
#ifdef WIN32_APP #ifdef WIN32_APP
i2p::win32::StopWin32App (); i2p::win32::StopWin32App ();
#endif #endif
return Daemon_Singleton::stop(); return Daemon_Singleton::stop();
} }
void DaemonWin32::run () void DaemonWin32::run ()
{ {
#ifdef WIN32_APP #ifdef WIN32_APP
i2p::win32::RunWin32App (); i2p::win32::RunWin32App ();
#else #else
while (running) while (running)
{ {
std::this_thread::sleep_for (std::chrono::seconds(1)); std::this_thread::sleep_for (std::chrono::seconds(1));
} }
#endif #endif
}
} }
} }
#endif }
#endif //_WIN32

View file

@ -9,6 +9,7 @@
#include "Tunnel.h" #include "Tunnel.h"
#include "version.h" #include "version.h"
#include "resource.h" #include "resource.h"
#include "Daemon.h"
#include "Win32App.h" #include "Win32App.h"
#include <stdio.h> #include <stdio.h>
@ -21,6 +22,8 @@
#define ID_CONSOLE 2002 #define ID_CONSOLE 2002
#define ID_APP 2003 #define ID_APP 2003
#define ID_GRACEFUL_SHUTDOWN 2004 #define ID_GRACEFUL_SHUTDOWN 2004
#define ID_STOP_GRACEFUL_SHUTDOWN 2005
#define ID_RELOAD 2006
#define ID_TRAY_ICON 2050 #define ID_TRAY_ICON 2050
#define WM_TRAYICON (WM_USER + 1) #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_APP, "Show app");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About..."); 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_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"); InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_EXIT, "E&xit");
SetMenuDefaultItem (hPopup, ID_CONSOLE, FALSE); SetMenuDefaultItem (hPopup, ID_CONSOLE, FALSE);
SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0); SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0);
@ -68,7 +75,7 @@ namespace win32
nid.uCallbackMessage = WM_TRAYICON; nid.uCallbackMessage = WM_TRAYICON;
nid.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE (MAINICON)); nid.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE (MAINICON));
strcpy (nid.szTip, "i2pd"); strcpy (nid.szTip, "i2pd");
strcpy (nid.szInfo, "i2pd is running"); strcpy (nid.szInfo, "i2pd is starting");
Shell_NotifyIcon(NIM_ADD, &nid ); Shell_NotifyIcon(NIM_ADD, &nid );
} }
@ -120,6 +127,7 @@ namespace win32
static void PrintMainWindowText (std::stringstream& s) static void PrintMainWindowText (std::stringstream& s)
{ {
s << "\n";
s << "Status: "; s << "Status: ";
switch (i2p::context.GetStatus()) switch (i2p::context.GetStatus())
{ {
@ -153,6 +161,7 @@ namespace win32
s << "In: " << i2p::tunnel::tunnels.CountInboundTunnels() << "; "; s << "In: " << i2p::tunnel::tunnels.CountInboundTunnels() << "; ";
s << "Out: " << i2p::tunnel::tunnels.CountOutboundTunnels() << "; "; s << "Out: " << i2p::tunnel::tunnels.CountOutboundTunnels() << "; ";
s << "Transit: " << i2p::tunnel::tunnels.CountTransitTunnels() << "\n"; s << "Transit: " << i2p::tunnel::tunnels.CountTransitTunnels() << "\n";
s << "\n";
} }
static LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) static LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
@ -192,6 +201,22 @@ namespace win32
{ {
i2p::context.SetAcceptsTunnels (false); i2p::context.SetAcceptsTunnels (false);
SetTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER, 10*60*1000, nullptr); // 10 minutes 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; return 0;
} }
case ID_CONSOLE: case ID_CONSOLE:
@ -322,7 +347,7 @@ namespace win32
wclx.lpszClassName = I2PD_WIN32_CLASSNAME; wclx.lpszClassName = I2PD_WIN32_CLASSNAME;
RegisterClassEx (&wclx); RegisterClassEx (&wclx);
// create new window // 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); MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
return false; return false;
@ -353,5 +378,14 @@ namespace win32
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_GRACEFUL_SHUTDOWN, 0), 0); PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_GRACEFUL_SHUTDOWN, 0), 0);
return hWnd; 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;
}
} }
} }

View file

@ -7,10 +7,11 @@ namespace i2p
{ {
namespace win32 namespace win32
{ {
bool StartWin32App (); bool StartWin32App ();
void StopWin32App (); void StopWin32App ();
int RunWin32App (); int RunWin32App ();
bool GracefulShutdown (); bool GracefulShutdown ();
bool StopGracefulShutdown ();
} }
} }
#endif // WIN32APP_H__ #endif // WIN32APP_H__

View file

@ -15,7 +15,6 @@ I2PService *I2PService::s_service = NULL;
BOOL I2PService::isService() BOOL I2PService::isService()
{ {
BOOL bIsService = FALSE; BOOL bIsService = FALSE;
HWINSTA hWinStation = GetProcessWindowStation(); HWINSTA hWinStation = GetProcessWindowStation();
if (hWinStation != NULL) if (hWinStation != NULL)
{ {
@ -31,28 +30,23 @@ BOOL I2PService::isService()
BOOL I2PService::Run(I2PService &service) BOOL I2PService::Run(I2PService &service)
{ {
s_service = &service; s_service = &service;
SERVICE_TABLE_ENTRY serviceTable[] = SERVICE_TABLE_ENTRY serviceTable[] =
{ {
{ service.m_name, ServiceMain }, { service.m_name, ServiceMain },
{ NULL, NULL } { NULL, NULL }
}; };
return StartServiceCtrlDispatcher(serviceTable); return StartServiceCtrlDispatcher(serviceTable);
} }
void WINAPI I2PService::ServiceMain(DWORD dwArgc, PSTR *pszArgv) void WINAPI I2PService::ServiceMain(DWORD dwArgc, PSTR *pszArgv)
{ {
assert(s_service != NULL); assert(s_service != NULL);
s_service->m_statusHandle = RegisterServiceCtrlHandler( s_service->m_statusHandle = RegisterServiceCtrlHandler(
s_service->m_name, ServiceCtrlHandler); s_service->m_name, ServiceCtrlHandler);
if (s_service->m_statusHandle == NULL) if (s_service->m_statusHandle == NULL)
{ {
throw GetLastError(); throw GetLastError();
} }
s_service->Start(dwArgc, pszArgv); s_service->Start(dwArgc, pszArgv);
} }
@ -61,12 +55,12 @@ void WINAPI I2PService::ServiceCtrlHandler(DWORD dwCtrl)
{ {
switch (dwCtrl) switch (dwCtrl)
{ {
case SERVICE_CONTROL_STOP: s_service->Stop(); break; case SERVICE_CONTROL_STOP: s_service->Stop(); break;
case SERVICE_CONTROL_PAUSE: s_service->Pause(); break; case SERVICE_CONTROL_PAUSE: s_service->Pause(); break;
case SERVICE_CONTROL_CONTINUE: s_service->Continue(); break; case SERVICE_CONTROL_CONTINUE: s_service->Continue(); break;
case SERVICE_CONTROL_SHUTDOWN: s_service->Shutdown(); break; case SERVICE_CONTROL_SHUTDOWN: s_service->Shutdown(); break;
case SERVICE_CONTROL_INTERROGATE: break; case SERVICE_CONTROL_INTERROGATE: break;
default: break; default: break;
} }
} }
@ -76,11 +70,8 @@ I2PService::I2PService(PSTR pszServiceName,
BOOL fCanPauseContinue) BOOL fCanPauseContinue)
{ {
m_name = (pszServiceName == NULL) ? (PSTR)"" : pszServiceName; m_name = (pszServiceName == NULL) ? (PSTR)"" : pszServiceName;
m_statusHandle = NULL; m_statusHandle = NULL;
m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
m_status.dwCurrentState = SERVICE_START_PENDING; m_status.dwCurrentState = SERVICE_START_PENDING;
DWORD dwControlsAccepted = 0; DWORD dwControlsAccepted = 0;
@ -90,15 +81,13 @@ I2PService::I2PService(PSTR pszServiceName,
dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN; dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
if (fCanPauseContinue) if (fCanPauseContinue)
dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE; dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
m_status.dwControlsAccepted = dwControlsAccepted;
m_status.dwControlsAccepted = dwControlsAccepted;
m_status.dwWin32ExitCode = NO_ERROR; m_status.dwWin32ExitCode = NO_ERROR;
m_status.dwServiceSpecificExitCode = 0; m_status.dwServiceSpecificExitCode = 0;
m_status.dwCheckPoint = 0; m_status.dwCheckPoint = 0;
m_status.dwWaitHint = 0; m_status.dwWaitHint = 0;
m_fStopping = FALSE; m_fStopping = FALSE;
// Create a manual-reset event that is not signaled at first to indicate // Create a manual-reset event that is not signaled at first to indicate
// the stopped signal of the service. // the stopped signal of the service.
m_hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL); m_hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
@ -108,7 +97,6 @@ I2PService::I2PService(PSTR pszServiceName,
} }
} }
I2PService::~I2PService(void) I2PService::~I2PService(void)
{ {
if (m_hStoppedEvent) if (m_hStoppedEvent)
@ -118,92 +106,73 @@ I2PService::~I2PService(void)
} }
} }
void I2PService::Start(DWORD dwArgc, PSTR *pszArgv) void I2PService::Start(DWORD dwArgc, PSTR *pszArgv)
{ {
try try
{ {
SetServiceStatus(SERVICE_START_PENDING); SetServiceStatus(SERVICE_START_PENDING);
OnStart(dwArgc, pszArgv); OnStart(dwArgc, pszArgv);
SetServiceStatus(SERVICE_RUNNING); SetServiceStatus(SERVICE_RUNNING);
} }
catch (DWORD dwError) catch (DWORD dwError)
{ {
LogPrint(eLogError, "Win32Service Start", dwError); LogPrint(eLogError, "Win32Service Start", dwError);
SetServiceStatus(SERVICE_STOPPED, dwError); SetServiceStatus(SERVICE_STOPPED, dwError);
} }
catch (...) catch (...)
{ {
LogPrint(eLogError, "Win32Service failed to start.", EVENTLOG_ERROR_TYPE); LogPrint(eLogError, "Win32Service failed to start.", EVENTLOG_ERROR_TYPE);
SetServiceStatus(SERVICE_STOPPED); SetServiceStatus(SERVICE_STOPPED);
} }
} }
void I2PService::OnStart(DWORD dwArgc, PSTR *pszArgv) void I2PService::OnStart(DWORD dwArgc, PSTR *pszArgv)
{ {
LogPrint(eLogInfo, "Win32Service in OnStart", EVENTLOG_INFORMATION_TYPE); LogPrint(eLogInfo, "Win32Service in OnStart", EVENTLOG_INFORMATION_TYPE);
Daemon.start(); Daemon.start();
//i2p::util::config::OptionParser(dwArgc, pszArgv); //i2p::util::config::OptionParser(dwArgc, pszArgv);
//i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs); //i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs);
//i2p::context.OverrideNTCPAddress(i2p::util::config::GetCharArg("-host", "127.0.0.1"), //i2p::context.OverrideNTCPAddress(i2p::util::config::GetCharArg("-host", "127.0.0.1"),
// i2p::util::config::GetArg("-port", 17070)); // i2p::util::config::GetArg("-port", 17070));
_worker = new std::thread(std::bind(&I2PService::WorkerThread, this)); _worker = new std::thread(std::bind(&I2PService::WorkerThread, this));
} }
void I2PService::WorkerThread() void I2PService::WorkerThread()
{ {
while (!m_fStopping) while (!m_fStopping)
{ {
::Sleep(1000); // Simulate some lengthy operations. ::Sleep(1000); // Simulate some lengthy operations.
} }
// Signal the stopped event. // Signal the stopped event.
SetEvent(m_hStoppedEvent); SetEvent(m_hStoppedEvent);
} }
void I2PService::Stop() void I2PService::Stop()
{ {
DWORD dwOriginalState = m_status.dwCurrentState; DWORD dwOriginalState = m_status.dwCurrentState;
try try
{ {
SetServiceStatus(SERVICE_STOP_PENDING); SetServiceStatus(SERVICE_STOP_PENDING);
OnStop(); OnStop();
SetServiceStatus(SERVICE_STOPPED); SetServiceStatus(SERVICE_STOPPED);
} }
catch (DWORD dwError) catch (DWORD dwError)
{ {
LogPrint(eLogInfo, "Win32Service Stop", dwError); LogPrint(eLogInfo, "Win32Service Stop", dwError);
SetServiceStatus(dwOriginalState); SetServiceStatus(dwOriginalState);
} }
catch (...) catch (...)
{ {
LogPrint(eLogError, "Win32Service failed to stop.", EVENTLOG_ERROR_TYPE); LogPrint(eLogError, "Win32Service failed to stop.", EVENTLOG_ERROR_TYPE);
SetServiceStatus(dwOriginalState); SetServiceStatus(dwOriginalState);
} }
} }
void I2PService::OnStop() void I2PService::OnStop()
{ {
// Log a service stop message to the Application log. // Log a service stop message to the Application log.
LogPrint(eLogInfo, "Win32Service in OnStop", EVENTLOG_INFORMATION_TYPE); LogPrint(eLogInfo, "Win32Service in OnStop", EVENTLOG_INFORMATION_TYPE);
Daemon.stop(); Daemon.stop();
m_fStopping = TRUE; m_fStopping = TRUE;
if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0) if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0)
{ {
@ -213,57 +182,46 @@ void I2PService::OnStop()
delete _worker; delete _worker;
} }
void I2PService::Pause() void I2PService::Pause()
{ {
try try
{ {
SetServiceStatus(SERVICE_PAUSE_PENDING); SetServiceStatus(SERVICE_PAUSE_PENDING);
OnPause(); OnPause();
SetServiceStatus(SERVICE_PAUSED); SetServiceStatus(SERVICE_PAUSED);
} }
catch (DWORD dwError) catch (DWORD dwError)
{ {
LogPrint(eLogError, "Win32Service Pause", dwError); LogPrint(eLogError, "Win32Service Pause", dwError);
SetServiceStatus(SERVICE_RUNNING); SetServiceStatus(SERVICE_RUNNING);
} }
catch (...) catch (...)
{ {
LogPrint(eLogError, "Win32Service failed to pause.", EVENTLOG_ERROR_TYPE); LogPrint(eLogError, "Win32Service failed to pause.", EVENTLOG_ERROR_TYPE);
SetServiceStatus(SERVICE_RUNNING); SetServiceStatus(SERVICE_RUNNING);
} }
} }
void I2PService::OnPause() void I2PService::OnPause()
{ {
} }
void I2PService::Continue() void I2PService::Continue()
{ {
try try
{ {
SetServiceStatus(SERVICE_CONTINUE_PENDING); SetServiceStatus(SERVICE_CONTINUE_PENDING);
OnContinue(); OnContinue();
SetServiceStatus(SERVICE_RUNNING); SetServiceStatus(SERVICE_RUNNING);
} }
catch (DWORD dwError) catch (DWORD dwError)
{ {
LogPrint(eLogError, "Win32Service Continue", dwError); LogPrint(eLogError, "Win32Service Continue", dwError);
SetServiceStatus(SERVICE_PAUSED); SetServiceStatus(SERVICE_PAUSED);
} }
catch (...) catch (...)
{ {
LogPrint(eLogError, "Win32Service failed to resume.", EVENTLOG_ERROR_TYPE); LogPrint(eLogError, "Win32Service failed to resume.", EVENTLOG_ERROR_TYPE);
SetServiceStatus(SERVICE_PAUSED); SetServiceStatus(SERVICE_PAUSED);
} }
} }
@ -277,7 +235,6 @@ void I2PService::Shutdown()
try try
{ {
OnShutdown(); OnShutdown();
SetServiceStatus(SERVICE_STOPPED); SetServiceStatus(SERVICE_STOPPED);
} }
catch (DWORD dwError) catch (DWORD dwError)
@ -299,11 +256,9 @@ void I2PService::SetServiceStatus(DWORD dwCurrentState,
DWORD dwWaitHint) DWORD dwWaitHint)
{ {
static DWORD dwCheckPoint = 1; static DWORD dwCheckPoint = 1;
m_status.dwCurrentState = dwCurrentState; m_status.dwCurrentState = dwCurrentState;
m_status.dwWin32ExitCode = dwWin32ExitCode; m_status.dwWin32ExitCode = dwWin32ExitCode;
m_status.dwWaitHint = dwWaitHint; m_status.dwWaitHint = dwWaitHint;
m_status.dwCheckPoint = m_status.dwCheckPoint =
((dwCurrentState == SERVICE_RUNNING) || ((dwCurrentState == SERVICE_RUNNING) ||
(dwCurrentState == SERVICE_STOPPED)) ? (dwCurrentState == SERVICE_STOPPED)) ?
@ -328,7 +283,7 @@ void FreeHandles(SC_HANDLE schSCManager, SC_HANDLE schService)
} }
} }
void InstallService(PSTR pszServiceName, PSTR pszDisplayName, DWORD dwStartType, PSTR pszDependencies, PSTR pszAccount, PSTR pszPassword) void InstallService(PCSTR pszServiceName, PCSTR pszDisplayName, DWORD dwStartType, PCSTR pszDependencies, PCSTR pszAccount, PCSTR pszPassword)
{ {
printf("Try to install Win32Service (%s).\n", pszServiceName); printf("Try to install Win32Service (%s).\n", pszServiceName);
@ -383,7 +338,7 @@ void InstallService(PSTR pszServiceName, PSTR pszDisplayName, DWORD dwStartType,
FreeHandles(schSCManager, schService); FreeHandles(schSCManager, schService);
} }
void UninstallService(PSTR pszServiceName) void UninstallService(PCSTR pszServiceName)
{ {
printf("Try to uninstall Win32Service (%s).\n", pszServiceName); printf("Try to uninstall Win32Service (%s).\n", pszServiceName);

View file

@ -4,7 +4,6 @@
#include <thread> #include <thread>
#include <windows.h> #include <windows.h>
#ifdef _WIN32 #ifdef _WIN32
// Internal name of the service // Internal name of the service
#define SERVICE_NAME "i2pdService" #define SERVICE_NAME "i2pdService"
@ -25,7 +24,6 @@
#define SERVICE_PASSWORD NULL #define SERVICE_PASSWORD NULL
#endif #endif
class I2PService class I2PService
{ {
public: public:
@ -72,13 +70,15 @@ private:
std::thread* _worker; std::thread* _worker;
}; };
void InstallService(PSTR pszServiceName, void InstallService(
PSTR pszDisplayName, PCSTR pszServiceName,
PCSTR pszDisplayName,
DWORD dwStartType, DWORD dwStartType,
PSTR pszDependencies, PCSTR pszDependencies,
PSTR pszAccount, PCSTR pszAccount,
PSTR pszPassword); PCSTR pszPassword
);
void UninstallService(PSTR pszServiceName); void UninstallService(PCSTR pszServiceName);
#endif // WIN_32_SERVICE_H__ #endif // WIN_32_SERVICE_H__

View file

@ -1,6 +1,7 @@
#APP_ABI := all #APP_ABI := all
#APP_ABI := armeabi-v7a x86 #APP_ABI := armeabi-v7a x86
#APP_ABI := x86 #APP_ABI := x86
#APP_ABI := x86_64
APP_ABI := armeabi-v7a APP_ABI := armeabi-v7a
#can be android-3 but will fail for x86 since arch-x86 is not present at ndkroot/platforms/android-3/ . libz is taken from there. #can be android-3 but will fail for x86 since arch-x86 is not present at ndkroot/platforms/android-3/ . libz is taken from there.
APP_PLATFORM := android-14 APP_PLATFORM := android-14

View file

@ -178,6 +178,9 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
endif () endif ()
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# more tweaks # more tweaks
if (NOT (MSVC OR MSYS OR APPLE))
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++" )
endif()
endif () endif ()
if (WITH_HARDENING AND MSVC) if (WITH_HARDENING AND MSVC)
@ -322,6 +325,10 @@ endif()
find_package ( OpenSSL REQUIRED ) find_package ( OpenSSL REQUIRED )
if(NOT DEFINED OPENSSL_INCLUDE_DIR) if(NOT DEFINED OPENSSL_INCLUDE_DIR)
message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!") message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!")
else()
if(NOT (OPENSSL_VERSION VERSION_LESS 1.1))
message(WARNING "Your OpenSSL version ${OPENSSL_VERSION} >=1.1 is experimental: build with v1.0 when possible.")
endif()
endif() endif()
if (WITH_UPNP) if (WITH_UPNP)
@ -393,7 +400,7 @@ message(STATUS " UPnP : ${WITH_UPNP}")
message(STATUS " PCH : ${WITH_PCH}") message(STATUS " PCH : ${WITH_PCH}")
message(STATUS " MESHNET : ${WITH_MESHNET}") message(STATUS " MESHNET : ${WITH_MESHNET}")
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}") message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
message(STATUS " THEADSANITIZER : ${WITH_THREADSANITIZER}") message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
message(STATUS " I2LUA : ${WITH_I2LUA}") message(STATUS " I2LUA : ${WITH_I2LUA}")
message(STATUS " WEBSOCKETS : ${WITH_WEBSOCKETS}") message(STATUS " WEBSOCKETS : ${WITH_WEBSOCKETS}")
message(STATUS "---------------------------------------") message(STATUS "---------------------------------------")
@ -453,6 +460,12 @@ if (WITH_BINARY)
fixup_bundle(\"${APPS}\" \"\" \"${DIRS}\") fixup_bundle(\"${APPS}\" \"\" \"${DIRS}\")
" COMPONENT Runtime) " COMPONENT Runtime)
endif () endif ()
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
if (NOT (MSVC OR MSYS OR APPLE)) # for Clang build on Linux
target_link_libraries("${PROJECT_NAME}" stdc++)
endif()
endif()
endif () endif ()
install(FILES ../LICENSE install(FILES ../LICENSE

View file

@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFvjCCA6agAwIBAgIQIDtv8tGMh0FyB2w5XjfZxTANBgkqhkiG9w0BAQsFADBt
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEWMBQGA1UEAwwN
aWdvckBub3ZnLm5ldDAeFw0xNzA3MjQxODI4NThaFw0yNzA3MjQxODI4NThaMG0x
CzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxHjAcBgNVBAoT
FUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRYwFAYDVQQDDA1p
Z29yQG5vdmcubmV0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxst4
cam3YibBtQHGPCPX13uRQti56U3XZytSZntaKrUFmJxjt41Q/mOy3KYo+lBvhfDF
x3tWKjgP9LJOJ28zvddFhZVNxqZRjcnAoPuSOVCw88g01D9OAasKF11hCfdxZP6h
vGm8WCnjD8KPcYFxJC4HJUiFeProAwuTzEAESTRk4CAQe3Ie91JspuqoLUc5Qxlm
w5QpjnjfZY4kaVHmZDKGIZDgNIt5v85bu4pWwZ6O+o90xQqjxvjyz/xccIec3sHw
MHJ8h8ZKMokCKEJTaRWBvdeNXki7nf3gUy/3GjYQlzo0Nxk/Hw4svPcA+eL0AYiy
Jn83bIB5VToW2zYUdV4u3qHeAhEg8Y7HI0kKcSUGm9AQXzbzP8YCHxi0sbb0GAJy
f1Xf3XzoPfT64giD8ReUHhwKpyMB6uvG/NfWSZAzeAO/NT7DAwXpKIVQdkVdqy8b
mvHvjf9/kWKOirA2Nygf3r79Vbg2mqbYC/b63XI9hheU689+O7qyhTEhNz+11X0d
Zax7UPrLrwOeB9TNfEnztsmrHNdv2n+KcOO2o11Wvz2nHP9g+dgwoZSD1ZEpFzWP
0sD5knKLwAL/64qLlAQ1feqW7hMr80IADcKjLSODkIDIIGm0ksXqEzTjz1JzbRDq
jUjq7EAlkw3G69rv1gHxIntllJRQidAqecyWHOMCAwEAAaNaMFgwDgYDVR0PAQH/
BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8E
BTADAQH/MBYGA1UdDgQPBA1pZ29yQG5vdmcubmV0MA0GCSqGSIb3DQEBCwUAA4IC
AQADyPaec28qc1HQtAV5dscJr47k92RTfvan+GEgIwyQDHZQm38eyTb05xipQCdk
5ruUDFXLB5qXXFJKUbQM6IpaktmWDJqk4Zn+1nGbtFEbKgrF55pd63+NQer5QW9o
3+dGj0eZJa3HX5EBkd2r7j2LFuB6uxv3r/xiTeHaaflCnsmyDLfb7axvYhyEzHQS
AUi1bR+ln+dXewdtuojqc1+YmVGDgzWZK2T0oOz2E21CpZUDiP3wv9QfMaotLEal
zECnbhS++q889inN3GB4kIoN6WpPpeYtTV+/r7FLv9+KUOV1s2z6mxIqC5wBFhZs
0Sr1kVo8hB/EW/YYhDp99LoAOjIO6nn1h+qttfzBYr6C16j+8lGK2A12REJ4LiUQ
cQI/0zTjt2C8Ns6ueNzMLQN1Mvmlg1Z8wIB7Az7jsIbY2zFJ0M5qR5VJveTj33K4
4WSbC/zMWOBYHTVBvGmc6JGhu5ZUTZ+mWP7QfimGu+tdhvtrybFjE9ROIE/4yFr6
GkxEyt0UY87TeKXJ/3KygvkMwdvqGWiZhItb807iy99+cySujtbGfF2ZXYGjBXVW
dJOVRbyGQkHh6lrWHQM4ntBv4x+5QA+OAan5PBF3tcDx1vefPx+asYslbOXpzII5
qhvoQxuRs6j5jsVFG6RdsKNeQAt87Mb2u2zK2ZakMdyD1w==
-----END CERTIFICATE-----

View file

@ -94,8 +94,12 @@ namespace i2p
std::string logs = ""; i2p::config::GetOption("log", logs); std::string logs = ""; i2p::config::GetOption("log", logs);
std::string logfile = ""; i2p::config::GetOption("logfile", logfile); std::string logfile = ""; i2p::config::GetOption("logfile", logfile);
std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel); std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel);
bool logclftime; i2p::config::GetOption("logclftime", logclftime);
/* setup logging */ /* setup logging */
if (logclftime)
i2p::log::Logger().SetTimeFormat ("[%d/%b/%Y:%H:%M:%S %z]");
if (isDaemon && (logs == "" || logs == "stdout")) if (isDaemon && (logs == "" || logs == "stdout"))
logs = "file"; logs = "file";

View file

@ -6,11 +6,11 @@
namespace i2p namespace i2p
{ {
namespace util namespace util
{
class Daemon_Singleton_Private;
class Daemon_Singleton
{ {
class Daemon_Singleton_Private;
class Daemon_Singleton
{
public: public:
virtual bool init(int argc, char* argv[]); virtual bool init(int argc, char* argv[]);
virtual bool start(); virtual bool start();
@ -29,40 +29,38 @@ namespace i2p
// d-pointer for httpServer, httpProxy, etc. // d-pointer for httpServer, httpProxy, etc.
class Daemon_Singleton_Private; class Daemon_Singleton_Private;
Daemon_Singleton_Private &d; Daemon_Singleton_Private &d;
}; };
#if defined(QT_GUI_LIB) // check if QT #if defined(QT_GUI_LIB) // check if QT
#define Daemon i2p::util::DaemonQT::Instance() #define Daemon i2p::util::DaemonQT::Instance()
// dummy, invoked from RunQT // dummy, invoked from RunQT
class DaemonQT: public i2p::util::Daemon_Singleton class DaemonQT: public i2p::util::Daemon_Singleton
{ {
public: public:
static DaemonQT& Instance() static DaemonQT& Instance()
{ {
static DaemonQT instance; static DaemonQT instance;
return instance; return instance;
} }
}; };
#elif defined(ANDROID) #elif defined(ANDROID)
#define Daemon i2p::util::DaemonAndroid::Instance() #define Daemon i2p::util::DaemonAndroid::Instance()
// dummy, invoked from android/jni/DaemonAndroid.* // dummy, invoked from android/jni/DaemonAndroid.*
class DaemonAndroid: public i2p::util::Daemon_Singleton class DaemonAndroid: public i2p::util::Daemon_Singleton
{ {
public: public:
static DaemonAndroid& Instance() static DaemonAndroid& Instance()
{ {
static DaemonAndroid instance; static DaemonAndroid instance;
return instance; return instance;
} }
}; };
#elif defined(_WIN32) #elif defined(_WIN32)
#define Daemon i2p::util::DaemonWin32::Instance() #define Daemon i2p::util::DaemonWin32::Instance()
class DaemonWin32 : public Daemon_Singleton class DaemonWin32 : public Daemon_Singleton
{ {
public: public:
static DaemonWin32& Instance() static DaemonWin32& Instance()
{ {
@ -74,34 +72,36 @@ namespace i2p
bool start(); bool start();
bool stop(); bool stop();
void run (); void run ();
};
bool isGraceful;
DaemonWin32 ():isGraceful(false) {}
};
#else #else
#define Daemon i2p::util::DaemonLinux::Instance() #define Daemon i2p::util::DaemonLinux::Instance()
class DaemonLinux : public Daemon_Singleton class DaemonLinux : public Daemon_Singleton
{ {
public: public:
static DaemonLinux& Instance() static DaemonLinux& Instance()
{ {
static DaemonLinux instance; static DaemonLinux instance;
return instance; return instance;
} }
bool start(); bool start();
bool stop(); bool stop();
void run (); void run ();
private: private:
std::string pidfile;
int pidFH;
std::string pidfile; public:
int pidFH; int gracefulShutdownInterval; // in seconds
};
public:
int gracefulShutdownInterval; // in seconds
};
#endif #endif
} }
} }
#endif // DAEMON_H__ #endif // DAEMON_H__

View file

@ -83,7 +83,7 @@ namespace http {
const char HTTP_COMMAND_DISABLE_TRANSIT[] = "disable_transit"; const char HTTP_COMMAND_DISABLE_TRANSIT[] = "disable_transit";
const char HTTP_COMMAND_SHUTDOWN_START[] = "shutdown_start"; const char HTTP_COMMAND_SHUTDOWN_START[] = "shutdown_start";
const char HTTP_COMMAND_SHUTDOWN_CANCEL[] = "shutdown_cancel"; const char HTTP_COMMAND_SHUTDOWN_CANCEL[] = "shutdown_cancel";
const char HTTP_COMMAND_SHUTDOWN_NOW[] = "terminate"; const char HTTP_COMMAND_SHUTDOWN_NOW[] = "terminate";
const char HTTP_COMMAND_RUN_PEER_TEST[] = "run_peer_test"; const char HTTP_COMMAND_RUN_PEER_TEST[] = "run_peer_test";
const char HTTP_COMMAND_RELOAD_CONFIG[] = "reload_config"; const char HTTP_COMMAND_RELOAD_CONFIG[] = "reload_config";
const char HTTP_PARAM_SAM_SESSION_ID[] = "id"; const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
@ -185,7 +185,7 @@ namespace http {
s << "<b>ERROR:</b>&nbsp;" << string << "<br>\r\n"; s << "<b>ERROR:</b>&nbsp;" << string << "<br>\r\n";
} }
static void ShowStatus (std::stringstream& s) void ShowStatus (std::stringstream& s, bool includeHiddenContent)
{ {
s << "<b>Uptime:</b> "; s << "<b>Uptime:</b> ";
ShowUptime(s, i2p::context.GetUptime ()); ShowUptime(s, i2p::context.GetUptime ());
@ -233,30 +233,32 @@ namespace http {
s << " (" << (double) i2p::transport::transports.GetTransitBandwidth () / 1024 << " KiB/s)<br>\r\n"; s << " (" << (double) i2p::transport::transports.GetTransitBandwidth () / 1024 << " KiB/s)<br>\r\n";
s << "<b>Data path:</b> " << i2p::fs::GetDataDir() << "<br>\r\n"; s << "<b>Data path:</b> " << i2p::fs::GetDataDir() << "<br>\r\n";
s << "<div class='slide'\r\n><label for='slide1'>Hidden content. Press on text to see.</label>\r\n<input type='checkbox' id='slide1'/>\r\n<p class='content'>\r\n"; s << "<div class='slide'\r\n><label for='slide1'>Hidden content. Press on text to see.</label>\r\n<input type='checkbox' id='slide1'/>\r\n<p class='content'>\r\n";
s << "<b>Router Ident:</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n"; if(includeHiddenContent) {
s << "<b>Router Family:</b> " << i2p::context.GetRouterInfo().GetProperty("family") << "<br>\r\n"; s << "<b>Router Ident:</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n";
s << "<b>Router Caps:</b> " << i2p::context.GetRouterInfo().GetProperty("caps") << "<br>\r\n"; s << "<b>Router Family:</b> " << i2p::context.GetRouterInfo().GetProperty("family") << "<br>\r\n";
s << "<b>Our external address:</b>" << "<br>\r\n" ; s << "<b>Router Caps:</b> " << i2p::context.GetRouterInfo().GetProperty("caps") << "<br>\r\n";
for (const auto& address : i2p::context.GetRouterInfo().GetAddresses()) s << "<b>Our external address:</b>" << "<br>\r\n" ;
{ for (const auto& address : i2p::context.GetRouterInfo().GetAddresses())
switch (address->transportStyle)
{ {
case i2p::data::RouterInfo::eTransportNTCP: switch (address->transportStyle)
if (address->host.is_v6 ()) {
s << "NTCP6&nbsp;&nbsp;"; case i2p::data::RouterInfo::eTransportNTCP:
else if (address->host.is_v6 ())
s << "NTCP&nbsp;&nbsp;"; s << "NTCP6&nbsp;&nbsp;";
break; else
case i2p::data::RouterInfo::eTransportSSU: s << "NTCP&nbsp;&nbsp;";
if (address->host.is_v6 ()) break;
s << "SSU6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"; case i2p::data::RouterInfo::eTransportSSU:
else if (address->host.is_v6 ())
s << "SSU&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"; s << "SSU6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
break; else
default: s << "SSU&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
s << "Unknown&nbsp;&nbsp;"; break;
default:
s << "Unknown&nbsp;&nbsp;";
}
s << address->host.to_string() << ":" << address->port << "<br>\r\n";
} }
s << address->host.to_string() << ":" << address->port << "<br>\r\n";
} }
s << "</p>\r\n</div>\r\n"; s << "</p>\r\n</div>\r\n";
s << "<b>Routers:</b> " << i2p::data::netdb.GetNumRouters () << " "; s << "<b>Routers:</b> " << i2p::data::netdb.GetNumRouters () << " ";
@ -271,7 +273,7 @@ namespace http {
s << "<b>Transit Tunnels:</b> " << std::to_string(transitTunnelCount) << "<br>\r\n"; s << "<b>Transit Tunnels:</b> " << std::to_string(transitTunnelCount) << "<br>\r\n";
} }
static void ShowLocalDestinations (std::stringstream& s) void ShowLocalDestinations (std::stringstream& s)
{ {
s << "<b>Local Destinations:</b><br>\r\n<br>\r\n"; s << "<b>Local Destinations:</b><br>\r\n<br>\r\n";
for (auto& it: i2p::client::context.GetDestinations ()) for (auto& it: i2p::client::context.GetDestinations ())
@ -339,7 +341,7 @@ namespace http {
s << "<br>" << std::endl; s << "<br>" << std::endl;
} }
static void ShowLocalDestination (std::stringstream& s, const std::string& b32) void ShowLocalDestination (std::stringstream& s, const std::string& b32)
{ {
s << "<b>Local Destination:</b><br>\r\n<br>\r\n"; s << "<b>Local Destination:</b><br>\r\n<br>\r\n";
i2p::data::IdentHash ident; i2p::data::IdentHash ident;
@ -376,12 +378,12 @@ namespace http {
s << "<td>" << it->GetWindowSize () << "</td>"; s << "<td>" << it->GetWindowSize () << "</td>";
s << "<td>" << (int)it->GetStatus () << "</td>"; s << "<td>" << (int)it->GetStatus () << "</td>";
s << "</tr><br>\r\n" << std::endl; s << "</tr><br>\r\n" << std::endl;
} }
s << "</table>"; s << "</table>";
} }
} }
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 (); auto i2cpServer = i2p::client::context.GetI2CPServer ();
if (i2cpServer) if (i2cpServer)
@ -397,7 +399,7 @@ namespace http {
ShowError(s, "I2CP is not enabled"); ShowError(s, "I2CP is not enabled");
} }
static void ShowLeasesSets(std::stringstream& s) void ShowLeasesSets(std::stringstream& s)
{ {
s << "<div id='leasesets'><b>LeaseSets (click on to show info):</b></div><br>\r\n"; s << "<div id='leasesets'><b>LeaseSets (click on to show info):</b></div><br>\r\n";
int counter = 1; int counter = 1;
@ -430,7 +432,7 @@ namespace http {
// end for each lease set // end for each lease set
} }
static void ShowTunnels (std::stringstream& s) void ShowTunnels (std::stringstream& s)
{ {
s << "<b>Queue size:</b> " << i2p::tunnel::tunnels.GetQueueSize () << "<br>\r\n"; s << "<b>Queue size:</b> " << i2p::tunnel::tunnels.GetQueueSize () << "<br>\r\n";
@ -467,14 +469,16 @@ namespace http {
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>"; s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
else else
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Start graceful shutdown</a><br>\r\n"; s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Start graceful shutdown</a><br>\r\n";
#endif #elif defined(WIN32_APP)
#ifdef WIN32_APP if (i2p::util::DaemonWin32::Instance().isGraceful)
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Graceful shutdown</a><br>\r\n"; s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
else
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Graceful shutdown</a><br>\r\n";
#endif #endif
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_NOW << "&token=" << token << "\">Force shutdown</a><br>\r\n"; s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_NOW << "&token=" << token << "\">Force shutdown</a><br>\r\n";
} }
static void ShowTransitTunnels (std::stringstream& s) void ShowTransitTunnels (std::stringstream& s)
{ {
s << "<b>Transit tunnels:</b><br>\r\n<br>\r\n"; s << "<b>Transit tunnels:</b><br>\r\n<br>\r\n";
for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ()) for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ())
@ -489,7 +493,7 @@ namespace http {
} }
} }
static void ShowTransports (std::stringstream& s) void ShowTransports (std::stringstream& s)
{ {
s << "<b>Transports:</b><br>\r\n<br>\r\n"; s << "<b>Transports:</b><br>\r\n<br>\r\n";
auto ntcpServer = i2p::transport::transports.GetNTCPServer (); auto ntcpServer = i2p::transport::transports.GetNTCPServer ();
@ -575,7 +579,7 @@ namespace http {
} }
} }
static void ShowSAMSessions (std::stringstream& s) void ShowSAMSessions (std::stringstream& s)
{ {
auto sam = i2p::client::context.GetSAMBridge (); auto sam = i2p::client::context.GetSAMBridge ();
if (!sam) { if (!sam) {
@ -585,8 +589,9 @@ namespace http {
s << "<b>SAM Sessions:</b><br>\r\n<br>\r\n"; s << "<b>SAM Sessions:</b><br>\r\n<br>\r\n";
for (auto& it: sam->GetSessions ()) for (auto& it: sam->GetSessions ())
{ {
auto& name = it.second->localDestination->GetNickname ();
s << "<a href=\"/?page=" << HTTP_PAGE_SAM_SESSION << "&sam_id=" << it.first << "\">"; s << "<a href=\"/?page=" << HTTP_PAGE_SAM_SESSION << "&sam_id=" << it.first << "\">";
s << it.first << "</a><br>\r\n" << std::endl; s << name << " (" << it.first << ")</a><br>\r\n" << std::endl;
} }
} }
@ -622,7 +627,7 @@ namespace http {
} }
} }
static void ShowI2PTunnels (std::stringstream& s) void ShowI2PTunnels (std::stringstream& s)
{ {
s << "<b>Client Tunnels:</b><br>\r\n<br>\r\n"; s << "<b>Client Tunnels:</b><br>\r\n<br>\r\n";
for (auto& it: i2p::client::context.GetClientTunnels ()) for (auto& it: i2p::client::context.GetClientTunnels ())
@ -651,15 +656,18 @@ namespace http {
s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "<br>\r\n"<< std::endl; s << "<br>\r\n"<< std::endl;
} }
s << "<br>\r\n<b>Server Tunnels:</b><br>\r\n<br>\r\n"; auto& serverTunnels = i2p::client::context.GetServerTunnels ();
for (auto& it: i2p::client::context.GetServerTunnels ()) if (!serverTunnels.empty ()) {
{ s << "<br>\r\n<b>Server Tunnels:</b><br>\r\n<br>\r\n";
auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); for (auto& it: serverTunnels)
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">"; {
s << it.second->GetName () << "</a> &#8658; "; auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << ":" << it.second->GetLocalPort (); s << it.second->GetName () << "</a> &#8658; ";
s << "</a><br>\r\n"<< std::endl; s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << ":" << it.second->GetLocalPort ();
s << "</a><br>\r\n"<< std::endl;
}
} }
auto& clientForwards = i2p::client::context.GetClientForwards (); auto& clientForwards = i2p::client::context.GetClientForwards ();
if (!clientForwards.empty ()) if (!clientForwards.empty ())
@ -751,8 +759,8 @@ namespace http {
} }
/* method #2: 'Authorization' header sent */ /* method #2: 'Authorization' header sent */
auto provided = req.GetHeader ("Authorization"); auto provided = req.GetHeader ("Authorization");
if (provided.length () > 0) if (provided.length () > 0)
{ {
bool result = false; bool result = false;
std::string expected = user + ":" + pass; std::string expected = user + ":" + pass;
@ -797,7 +805,7 @@ namespace http {
} else if (req.uri.find("cmd=") != std::string::npos) { } else if (req.uri.find("cmd=") != std::string::npos) {
HandleCommand (req, res, s); HandleCommand (req, res, s);
} else { } else {
ShowStatus (s); ShowStatus (s, true);
res.add_header("Refresh", "10"); res.add_header("Refresh", "10");
} }
ShowPageTail (s); ShowPageTail (s);
@ -809,7 +817,7 @@ namespace http {
std::map<uint32_t, uint32_t> HTTPConnection::m_Tokens; std::map<uint32_t, uint32_t> HTTPConnection::m_Tokens;
void HTTPConnection::HandlePage (const HTTPReq& req, HTTPRes& res, std::stringstream& s) void HTTPConnection::HandlePage (const HTTPReq& req, HTTPRes& res, std::stringstream& s)
{ {
std::map<std::string, std::string> params; std::map<std::string, std::string> params;
std::string page(""); std::string page("");
URL url; URL url;
@ -859,7 +867,7 @@ namespace http {
ShowError(s, "Unknown page: " + page); ShowError(s, "Unknown page: " + page);
return; return;
} }
} }
void HTTPConnection::HandleCommand (const HTTPReq& req, HTTPRes& res, std::stringstream& s) void HTTPConnection::HandleCommand (const HTTPReq& req, HTTPRes& res, std::stringstream& s)
{ {
@ -889,14 +897,15 @@ namespace http {
i2p::context.SetAcceptsTunnels (false); i2p::context.SetAcceptsTunnels (false);
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) #if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
Daemon.gracefulShutdownInterval = 10*60; Daemon.gracefulShutdownInterval = 10*60;
#endif #elif defined(WIN32_APP)
#ifdef WIN32_APP
i2p::win32::GracefulShutdown (); i2p::win32::GracefulShutdown ();
#endif #endif
} else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) { } else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) {
i2p::context.SetAcceptsTunnels (true); i2p::context.SetAcceptsTunnels (true);
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) #if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
Daemon.gracefulShutdownInterval = 0; Daemon.gracefulShutdownInterval = 0;
#elif defined(WIN32_APP)
i2p::win32::StopGracefulShutdown ();
#endif #endif
} else if (cmd == HTTP_COMMAND_SHUTDOWN_NOW) { } else if (cmd == HTTP_COMMAND_SHUTDOWN_NOW) {
Daemon.running = false; Daemon.running = false;

View file

@ -7,6 +7,7 @@
#include <map> #include <map>
#include <thread> #include <thread>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <sstream>
#include "HTTP.h" #include "HTTP.h"
namespace i2p namespace i2p
@ -75,6 +76,17 @@ namespace http
boost::asio::io_service::work m_Work; boost::asio::io_service::work m_Work;
boost::asio::ip::tcp::acceptor m_Acceptor; boost::asio::ip::tcp::acceptor m_Acceptor;
}; };
//all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml
void ShowStatus (std::stringstream& s, bool includeHiddenContent);
void ShowLocalDestinations (std::stringstream& s);
void ShowLeasesSets(std::stringstream& s);
void ShowTunnels (std::stringstream& s);
void ShowTransitTunnels (std::stringstream& s);
void ShowTransports (std::stringstream& s);
void ShowSAMSessions (std::stringstream& s);
void ShowI2PTunnels (std::stringstream& s);
void ShowLocalDestination (std::stringstream& s, const std::string& b32);
} // http } // http
} // i2p } // i2p

View file

@ -512,10 +512,10 @@ namespace client
{ {
for (auto it = params.begin (); it != params.end (); it++) for (auto it = params.begin (); it != params.end (); it++)
{ {
if (it != params.begin ()) results << ",";
LogPrint (eLogDebug, "I2PControl: NetworkSetting request: ", it->first); LogPrint (eLogDebug, "I2PControl: NetworkSetting request: ", it->first);
auto it1 = m_NetworkSettingHandlers.find (it->first); auto it1 = m_NetworkSettingHandlers.find (it->first);
if (it1 != m_NetworkSettingHandlers.end ()) { if (it1 != m_NetworkSettingHandlers.end ()) {
if (it != params.begin ()) results << ",";
(this->*(it1->second))(it->second.data (), results); (this->*(it1->second))(it->second.data (), results);
} else } else
LogPrint (eLogError, "I2PControl: NetworkSetting unknown request: ", it->first); LogPrint (eLogError, "I2PControl: NetworkSetting unknown request: ", it->first);

4
debian/control vendored
View file

@ -2,7 +2,7 @@ Source: i2pd
Section: net Section: net
Priority: optional Priority: optional
Maintainer: R4SAS <r4sas@i2pmail.org> Maintainer: R4SAS <r4sas@i2pmail.org>
Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.16.1~), gcc (>= 4.7) | clang (>= 3.3), libboost-system-dev (>= 1.46), libboost-date-time-dev, libboost-filesystem-dev, libboost-program-options-dev, libminiupnpc-dev, libssl-dev, zlib1g-dev Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.16.1~), gcc (>= 4.7) | clang (>= 3.3), libboost-system-dev (>= 1.46), libboost-date-time-dev, libboost-filesystem-dev, libboost-program-options-dev, libminiupnpc-dev, libssl-dev, zlib1g-dev, dh-apparmor
Standards-Version: 3.9.6 Standards-Version: 3.9.6
Homepage: http://i2pd.website/ Homepage: http://i2pd.website/
Vcs-Git: git://github.com/PurpleI2P/i2pd.git Vcs-Git: git://github.com/PurpleI2P/i2pd.git
@ -12,7 +12,7 @@ Package: i2pd
Architecture: any Architecture: any
Pre-Depends: adduser Pre-Depends: adduser
Depends: ${shlibs:Depends}, ${misc:Depends} Depends: ${shlibs:Depends}, ${misc:Depends}
Suggests: tor, privoxy Suggests: tor, privoxy, apparmor
Description: A full-featured C++ implementation of I2P client. Description: A full-featured C++ implementation of I2P client.
I2P (Invisible Internet Protocol) is a universal anonymous network layer. All I2P (Invisible Internet Protocol) is a universal anonymous network layer. All
communications over I2P are anonymous and end-to-end encrypted, participants communications over I2P are anonymous and end-to-end encrypted, participants

1
debian/i2pd.install vendored
View file

@ -3,3 +3,4 @@ contrib/i2pd.conf etc/i2pd/
contrib/tunnels.conf etc/i2pd/ contrib/tunnels.conf etc/i2pd/
contrib/subscriptions.txt etc/i2pd/ contrib/subscriptions.txt etc/i2pd/
contrib/certificates/ usr/share/i2pd/ contrib/certificates/ usr/share/i2pd/
contrib/apparmor/usr.sbin.i2pd etc/apparmor.d

1
debian/rules vendored
View file

@ -12,6 +12,7 @@ PREFIX=/usr
%: %:
dh $@ --parallel dh $@ --parallel
dh_apparmor --profile-name=usr.sbin.i2pd -pi2pd
override_dh_strip: override_dh_strip:
dh_strip --dbg-package=i2pd-dbg dh_strip --dbg-package=i2pd-dbg

View file

@ -38,6 +38,7 @@ namespace config {
("log", value<std::string>()->default_value(""), "Logs destination: stdout, file, syslog (stdout if not set)") ("log", value<std::string>()->default_value(""), "Logs destination: stdout, file, syslog (stdout if not set)")
("logfile", value<std::string>()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)") ("logfile", value<std::string>()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)")
("loglevel", value<std::string>()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)") ("loglevel", value<std::string>()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)")
("logclftime", value<bool>()->default_value(false), "Write full CLF-formatted date and time to log (default: write only time)")
("family", value<std::string>()->default_value(""), "Specify a family, router belongs to") ("family", value<std::string>()->default_value(""), "Specify a family, router belongs to")
("datadir", value<std::string>()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)") ("datadir", value<std::string>()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)")
("host", value<std::string>()->default_value("0.0.0.0"), "External IP") ("host", value<std::string>()->default_value("0.0.0.0"), "External IP")
@ -70,6 +71,8 @@ namespace config {
("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)") ("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)")
("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)") ("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)")
("limits.transittunnels", value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)") ("limits.transittunnels", value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)")
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Threshold to start probabalistic backoff with ntcp sessions (default: use system limit)")
("limits.ntcphard", value<uint16_t>()->default_value(0), "Maximum number of ntcp sessions (default: use system limit)")
; ;
options_description httpserver("HTTP Server options"); options_description httpserver("HTTP Server options");
@ -189,7 +192,8 @@ namespace config {
"https://reseed.memcpy.io/," "https://reseed.memcpy.io/,"
"https://reseed.onion.im/," "https://reseed.onion.im/,"
"https://itoopie.atomike.ninja/," "https://itoopie.atomike.ninja/,"
"https://i2pseed.creativecowpat.net:8443/" "https://i2pseed.creativecowpat.net:8443/,"
"https://i2p.novg.net/"
), "Reseed URLs, separated by comma") ), "Reseed URLs, separated by comma")
; ;

View file

@ -372,6 +372,107 @@ namespace crypto
BN_CTX_free (ctx); BN_CTX_free (ctx);
} }
// ECICS
void ECICSEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
{
BN_CTX_start (ctx);
BIGNUM * q = BN_CTX_get (ctx);
EC_GROUP_get_order(curve, q, ctx);
int len = BN_num_bytes (q);
BIGNUM * k = BN_CTX_get (ctx);
BN_rand_range (k, q); // 0 < k < q
// point for shared secret
auto p = EC_POINT_new (curve);
EC_POINT_mul (curve, p, k, nullptr, nullptr, ctx);
BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
bn2buf (x, encrypted, len);
bn2buf (y, encrypted + len, len);
RAND_bytes (encrypted + 2*len, 256 - 2*len);
// ecryption key and iv
EC_POINT_mul (curve, p, nullptr, key, k, ctx);
EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
uint8_t keyBuf[64], iv[64], shared[32];
bn2buf (x, keyBuf, len);
bn2buf (y, iv, len);
SHA256 (keyBuf, len, shared);
// create buffer
uint8_t m[256];
m[0] = 0xFF; m[255] = 0xFF;
memcpy (m+33, data, 222);
SHA256 (m+33, 222, m+1);
// encrypt
CBCEncryption encryption;
encryption.SetKey (shared);
encryption.SetIV (iv);
encryption.Encrypt (m, 256, encrypted + 256);
EC_POINT_free (p);
BN_CTX_end (ctx);
}
bool ECICSDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
{
bool ret = true;
BN_CTX_start (ctx);
BIGNUM * q = BN_CTX_get (ctx);
EC_GROUP_get_order(curve, q, ctx);
int len = BN_num_bytes (q);
// point for shared secret
BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
BN_bin2bn (encrypted, len, x);
BN_bin2bn (encrypted + len, len, y);
auto p = EC_POINT_new (curve);
if (EC_POINT_set_affine_coordinates_GFp (curve, p, x, y, nullptr))
{
auto s = EC_POINT_new (curve);
EC_POINT_mul (curve, s, nullptr, p, key, ctx);
EC_POINT_get_affine_coordinates_GFp (curve, s, x, y, nullptr);
EC_POINT_free (s);
uint8_t keyBuf[64], iv[64], shared[32];
bn2buf (x, keyBuf, len);
bn2buf (y, iv, len);
SHA256 (keyBuf, len, shared);
// decrypt
uint8_t m[256];
CBCDecryption decryption;
decryption.SetKey (shared);
decryption.SetIV (iv);
decryption.Decrypt (encrypted + 256, 256, m);
// verify and copy
uint8_t hash[32];
SHA256 (m + 33, 222, hash);
if (!memcmp (m + 1, hash, 32))
memcpy (data, m + 33, 222);
else
{
LogPrint (eLogError, "ECICS decrypt hash doesn't match");
ret = false;
}
}
else
{
LogPrint (eLogError, "ECICS decrypt point is invalid");
ret = false;
}
EC_POINT_free (p);
BN_CTX_end (ctx);
return ret;
}
void GenerateECICSKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub)
{
BN_CTX * ctx = BN_CTX_new ();
BIGNUM * q = BN_new ();
EC_GROUP_get_order(curve, q, ctx);
priv = BN_new ();
BN_rand_range (priv, q);
pub = EC_POINT_new (curve);
EC_POINT_mul (curve, pub, priv, nullptr, nullptr, ctx);
BN_free (q);
BN_CTX_free (ctx);
}
// HMAC // HMAC
const uint64_t IPAD = 0x3636363636363636; const uint64_t IPAD = 0x3636363636363636;
const uint64_t OPAD = 0x5C5C5C5C5C5C5C5C; const uint64_t OPAD = 0x5C5C5C5C5C5C5C5C;

View file

@ -52,6 +52,11 @@ namespace crypto
bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false); bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false);
void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub); void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub);
// ECICS
void ECICSEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); // 222 bytes data, 512 bytes encrypted
bool ECICSDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
void GenerateECICSKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub);
// HMAC // HMAC
typedef i2p::data::Tag<32> MACKey; typedef i2p::data::Tag<32> MACKey;
void HMACMD5Digest (uint8_t * msg, size_t len, const MACKey& key, uint8_t * digest); void HMACMD5Digest (uint8_t * msg, size_t len, const MACKey& key, uint8_t * digest);

View file

@ -1,5 +1,6 @@
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <string>
#include "Crypto.h" #include "Crypto.h"
#include "Log.h" #include "Log.h"
#include "FS.h" #include "FS.h"
@ -23,8 +24,10 @@ namespace client
int outQty = DEFAULT_OUTBOUND_TUNNELS_QUANTITY; int outQty = DEFAULT_OUTBOUND_TUNNELS_QUANTITY;
int numTags = DEFAULT_TAGS_TO_SEND; int numTags = DEFAULT_TAGS_TO_SEND;
std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers; std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers;
try { try
if (params) { {
if (params)
{
auto it = params->find (I2CP_PARAM_INBOUND_TUNNEL_LENGTH); auto it = params->find (I2CP_PARAM_INBOUND_TUNNEL_LENGTH);
if (it != params->end ()) if (it != params->end ())
inLen = std::stoi(it->second); inLen = std::stoi(it->second);
@ -55,8 +58,12 @@ namespace client
LogPrint (eLogInfo, "Destination: Added to explicit peers list: ", b64); LogPrint (eLogInfo, "Destination: Added to explicit peers list: ", b64);
} }
} }
it = params->find (I2CP_PARAM_INBOUND_NICKNAME);
if (it != params->end ()) m_Nickname = it->second; // otherwise we set deafult nickname in Start when we know local address
} }
} catch (std::exception & ex) { }
catch (std::exception & ex)
{
LogPrint(eLogError, "Destination: unable to parse parameters for destination: ", ex.what()); LogPrint(eLogError, "Destination: unable to parse parameters for destination: ", ex.what());
} }
SetNumTags (numTags); SetNumTags (numTags);
@ -110,6 +117,8 @@ namespace client
{ {
if (!m_IsRunning) if (!m_IsRunning)
{ {
if (m_Nickname.empty ())
m_Nickname = i2p::data::GetIdentHashAbbreviation (GetIdentHash ()); // set default nickname
LoadTags (); LoadTags ();
m_IsRunning = true; m_IsRunning = true;
m_Pool->SetLocalDestination (shared_from_this ()); m_Pool->SetLocalDestination (shared_from_this ());

View file

@ -50,6 +50,7 @@ namespace client
const int STREAM_REQUEST_TIMEOUT = 60; //in seconds const int STREAM_REQUEST_TIMEOUT = 60; //in seconds
const char I2CP_PARAM_TAGS_TO_SEND[] = "crypto.tagsToSend"; const char I2CP_PARAM_TAGS_TO_SEND[] = "crypto.tagsToSend";
const int DEFAULT_TAGS_TO_SEND = 40; const int DEFAULT_TAGS_TO_SEND = 40;
const char I2CP_PARAM_INBOUND_NICKNAME[] = "inbound.nickname";
// latency // latency
const char I2CP_PARAM_MIN_TUNNEL_LATENCY[] = "latency.min"; const char I2CP_PARAM_MIN_TUNNEL_LATENCY[] = "latency.min";
@ -86,6 +87,7 @@ namespace client
LeaseSetDestination (bool isPublic, const std::map<std::string, std::string> * params = nullptr); LeaseSetDestination (bool isPublic, const std::map<std::string, std::string> * params = nullptr);
~LeaseSetDestination (); ~LeaseSetDestination ();
const std::string& GetNickname () const { return m_Nickname; };
virtual bool Start (); virtual bool Start ();
virtual bool Stop (); virtual bool Stop ();
@ -153,6 +155,7 @@ namespace client
boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer,
m_PublishDelayTimer, m_CleanupTimer; m_PublishDelayTimer, m_CleanupTimer;
std::string m_Nickname;
public: public:

View file

@ -179,122 +179,596 @@ namespace crypto
// ГОСТ 34.11-2012 // ГОСТ 34.11-2012
static const uint8_t sbox_[256] = static const uint64_t T0[256] =
{ {
0xFC, 0xEE, 0xDD, 0x11, 0xCF, 0x6E, 0x31, 0x16, 0xFB, 0xC4, 0xFA, 0xDA, 0x23, 0xC5, 0x04, 0x4D, 0xE6F87E5C5B711FD0, 0x258377800924FA16, 0xC849E07E852EA4A8, 0x5B4686A18F06C16A,
0xE9, 0x77, 0xF0, 0xDB, 0x93, 0x2E, 0x99, 0xBA, 0x17, 0x36, 0xF1, 0xBB, 0x14, 0xCD, 0x5F, 0xC1, 0x0B32E9A2D77B416E, 0xABDA37A467815C66, 0xF61796A81A686676, 0xF5DC0B706391954B,
0xF9, 0x18, 0x65, 0x5A, 0xE2, 0x5C, 0xEF, 0x21, 0x81, 0x1C, 0x3C, 0x42, 0x8B, 0x01, 0x8E, 0x4F, 0x4862F38DB7E64BF1, 0xFF5C629A68BD85C5, 0xCB827DA6FCD75795, 0x66D36DAF69B9F089,
0x05, 0x84, 0x02, 0xAE, 0xE3, 0x6A, 0x8F, 0xA0, 0x06, 0x0B, 0xED, 0x98, 0x7F, 0xD4, 0xD3, 0x1F, 0x356C9F74483D83B0, 0x7CBCECB1238C99A1, 0x36A702AC31C4708D, 0x9EB6A8D02FBCDFD6,
0xEB, 0x34, 0x2C, 0x51, 0xEA, 0xC8, 0x48, 0xAB, 0xF2, 0x2A, 0x68, 0xA2, 0xFD, 0x3A, 0xCE, 0xCC, 0x8B19FA51E5B3AE37, 0x9CCFB5408A127D0B, 0xBC0C78B508208F5A, 0xE533E3842288ECED,
0xB5, 0x70, 0x0E, 0x56, 0x08, 0x0C, 0x76, 0x12, 0xBF, 0x72, 0x13, 0x47, 0x9C, 0xB7, 0x5D, 0x87, 0xCEC2C7D377C15FD2, 0xEC7817B6505D0F5E, 0xB94CC2C08336871D, 0x8C205DB4CB0B04AD,
0x15, 0xA1, 0x96, 0x29, 0x10, 0x7B, 0x9A, 0xC7, 0xF3, 0x91, 0x78, 0x6F, 0x9D, 0x9E, 0xB2, 0xB1, 0x763C855B28A0892F, 0x588D1B79F6FF3257, 0x3FECF69E4311933E, 0x0FC0D39F803A18C9,
0x32, 0x75, 0x19, 0x3D, 0xFF, 0x35, 0x8A, 0x7E, 0x6D, 0x54, 0xC6, 0x80, 0xC3, 0xBD, 0x0D, 0x57, 0xEE010A26F5F3AD83, 0x10EFE8F4411979A6, 0x5DCDA10C7DE93A10, 0x4A1BEE1D1248E92C,
0xDF, 0xF5, 0x24, 0xA9, 0x3E, 0xA8, 0x43, 0xC9, 0xD7, 0x79, 0xD6, 0xF6, 0x7C, 0x22, 0xB9, 0x03, 0x53BFF2DB21847339, 0xB4F50CCFA6A23D09, 0x5FB4BC9CD84798CD, 0xE88A2D8B071C56F9,
0xE0, 0x0F, 0xEC, 0xDE, 0x7A, 0x94, 0xB0, 0xBC, 0xDC, 0xE8, 0x28, 0x50, 0x4E, 0x33, 0x0A, 0x4A, 0x7F7771695A756A9C, 0xC5F02E71A0BA1EBC, 0xA663F9AB4215E672, 0x2EB19E22DE5FBB78,
0xA7, 0x97, 0x60, 0x73, 0x1E, 0x00, 0x62, 0x44, 0x1A, 0xB8, 0x38, 0x82, 0x64, 0x9F, 0x26, 0x41, 0x0DB9CE0F2594BA14, 0x82520E6397664D84, 0x2F031E6A0208EA98, 0x5C7F2144A1BE6BF0,
0xAD, 0x45, 0x46, 0x92, 0x27, 0x5E, 0x55, 0x2F, 0x8C, 0xA3, 0xA5, 0x7D, 0x69, 0xD5, 0x95, 0x3B, 0x7A37CB1CD16362DB, 0x83E08E2B4B311C64, 0xCF70479BAB960E32, 0x856BA986B9DEE71E,
0x07, 0x58, 0xB3, 0x40, 0x86, 0xAC, 0x1D, 0xF7, 0x30, 0x37, 0x6B, 0xE4, 0x88, 0xD9, 0xE7, 0x89, 0xB5478C877AF56CE9, 0xB8FE42885F61D6FD, 0x1BDD0156966238C8, 0x622157923EF8A92E,
0xE1, 0x1B, 0x83, 0x49, 0x4C, 0x3F, 0xF8, 0xFE, 0x8D, 0x53, 0xAA, 0x90, 0xCA, 0xD8, 0x85, 0x61, 0xFC97FF42114476F8, 0x9D7D350856452CEB, 0x4C90C9B0E0A71256, 0x2308502DFBCB016C,
0x20, 0x71, 0x67, 0xA4, 0x2D, 0x2B, 0x09, 0x5B, 0xCB, 0x9B, 0x25, 0xD0, 0xBE, 0xE5, 0x6C, 0x52, 0x2D7A03FAA7A64845, 0xF46E8B38BFC6C4AB, 0xBDBEF8FDD477DEBA, 0x3AAC4CEBC8079B79,
0x59, 0xA6, 0x74, 0xD2, 0xE6, 0xF4, 0xB4, 0xC0, 0xD1, 0x66, 0xAF, 0xC2, 0x39, 0x4B, 0x63, 0xB6 0xF09CB105E8879D0C, 0x27FA6A10AC8A58CB, 0x8960E7C1401D0CEA, 0x1A6F811E4A356928,
0x90C4FB0773D196FF, 0x43501A2F609D0A9F, 0xF7A516E0C63F3796, 0x1CE4A6B3B8DA9252,
0x1324752C38E08A9B, 0xA5A864733BEC154F, 0x2BF124575549B33F, 0xD766DB15440DC5C7,
0xA7D179E39E42B792, 0xDADF151A61997FD3, 0x86A0345EC0271423, 0x38D5517B6DA939A4,
0x6518F077104003B4, 0x02791D90A5AEA2DD, 0x88D267899C4A5D0A, 0x930F66DF0A2865C2,
0x4EE9D4204509B08B, 0x325538916685292A, 0x412907BFC533A842, 0xB27E2B62544DC673,
0x6C5304456295E007, 0x5AF406E95351908A, 0x1F2F3B6BC123616F, 0xC37B09DC5255E5C6,
0x3967D133B1FE6844, 0x298839C7F0E711E2, 0x409B87F71964F9A2, 0xE938ADC3DB4B0719,
0x0C0B4E47F9C3EBF4, 0x5534D576D36B8843, 0x4610A05AEB8B02D8, 0x20C3CDF58232F251,
0x6DE1840DBEC2B1E7, 0xA0E8DE06B0FA1D08, 0x7B854B540D34333B, 0x42E29A67BCCA5B7F,
0xD8A6088AC437DD0E, 0xC63BB3A9D943ED81, 0x21714DBD5E65A3B1, 0x6761EDE7B5EEA169,
0x2431F7C8D573ABF6, 0xD51FC685E1A3671A, 0x5E063CD40410C92D, 0x283AB98F2CB04002,
0x8FEBC06CB2F2F790, 0x17D64F116FA1D33C, 0xE07359F1A99EE4AA, 0x784ED68C74CDC006,
0x6E2A19D5C73B42DA, 0x8712B4161C7045C3, 0x371582E4ED93216D, 0xACE390414939F6FC,
0x7EC5F12186223B7C, 0xC0B094042BAC16FB, 0xF9D745379A527EBF, 0x737C3F2EA3B68168,
0x33E7B8D9BAD278CA, 0xA9A32A34C22FFEBB, 0xE48163CCFEDFBD0D, 0x8E5940246EA5A670,
0x51C6EF4B842AD1E4, 0x22BAD065279C508C, 0xD91488C218608CEE, 0x319EA5491F7CDA17,
0xD394E128134C9C60, 0x094BF43272D5E3B3, 0x9BF612A5A4AAD791, 0xCCBBDA43D26FFD0F,
0x34DE1F3C946AD250, 0x4F5B5468995EE16B, 0xDF9FAF6FEA8F7794, 0x2648EA5870DD092B,
0xBFC7E56D71D97C67, 0xDDE6B2FF4F21D549, 0x3C276B463AE86003, 0x91767B4FAF86C71F,
0x68A13E7835D4B9A0, 0xB68C115F030C9FD4, 0x141DD2C916582001, 0x983D8F7DDD5324AC,
0x64AA703FCC175254, 0xC2C989948E02B426, 0x3E5E76D69F46C2DE, 0x50746F03587D8004,
0x45DB3D829272F1E5, 0x60584A029B560BF3, 0xFBAE58A73FFCDC62, 0xA15A5E4E6CAD4CE8,
0x4BA96E55CE1FB8CC, 0x08F9747AAE82B253, 0xC102144CF7FB471B, 0x9F042898F3EB8E36,
0x068B27ADF2EFFB7A, 0xEDCA97FE8C0A5EBE, 0x778E0513F4F7D8CF, 0x302C2501C32B8BF7,
0x8D92DDFC175C554D, 0xF865C57F46052F5F, 0xEAF3301BA2B2F424, 0xAA68B7ECBBD60D86,
0x998F0F350104754C, 0x0000000000000000, 0xF12E314D34D0CCEC, 0x710522BE061823B5,
0xAF280D9930C005C1, 0x97FD5CE25D693C65, 0x19A41CC633CC9A15, 0x95844172F8C79EB8,
0xDC5432B7937684A9, 0x9436C13A2490CF58, 0x802B13F332C8EF59, 0xC442AE397CED4F5C,
0xFA1CD8EFE3AB8D82, 0xF2E5AC954D293FD1, 0x6AD823E8907A1B7D, 0x4D2249F83CF043B6,
0x03CB9DD879F9F33D, 0xDE2D2F2736D82674, 0x2A43A41F891EE2DF, 0x6F98999D1B6C133A,
0xD4AD46CD3DF436FA, 0xBB35DF50269825C0, 0x964FDCAA813E6D85, 0xEB41B0537EE5A5C4,
0x0540BA758B160847, 0xA41AE43BE7BB44AF, 0xE3B8C429D0671797, 0x819993BBEE9FBEB9,
0xAE9A8DD1EC975421, 0xF3572CDD917E6E31, 0x6393D7DAE2AFF8CE, 0x47A2201237DC5338,
0xA32343DEC903EE35, 0x79FC56C4A89A91E6, 0x01B28048DC5751E0, 0x1296F564E4B7DB7B,
0x75F7188351597A12, 0xDB6D9552BDCE2E33, 0x1E9DBB231D74308F, 0x520D7293FDD322D9,
0xE20A44610C304677, 0xFEEEE2D2B4EAD425, 0xCA30FDEE20800675, 0x61EACA4A47015A13,
0xE74AFE1487264E30, 0x2CC883B27BF119A5, 0x1664CF59B3F682DC, 0xA811AA7C1E78AF5B,
0x1D5626FB648DC3B2, 0xB73E9117DF5BCE34, 0xD05F7CF06AB56F5D, 0xFD257F0ACD132718,
0x574DC8E676C52A9E, 0x0739A7E52EB8AA9A, 0x5486553E0F3CD9A3, 0x56FF48AEAA927B7E,
0xBE756525AD8E2D87, 0x7D0E6CF9FFDBC841, 0x3B1ECCA31450CA99, 0x6913BE30E983E840,
0xAD511009956EA71C, 0xB1B5B6BA2DB4354E, 0x4469BDCA4E25A005, 0x15AF5281CA0F71E1,
0x744598CB8D0E2BF2, 0x593F9B312AA863B7, 0xEFB38A6E29A4FC63, 0x6B6AA3A04C2D4A9D,
0x3D95EB0EE6BF31E3, 0xA291C3961554BFD5, 0x18169C8EEF9BCBF5, 0x115D68BC9D4E2846,
0xBA875F18FACF7420, 0xD1EDFCB8B6E23EBD, 0xB00736F2F1E364AE, 0x84D929CE6589B6FE,
0x70B7A2F6DA4F7255, 0x0E7253D75C6D4929, 0x04F23A3D574159A7, 0x0A8069EA0B2C108E,
0x49D073C56BB11A11, 0x8AAB7A1939E4FFD7, 0xCD095A0B0E38ACEF, 0xC9FB60365979F548,
0x92BDE697D67F3422, 0xC78933E10514BC61, 0xE1C1D9B975C9B54A, 0xD2266160CF1BCD80,
0x9A4492ED78FD8671, 0xB3CCAB2A881A9793, 0x72CEBF667FE1D088, 0xD6D45B5D985A9427
};
static const uint64_t T1[256] =
{
0xC811A8058C3F55DE, 0x65F5B43196B50619, 0xF74F96B1D6706E43, 0x859D1E8BCB43D336,
0x5AAB8A85CCFA3D84, 0xF9C7BF99C295FCFD, 0xA21FD5A1DE4B630F, 0xCDB3EF763B8B456D,
0x803F59F87CF7C385, 0xB27C73BE5F31913C, 0x98E3AC6633B04821, 0xBF61674C26B8F818,
0x0FFBC995C4C130C8, 0xAAA0862010761A98, 0x6057F342210116AA, 0xF63C760C0654CC35,
0x2DDB45CC667D9042, 0xBCF45A964BD40382, 0x68E8A0C3EF3C6F3D, 0xA7BD92D269FF73BC,
0x290AE20201ED2287, 0xB7DE34CDE885818F, 0xD901EEA7DD61059B, 0xD6FA273219A03553,
0xD56F1AE874CCCEC9, 0xEA31245C2E83F554, 0x7034555DA07BE499, 0xCE26D2AC56E7BEF7,
0xFD161857A5054E38, 0x6A0E7DA4527436D1, 0x5BD86A381CDE9FF2, 0xCAF7756231770C32,
0xB09AAED9E279C8D0, 0x5DEF1091C60674DB, 0x111046A2515E5045, 0x23536CE4729802FC,
0xC50CBCF7F5B63CFA, 0x73A16887CD171F03, 0x7D2941AFD9F28DBD, 0x3F5E3EB45A4F3B9D,
0x84EEFE361B677140, 0x3DB8E3D3E7076271, 0x1A3A28F9F20FD248, 0x7EBC7C75B49E7627,
0x74E5F293C7EB565C, 0x18DCF59E4F478BA4, 0x0C6EF44FA9ADCB52, 0xC699812D98DAC760,
0x788B06DC6E469D0E, 0xFC65F8EA7521EC4E, 0x30A5F7219E8E0B55, 0x2BEC3F65BCA57B6B,
0xDDD04969BAF1B75E, 0x99904CDBE394EA57, 0x14B201D1E6EA40F6, 0xBBB0C08241284ADD,
0x50F20463BF8F1DFF, 0xE8D7F93B93CBACB8, 0x4D8CB68E477C86E8, 0xC1DD1B3992268E3F,
0x7C5AA11209D62FCB, 0x2F3D98ABDB35C9AE, 0x671369562BFD5FF5, 0x15C1E16C36CEE280,
0x1D7EB2EDF8F39B17, 0xDA94D37DB00DFE01, 0x877BC3EC760B8ADA, 0xCB8495DFE153AE44,
0x05A24773B7B410B3, 0x12857B783C32ABDF, 0x8EB770D06812513B, 0x536739B9D2E3E665,
0x584D57E271B26468, 0xD789C78FC9849725, 0xA935BBFA7D1AE102, 0x8B1537A3DFA64188,
0xD0CD5D9BC378DE7A, 0x4AC82C9A4D80CFB7, 0x42777F1B83BDB620, 0x72D2883A1D33BD75,
0x5E7A2D4BAB6A8F41, 0xF4DAAB6BBB1C95D9, 0x905CFFE7FD8D31B6, 0x83AA6422119B381F,
0xC0AEFB8442022C49, 0xA0F908C663033AE3, 0xA428AF0804938826, 0xADE41C341A8A53C7,
0xAE7121EE77E6A85D, 0xC47F5C4A25929E8C, 0xB538E9AA55CDD863, 0x06377AA9DAD8EB29,
0xA18AE87BB3279895, 0x6EDFDA6A35E48414, 0x6B7D9D19825094A7, 0xD41CFA55A4E86CBF,
0xE5CAEDC9EA42C59C, 0xA36C351C0E6FC179, 0x5181E4DE6FABBF89, 0xFFF0C530184D17D4,
0x9D41EB1584045892, 0x1C0D525028D73961, 0xF178EC180CA8856A, 0x9A0571018EF811CD,
0x4091A27C3EF5EFCC, 0x19AF15239F6329D2, 0x347450EFF91EB990, 0xE11B4A078DD27759,
0xB9561DE5FC601331, 0x912F1F5A2DA993C0, 0x1654DCB65BA2191A, 0x3E2DDE098A6B99EB,
0x8A66D71E0F82E3FE, 0x8C51ADB7D55A08D7, 0x4533E50F8941FF7F, 0x02E6DD67BD4859EC,
0xE068AABA5DF6D52F, 0xC24826E3FF4A75A5, 0x6C39070D88ACDDF8, 0x6486548C4691A46F,
0xD1BEBD26135C7C0C, 0xB30F93038F15334A, 0x82D9849FC1BF9A69, 0x9C320BA85420FAE4,
0xFA528243AFF90767, 0x9ED4D6CFE968A308, 0xB825FD582C44B147, 0x9B7691BC5EDCB3BB,
0xC7EA619048FE6516, 0x1063A61F817AF233, 0x47D538683409A693, 0x63C2CE984C6DED30,
0x2A9FDFD86C81D91D, 0x7B1E3B06032A6694, 0x666089EBFBD9FD83, 0x0A598EE67375207B,
0x07449A140AFC495F, 0x2CA8A571B6593234, 0x1F986F8A45BBC2FB, 0x381AA4A050B372C2,
0x5423A3ADD81FAF3A, 0x17273C0B8B86BB6C, 0xFE83258DC869B5A2, 0x287902BFD1C980F1,
0xF5A94BD66B3837AF, 0x88800A79B2CABA12, 0x55504310083B0D4C, 0xDF36940E07B9EEB2,
0x04D1A7CE6790B2C5, 0x612413FFF125B4DC, 0x26F12B97C52C124F, 0x86082351A62F28AC,
0xEF93632F9937E5E7, 0x3507B052293A1BE6, 0xE72C30AE570A9C70, 0xD3586041AE1425E0,
0xDE4574B3D79D4CC4, 0x92BA228040C5685A, 0xF00B0CA5DC8C271C, 0xBE1287F1F69C5A6E,
0xF39E317FB1E0DC86, 0x495D114020EC342D, 0x699B407E3F18CD4B, 0xDCA3A9D46AD51528,
0x0D1D14F279896924, 0x0000000000000000, 0x593EB75FA196C61E, 0x2E4E78160B116BD8,
0x6D4AE7B058887F8E, 0xE65FD013872E3E06, 0x7A6DDBBBD30EC4E2, 0xAC97FC89CAAEF1B1,
0x09CCB33C1E19DBE1, 0x89F3EAC462EE1864, 0x7770CF49AA87ADC6, 0x56C57ECA6557F6D6,
0x03953DDA6D6CFB9A, 0x36928D884456E07C, 0x1EEB8F37959F608D, 0x31D6179C4EAAA923,
0x6FAC3AD7E5C02662, 0x43049FA653991456, 0xABD3669DC052B8EE, 0xAF02C153A7C20A2B,
0x3CCB036E3723C007, 0x93C9C23D90E1CA2C, 0xC33BC65E2F6ED7D3, 0x4CFF56339758249E,
0xB1E94E64325D6AA6, 0x37E16D359472420A, 0x79F8E661BE623F78, 0x5214D90402C74413,
0x482EF1FDF0C8965B, 0x13F69BC5EC1609A9, 0x0E88292814E592BE, 0x4E198B542A107D72,
0xCCC00FCBEBAFE71B, 0x1B49C844222B703E, 0x2564164DA840E9D5, 0x20C6513E1FF4F966,
0xBAC3203F910CE8AB, 0xF2EDD1C261C47EF0, 0x814CB945ACD361F3, 0x95FEB8944A392105,
0x5C9CF02C1622D6AD, 0x971865F3F77178E9, 0xBD87BA2B9BF0A1F4, 0x444005B259655D09,
0xED75BE48247FBC0B, 0x7596122E17CFF42A, 0xB44B091785E97A15, 0x966B854E2755DA9F,
0xEEE0839249134791, 0x32432A4623C652B9, 0xA8465B47AD3E4374, 0xF8B45F2412B15E8B,
0x2417F6F078644BA3, 0xFB2162FE7FDDA511, 0x4BBBCC279DA46DC1, 0x0173E0BDD024A276,
0x22208C59A2BCA08A, 0x8FC4906DB836F34D, 0xE4B90D743A6667EA, 0x7147B5E0705F46EF,
0x2782CB2A1508B039, 0xEC065EF5F45B1E7D, 0x21B5B183CFD05B10, 0xDBE733C060295C77,
0x9FA73672394C017E, 0xCF55321186C31C81, 0xD8720E1A0D45A7ED, 0x3B8F997A3DDF8958,
0x3AFC79C7EDFB2B2E, 0xE9A4198643EF0ECE, 0x5F09CDF67B4E2D37, 0x4F6A6BE9FA34DF04,
0xB6ADD47038A123F9, 0x8D224D0A057EAAA1, 0xC96248B85C1BF7A8, 0xE3FD9760309A2EB5,
0x0B2A6E5BA351820D, 0xEB42C4E1FEA75722, 0x948D58299A1D8373, 0x7FCF9CC864BAD451,
0xA55B4FB5D4B72A50, 0x08BF5381CE3D7997, 0x46A6D8D5E42D04E5, 0xD22B80FC7E308796,
0x57B69E77B57354A0, 0x3969441D8097D0B4, 0x3330CAFBF3E2F0CF, 0xE28E77DDE0BE8CC3,
0x62B12E259C494F46, 0xA6CE726FB9DBD1CA, 0x41E242C1EED14DBA, 0x76032FF47AA30FB0
};
static const uint64_t T2[256] =
{
0x45B268A93ACDE4CC, 0xAF7F0BE884549D08, 0x048354B3C1468263, 0x925435C2C80EFED2,
0xEE4E37F27FDFFBA7, 0x167A33920C60F14D, 0xFB123B52EA03E584, 0x4A0CAB53FDBB9007,
0x9DEAF6380F788A19, 0xCB48EC558F0CB32A, 0xB59DC4B2D6FEF7E0, 0xDCDBCA22F4F3ECB6,
0x11DF5813549A9C40, 0xE33FDEDF568ACED3, 0xA0C1C8124322E9C3, 0x07A56B8158FA6D0D,
0x77279579B1E1F3DD, 0xD9B18B74422AC004, 0xB8EC2D9FFFABC294, 0xF4ACF8A82D75914F,
0x7BBF69B1EF2B6878, 0xC4F62FAF487AC7E1, 0x76CE809CC67E5D0C, 0x6711D88F92E4C14C,
0x627B99D9243DEDFE, 0x234AA5C3DFB68B51, 0x909B1F15262DBF6D, 0x4F66EA054B62BCB5,
0x1AE2CF5A52AA6AE8, 0xBEA053FBD0CE0148, 0xED6808C0E66314C9, 0x43FE16CD15A82710,
0xCD049231A06970F6, 0xE7BC8A6C97CC4CB0, 0x337CE835FCB3B9C0, 0x65DEF2587CC780F3,
0x52214EDE4132BB50, 0x95F15E4390F493DF, 0x870839625DD2E0F1, 0x41313C1AFB8B66AF,
0x91720AF051B211BC, 0x477D427ED4EEA573, 0x2E3B4CEEF6E3BE25, 0x82627834EB0BCC43,
0x9C03E3DD78E724C8, 0x2877328AD9867DF9, 0x14B51945E243B0F2, 0x574B0F88F7EB97E2,
0x88B6FA989AA4943A, 0x19C4F068CB168586, 0x50EE6409AF11FAEF, 0x7DF317D5C04EABA4,
0x7A567C5498B4C6A9, 0xB6BBFB804F42188E, 0x3CC22BCF3BC5CD0B, 0xD04336EAAA397713,
0xF02FAC1BEC33132C, 0x2506DBA7F0D3488D, 0xD7E65D6BF2C31A1E, 0x5EB9B2161FF820F5,
0x842E0650C46E0F9F, 0x716BEB1D9E843001, 0xA933758CAB315ED4, 0x3FE414FDA2792265,
0x27C9F1701EF00932, 0x73A4C1CA70A771BE, 0x94184BA6E76B3D0E, 0x40D829FF8C14C87E,
0x0FBEC3FAC77674CB, 0x3616A9634A6A9572, 0x8F139119C25EF937, 0xF545ED4D5AEA3F9E,
0xE802499650BA387B, 0x6437E7BD0B582E22, 0xE6559F89E053E261, 0x80AD52E305288DFC,
0x6DC55A23E34B9935, 0xDE14E0F51AD0AD09, 0xC6390578A659865E, 0x96D7617109487CB1,
0xE2D6CB3A21156002, 0x01E915E5779FAED1, 0xADB0213F6A77DCB7, 0x9880B76EB9A1A6AB,
0x5D9F8D248644CF9B, 0xFD5E4536C5662658, 0xF1C6B9FE9BACBDFD, 0xEACD6341BE9979C4,
0xEFA7221708405576, 0x510771ECD88E543E, 0xC2BA51CB671F043D, 0x0AD482AC71AF5879,
0xFE787A045CDAC936, 0xB238AF338E049AED, 0xBD866CC94972EE26, 0x615DA6EBBD810290,
0x3295FDD08B2C1711, 0xF834046073BF0AEA, 0xF3099329758FFC42, 0x1CAEB13E7DCFA934,
0xBA2307481188832B, 0x24EFCE42874CE65C, 0x0E57D61FB0E9DA1A, 0xB3D1BAD6F99B343C,
0xC0757B1C893C4582, 0x2B510DB8403A9297, 0x5C7698C1F1DB614A, 0x3E0D0118D5E68CB4,
0xD60F488E855CB4CF, 0xAE961E0DF3CB33D9, 0x3A8E55AB14A00ED7, 0x42170328623789C1,
0x838B6DD19C946292, 0x895FEF7DED3B3AEB, 0xCFCBB8E64E4A3149, 0x064C7E642F65C3DC,
0x3D2B3E2A4C5A63DA, 0x5BD3F340A9210C47, 0xB474D157A1615931, 0xAC5934DA1DE87266,
0x6EE365117AF7765B, 0xC86ED36716B05C44, 0x9BA6885C201D49C5, 0xB905387A88346C45,
0x131072C4BAB9DDFF, 0xBF49461EA751AF99, 0xD52977BC1CE05BA1, 0xB0F785E46027DB52,
0x546D30BA6E57788C, 0x305AD707650F56AE, 0xC987C682612FF295, 0xA5AB8944F5FBC571,
0x7ED528E759F244CA, 0x8DDCBBCE2C7DB888, 0xAA154ABE328DB1BA, 0x1E619BE993ECE88B,
0x09F2BD9EE813B717, 0x7401AA4B285D1CB3, 0x21858F143195CAEE, 0x48C381841398D1B8,
0xFCB750D3B2F98889, 0x39A86A998D1CE1B9, 0x1F888E0CE473465A, 0x7899568376978716,
0x02CF2AD7EE2341BF, 0x85C713B5B3F1A14E, 0xFF916FE12B4567E7, 0x7C1A0230B7D10575,
0x0C98FCC85ECA9BA5, 0xA3E7F720DA9E06AD, 0x6A6031A2BBB1F438, 0x973E74947ED7D260,
0x2CF4663918C0FF9A, 0x5F50A7F368678E24, 0x34D983B4A449D4CD, 0x68AF1B755592B587,
0x7F3C3D022E6DEA1B, 0xABFC5F5B45121F6B, 0x0D71E92D29553574, 0xDFFDF5106D4F03D8,
0x081BA87B9F8C19C6, 0xDB7EA1A3AC0981BB, 0xBBCA12AD66172DFA, 0x79704366010829C7,
0x179326777BFF5F9C, 0x0000000000000000, 0xEB2476A4C906D715, 0x724DD42F0738DF6F,
0xB752EE6538DDB65F, 0x37FFBC863DF53BA3, 0x8EFA84FCB5C157E6, 0xE9EB5C73272596AA,
0x1B0BDABF2535C439, 0x86E12C872A4D4E20, 0x9969A28BCE3E087A, 0xFAFB2EB79D9C4B55,
0x056A4156B6D92CB2, 0x5A3AE6A5DEBEA296, 0x22A3B026A8292580, 0x53C85B3B36AD1581,
0xB11E900117B87583, 0xC51F3A4A3FE56930, 0xE019E1EDCF3621BD, 0xEC811D2591FCBA18,
0x445B7D4C4D524A1D, 0xA8DA6069DCAEF005, 0x58F5CC72309DE329, 0xD4C062596B7FF570,
0xCE22AD0339D59F98, 0x591CD99747024DF8, 0x8B90C5AA03187B54, 0xF663D27FC356D0F0,
0xD8589E9135B56ED5, 0x35309651D3D67A1C, 0x12F96721CD26732E, 0xD28C1C3D441A36AC,
0x492A946164077F69, 0x2D1D73DC6F5F514B, 0x6F0A70F40D68D88A, 0x60B4B30ECA1EAC41,
0xD36509D83385987D, 0x0B3D97490630F6A8, 0x9ECCC90A96C46577, 0xA20EE2C5AD01A87C,
0xE49AB55E0E70A3DE, 0xA4429CA182646BA0, 0xDA97B446DB962F6A, 0xCCED87D4D7F6DE27,
0x2AB8185D37A53C46, 0x9F25DCEFE15BCBA6, 0xC19C6EF9FEA3EB53, 0xA764A3931BD884CE,
0x2FD2590B817C10F4, 0x56A21A6D80743933, 0xE573A0BB79EF0D0F, 0x155C0CA095DC1E23,
0x6C2C4FC694D437E4, 0x10364DF623053291, 0xDD32DFC7836C4267, 0x03263F3299BCEF6E,
0x66F8CD6AE57B6F9D, 0x8C35AE2B5BE21659, 0x31B3C2E21290F87F, 0x93BD2027BF915003,
0x69460E90220D1B56, 0x299E276FAE19D328, 0x63928C3C53A2432F, 0x7082FEF8E91B9ED0,
0xBC6F792C3EED40F7, 0x4C40D537D2DE53DB, 0x75E8BFAE5FC2B262, 0x4DA9C0D2A541FD0A,
0x4E8FFFE03CFD1264, 0x2620E495696FA7E3, 0xE1F0F408B8A98F6C, 0xD1AA230FDDA6D9C2,
0xC7D0109DD1C6288F, 0x8A79D04F7487D585, 0x4694579BA3710BA2, 0x38417F7CFA834F68,
0x1D47A4DB0A5007E5, 0x206C9AF1460A643F, 0xA128DDF734BD4712, 0x8144470672B7232D,
0xF2E086CC02105293, 0x182DE58DBC892B57, 0xCAA1F9B0F8931DFB, 0x6B892447CC2E5AE9,
0xF9DD11850420A43B, 0x4BE5BEB68A243ED6, 0x5584255F19C8D65D, 0x3B67404E633FA006,
0xA68DB6766C472A1F, 0xF78AC79AB4C97E21, 0xC353442E1080AAEC, 0x9A4F9DB95782E714
};
static const uint64_t T3[256] =
{
0x05BA7BC82C9B3220, 0x31A54665F8B65E4F, 0xB1B651F77547F4D4, 0x8BFA0D857BA46682,
0x85A96C5AA16A98BB, 0x990FAEF908EB79C9, 0xA15E37A247F4A62D, 0x76857DCD5D27741E,
0xF8C50B800A1820BC, 0xBE65DCB201F7A2B4, 0x666D1B986F9426E7, 0x4CC921BF53C4E648,
0x95410A0F93D9CA42, 0x20CDCCAA647BA4EF, 0x429A4060890A1871, 0x0C4EA4F69B32B38B,
0xCCDA362DDE354CD3, 0x96DC23BC7C5B2FA9, 0xC309BB68AA851AB3, 0xD26131A73648E013,
0x021DC52941FC4DB2, 0xCD5ADAB7704BE48A, 0xA77965D984ED71E6, 0x32386FD61734BBA4,
0xE82D6DD538AB7245, 0x5C2147EA6177B4B1, 0x5DA1AB70CF091CE8, 0xAC907FCE72B8BDFF,
0x57C85DFD972278A8, 0xA4E44C6A6B6F940D, 0x3851995B4F1FDFE4, 0x62578CCAED71BC9E,
0xD9882BB0C01D2C0A, 0x917B9D5D113C503B, 0xA2C31E11A87643C6, 0xE463C923A399C1CE,
0xF71686C57EA876DC, 0x87B4A973E096D509, 0xAF0D567D9D3A5814, 0xB40C2A3F59DCC6F4,
0x3602F88495D121DD, 0xD3E1DD3D9836484A, 0xF945E71AA46688E5, 0x7518547EB2A591F5,
0x9366587450C01D89, 0x9EA81018658C065B, 0x4F54080CBC4603A3, 0x2D0384C65137BF3D,
0xDC325078EC861E2A, 0xEA30A8FC79573FF7, 0x214D2030CA050CB6, 0x65F0322B8016C30C,
0x69BE96DD1B247087, 0xDB95EE9981E161B8, 0xD1FC1814D9CA05F8, 0x820ED2BBCC0DE729,
0x63D76050430F14C7, 0x3BCCB0E8A09D3A0F, 0x8E40764D573F54A2, 0x39D175C1E16177BD,
0x12F5A37C734F1F4B, 0xAB37C12F1FDFC26D, 0x5648B167395CD0F1, 0x6C04ED1537BF42A7,
0xED97161D14304065, 0x7D6C67DAAB72B807, 0xEC17FA87BA4EE83C, 0xDFAF79CB0304FBC1,
0x733F060571BC463E, 0x78D61C1287E98A27, 0xD07CF48E77B4ADA1, 0xB9C262536C90DD26,
0xE2449B5860801605, 0x8FC09AD7F941FCFB, 0xFAD8CEA94BE46D0E, 0xA343F28B0608EB9F,
0x9B126BD04917347B, 0x9A92874AE7699C22, 0x1B017C42C4E69EE0, 0x3A4C5C720EE39256,
0x4B6E9F5E3EA399DA, 0x6BA353F45AD83D35, 0xE7FEE0904C1B2425, 0x22D009832587E95D,
0x842980C00F1430E2, 0xC6B3C0A0861E2893, 0x087433A419D729F2, 0x341F3DADD42D6C6F,
0xEE0A3FAEFBB2A58E, 0x4AEE73C490DD3183, 0xAAB72DB5B1A16A34, 0xA92A04065E238FDF,
0x7B4B35A1686B6FCC, 0x6A23BF6EF4A6956C, 0x191CB96B851AD352, 0x55D598D4D6DE351A,
0xC9604DE5F2AE7EF3, 0x1CA6C2A3A981E172, 0xDE2F9551AD7A5398, 0x3025AAFF56C8F616,
0x15521D9D1E2860D9, 0x506FE31CFA45073A, 0x189C55F12B647B0B, 0x0180EC9AAE7EA859,
0x7CEC8B40050C105E, 0x2350E5198BF94104, 0xEF8AD33455CC0DD7, 0x07A7BEE16D677F92,
0xE5E325B90DE76997, 0x5A061591A26E637A, 0xB611EF1618208B46, 0x09F4DF3EB7A981AB,
0x1EBB078AE87DACC0, 0xB791038CB65E231F, 0x0FD38D4574B05660, 0x67EDF702C1EA8EBE,
0xBA5F4BE0831238CD, 0xE3C477C2CEFEBE5C, 0x0DCE486C354C1BD2, 0x8C5DB36416C31910,
0x26EA9ED1A7627324, 0x039D29B3EF82E5EB, 0x9F28FC82CBF2AE02, 0xA8AAE89CF05D2786,
0x431AACFA2774B028, 0xCF471F9E31B7A938, 0x581BD0B8E3922EC8, 0xBC78199B400BEF06,
0x90FB71C7BF42F862, 0x1F3BEB1046030499, 0x683E7A47B55AD8DE, 0x988F4263A695D190,
0xD808C72A6E638453, 0x0627527BC319D7CB, 0xEBB04466D72997AE, 0xE67E0C0AE2658C7C,
0x14D2F107B056C880, 0x7122C32C30400B8C, 0x8A7AE11FD5DACEDB, 0xA0DEDB38E98A0E74,
0xAD109354DCC615A6, 0x0BE91A17F655CC19, 0x8DDD5FFEB8BDB149, 0xBFE53028AF890AED,
0xD65BA6F5B4AD7A6A, 0x7956F0882997227E, 0x10E8665532B352F9, 0x0E5361DFDACEFE39,
0xCEC7F3049FC90161, 0xFF62B561677F5F2E, 0x975CCF26D22587F0, 0x51EF0F86543BAF63,
0x2F1E41EF10CBF28F, 0x52722635BBB94A88, 0xAE8DBAE73344F04D, 0x410769D36688FD9A,
0xB3AB94DE34BBB966, 0x801317928DF1AA9B, 0xA564A0F0C5113C54, 0xF131D4BEBDB1A117,
0x7F71A2F3EA8EF5B5, 0x40878549C8F655C3, 0x7EF14E6944F05DEC, 0xD44663DCF55137D8,
0xF2ACFD0D523344FC, 0x0000000000000000, 0x5FBC6E598EF5515A, 0x16CF342EF1AA8532,
0xB036BD6DDB395C8D, 0x13754FE6DD31B712, 0xBBDFA77A2D6C9094, 0x89E7C8AC3A582B30,
0x3C6B0E09CDFA459D, 0xC4AE0589C7E26521, 0x49735A777F5FD468, 0xCAFD64561D2C9B18,
0xDA1502032F9FC9E1, 0x8867243694268369, 0x3782141E3BAF8984, 0x9CB5D53124704BE9,
0xD7DB4A6F1AD3D233, 0xA6F989432A93D9BF, 0x9D3539AB8A0EE3B0, 0x53F2CAAF15C7E2D1,
0x6E19283C76430F15, 0x3DEBE2936384EDC4, 0x5E3C82C3208BF903, 0x33B8834CB94A13FD,
0x6470DEB12E686B55, 0x359FD1377A53C436, 0x61CAA57902F35975, 0x043A975282E59A79,
0xFD7F70482683129C, 0xC52EE913699CCD78, 0x28B9FF0E7DAC8D1D, 0x5455744E78A09D43,
0xCB7D88CCB3523341, 0x44BD121B4A13CFBA, 0x4D49CD25FDBA4E11, 0x3E76CB208C06082F,
0x3FF627BA2278A076, 0xC28957F204FBB2EA, 0x453DFE81E46D67E3, 0x94C1E6953DA7621B,
0x2C83685CFF491764, 0xF32C1197FC4DECA5, 0x2B24D6BD922E68F6, 0xB22B78449AC5113F,
0x48F3B6EDD1217C31, 0x2E9EAD75BEB55AD6, 0x174FD8B45FD42D6B, 0x4ED4E4961238ABFA,
0x92E6B4EEFEBEB5D0, 0x46A0D7320BEF8208, 0x47203BA8A5912A51, 0x24F75BF8E69E3E96,
0xF0B1382413CF094E, 0xFEE259FBC901F777, 0x276A724B091CDB7D, 0xBDF8F501EE75475F,
0x599B3C224DEC8691, 0x6D84018F99C1EAFE, 0x7498B8E41CDB39AC, 0xE0595E71217C5BB7,
0x2AA43A273C50C0AF, 0xF50B43EC3F543B6E, 0x838E3E2162734F70, 0xC09492DB4507FF58,
0x72BFEA9FDFC2EE67, 0x11688ACF9CCDFAA0, 0x1A8190D86A9836B9, 0x7ACBD93BC615C795,
0xC7332C3A286080CA, 0x863445E94EE87D50, 0xF6966A5FD0D6DE85, 0xE9AD814F96D5DA1C,
0x70A22FB69E3EA3D5, 0x0A69F68D582B6440, 0xB8428EC9C2EE757F, 0x604A49E3AC8DF12C,
0x5B86F90B0C10CB23, 0xE1D9B2EB8F02F3EE, 0x29391394D3D22544, 0xC8E0A17F5CD0D6AA,
0xB58CC6A5F7A26EAD, 0x8193FB08238F02C2, 0xD5C68F465B2F9F81, 0xFCFF9CD288FDBAC5,
0x77059157F359DC47, 0x1D262E3907FF492B, 0xFB582233E59AC557, 0xDDB2BCE242F8B673,
0x2577B76248E096CF, 0x6F99C4A6D83DA74C, 0xC1147E41EB795701, 0xF48BAF76912A9337
};
static const uint64_t T4[256] =
{
0x3EF29D249B2C0A19, 0xE9E16322B6F8622F, 0x5536994047757F7A, 0x9F4D56D5A47B0B33,
0x822567466AA1174C, 0xB8F5057DEB082FB2, 0xCC48C10BF4475F53, 0x373088D4275DEC3A,
0x968F4325180AED10, 0x173D232CF7016151, 0xAE4ED09F946FCC13, 0xFD4B4741C4539873,
0x1B5B3F0DD9933765, 0x2FFCB0967B644052, 0xE02376D20A89840C, 0xA3AE3A70329B18D7,
0x419CBD2335DE8526, 0xFAFEBF115B7C3199, 0x0397074F85AA9B0D, 0xC58AD4FB4836B970,
0xBEC60BE3FC4104A8, 0x1EFF36DC4B708772, 0x131FDC33ED8453B6, 0x0844E33E341764D3,
0x0FF11B6EAB38CD39, 0x64351F0A7761B85A, 0x3B5694F509CFBA0E, 0x30857084B87245D0,
0x47AFB3BD2297AE3C, 0xF2BA5C2F6F6B554A, 0x74BDC4761F4F70E1, 0xCFDFC64471EDC45E,
0xE610784C1DC0AF16, 0x7ACA29D63C113F28, 0x2DED411776A859AF, 0xAC5F211E99A3D5EE,
0xD484F949A87EF33B, 0x3CE36CA596E013E4, 0xD120F0983A9D432C, 0x6BC40464DC597563,
0x69D5F5E5D1956C9E, 0x9AE95F043698BB24, 0xC9ECC8DA66A4EF44, 0xD69508C8A5B2EAC6,
0xC40C2235C0503B80, 0x38C193BA8C652103, 0x1CEEC75D46BC9E8F, 0xD331011937515AD1,
0xD8E2E56886ECA50F, 0xB137108D5779C991, 0x709F3B6905CA4206, 0x4FEB50831680CAEF,
0xEC456AF3241BD238, 0x58D673AFE181ABBE, 0x242F54E7CAD9BF8C, 0x0211F1810DCC19FD,
0x90BC4DBB0F43C60A, 0x9518446A9DA0761D, 0xA1BFCBF13F57012A, 0x2BDE4F8961E172B5,
0x27B853A84F732481, 0xB0B1E643DF1F4B61, 0x18CC38425C39AC68, 0xD2B7F7D7BF37D821,
0x3103864A3014C720, 0x14AA246372ABFA5C, 0x6E600DB54EBAC574, 0x394765740403A3F3,
0x09C215F0BC71E623, 0x2A58B947E987F045, 0x7B4CDF18B477BDD8, 0x9709B5EB906C6FE0,
0x73083C268060D90B, 0xFEDC400E41F9037E, 0x284948C6E44BE9B8, 0x728ECAE808065BFB,
0x06330E9E17492B1A, 0x5950856169E7294E, 0xBAE4F4FCE6C4364F, 0xCA7BCF95E30E7449,
0x7D7FD186A33E96C2, 0x52836110D85AD690, 0x4DFAA1021B4CD312, 0x913ABB75872544FA,
0xDD46ECB9140F1518, 0x3D659A6B1E869114, 0xC23F2CABD719109A, 0xD713FE062DD46836,
0xD0A60656B2FBC1DC, 0x221C5A79DD909496, 0xEFD26DBCA1B14935, 0x0E77EDA0235E4FC9,
0xCBFD395B6B68F6B9, 0x0DE0EAEFA6F4D4C4, 0x0422FF1F1A8532E7, 0xF969B85EDED6AA94,
0x7F6E2007AEF28F3F, 0x3AD0623B81A938FE, 0x6624EE8B7AADA1A7, 0xB682E8DDC856607B,
0xA78CC56F281E2A30, 0xC79B257A45FAA08D, 0x5B4174E0642B30B3, 0x5F638BFF7EAE0254,
0x4BC9AF9C0C05F808, 0xCE59308AF98B46AE, 0x8FC58DA9CC55C388, 0x803496C7676D0EB1,
0xF33CAAE1E70DD7BA, 0xBB6202326EA2B4BF, 0xD5020F87201871CB, 0x9D5CA754A9B712CE,
0x841669D87DE83C56, 0x8A6184785EB6739F, 0x420BBA6CB0741E2B, 0xF12D5B60EAC1CE47,
0x76AC35F71283691C, 0x2C6BB7D9FECEDB5F, 0xFCCDB18F4C351A83, 0x1F79C012C3160582,
0xF0ABADAE62A74CB7, 0xE1A5801C82EF06FC, 0x67A21845F2CB2357, 0x5114665F5DF04D9D,
0xBF40FD2D74278658, 0xA0393D3FB73183DA, 0x05A409D192E3B017, 0xA9FB28CF0B4065F9,
0x25A9A22942BF3D7C, 0xDB75E22703463E02, 0xB326E10C5AB5D06C, 0xE7968E8295A62DE6,
0xB973F3B3636EAD42, 0xDF571D3819C30CE5, 0xEE549B7229D7CBC5, 0x12992AFD65E2D146,
0xF8EF4E9056B02864, 0xB7041E134030E28B, 0xC02EDD2ADAD50967, 0x932B4AF48AE95D07,
0x6FE6FB7BC6DC4784, 0x239AACB755F61666, 0x401A4BEDBDB807D6, 0x485EA8D389AF6305,
0xA41BC220ADB4B13D, 0x753B32B89729F211, 0x997E584BB3322029, 0x1D683193CEDA1C7F,
0xFF5AB6C0C99F818E, 0x16BBD5E27F67E3A1, 0xA59D34EE25D233CD, 0x98F8AE853B54A2D9,
0x6DF70AFACB105E79, 0x795D2E99B9BBA425, 0x8E437B6744334178, 0x0186F6CE886682F0,
0xEBF092A3BB347BD2, 0xBCD7FA62F18D1D55, 0xADD9D7D011C5571E, 0x0BD3E471B1BDFFDE,
0xAA6C2F808EEAFEF4, 0x5EE57D31F6C880A4, 0xF50FA47FF044FCA0, 0x1ADDC9C351F5B595,
0xEA76646D3352F922, 0x0000000000000000, 0x85909F16F58EBEA6, 0x46294573AAF12CCC,
0x0A5512BF39DB7D2E, 0x78DBD85731DD26D5, 0x29CFBE086C2D6B48, 0x218B5D36583A0F9B,
0x152CD2ADFACD78AC, 0x83A39188E2C795BC, 0xC3B9DA655F7F926A, 0x9ECBA01B2C1D89C3,
0x07B5F8509F2FA9EA, 0x7EE8D6C926940DCF, 0x36B67E1AAF3B6ECA, 0x86079859702425AB,
0xFB7849DFD31AB369, 0x4C7C57CC932A51E2, 0xD96413A60E8A27FF, 0x263EA566C715A671,
0x6C71FC344376DC89, 0x4A4F595284637AF8, 0xDAF314E98B20BCF2, 0x572768C14AB96687,
0x1088DB7C682EC8BB, 0x887075F9537A6A62, 0x2E7A4658F302C2A2, 0x619116DBE582084D,
0xA87DDE018326E709, 0xDCC01A779C6997E8, 0xEDC39C3DAC7D50C8, 0xA60A33A1A078A8C0,
0xC1A82BE452B38B97, 0x3F746BEA134A88E9, 0xA228CCBEBAFD9A27, 0xABEAD94E068C7C04,
0xF48952B178227E50, 0x5CF48CB0FB049959, 0x6017E0156DE48ABD, 0x4438B4F2A73D3531,
0x8C528AE649FF5885, 0xB515EF924DFCFB76, 0x0C661C212E925634, 0xB493195CC59A7986,
0x9CDA519A21D1903E, 0x32948105B5BE5C2D, 0x194ACE8CD45F2E98, 0x438D4CA238129CDB,
0x9B6FA9CABEFE39D4, 0x81B26009EF0B8C41, 0xDED1EBF691A58E15, 0x4E6DA64D9EE6481F,
0x54B06F8ECF13FD8A, 0x49D85E1D01C9E1F5, 0xAFC826511C094EE3, 0xF698A33075EE67AD,
0x5AC7822EEC4DB243, 0x8DD47C28C199DA75, 0x89F68337DB1CE892, 0xCDCE37C57C21DDA3,
0x530597DE503C5460, 0x6A42F2AA543FF793, 0x5D727A7E73621BA9, 0xE232875307459DF1,
0x56A19E0FC2DFE477, 0xC61DD3B4CD9C227D, 0xE5877F03986A341B, 0x949EB2A415C6F4ED,
0x6206119460289340, 0x6380E75AE84E11B0, 0x8BE772B6D6D0F16F, 0x50929091D596CF6D,
0xE86795EC3E9EE0DF, 0x7CF927482B581432, 0xC86A3E14EEC26DB4, 0x7119CDA78DACC0F6,
0xE40189CD100CB6EB, 0x92ADBC3A028FDFF7, 0xB2A017C2D2D3529C, 0x200DABF8D05C8D6B,
0x34A78F9BA2F77737, 0xE3B4719D8F231F01, 0x45BE423C2F5BB7C1, 0xF71E55FEFD88E55D,
0x6853032B59F3EE6E, 0x65B3E9C4FF073AAA, 0x772AC3399AE5EBEC, 0x87816E97F842A75B,
0x110E2DB2E0484A4B, 0x331277CB3DD8DEDD, 0xBD510CAC79EB9FA5, 0x352179552A91F5C7
};
static const uint64_t T5[256] =
{
0x8AB0A96846E06A6D, 0x43C7E80B4BF0B33A, 0x08C9B3546B161EE5, 0x39F1C235EBA990BE,
0xC1BEF2376606C7B2, 0x2C209233614569AA, 0xEB01523B6FC3289A, 0x946953AB935ACEDD,
0x272838F63E13340E, 0x8B0455ECA12BA052, 0x77A1B2C4978FF8A2, 0xA55122CA13E54086,
0x2276135862D3F1CD, 0xDB8DDFDE08B76CFE, 0x5D1E12C89E4A178A, 0x0E56816B03969867,
0xEE5F79953303ED59, 0xAFED748BAB78D71D, 0x6D929F2DF93E53EE, 0xF5D8A8F8BA798C2A,
0xF619B1698E39CF6B, 0x95DDAF2F749104E2, 0xEC2A9C80E0886427, 0xCE5C8FD8825B95EA,
0xC4E0D9993AC60271, 0x4699C3A5173076F9, 0x3D1B151F50A29F42, 0x9ED505EA2BC75946,
0x34665ACFDC7F4B98, 0x61B1FB53292342F7, 0xC721C0080E864130, 0x8693CD1696FD7B74,
0x872731927136B14B, 0xD3446C8A63A1721B, 0x669A35E8A6680E4A, 0xCAB658F239509A16,
0xA4E5DE4EF42E8AB9, 0x37A7435EE83F08D9, 0x134E6239E26C7F96, 0x82791A3C2DF67488,
0x3F6EF00A8329163C, 0x8E5A7E42FDEB6591, 0x5CAAEE4C7981DDB5, 0x19F234785AF1E80D,
0x255DDDE3ED98BD70, 0x50898A32A99CCCAC, 0x28CA4519DA4E6656, 0xAE59880F4CB31D22,
0x0D9798FA37D6DB26, 0x32F968F0B4FFCD1A, 0xA00F09644F258545, 0xFA3AD5175E24DE72,
0xF46C547C5DB24615, 0x713E80FBFF0F7E20, 0x7843CF2B73D2AAFA, 0xBD17EA36AEDF62B4,
0xFD111BACD16F92CF, 0x4ABAA7DBC72D67E0, 0xB3416B5DAD49FAD3, 0xBCA316B24914A88B,
0x15D150068AECF914, 0xE27C1DEBE31EFC40, 0x4FE48C759BEDA223, 0x7EDCFD141B522C78,
0x4E5070F17C26681C, 0xE696CAC15815F3BC, 0x35D2A64B3BB481A7, 0x800CFF29FE7DFDF6,
0x1ED9FAC3D5BAA4B0, 0x6C2663A91EF599D1, 0x03C1199134404341, 0xF7AD4DED69F20554,
0xCD9D9649B61BD6AB, 0xC8C3BDE7EADB1368, 0xD131899FB02AFB65, 0x1D18E352E1FAE7F1,
0xDA39235AEF7CA6C1, 0xA1BBF5E0A8EE4F7A, 0x91377805CF9A0B1E, 0x3138716180BF8E5B,
0xD9F83ACBDB3CE580, 0x0275E515D38B897E, 0x472D3F21F0FBBCC6, 0x2D946EB7868EA395,
0xBA3C248D21942E09, 0xE7223645BFDE3983, 0xFF64FEB902E41BB1, 0xC97741630D10D957,
0xC3CB1722B58D4ECC, 0xA27AEC719CAE0C3B, 0x99FECB51A48C15FB, 0x1465AC826D27332B,
0xE1BD047AD75EBF01, 0x79F733AF941960C5, 0x672EC96C41A3C475, 0xC27FEBA6524684F3,
0x64EFD0FD75E38734, 0xED9E60040743AE18, 0xFB8E2993B9EF144D, 0x38453EB10C625A81,
0x6978480742355C12, 0x48CF42CE14A6EE9E, 0x1CAC1FD606312DCE, 0x7B82D6BA4792E9BB,
0x9D141C7B1F871A07, 0x5616B80DC11C4A2E, 0xB849C198F21FA777, 0x7CA91801C8D9A506,
0xB1348E487EC273AD, 0x41B20D1E987B3A44, 0x7460AB55A3CFBBE3, 0x84E628034576F20A,
0x1B87D16D897A6173, 0x0FE27DEFE45D5258, 0x83CDE6B8CA3DBEB7, 0x0C23647ED01D1119,
0x7A362A3EA0592384, 0xB61F40F3F1893F10, 0x75D457D1440471DC, 0x4558DA34237035B8,
0xDCA6116587FC2043, 0x8D9B67D3C9AB26D0, 0x2B0B5C88EE0E2517, 0x6FE77A382AB5DA90,
0x269CC472D9D8FE31, 0x63C41E46FAA8CB89, 0xB7ABBC771642F52F, 0x7D1DE4852F126F39,
0xA8C6BA3024339BA0, 0x600507D7CEE888C8, 0x8FEE82C61A20AFAE, 0x57A2448926D78011,
0xFCA5E72836A458F0, 0x072BCEBB8F4B4CBD, 0x497BBE4AF36D24A1, 0x3CAFE99BB769557D,
0x12FA9EBD05A7B5A9, 0xE8C04BAA5B836BDB, 0x4273148FAC3B7905, 0x908384812851C121,
0xE557D3506C55B0FD, 0x72FF996ACB4F3D61, 0x3EDA0C8E64E2DC03, 0xF0868356E6B949E9,
0x04EAD72ABB0B0FFC, 0x17A4B5135967706A, 0xE3C8E16F04D5367F, 0xF84F30028DAF570C,
0x1846C8FCBD3A2232, 0x5B8120F7F6CA9108, 0xD46FA231ECEA3EA6, 0x334D947453340725,
0x58403966C28AD249, 0xBED6F3A79A9F21F5, 0x68CCB483A5FE962D, 0xD085751B57E1315A,
0xFED0023DE52FD18E, 0x4B0E5B5F20E6ADDF, 0x1A332DE96EB1AB4C, 0xA3CE10F57B65C604,
0x108F7BA8D62C3CD7, 0xAB07A3A11073D8E1, 0x6B0DAD1291BED56C, 0xF2F366433532C097,
0x2E557726B2CEE0D4, 0x0000000000000000, 0xCB02A476DE9B5029, 0xE4E32FD48B9E7AC2,
0x734B65EE2C84F75E, 0x6E5386BCCD7E10AF, 0x01B4FC84E7CBCA3F, 0xCFE8735C65905FD5,
0x3613BFDA0FF4C2E6, 0x113B872C31E7F6E8, 0x2FE18BA255052AEB, 0xE974B72EBC48A1E4,
0x0ABC5641B89D979B, 0xB46AA5E62202B66E, 0x44EC26B0C4BBFF87, 0xA6903B5B27A503C7,
0x7F680190FC99E647, 0x97A84A3AA71A8D9C, 0xDD12EDE16037EA7C, 0xC554251DDD0DC84E,
0x88C54C7D956BE313, 0x4D91696048662B5D, 0xB08072CC9909B992, 0xB5DE5962C5C97C51,
0x81B803AD19B637C9, 0xB2F597D94A8230EC, 0x0B08AAC55F565DA4, 0xF1327FD2017283D6,
0xAD98919E78F35E63, 0x6AB9519676751F53, 0x24E921670A53774F, 0xB9FD3D1C15D46D48,
0x92F66194FBDA485F, 0x5A35DC7311015B37, 0xDED3F4705477A93D, 0xC00A0EB381CD0D8D,
0xBB88D809C65FE436, 0x16104997BEACBA55, 0x21B70AC95693B28C, 0x59F4C5E225411876,
0xD5DB5EB50B21F499, 0x55D7A19CF55C096F, 0xA97246B4C3F8519F, 0x8552D487A2BD3835,
0x54635D181297C350, 0x23C2EFDC85183BF2, 0x9F61F96ECC0C9379, 0x534893A39DDC8FED,
0x5EDF0B59AA0A54CB, 0xAC2C6D1A9F38945C, 0xD7AEBBA0D8AA7DE7, 0x2ABFA00C09C5EF28,
0xD84CC64F3CF72FBF, 0x2003F64DB15878B3, 0xA724C7DFC06EC9F8, 0x069F323F68808682,
0xCC296ACD51D01C94, 0x055E2BAE5CC0C5C3, 0x6270E2C21D6301B6, 0x3B842720382219C0,
0xD2F0900E846AB824, 0x52FC6F277A1745D2, 0xC6953C8CE94D8B0F, 0xE009F8FE3095753E,
0x655B2C7992284D0B, 0x984A37D54347DFC4, 0xEAB5AEBF8808E2A5, 0x9A3FD2C090CC56BA,
0x9CA0E0FFF84CD038, 0x4C2595E4AFADE162, 0xDF6708F4B3BC6302, 0xBF620F237D54EBCA,
0x93429D101C118260, 0x097D4FD08CDDD4DA, 0x8C2F9B572E60ECEF, 0x708A7C7F18C4B41F,
0x3A30DBA4DFE9D3FF, 0x4006F19A7FB0F07B, 0x5F6BF7DD4DC19EF4, 0x1F6D064732716E8F,
0xF9FBCC866A649D33, 0x308C8DE567744464, 0x8971B0F972A0292C, 0xD61A47243F61B7D8,
0xEFEB8511D4C82766, 0x961CB6BE40D147A3, 0xAAB35F25F7B812DE, 0x76154E407044329D,
0x513D76B64E570693, 0xF3479AC7D2F90AA8, 0x9B8B2E4477079C85, 0x297EB99D3D85AC69
};
static const uint64_t T6[256] =
{
0x7E37E62DFC7D40C3, 0x776F25A4EE939E5B, 0xE045C850DD8FB5AD, 0x86ED5BA711FF1952,
0xE91D0BD9CF616B35, 0x37E0AB256E408FFB, 0x9607F6C031025A7A, 0x0B02F5E116D23C9D,
0xF3D8486BFB50650C, 0x621CFF27C40875F5, 0x7D40CB71FA5FD34A, 0x6DAA6616DAA29062,
0x9F5F354923EC84E2, 0xEC847C3DC507C3B3, 0x025A3668043CE205, 0xA8BF9E6C4DAC0B19,
0xFA808BE2E9BEBB94, 0xB5B99C5277C74FA3, 0x78D9BC95F0397BCC, 0xE332E50CDBAD2624,
0xC74FCE129332797E, 0x1729ECEB2EA709AB, 0xC2D6B9F69954D1F8, 0x5D898CBFBAB8551A,
0x859A76FB17DD8ADB, 0x1BE85886362F7FB5, 0xF6413F8FF136CD8A, 0xD3110FA5BBB7E35C,
0x0A2FEED514CC4D11, 0xE83010EDCD7F1AB9, 0xA1E75DE55F42D581, 0xEEDE4A55C13B21B6,
0xF2F5535FF94E1480, 0x0CC1B46D1888761E, 0xBCE15FDB6529913B, 0x2D25E8975A7181C2,
0x71817F1CE2D7A554, 0x2E52C5CB5C53124B, 0xF9F7A6BEEF9C281D, 0x9E722E7D21F2F56E,
0xCE170D9B81DCA7E6, 0x0E9B82051CB4941B, 0x1E712F623C49D733, 0x21E45CFA42F9F7DC,
0xCB8E7A7F8BBA0F60, 0x8E98831A010FB646, 0x474CCF0D8E895B23, 0xA99285584FB27A95,
0x8CC2B57205335443, 0x42D5B8E984EFF3A5, 0x012D1B34021E718C, 0x57A6626AAE74180B,
0xFF19FC06E3D81312, 0x35BA9D4D6A7C6DFE, 0xC9D44C178F86ED65, 0x506523E6A02E5288,
0x03772D5C06229389, 0x8B01F4FE0B691EC0, 0xF8DABD8AED825991, 0x4C4E3AEC985B67BE,
0xB10DF0827FBF96A9, 0x6A69279AD4F8DAE1, 0xE78689DCD3D5FF2E, 0x812E1A2B1FA553D1,
0xFBAD90D6EBA0CA18, 0x1AC543B234310E39, 0x1604F7DF2CB97827, 0xA6241C6951189F02,
0x753513CCEAAF7C5E, 0x64F2A59FC84C4EFA, 0x247D2B1E489F5F5A, 0xDB64D718AB474C48,
0x79F4A7A1F2270A40, 0x1573DA832A9BEBAE, 0x3497867968621C72, 0x514838D2A2302304,
0xF0AF6537FD72F685, 0x1D06023E3A6B44BA, 0x678588C3CE6EDD73, 0x66A893F7CC70ACFF,
0xD4D24E29B5EDA9DF, 0x3856321470EA6A6C, 0x07C3418C0E5A4A83, 0x2BCBB22F5635BACD,
0x04B46CD00878D90A, 0x06EE5AB80C443B0F, 0x3B211F4876C8F9E5, 0x0958C38912EEDE98,
0xD14B39CDBF8B0159, 0x397B292072F41BE0, 0x87C0409313E168DE, 0xAD26E98847CAA39F,
0x4E140C849C6785BB, 0xD5FF551DB7F3D853, 0xA0CA46D15D5CA40D, 0xCD6020C787FE346F,
0x84B76DCF15C3FB57, 0xDEFDA0FCA121E4CE, 0x4B8D7B6096012D3D, 0x9AC642AD298A2C64,
0x0875D8BD10F0AF14, 0xB357C6EA7B8374AC, 0x4D6321D89A451632, 0xEDA96709C719B23F,
0xF76C24BBF328BC06, 0xC662D526912C08F2, 0x3CE25EC47892B366, 0xB978283F6F4F39BD,
0xC08C8F9E9D6833FD, 0x4F3917B09E79F437, 0x593DE06FB2C08C10, 0xD6887841B1D14BDA,
0x19B26EEE32139DB0, 0xB494876675D93E2F, 0x825937771987C058, 0x90E9AC783D466175,
0xF1827E03FF6C8709, 0x945DC0A8353EB87F, 0x4516F9658AB5B926, 0x3F9573987EB020EF,
0xB855330B6D514831, 0x2AE6A91B542BCB41, 0x6331E413C6160479, 0x408F8E8180D311A0,
0xEFF35161C325503A, 0xD06622F9BD9570D5, 0x8876D9A20D4B8D49, 0xA5533135573A0C8B,
0xE168D364DF91C421, 0xF41B09E7F50A2F8F, 0x12B09B0F24C1A12D, 0xDA49CC2CA9593DC4,
0x1F5C34563E57A6BF, 0x54D14F36A8568B82, 0xAF7CDFE043F6419A, 0xEA6A2685C943F8BC,
0xE5DCBFB4D7E91D2B, 0xB27ADDDE799D0520, 0x6B443CAED6E6AB6D, 0x7BAE91C9F61BE845,
0x3EB868AC7CAE5163, 0x11C7B65322E332A4, 0xD23C1491B9A992D0, 0x8FB5982E0311C7CA,
0x70AC6428E0C9D4D8, 0x895BC2960F55FCC5, 0x76423E90EC8DEFD7, 0x6FF0507EDE9E7267,
0x3DCF45F07A8CC2EA, 0x4AA06054941F5CB1, 0x5810FB5BB0DEFD9C, 0x5EFEA1E3BC9AC693,
0x6EDD4B4ADC8003EB, 0x741808F8E8B10DD2, 0x145EC1B728859A22, 0x28BC9F7350172944,
0x270A06424EBDCCD3, 0x972AEDF4331C2BF6, 0x059977E40A66A886, 0x2550302A4A812ED6,
0xDD8A8DA0A7037747, 0xC515F87A970E9B7B, 0x3023EAA9601AC578, 0xB7E3AA3A73FBADA6,
0x0FB699311EAAE597, 0x0000000000000000, 0x310EF19D6204B4F4, 0x229371A644DB6455,
0x0DECAF591A960792, 0x5CA4978BB8A62496, 0x1C2B190A38753536, 0x41A295B582CD602C,
0x3279DCC16426277D, 0xC1A194AA9F764271, 0x139D803B26DFD0A1, 0xAE51C4D441E83016,
0xD813FA44AD65DFC1, 0xAC0BF2BC45D4D213, 0x23BE6A9246C515D9, 0x49D74D08923DCF38,
0x9D05032127D066E7, 0x2F7FDEFF5E4D63C7, 0xA47E2A0155247D07, 0x99B16FF12FA8BFED,
0x4661D4398C972AAF, 0xDFD0BBC8A33F9542, 0xDCA79694A51D06CB, 0xB020EBB67DA1E725,
0xBA0F0563696DAA34, 0xE4F1A480D5F76CA7, 0xC438E34E9510EAF7, 0x939E81243B64F2FC,
0x8DEFAE46072D25CF, 0x2C08F3A3586FF04E, 0xD7A56375B3CF3A56, 0x20C947CE40E78650,
0x43F8A3DD86F18229, 0x568B795EAC6A6987, 0x8003011F1DBB225D, 0xF53612D3F7145E03,
0x189F75DA300DEC3C, 0x9570DB9C3720C9F3, 0xBB221E576B73DBB8, 0x72F65240E4F536DD,
0x443BE25188ABC8AA, 0xE21FFE38D9B357A8, 0xFD43CA6EE7E4F117, 0xCAA3614B89A47EEC,
0xFE34E732E1C6629E, 0x83742C431B99B1D4, 0xCF3A16AF83C2D66A, 0xAAE5A8044990E91C,
0x26271D764CA3BD5F, 0x91C4B74C3F5810F9, 0x7C6DD045F841A2C6, 0x7F1AFD19FE63314F,
0xC8F957238D989CE9, 0xA709075D5306EE8E, 0x55FC5402AA48FA0E, 0x48FA563C9023BEB4,
0x65DFBEABCA523F76, 0x6C877D22D8BCE1EE, 0xCC4D3BF385E045E3, 0xBEBB69B36115733E,
0x10EAAD6720FD4328, 0xB6CEB10E71E5DC2A, 0xBDCC44EF6737E0B7, 0x523F158EA412B08D,
0x989C74C52DB6CE61, 0x9BEB59992B945DE8, 0x8A2CEFCA09776F4C, 0xA3BD6B8D5B7E3784,
0xEB473DB1CB5D8930, 0xC3FBA2C29B4AA074, 0x9C28181525CE176B, 0x683311F2D0C438E4,
0x5FD3BAD7BE84B71F, 0xFC6ED15AE5FA809B, 0x36CDB0116C5EFE77, 0x29918447520958C8,
0xA29070B959604608, 0x53120EBAA60CC101, 0x3A0C047C74D68869, 0x691E0AC6D2DA4968,
0x73DB4974E6EB4751, 0x7A838AFDF40599C9, 0x5A4ACD33B4E21F99, 0x6046C94FC03497F0,
0xE6AB92E8D1CB8EA2, 0x3354C7F5663856F1, 0xD93EE170AF7BAE4D, 0x616BD27BC22AE67C,
0x92B39A10397A8370, 0xABC8B3304B8E9890, 0xBF967287630B02B2, 0x5B67D607B6FC6E15
};
static uint64_t T7[256] =
{
0xD031C397CE553FE6, 0x16BA5B01B006B525, 0xA89BADE6296E70C8, 0x6A1F525D77D3435B,
0x6E103570573DFA0B, 0x660EFB2A17FC95AB, 0x76327A9E97634BF6, 0x4BAD9D6462458BF5,
0xF1830CAEDBC3F748, 0xC5C8F542669131FF, 0x95044A1CDC48B0CB, 0x892962DF3CF8B866,
0xB0B9E208E930C135, 0xA14FB3F0611A767C, 0x8D2605F21C160136, 0xD6B71922FECC549E,
0x37089438A5907D8B, 0x0B5DA38E5803D49C, 0x5A5BCC9CEA6F3CBC, 0xEDAE246D3B73FFE5,
0xD2B87E0FDE22EDCE, 0x5E54ABB1CA8185EC, 0x1DE7F88FE80561B9, 0xAD5E1A870135A08C,
0x2F2ADBD665CECC76, 0x5780B5A782F58358, 0x3EDC8A2EEDE47B3F, 0xC9D95C3506BEE70F,
0x83BE111D6C4E05EE, 0xA603B90959367410, 0x103C81B4809FDE5D, 0x2C69B6027D0C774A,
0x399080D7D5C87953, 0x09D41E16487406B4, 0xCDD63B1826505E5F, 0xF99DC2F49B0298E8,
0x9CD0540A943CB67F, 0xBCA84B7F891F17C5, 0x723D1DB3B78DF2A6, 0x78AA6E71E73B4F2E,
0x1433E699A071670D, 0x84F21BE454620782, 0x98DF3327B4D20F2F, 0xF049DCE2D3769E5C,
0xDB6C60199656EB7A, 0x648746B2078B4783, 0x32CD23598DCBADCF, 0x1EA4955BF0C7DA85,
0xE9A143401B9D46B5, 0xFD92A5D9BBEC21B8, 0xC8138C790E0B8E1B, 0x2EE00B9A6D7BA562,
0xF85712B893B7F1FC, 0xEB28FED80BEA949D, 0x564A65EB8A40EA4C, 0x6C9988E8474A2823,
0x4535898B121D8F2D, 0xABD8C03231ACCBF4, 0xBA2E91CAB9867CBD, 0x7960BE3DEF8E263A,
0x0C11A977602FD6F0, 0xCB50E1AD16C93527, 0xEAE22E94035FFD89, 0x2866D12F5DE2CE1A,
0xFF1B1841AB9BF390, 0x9F9339DE8CFE0D43, 0x964727C8C48A0BF7, 0x524502C6AAAE531C,
0x9B9C5EF3AC10B413, 0x4FA2FA4942AB32A5, 0x3F165A62E551122B, 0xC74148DA76E6E3D7,
0x924840E5E464B2A7, 0xD372AE43D69784DA, 0x233B72A105E11A86, 0xA48A04914941A638,
0xB4B68525C9DE7865, 0xDDEABAACA6CF8002, 0x0A9773C250B6BD88, 0xC284FFBB5EBD3393,
0x8BA0DF472C8F6A4E, 0x2AEF6CB74D951C32, 0x427983722A318D41, 0x73F7CDFFBF389BB2,
0x074C0AF9382C026C, 0x8A6A0F0B243A035A, 0x6FDAE53C5F88931F, 0xC68B98967E538AC3,
0x44FF59C71AA8E639, 0xE2FCE0CE439E9229, 0xA20CDE2479D8CD40, 0x19E89FA2C8EBD8E9,
0xF446BBCFF398270C, 0x43B3533E2284E455, 0xD82F0DCD8E945046, 0x51066F12B26CE820,
0xE73957AF6BC5426D, 0x081ECE5A40C16FA0, 0x3B193D4FC5BFAB7B, 0x7FE66488DF174D42,
0x0E9814EF705804D8, 0x8137AC857C39D7C6, 0xB1733244E185A821, 0x695C3F896F11F867,
0xF6CF0657E3EFF524, 0x1AABF276D02963D5, 0x2DA3664E75B91E5E, 0x0289BD981077D228,
0x90C1FD7DF413608F, 0x3C5537B6FD93A917, 0xAA12107E3919A2E0, 0x0686DAB530996B78,
0xDAA6B0559EE3826E, 0xC34E2FF756085A87, 0x6D5358A44FFF4137, 0xFC587595B35948AC,
0x7CA5095CC7D5F67E, 0xFB147F6C8B754AC0, 0xBFEB26AB91DDACF9, 0x6896EFC567A49173,
0xCA9A31E11E7C5C33, 0xBBE44186B13315A9, 0x0DDB793B689ABFE4, 0x70B4A02BA7FA208E,
0xE47A3A7B7307F951, 0x8CECD5BE14A36822, 0xEEED49B923B144D9, 0x17708B4DB8B3DC31,
0x6088219F2765FED3, 0xB3FA8FDCF1F27A09, 0x910B2D31FCA6099B, 0x0F52C4A378ED6DCC,
0x50CCBF5EBAD98134, 0x6BD582117F662A4F, 0x94CE9A50D4FDD9DF, 0x2B25BCFB45207526,
0x67C42B661F49FCBF, 0x492420FC723259DD, 0x03436DD418C2BB3C, 0x1F6E4517F872B391,
0xA08563BC69AF1F68, 0xD43EA4BAEEBB86B6, 0x01CAD04C08B56914, 0xAC94CACB0980C998,
0x54C3D8739A373864, 0x26FEC5C02DBACAC2, 0xDEA9D778BE0D3B3E, 0x040F672D20EEB950,
0xE5B0EA377BB29045, 0xF30AB136CBB42560, 0x62019C0737122CFB, 0xE86B930C13282FA1,
0xCC1CEB542EE5374B, 0x538FD28AA21B3A08, 0x1B61223AD89C0AC1, 0x36C24474AD25149F,
0x7A23D3E9F74C9D06, 0xBE21F6E79968C5ED, 0xCF5F868036278C77, 0xF705D61BEB5A9C30,
0x4D2B47D152DCE08D, 0x5F9E7BFDC234ECF8, 0x247778583DCD18EA, 0x867BA67C4415D5AA,
0x4CE1979D5A698999, 0x0000000000000000, 0xEC64F42133C696F1, 0xB57C5569C16B1171,
0xC1C7926F467F88AF, 0x654D96FE0F3E2E97, 0x15F936D5A8C40E19, 0xB8A72C52A9F1AE95,
0xA9517DAA21DB19DC, 0x58D27104FA18EE94, 0x5918A148F2AD8780, 0x5CDD1629DAF657C4,
0x8274C15164FB6CFA, 0xD1FB13DBC6E056F2, 0x7D6FD910CF609F6A, 0xB63F38BDD9A9AA4D,
0x3D9FE7FAF526C003, 0x74BBC706871499DE, 0xDF630734B6B8522A, 0x3AD3ED03CD0AC26F,
0xFADEAF2083C023D4, 0xC00D42234ECAE1BB, 0x8538CBA85CD76E96, 0xC402250E6E2458EB,
0x47BC3413026A5D05, 0xAFD7A71F114272A4, 0x978DF784CC3F62E3, 0xB96DFC1EA144C781,
0x21B2CF391596C8AE, 0x318E4E8D950916F3, 0xCE9556CC3E92E563, 0x385A509BDD7D1047,
0x358129A0B5E7AFA3, 0xE6F387E363702B79, 0xE0755D5653E94001, 0x7BE903A5FFF9F412,
0x12B53C2C90E80C75, 0x3307F315857EC4DB, 0x8FAFB86A0C61D31E, 0xD9E5DD8186213952,
0x77F8AAD29FD622E2, 0x25BDA814357871FE, 0x7571174A8FA1F0CA, 0x137FEC60985D6561,
0x30449EC19DBC7FE7, 0xA540D4DD41F4CF2C, 0xDC206AE0AE7AE916, 0x5B911CD0E2DA55A8,
0xB2305F90F947131D, 0x344BF9ECBD52C6B7, 0x5D17C665D2433ED0, 0x18224FEEC05EB1FD,
0x9E59E992844B6457, 0x9A568EBFA4A5DD07, 0xA3C60E68716DA454, 0x7E2CB4C4D7A22456,
0x87B176304CA0BCBE, 0x413AEEA632F3367D, 0x9915E36BBC67663B, 0x40F03EEA3A465F69,
0x1C2D28C3E0B008AD, 0x4E682A054A1E5BB1, 0x05C5B761285BD044, 0xE1BF8D1A5B5C2915,
0xF2C0617AC3014C74, 0xB7F5E8F1D11CC359, 0x63CB4C4B3FA745EF, 0x9D1A84469C89DF6B,
0xE33630824B2BFB3D, 0xD5F474F6E60EEFA2, 0xF58C6B83FB2D4E18, 0x4676E45F0ADF3411,
0x20781F751D23A1BA, 0xBD629B3381AA7ED1, 0xAE1D775319F71BB0, 0xFED1C80DA32E9A84,
0x5509083F92825170, 0x29AC01635557A70E, 0xA7C9694551831D04, 0x8E65682604D4BA0A,
0x11F651F8882AB749, 0xD77DC96EF6793D8A, 0xEF2799F52B042DCD, 0x48EEF0B07A8730C9,
0x22F1A2ED0D547392, 0x6142F1D32FD097C7, 0x4A674D286AF0E2E1, 0x80FD7CC9748CBED2,
0x717E7067AF4F499A, 0x938290A9ECD1DBB3, 0x88E3B293344DD172, 0x2734158C250FA3D6
}; };
static const uint64_t A_[64] = static const uint64_t C_[12][8] =
{
0x8e20faa72ba0b470, 0x47107ddd9b505a38, 0xad08b0e0c3282d1c, 0xd8045870ef14980e,
0x6c022c38f90a4c07, 0x3601161cf205268d, 0x1b8e0b0e798c13c8, 0x83478b07b2468764,
0xa011d380818e8f40, 0x5086e740ce47c920, 0x2843fd2067adea10, 0x14aff010bdd87508,
0x0ad97808d06cb404, 0x05e23c0468365a02, 0x8c711e02341b2d01, 0x46b60f011a83988e,
0x90dab52a387ae76f, 0x486dd4151c3dfdb9, 0x24b86a840e90f0d2, 0x125c354207487869,
0x092e94218d243cba, 0x8a174a9ec8121e5d, 0x4585254f64090fa0, 0xaccc9ca9328a8950,
0x9d4df05d5f661451, 0xc0a878a0a1330aa6, 0x60543c50de970553, 0x302a1e286fc58ca7,
0x18150f14b9ec46dd, 0x0c84890ad27623e0, 0x0642ca05693b9f70, 0x0321658cba93c138,
0x86275df09ce8aaa8, 0x439da0784e745554, 0xafc0503c273aa42a, 0xd960281e9d1d5215,
0xe230140fc0802984, 0x71180a8960409a42, 0xb60c05ca30204d21, 0x5b068c651810a89e,
0x456c34887a3805b9, 0xac361a443d1c8cd2, 0x561b0d22900e4669, 0x2b838811480723ba,
0x9bcf4486248d9f5d, 0xc3e9224312c8c1a0, 0xeffa11af0964ee50, 0xf97d86d98a327728,
0xe4fa2054a80b329c, 0x727d102a548b194e, 0x39b008152acb8227, 0x9258048415eb419d,
0x492c024284fbaec0, 0xaa16012142f35760, 0x550b8e9e21f7a530, 0xa48b474f9ef5dc18,
0x70a6a56e2440598e, 0x3853dc371220a247, 0x1ca76e95091051ad, 0x0edd37c48a08a6d8,
0x07e095624504536c, 0x8d70c431ac02a736, 0xc83862965601dd1b, 0x641c314b2b8ee083
};
static const uint8_t C_[12][64] =
{ {
{ {
0xb1,0x08,0x5b,0xda,0x1e,0xca,0xda,0xe9,0xeb,0xcb,0x2f,0x81,0xc0,0x65,0x7c,0x1f, 0xe9daca1eda5b08b1, 0x1f7c65c0812fcbeb, 0x16d0452e43766a2f, 0xfcc485758db84e71,
0x2f,0x6a,0x76,0x43,0x2e,0x45,0xd0,0x16,0x71,0x4e,0xb8,0x8d,0x75,0x85,0xc4,0xfc, 0x0169679291e07c4b, 0x15d360a4082a42a2, 0x234d74cc36747605, 0x0745a6f2596580dd
0x4b,0x7c,0xe0,0x91,0x92,0x67,0x69,0x01,0xa2,0x42,0x2a,0x08,0xa4,0x60,0xd3,0x15,
0x05,0x76,0x74,0x36,0xcc,0x74,0x4d,0x23,0xdd,0x80,0x65,0x59,0xf2,0xa6,0x45,0x07
}, },
{ {
0x6f,0xa3,0xb5,0x8a,0xa9,0x9d,0x2f,0x1a,0x4f,0xe3,0x9d,0x46,0x0f,0x70,0xb5,0xd7, 0x1a2f9da98ab5a36f, 0xd7b5700f469de34f, 0x982b230a72eafef3, 0x3101b5160f5ed561,
0xf3,0xfe,0xea,0x72,0x0a,0x23,0x2b,0x98,0x61,0xd5,0x5e,0x0f,0x16,0xb5,0x01,0x31, 0x5899d6126b17b59a, 0xcaa70adbc261b55c, 0x56cdcbd71ba2dd55, 0xb79bb121700479e6
0x9a,0xb5,0x17,0x6b,0x12,0xd6,0x99,0x58,0x5c,0xb5,0x61,0xc2,0xdb,0x0a,0xa7,0xca,
0x55,0xdd,0xa2,0x1b,0xd7,0xcb,0xcd,0x56,0xe6,0x79,0x04,0x70,0x21,0xb1,0x9b,0xb7
}, },
{ {
0xf5,0x74,0xdc,0xac,0x2b,0xce,0x2f,0xc7,0x0a,0x39,0xfc,0x28,0x6a,0x3d,0x84,0x35, 0xc72fce2bacdc74f5, 0x35843d6a28fc390a, 0x8b1f9c525f5ef106, 0x7b7b29b11475eaf2,
0x06,0xf1,0x5e,0x5f,0x52,0x9c,0x1f,0x8b,0xf2,0xea,0x75,0x14,0xb1,0x29,0x7b,0x7b, 0xb19e3590e40fe2d3, 0x09db6260373ac9c1, 0x31db7a8643f4b6c2, 0xb20aba0af5961e99
0xd3,0xe2,0x0f,0xe4,0x90,0x35,0x9e,0xb1,0xc1,0xc9,0x3a,0x37,0x60,0x62,0xdb,0x09,
0xc2,0xb6,0xf4,0x43,0x86,0x7a,0xdb,0x31,0x99,0x1e,0x96,0xf5,0x0a,0xba,0x0a,0xb2
}, },
{ {
0xef,0x1f,0xdf,0xb3,0xe8,0x15,0x66,0xd2,0xf9,0x48,0xe1,0xa0,0x5d,0x71,0xe4,0xdd, 0xd26615e8b3df1fef, 0xdde4715da0e148f9, 0x7d3c5c337e858e48, 0x3f355e68ad1c729d,
0x48,0x8e,0x85,0x7e,0x33,0x5c,0x3c,0x7d,0x9d,0x72,0x1c,0xad,0x68,0x5e,0x35,0x3f, 0x75d603ed822cd7a9, 0xbe0352933313b7d8, 0xf137e893a1ea5334, 0x2ed1e384bcbe0c22
0xa9,0xd7,0x2c,0x82,0xed,0x03,0xd6,0x75,0xd8,0xb7,0x13,0x33,0x93,0x52,0x03,0xbe,
0x34,0x53,0xea,0xa1,0x93,0xe8,0x37,0xf1,0x22,0x0c,0xbe,0xbc,0x84,0xe3,0xd1,0x2e
}, },
{ {
0x4b,0xea,0x6b,0xac,0xad,0x47,0x47,0x99,0x9a,0x3f,0x41,0x0c,0x6c,0xa9,0x23,0x63, 0x994747adac6bea4b, 0x6323a96c0c413f9a, 0x4a1086161f1c157f, 0xbdff0f80d7359e35,
0x7f,0x15,0x1c,0x1f,0x16,0x86,0x10,0x4a,0x35,0x9e,0x35,0xd7,0x80,0x0f,0xff,0xbd, 0xa3f53a254717cdbf, 0x161a2723b700ffdf, 0xf563eaa97ea2567a, 0x57fe6c7cfd581760
0xbf,0xcd,0x17,0x47,0x25,0x3a,0xf5,0xa3,0xdf,0xff,0x00,0xb7,0x23,0x27,0x1a,0x16,
0x7a,0x56,0xa2,0x7e,0xa9,0xea,0x63,0xf5,0x60,0x17,0x58,0xfd,0x7c,0x6c,0xfe,0x57
}, },
{ {
0xae,0x4f,0xae,0xae,0x1d,0x3a,0xd3,0xd9,0x6f,0xa4,0xc3,0x3b,0x7a,0x30,0x39,0xc0, 0xd9d33a1daeae4fae, 0xc039307a3bc3a46f, 0x6ca44251f9c4662d, 0xc68ef09ab49a7f18,
0x2d,0x66,0xc4,0xf9,0x51,0x42,0xa4,0x6c,0x18,0x7f,0x9a,0xb4,0x9a,0xf0,0x8e,0xc6, 0xb4b79a1cb7a6facf, 0xb6c6bec2661ff20a, 0x354f903672c571bf, 0x6e7d64467a4068fa
0xcf,0xfa,0xa6,0xb7,0x1c,0x9a,0xb7,0xb4,0x0a,0xf2,0x1f,0x66,0xc2,0xbe,0xc6,0xb6,
0xbf,0x71,0xc5,0x72,0x36,0x90,0x4f,0x35,0xfa,0x68,0x40,0x7a,0x46,0x64,0x7d,0x6e
}, },
{ {
0xf4,0xc7,0x0e,0x16,0xee,0xaa,0xc5,0xec,0x51,0xac,0x86,0xfe,0xbf,0x24,0x09,0x54, 0xecc5aaee160ec7f4, 0x540924bffe86ac51, 0xc987bfe6c7c69e39, 0xc9937a19333e47d3,
0x39,0x9e,0xc6,0xc7,0xe6,0xbf,0x87,0xc9,0xd3,0x47,0x3e,0x33,0x19,0x7a,0x93,0xc9, 0x372c822dc5ab9209, 0x04054a2883694706, 0xf34a3ca24c451735, 0x93d4143a4d568688
0x09,0x92,0xab,0xc5,0x2d,0x82,0x2c,0x37,0x06,0x47,0x69,0x83,0x28,0x4a,0x05,0x04,
0x35,0x17,0x45,0x4c,0xa2,0x3c,0x4a,0xf3,0x88,0x86,0x56,0x4d,0x3a,0x14,0xd4,0x93
}, },
{ {
0x9b,0x1f,0x5b,0x42,0x4d,0x93,0xc9,0xa7,0x03,0xe7,0xaa,0x02,0x0c,0x6e,0x41,0x41, 0xa7c9934d425b1f9b, 0x41416e0c02aae703, 0x1ede369c71f8b74e, 0x9ac4db4d3b44b489,
0x4e,0xb7,0xf8,0x71,0x9c,0x36,0xde,0x1e,0x89,0xb4,0x44,0x3b,0x4d,0xdb,0xc4,0x9a, 0x90069b92cb2b89f4, 0x2fc4a5d12b8dd169, 0xd9a8515935c2ac36, 0x1ee702bfd40d7fa4
0xf4,0x89,0x2b,0xcb,0x92,0x9b,0x06,0x90,0x69,0xd1,0x8d,0x2b,0xd1,0xa5,0xc4,0x2f,
0x36,0xac,0xc2,0x35,0x59,0x51,0xa8,0xd9,0xa4,0x7f,0x0d,0xd4,0xbf,0x02,0xe7,0x1e
}, },
{ {
0x37,0x8f,0x5a,0x54,0x16,0x31,0x22,0x9b,0x94,0x4c,0x9a,0xd8,0xec,0x16,0x5f,0xde, 0x9b223116545a8f37, 0xde5f16ecd89a4c94, 0x244289251b3a7d3a, 0x84090de0b755d93c,
0x3a,0x7d,0x3a,0x1b,0x25,0x89,0x42,0x24,0x3c,0xd9,0x55,0xb7,0xe0,0x0d,0x09,0x84, 0xb1ceb2db0b440a80, 0x549c07a69a8a2b7b, 0x602a1fcb92dc380e, 0xdb5a238351446172
0x80,0x0a,0x44,0x0b,0xdb,0xb2,0xce,0xb1,0x7b,0x2b,0x8a,0x9a,0xa6,0x07,0x9c,0x54,
0x0e,0x38,0xdc,0x92,0xcb,0x1f,0x2a,0x60,0x72,0x61,0x44,0x51,0x83,0x23,0x5a,0xdb
}, },
{ {
0xab,0xbe,0xde,0xa6,0x80,0x05,0x6f,0x52,0x38,0x2a,0xe5,0x48,0xb2,0xe4,0xf3,0xf3, 0x526f0580a6debeab, 0xf3f3e4b248e52a38, 0xdb788aff1ce74189, 0x0361331b8ae1ff1f,
0x89,0x41,0xe7,0x1c,0xff,0x8a,0x78,0xdb,0x1f,0xff,0xe1,0x8a,0x1b,0x33,0x61,0x03, 0x4b3369af0267e79f, 0xf452763b306c1e7a, 0xc3b63b15d1fa9836, 0xed9c4598fbc7b474
0x9f,0xe7,0x67,0x02,0xaf,0x69,0x33,0x4b,0x7a,0x1e,0x6c,0x30,0x3b,0x76,0x52,0xf4,
0x36,0x98,0xfa,0xd1,0x15,0x3b,0xb6,0xc3,0x74,0xb4,0xc7,0xfb,0x98,0x45,0x9c,0xed
}, },
{ {
0x7b,0xcd,0x9e,0xd0,0xef,0xc8,0x89,0xfb,0x30,0x02,0xc6,0xcd,0x63,0x5a,0xfe,0x94, 0xfb89c8efd09ecd7b, 0x94fe5a63cdc60230, 0x6107abebbb6bfad8, 0x7966841421800120,
0xd8,0xfa,0x6b,0xbb,0xeb,0xab,0x07,0x61,0x20,0x01,0x80,0x21,0x14,0x84,0x66,0x79, 0xcab948eaef711d8a, 0x986e477d1dcdbaef, 0x5dd86fc04a59a2de, 0x1b2df381cda4ca6b
0x8a,0x1d,0x71,0xef,0xea,0x48,0xb9,0xca,0xef,0xba,0xcd,0x1d,0x7d,0x47,0x6e,0x98,
0xde,0xa2,0x59,0x4a,0xc0,0x6f,0xd8,0x5d,0x6b,0xca,0xa4,0xcd,0x81,0xf3,0x2d,0x1b
}, },
{ {
0x37,0x8e,0xe7,0x67,0xf1,0x16,0x31,0xba,0xd2,0x13,0x80,0xb0,0x04,0x49,0xb1,0x7a, 0xba3116f167e78e37, 0x7ab14904b08013d2, 0x771ddfbc323ca4cd, 0x9b9f2130d41220f8,
0xcd,0xa4,0x3c,0x32,0xbc,0xdf,0x1d,0x77,0xf8,0x20,0x12,0xd4,0x30,0x21,0x9f,0x9b, 0x86cc91189def805d, 0x5228e188aaa41de7, 0x991bb2d9d517f4fa, 0x20d71bf14a92bc48
0x5d,0x80,0xef,0x9d,0x18,0x91,0xcc,0x86,0xe7,0x1d,0xa4,0xaa,0x88,0xe1,0x28,0x52,
0xfa,0xf4,0x17,0xd5,0xd9,0xb2,0x1b,0x99,0x48,0xbc,0x92,0x4a,0xf1,0x1b,0xd7,0x20
} }
}; };
union GOST3411Block // 8 bytes aligned union GOST3411Block // 8 bytes aligned
{ {
uint8_t buf[64]; uint8_t buf[64];
@ -308,11 +782,11 @@ namespace crypto
return ret; return ret;
} }
GOST3411Block operator^(const uint8_t * other) const GOST3411Block operator^(const uint64_t * other) const
{ {
GOST3411Block ret; GOST3411Block ret;
for (int i = 0; i < 64; i++) for (int i = 0; i < 8; i++)
ret.buf[i] = buf[i]^other[i]; ret.ll[i] = ll[i]^other[i];
return ret; return ret;
} }
@ -340,25 +814,23 @@ namespace crypto
} }
} }
void SPL () void F ()
{ {
uint8_t p[64]; uint64_t res[8];
memcpy (p, buf, 64); // we need to copy it for P's transposition for (int b=0; b<8; b++)
for (int i = 0; i < 8; i++)
{ {
uint64_t c = 0; uint64_t r;
for (int j = 0; j < 8; j++) r = T0[buf[b+56]];
{ r ^= T1[buf[b+48]];
uint8_t bit = 0x80; r ^= T2[buf[b+40]];
uint8_t byte = sbox_[p[j*8+i]]; // S - sbox_, P - transpose (i,j) r ^= T3[buf[b+32]];
for (int k = 0; k < 8; k++) r ^= T4[buf[b+24]];
{ r ^= T5[buf[b+16]];
if (byte & bit) c ^= A_[j*8+k]; r ^= T6[buf[b+8]];
bit >>= 1; r ^= T7[buf[b]];
} res[b] = r;
}
ll[i] = htobe64 (c);
} }
memcpy (buf, res, 64);
} }
GOST3411Block E (const GOST3411Block& m) GOST3411Block E (const GOST3411Block& m)
@ -367,9 +839,9 @@ namespace crypto
GOST3411Block res = k^m; GOST3411Block res = k^m;
for (int i = 0; i < 12; i++) for (int i = 0; i < 12; i++)
{ {
res.SPL (); res.F ();
k = k^C_[i]; k = k^C_[i];
k.SPL (); k.F ();
res = k^res; res = k^res;
} }
return res; return res;
@ -379,7 +851,7 @@ namespace crypto
static GOST3411Block gN (const GOST3411Block& N, const GOST3411Block& h, const GOST3411Block& m) static GOST3411Block gN (const GOST3411Block& N, const GOST3411Block& h, const GOST3411Block& m)
{ {
GOST3411Block res = N ^ h; GOST3411Block res = N ^ h;
res.SPL (); res.F ();
res = res.E (m); res = res.E (m);
res = res^h; res = res^h;
res = res^m; res = res^m;

View file

@ -195,6 +195,11 @@ namespace http {
return out; return out;
} }
bool URL::is_i2p() const
{
return host.rfind(".i2p") == ( host.size() - 4 );
}
void HTTPMsg::add_header(const char *name, std::string & value, bool replace) { void HTTPMsg::add_header(const char *name, std::string & value, bool replace) {
add_header(name, value.c_str(), replace); add_header(name, value.c_str(), replace);
} }

View file

@ -56,6 +56,11 @@ namespace http
* @note Returns relative url if schema if empty, absolute url otherwise * @note Returns relative url if schema if empty, absolute url otherwise
*/ */
std::string to_string (); std::string to_string ();
/**
* @brief return true if the host is inside i2p
*/
bool is_i2p() const;
}; };
struct HTTPMsg struct HTTPMsg
@ -89,7 +94,7 @@ namespace http
/** @brief Serialize HTTP request to string */ /** @brief Serialize HTTP request to string */
std::string to_string(); std::string to_string();
void write(std::ostream & o); void write(std::ostream & o);
void AddHeader (const std::string& name, const std::string& value); void AddHeader (const std::string& name, const std::string& value);
void UpdateHeader (const std::string& name, const std::string& value); void UpdateHeader (const std::string& name, const std::string& value);

View file

@ -58,7 +58,7 @@ namespace log {
Log::Log(): Log::Log():
m_Destination(eLogStdout), m_MinLevel(eLogInfo), m_Destination(eLogStdout), m_MinLevel(eLogInfo),
m_LogStream (nullptr), m_Logfile(""), m_HasColors(true), m_LogStream (nullptr), m_Logfile(""), m_HasColors(true), m_TimeFormat("%H:%M:%S"),
m_IsRunning (false), m_Thread (nullptr) m_IsRunning (false), m_Thread (nullptr)
{ {
} }
@ -118,7 +118,7 @@ namespace log {
const char * Log::TimeAsString(std::time_t t) { const char * Log::TimeAsString(std::time_t t) {
if (t != m_LastTimestamp) { if (t != m_LastTimestamp) {
strftime(m_LastDateTime, sizeof(m_LastDateTime), "%H:%M:%S", localtime(&t)); strftime(m_LastDateTime, sizeof(m_LastDateTime), m_TimeFormat.c_str(), localtime(&t));
m_LastTimestamp = t; m_LastTimestamp = t;
} }
return m_LastDateTime; return m_LastDateTime;

View file

@ -58,6 +58,7 @@ namespace log {
char m_LastDateTime[64]; char m_LastDateTime[64];
i2p::util::Queue<std::shared_ptr<LogMsg> > m_Queue; i2p::util::Queue<std::shared_ptr<LogMsg> > m_Queue;
bool m_HasColors; bool m_HasColors;
std::string m_TimeFormat;
volatile bool m_IsRunning; volatile bool m_IsRunning;
std::thread * m_Thread; std::thread * m_Thread;
@ -107,6 +108,12 @@ namespace log {
*/ */
void SendTo (std::shared_ptr<std::ostream> os); void SendTo (std::shared_ptr<std::ostream> os);
/**
* @brief Sets format for timestamps in log
* @param format String with timestamp format
*/
void SetTimeFormat (std::string format) { m_TimeFormat = format; };
#ifndef _WIN32 #ifndef _WIN32
/** /**
* @brief Sets log destination to syslog * @brief Sets log destination to syslog

View file

@ -791,7 +791,8 @@ namespace transport
NTCPServer::NTCPServer (): NTCPServer::NTCPServer ():
m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service), m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service),
m_TerminationTimer (m_Service), m_NTCPAcceptor (nullptr), m_NTCPV6Acceptor (nullptr), m_TerminationTimer (m_Service), m_NTCPAcceptor (nullptr), m_NTCPV6Acceptor (nullptr),
m_ProxyType(eNoProxy), m_Resolver(m_Service), m_ProxyEndpoint(nullptr) m_ProxyType(eNoProxy), m_Resolver(m_Service), m_ProxyEndpoint(nullptr),
m_SoftLimit(0), m_HardLimit(0)
{ {
} }
@ -965,6 +966,13 @@ namespace transport
auto ep = conn->GetSocket ().remote_endpoint(ec); auto ep = conn->GetSocket ().remote_endpoint(ec);
if (!ec) if (!ec)
{ {
if(ShouldLimit())
{
// hit limit, close premature
LogPrint(eLogWarning, "NTCP: limiting with backoff session from ", ep);
conn->Terminate();
return;
}
LogPrint (eLogDebug, "NTCP: Connected from ", ep); LogPrint (eLogDebug, "NTCP: Connected from ", ep);
if (conn) if (conn)
{ {
@ -993,6 +1001,14 @@ namespace transport
auto ep = conn->GetSocket ().remote_endpoint(ec); auto ep = conn->GetSocket ().remote_endpoint(ec);
if (!ec) if (!ec)
{ {
if(ShouldLimit())
{
// hit limit, close premature
LogPrint(eLogWarning, "NTCP: limiting with backoff on session from ", ep);
conn->Terminate();
return;
}
LogPrint (eLogDebug, "NTCP: Connected from ", ep); LogPrint (eLogDebug, "NTCP: Connected from ", ep);
if (conn) if (conn)
{ {

View file

@ -167,8 +167,19 @@ namespace transport
boost::asio::io_service& GetService () { return m_Service; }; boost::asio::io_service& GetService () { return m_Service; };
void SetSessionLimits(uint16_t softLimit, uint16_t hardLimit) { m_SoftLimit = softLimit; m_HardLimit = hardLimit; }
bool ShouldLimit() const { return ShouldHardLimit() || ShouldSoftLimit(); }
private: private:
/** @brief return true for hard limit */
bool ShouldHardLimit() const { return m_HardLimit && m_NTCPSessions.size() >= m_HardLimit; }
/** @brief return true for probabalistic soft backoff */
bool ShouldSoftLimit() const
{
auto sessions = m_NTCPSessions.size();
return sessions && m_SoftLimit && m_SoftLimit < sessions && ( rand() % sessions ) <= m_SoftLimit;
}
void Run (); void Run ();
void HandleAccept (std::shared_ptr<NTCPSession> conn, const boost::system::error_code& error); void HandleAccept (std::shared_ptr<NTCPSession> conn, const boost::system::error_code& error);
void HandleAcceptV6 (std::shared_ptr<NTCPSession> conn, const boost::system::error_code& error); void HandleAcceptV6 (std::shared_ptr<NTCPSession> conn, const boost::system::error_code& error);
@ -198,6 +209,8 @@ namespace transport
uint16_t m_ProxyPort; uint16_t m_ProxyPort;
boost::asio::ip::tcp::resolver m_Resolver; boost::asio::ip::tcp::resolver m_Resolver;
boost::asio::ip::tcp::endpoint * m_ProxyEndpoint; boost::asio::ip::tcp::endpoint * m_ProxyEndpoint;
uint16_t m_SoftLimit, m_HardLimit;
public: public:
// for HTTP/I2PControl // for HTTP/I2PControl

View file

@ -87,7 +87,7 @@ namespace i2p
routerInfo.SetCaps (i2p::data::RouterInfo::eReachable | routerInfo.SetCaps (i2p::data::RouterInfo::eReachable |
i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC
routerInfo.SetProperty ("netId", std::to_string (m_NetID)); routerInfo.SetProperty ("netId", std::to_string (m_NetID));
routerInfo.SetProperty ("router.version", I2P_VERSION); routerInfo.SetProperty ("router.version", I2P_VERSION);
routerInfo.CreateBuffer (m_Keys); routerInfo.CreateBuffer (m_Keys);
m_RouterInfo.SetRouterIdentity (GetIdentity ()); m_RouterInfo.SetRouterIdentity (GetIdentity ());
@ -203,8 +203,9 @@ namespace i2p
} }
} }
void RouterContext::SetBandwidth (char L) { void RouterContext::SetBandwidth (char L)
uint16_t limit = 0; {
uint32_t limit = 0;
enum { low, high, extra, unlim } type = high; enum { low, high, extra, unlim } type = high;
/* detect parameters */ /* detect parameters */
switch (L) switch (L)
@ -215,7 +216,7 @@ namespace i2p
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break; case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break;
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = 256; type = high; break; case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = 256; type = high; break;
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = 2048; type = extra; break; case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = 2048; type = extra; break;
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 9999; type = unlim; break; case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 1000000; type = unlim; break; // 1Gbyte/s
default: default:
limit = 48; type = low; limit = 48; type = low;
} }

View file

@ -166,7 +166,6 @@ namespace data
for (int i = 0; i < numAddresses; i++) for (int i = 0; i < numAddresses; i++)
{ {
uint8_t supportedTransports = 0; uint8_t supportedTransports = 0;
bool isValidAddress = true;
auto address = std::make_shared<Address>(); auto address = std::make_shared<Address>();
s.read ((char *)&address->cost, sizeof (address->cost)); s.read ((char *)&address->cost, sizeof (address->cost));
s.read ((char *)&address->date, sizeof (address->date)); s.read ((char *)&address->date, sizeof (address->date));
@ -269,7 +268,8 @@ namespace data
} }
if (!s) return; if (!s) return;
} }
if (isValidAddress) if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented
if (supportedTransports)
{ {
addresses->push_back(address); addresses->push_back(address);
m_SupportedTransports |= supportedTransports; m_SupportedTransports |= supportedTransports;

View file

@ -353,6 +353,7 @@ namespace crypto
BN_mod_mul (x, x, I, q, ctx); BN_mod_mul (x, x, I, q, ctx);
if (BN_is_odd (x)) if (BN_is_odd (x))
BN_sub (x, q, x); BN_sub (x, q, x);
BN_CTX_end (ctx);
return x; return x;
} }
@ -370,7 +371,7 @@ namespace crypto
buf1[0] &= 0x7f; // clear highest bit buf1[0] &= 0x7f; // clear highest bit
BIGNUM * y = BN_new (); BIGNUM * y = BN_new ();
BN_bin2bn (buf1, EDDSA25519_PUBLIC_KEY_LENGTH, y); BN_bin2bn (buf1, EDDSA25519_PUBLIC_KEY_LENGTH, y);
auto x = RecoverX (y, ctx); BIGNUM * x = RecoverX (y, ctx);
if (BN_is_bit_set (x, 0) != isHighestBitSet) if (BN_is_bit_set (x, 0) != isHighestBitSet)
BN_sub (x, q, x); // x = q - x BN_sub (x, q, x); // x = q - x
BIGNUM * z = BN_new (), * t = BN_new (); BIGNUM * z = BN_new (), * t = BN_new ();

View file

@ -363,31 +363,43 @@ namespace crypto
// EdDSA // EdDSA
struct EDDSAPoint struct EDDSAPoint
{ {
BIGNUM * x, * y; BIGNUM * x {nullptr};
BIGNUM * z, * t; // projective coordinates BIGNUM * y {nullptr};
EDDSAPoint (): x(nullptr), y(nullptr), z(nullptr), t(nullptr) {}; BIGNUM * z {nullptr};
EDDSAPoint (const EDDSAPoint& other): x(nullptr), y(nullptr), z(nullptr), t(nullptr) BIGNUM * t {nullptr}; // projective coordinates
{ *this = other; };
EDDSAPoint (EDDSAPoint&& other): x(nullptr), y(nullptr), z(nullptr), t(nullptr) EDDSAPoint () {}
{ *this = std::move (other); }; EDDSAPoint (const EDDSAPoint& other) { *this = other; }
EDDSAPoint (BIGNUM * x1, BIGNUM * y1, BIGNUM * z1 = nullptr, BIGNUM * t1 = nullptr): x(x1), y(y1), z(z1), t(t1) {}; EDDSAPoint (EDDSAPoint&& other) { *this = std::move (other); }
~EDDSAPoint () { BN_free (x); BN_free (y); BN_free(z); BN_free(t); }; EDDSAPoint (BIGNUM * x1, BIGNUM * y1, BIGNUM * z1 = nullptr, BIGNUM * t1 = nullptr)
: x(x1)
, y(y1)
, z(z1)
, t(t1)
{}
~EDDSAPoint () { BN_free (x); BN_free (y); BN_free(z); BN_free(t); }
EDDSAPoint& operator=(EDDSAPoint&& other) EDDSAPoint& operator=(EDDSAPoint&& other)
{ {
if (x) BN_free (x); x = other.x; other.x = nullptr; if (this != &other)
if (y) BN_free (y); y = other.y; other.y = nullptr; {
if (z) BN_free (z); z = other.z; other.z = nullptr; BN_free (x); x = other.x; other.x = nullptr;
if (t) BN_free (t); t = other.t; other.t = nullptr; BN_free (y); y = other.y; other.y = nullptr;
BN_free (z); z = other.z; other.z = nullptr;
BN_free (t); t = other.t; other.t = nullptr;
}
return *this; return *this;
} }
EDDSAPoint& operator=(const EDDSAPoint& other) EDDSAPoint& operator=(const EDDSAPoint& other)
{ {
if (x) BN_free (x); x = other.x ? BN_dup (other.x) : nullptr; if (this != &other)
if (y) BN_free (y); y = other.y ? BN_dup (other.y) : nullptr; {
if (z) BN_free (z); z = other.z ? BN_dup (other.z) : nullptr; BN_free (x); x = other.x ? BN_dup (other.x) : nullptr;
if (t) BN_free (t); t = other.t ? BN_dup (other.t) : nullptr; BN_free (y); y = other.y ? BN_dup (other.y) : nullptr;
BN_free (z); z = other.z ? BN_dup (other.z) : nullptr;
BN_free (t); t = other.t ? BN_dup (other.t) : nullptr;
}
return *this; return *this;
} }

View file

@ -276,8 +276,8 @@ namespace stream
/** set max connections per minute per destination */ /** set max connections per minute per destination */
void SetMaxConnsPerMinute(const uint32_t conns); void SetMaxConnsPerMinute(const uint32_t conns);
Packet * NewPacket () { return m_PacketsPool.Acquire (); }; Packet * NewPacket () { return m_PacketsPool.Acquire (); }
void DeletePacket (Packet * p) { if (p) m_PacketsPool.Release (p); }; void DeletePacket (Packet * p) { m_PacketsPool.Release (p); }
private: private:

View file

@ -102,9 +102,14 @@ namespace transport
void DHKeysPairSupplier::Return (std::shared_ptr<i2p::crypto::DHKeys> pair) void DHKeysPairSupplier::Return (std::shared_ptr<i2p::crypto::DHKeys> pair)
{ {
std::unique_lock<std::mutex>l(m_AcquiredMutex); if (pair)
if ((int)m_Queue.size () < 2*m_QueueSize) {
m_Queue.push (pair); std::unique_lock<std::mutex>l(m_AcquiredMutex);
if ((int)m_Queue.size () < 2*m_QueueSize)
m_Queue.push (pair);
}
else
LogPrint(eLogError, "Transports: return null DHKeys");
} }
Transports transports; Transports transports;
@ -142,13 +147,20 @@ namespace transport
m_PeerTestTimer = new boost::asio::deadline_timer (*m_Service); m_PeerTestTimer = new boost::asio::deadline_timer (*m_Service);
} }
i2p::config::GetOption("nat", m_IsNAT); i2p::config::GetOption("nat", m_IsNAT);
m_DHKeysPairSupplier.Start (); m_DHKeysPairSupplier.Start ();
m_IsRunning = true; m_IsRunning = true;
m_Thread = new std::thread (std::bind (&Transports::Run, this)); m_Thread = new std::thread (std::bind (&Transports::Run, this));
std::string ntcpproxy; i2p::config::GetOption("ntcpproxy", ntcpproxy); std::string ntcpproxy; i2p::config::GetOption("ntcpproxy", ntcpproxy);
i2p::http::URL proxyurl; i2p::http::URL proxyurl;
uint16_t softLimit, hardLimit;
i2p::config::GetOption("limits.ntcpsoft", softLimit);
i2p::config::GetOption("limits.ntcphard", hardLimit);
if(softLimit > 0 && hardLimit > 0 && softLimit >= hardLimit)
{
LogPrint(eLogError, "ntcp soft limit must be less than ntcp hard limit");
return;
}
if(ntcpproxy.size() && enableNTCP) if(ntcpproxy.size() && enableNTCP)
{ {
if(proxyurl.parse(ntcpproxy)) if(proxyurl.parse(ntcpproxy))
@ -156,12 +168,11 @@ namespace transport
if(proxyurl.schema == "socks" || proxyurl.schema == "http") if(proxyurl.schema == "socks" || proxyurl.schema == "http")
{ {
m_NTCPServer = new NTCPServer(); m_NTCPServer = new NTCPServer();
m_NTCPServer->SetSessionLimits(softLimit, hardLimit);
NTCPServer::ProxyType proxytype = NTCPServer::eSocksProxy; NTCPServer::ProxyType proxytype = NTCPServer::eSocksProxy;
if (proxyurl.schema == "http") if (proxyurl.schema == "http")
proxytype = NTCPServer::eHTTPProxy; proxytype = NTCPServer::eHTTPProxy;
m_NTCPServer->UseProxy(proxytype, proxyurl.host, proxyurl.port) ; m_NTCPServer->UseProxy(proxytype, proxyurl.host, proxyurl.port) ;
m_NTCPServer->Start(); m_NTCPServer->Start();
if(!m_NTCPServer->NetworkIsReady()) if(!m_NTCPServer->NetworkIsReady())
@ -188,6 +199,7 @@ namespace transport
if (m_NTCPServer == nullptr && enableNTCP) if (m_NTCPServer == nullptr && enableNTCP)
{ {
m_NTCPServer = new NTCPServer (); m_NTCPServer = new NTCPServer ();
m_NTCPServer->SetSessionLimits(softLimit, hardLimit);
m_NTCPServer->Start (); m_NTCPServer->Start ();
if (!(m_NTCPServer->IsBoundV6() || m_NTCPServer->IsBoundV4())) { if (!(m_NTCPServer->IsBoundV6() || m_NTCPServer->IsBoundV4())) {
/** failed to bind to NTCP */ /** failed to bind to NTCP */
@ -389,20 +401,27 @@ namespace transport
{ {
if (!peer.router->UsesIntroducer () && !peer.router->IsUnreachable ()) if (!peer.router->UsesIntroducer () && !peer.router->IsUnreachable ())
{ {
auto s = std::make_shared<NTCPSession> (*m_NTCPServer, peer.router); if(!m_NTCPServer->ShouldLimit())
if(m_NTCPServer->UsingProxy())
{ {
NTCPServer::RemoteAddressType remote = NTCPServer::eIP4Address; auto s = std::make_shared<NTCPSession> (*m_NTCPServer, peer.router);
std::string addr = address->host.to_string(); if(m_NTCPServer->UsingProxy())
{
NTCPServer::RemoteAddressType remote = NTCPServer::eIP4Address;
std::string addr = address->host.to_string();
if(address->host.is_v6()) if(address->host.is_v6())
remote = NTCPServer::eIP6Address; remote = NTCPServer::eIP6Address;
m_NTCPServer->ConnectWithProxy(addr, address->port, remote, s); m_NTCPServer->ConnectWithProxy(addr, address->port, remote, s);
}
else
m_NTCPServer->Connect (address->host, address->port, s);
return true;
} }
else else
m_NTCPServer->Connect (address->host, address->port, s); {
return true; LogPrint(eLogWarning, "Transports: NTCP Limit hit falling back to SSU");
}
} }
} }
else // we don't have address else // we don't have address

View file

@ -5,6 +5,7 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <utility>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#ifdef ANDROID #ifdef ANDROID
@ -14,7 +15,7 @@ namespace std
template <typename T> template <typename T>
std::string to_string(T value) std::string to_string(T value)
{ {
return boost::lexical_cast<std::string>(value); return boost::lexical_cast<std::string>(value);
} }
inline int stoi(const std::string& str) inline int stoi(const std::string& str)
@ -32,9 +33,11 @@ namespace util
template<class T> template<class T>
class MemoryPool class MemoryPool
{ {
//BOOST_STATIC_ASSERT_MSG(sizeof(T) >= sizeof(void*), "size cannot be less that general pointer size");
public: public:
MemoryPool (): m_Head (nullptr) {}; MemoryPool (): m_Head (nullptr) {}
~MemoryPool () ~MemoryPool ()
{ {
while (m_Head) while (m_Head)
@ -48,12 +51,12 @@ namespace util
template<typename... TArgs> template<typename... TArgs>
T * Acquire (TArgs&&... args) T * Acquire (TArgs&&... args)
{ {
if (!m_Head) return new T(args...); if (!m_Head) return new T(std::forward<TArgs>(args)...);
else else
{ {
auto tmp = m_Head; auto tmp = m_Head;
m_Head = static_cast<T*>(*(void * *)m_Head); // next m_Head = static_cast<T*>(*(void * *)m_Head); // next
return new (tmp)T(args...); return new (tmp)T(std::forward<TArgs>(args)...);
} }
} }
@ -68,14 +71,15 @@ namespace util
template<typename... TArgs> template<typename... TArgs>
std::unique_ptr<T, std::function<void(T*)> > AcquireUnique (TArgs&&... args) std::unique_ptr<T, std::function<void(T*)> > AcquireUnique (TArgs&&... args)
{ {
return std::unique_ptr<T, std::function<void(T*)> >(Acquire (args...), return std::unique_ptr<T, std::function<void(T*)> >(Acquire (std::forward<TArgs>(args)...),
std::bind (&MemoryPool<T>::Release, this, std::placeholders::_1)); std::bind (&MemoryPool<T>::Release, this, std::placeholders::_1));
} }
template<typename... TArgs> template<typename... TArgs>
std::shared_ptr<T> AcquireShared (TArgs&&... args) std::shared_ptr<T> AcquireShared (TArgs&&... args)
{ {
return std::shared_ptr<T>(Acquire (args...), std::bind (&MemoryPool<T>::Release, this, std::placeholders::_1)); return std::shared_ptr<T>(Acquire (std::forward<TArgs>(args)...),
std::bind (&MemoryPool<T>::Release, this, std::placeholders::_1));
} }
protected: protected:
@ -88,13 +92,13 @@ namespace util
{ {
public: public:
MemoryPoolMt () {}; MemoryPoolMt () {}
template<typename... TArgs> template<typename... TArgs>
T * AcquireMt (TArgs&&... args) T * AcquireMt (TArgs&&... args)
{ {
if (!this->m_Head) return new T(args...); if (!this->m_Head) return new T(std::forward<TArgs>(args)...);
std::lock_guard<std::mutex> l(m_Mutex); std::lock_guard<std::mutex> l(m_Mutex);
return this->Acquire (args...); return this->Acquire (std::forward<TArgs>(args)...);
} }
void ReleaseMt (T * t) void ReleaseMt (T * t)

View file

@ -54,6 +54,7 @@ namespace client
std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr); std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr);
uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort); uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort);
i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType); i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType);
std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL);
LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort); LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort);
if (httpProxyKeys.length () > 0) if (httpProxyKeys.length () > 0)
{ {
@ -70,7 +71,7 @@ namespace client
} }
try try
{ {
m_HttpProxy = new i2p::proxy::HTTPProxy(httpProxyAddr, httpProxyPort, localDestination); m_HttpProxy = new i2p::proxy::HTTPProxy(httpProxyAddr, httpProxyPort, httpOutProxyURL, localDestination);
m_HttpProxy->Start(); m_HttpProxy->Start();
} }
catch (std::exception& e) catch (std::exception& e)
@ -536,7 +537,8 @@ namespace client
else if (type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY) else if (type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY)
{ {
// http proxy // http proxy
clientTunnel = new i2p::proxy::HTTPProxy(address, port, localDestination); std::string outproxy = section.second.get("outproxy", "");
clientTunnel = new i2p::proxy::HTTPProxy(address, port, outproxy, localDestination);
clientEndpoint = ((i2p::proxy::HTTPProxy*)clientTunnel)->GetLocalEndpoint (); clientEndpoint = ((i2p::proxy::HTTPProxy*)clientTunnel)->GetLocalEndpoint ();
} }
else if (type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS) else if (type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS)
@ -551,6 +553,13 @@ namespace client
clientTunnel = new I2PClientTunnel (name, dest, address, port, localDestination, destinationPort); clientTunnel = new I2PClientTunnel (name, dest, address, port, localDestination, destinationPort);
clientEndpoint = ((I2PClientTunnel*)clientTunnel)->GetLocalEndpoint (); clientEndpoint = ((I2PClientTunnel*)clientTunnel)->GetLocalEndpoint ();
} }
uint32_t timeout = section.second.get<uint32_t>(I2P_CLIENT_TUNNEL_CONNECT_TIMEOUT, 0);
if(timeout)
{
clientTunnel->SetConnectTimeout(timeout);
LogPrint(eLogInfo, "Clients: I2P Client tunnel connect timeout set to ", timeout);
}
auto ins = m_ClientTunnels.insert (std::make_pair (clientEndpoint, std::unique_ptr<I2PService>(clientTunnel))); auto ins = m_ClientTunnels.insert (std::make_pair (clientEndpoint, std::unique_ptr<I2PService>(clientTunnel)));
if (ins.second) if (ins.second)
{ {
@ -560,8 +569,13 @@ namespace client
else else
{ {
// TODO: update // TODO: update
if (ins.first->second->GetLocalDestination () != clientTunnel->GetLocalDestination ())
{
LogPrint (eLogInfo, "Clients: I2P client tunnel destination updated");
ins.first->second->SetLocalDestination (clientTunnel->GetLocalDestination ());
}
ins.first->second->isUpdated = true; ins.first->second->isUpdated = true;
LogPrint (eLogInfo, "Clients: I2P client tunnel for endpoint ", clientEndpoint, "already exists"); LogPrint (eLogInfo, "Clients: I2P client tunnel for endpoint ", clientEndpoint, " already exists");
} }
} }
} }
@ -666,6 +680,11 @@ namespace client
else else
{ {
// TODO: update // TODO: update
if (ins.first->second->GetLocalDestination () != serverTunnel->GetLocalDestination ())
{
LogPrint (eLogInfo, "Clients: I2P server tunnel destination updated");
ins.first->second->SetLocalDestination (serverTunnel->GetLocalDestination ());
}
ins.first->second->isUpdated = true; ins.first->second->isUpdated = true;
LogPrint (eLogInfo, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists"); LogPrint (eLogInfo, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists");
} }

View file

@ -36,6 +36,7 @@ namespace client
const char I2P_CLIENT_TUNNEL_SIGNATURE_TYPE[] = "signaturetype"; const char I2P_CLIENT_TUNNEL_SIGNATURE_TYPE[] = "signaturetype";
const char I2P_CLIENT_TUNNEL_DESTINATION_PORT[] = "destinationport"; const char I2P_CLIENT_TUNNEL_DESTINATION_PORT[] = "destinationport";
const char I2P_CLIENT_TUNNEL_MATCH_TUNNELS[] = "matchtunnels"; const char I2P_CLIENT_TUNNEL_MATCH_TUNNELS[] = "matchtunnels";
const char I2P_CLIENT_TUNNEL_CONNECT_TIMEOUT[] = "connecttimeout";
const char I2P_SERVER_TUNNEL_HOST[] = "host"; const char I2P_SERVER_TUNNEL_HOST[] = "host";
const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride"; const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride";
const char I2P_SERVER_TUNNEL_PORT[] = "port"; const char I2P_SERVER_TUNNEL_PORT[] = "port";

View file

@ -67,6 +67,8 @@ namespace proxy {
void ForwardToUpstreamProxy(); void ForwardToUpstreamProxy();
void HandleUpstreamHTTPProxyConnect(const boost::system::error_code & ec); void HandleUpstreamHTTPProxyConnect(const boost::system::error_code & ec);
void HandleUpstreamSocksProxyConnect(const boost::system::error_code & ec); void HandleUpstreamSocksProxyConnect(const boost::system::error_code & ec);
void HTTPConnect(const std::string & host, uint16_t port);
void HandleHTTPConnectStreamRequestComplete(std::shared_ptr<i2p::stream::Stream> stream);
void HandleSocksProxySendHandshake(const boost::system::error_code & ec, std::size_t bytes_transfered); void HandleSocksProxySendHandshake(const boost::system::error_code & ec, std::size_t bytes_transfered);
void HandleSocksProxyReply(const boost::system::error_code & ec, std::size_t bytes_transfered); void HandleSocksProxyReply(const boost::system::error_code & ec, std::size_t bytes_transfered);
@ -84,6 +86,7 @@ namespace proxy {
std::shared_ptr<boost::asio::ip::tcp::socket> m_sock; std::shared_ptr<boost::asio::ip::tcp::socket> m_sock;
std::shared_ptr<boost::asio::ip::tcp::socket> m_proxysock; std::shared_ptr<boost::asio::ip::tcp::socket> m_proxysock;
boost::asio::ip::tcp::resolver m_proxy_resolver; boost::asio::ip::tcp::resolver m_proxy_resolver;
std::string m_OutproxyUrl;
i2p::http::URL m_ProxyURL; i2p::http::URL m_ProxyURL;
i2p::http::URL m_RequestURL; i2p::http::URL m_RequestURL;
uint8_t m_socks_buf[255+8]; // for socks request/response uint8_t m_socks_buf[255+8]; // for socks request/response
@ -97,7 +100,8 @@ namespace proxy {
HTTPReqHandler(HTTPProxy * parent, std::shared_ptr<boost::asio::ip::tcp::socket> sock) : HTTPReqHandler(HTTPProxy * parent, std::shared_ptr<boost::asio::ip::tcp::socket> sock) :
I2PServiceHandler(parent), m_sock(sock), I2PServiceHandler(parent), m_sock(sock),
m_proxysock(std::make_shared<boost::asio::ip::tcp::socket>(parent->GetService())), m_proxysock(std::make_shared<boost::asio::ip::tcp::socket>(parent->GetService())),
m_proxy_resolver(parent->GetService()) {} m_proxy_resolver(parent->GetService()),
m_OutproxyUrl(parent->GetOutproxyURL()) {}
~HTTPReqHandler() { Terminate(); } ~HTTPReqHandler() { Terminate(); }
void Handle () { AsyncSockRead(); } /* overload */ void Handle () { AsyncSockRead(); } /* overload */
}; };
@ -200,10 +204,11 @@ namespace proxy {
void HTTPReqHandler::SanitizeHTTPRequest(i2p::http::HTTPReq & req) void HTTPReqHandler::SanitizeHTTPRequest(i2p::http::HTTPReq & req)
{ {
/* drop common headers */ /* drop common headers */
req.RemoveHeader ("Referer"); req.RemoveHeader("Referer");
req.RemoveHeader("Via"); req.RemoveHeader("Via");
req.RemoveHeader("From");
req.RemoveHeader("Forwarded"); req.RemoveHeader("Forwarded");
req.RemoveHeader("Accept-", "Accept-Encoding"); // Accept-*, but Accept-Encoding req.RemoveHeader("Accept", "Accept-Encoding"); // Accept*, but Accept-Encoding
/* drop proxy-disclosing headers */ /* drop proxy-disclosing headers */
req.RemoveHeader("X-Forwarded"); req.RemoveHeader("X-Forwarded");
req.RemoveHeader("Proxy-"); // Proxy-* req.RemoveHeader("Proxy-"); // Proxy-*
@ -256,43 +261,63 @@ namespace proxy {
GenericProxyInfo("Addresshelper found", ss.str().c_str()); GenericProxyInfo("Addresshelper found", ss.str().c_str());
return true; /* request processed */ return true; /* request processed */
} }
std::string dest_host;
SanitizeHTTPRequest(m_ClientRequest); uint16_t dest_port;
bool useConnect = false;
std::string dest_host = m_RequestURL.host; if(m_ClientRequest.method == "CONNECT")
uint16_t dest_port = m_RequestURL.port;
/* always set port, even if missing in request */
if (!dest_port)
dest_port = (m_RequestURL.schema == "https") ? 443 : 80;
/* detect dest_host, set proper 'Host' header in upstream request */
if (dest_host != "")
{ {
/* absolute url, replace 'Host' header */ std::string uri(m_ClientRequest.uri);
std::string h = dest_host; auto pos = uri.find(":");
if (dest_port != 0 && dest_port != 80) if(pos == std::string::npos || pos == uri.size() - 1)
h += ":" + std::to_string(dest_port);
m_ClientRequest.UpdateHeader("Host", h);
}
else
{
auto h = m_ClientRequest.GetHeader ("Host");
if (h.length () > 0)
{ {
/* relative url and 'Host' header provided. transparent proxy mode? */ GenericProxyError("Invalid Request", "invalid request uri");
i2p::http::URL u; return true;
std::string t = "http://" + h;
u.parse(t);
dest_host = u.host;
dest_port = u.port;
} }
else else
{ {
/* relative url and missing 'Host' header */ useConnect = true;
GenericProxyError("Invalid request", "Can't detect destination host from request"); dest_port = std::stoi(uri.substr(pos+1));
return true; dest_host = uri.substr(0, pos);
} }
} }
else
{
SanitizeHTTPRequest(m_ClientRequest);
dest_host = m_RequestURL.host;
dest_port = m_RequestURL.port;
/* always set port, even if missing in request */
if (!dest_port)
dest_port = (m_RequestURL.schema == "https") ? 443 : 80;
/* detect dest_host, set proper 'Host' header in upstream request */
if (dest_host != "")
{
/* absolute url, replace 'Host' header */
std::string h = dest_host;
if (dest_port != 0 && dest_port != 80)
h += ":" + std::to_string(dest_port);
m_ClientRequest.UpdateHeader("Host", h);
}
else
{
auto h = m_ClientRequest.GetHeader ("Host");
if (h.length () > 0)
{
/* relative url and 'Host' header provided. transparent proxy mode? */
i2p::http::URL u;
std::string t = "http://" + h;
u.parse(t);
dest_host = u.host;
dest_port = u.port;
}
else
{
/* relative url and missing 'Host' header */
GenericProxyError("Invalid request", "Can't detect destination host from request");
return true;
}
}
}
/* check dest_host really exists and inside I2P network */ /* check dest_host really exists and inside I2P network */
i2p::data::IdentHash identHash; i2p::data::IdentHash identHash;
if (str_rmatch(dest_host, ".i2p")) { if (str_rmatch(dest_host, ".i2p")) {
@ -301,10 +326,9 @@ namespace proxy {
return true; /* request processed */ return true; /* request processed */
} }
} else { } else {
std::string outproxyUrl; i2p::config::GetOption("httpproxy.outproxy", outproxyUrl); if(m_OutproxyUrl.size()) {
if(outproxyUrl.size()) { LogPrint (eLogDebug, "HTTPProxy: use outproxy ", m_OutproxyUrl);
LogPrint (eLogDebug, "HTTPProxy: use outproxy ", outproxyUrl); if(m_ProxyURL.parse(m_OutproxyUrl))
if(m_ProxyURL.parse(outproxyUrl))
ForwardToUpstreamProxy(); ForwardToUpstreamProxy();
else else
GenericProxyError("Outproxy failure", "bad outproxy settings"); GenericProxyError("Outproxy failure", "bad outproxy settings");
@ -315,6 +339,11 @@ namespace proxy {
} }
return true; return true;
} }
if(useConnect)
{
HTTPConnect(dest_host, dest_port);
return true;
}
/* make relative url */ /* make relative url */
m_RequestURL.schema = ""; m_RequestURL.schema = "";
@ -351,10 +380,19 @@ namespace proxy {
if (m_ProxyURL.schema == "" || m_ProxyURL.schema == "http") { if (m_ProxyURL.schema == "" || m_ProxyURL.schema == "http") {
// handle upstream http proxy // handle upstream http proxy
if (!m_ProxyURL.port) m_ProxyURL.port = 80; if (!m_ProxyURL.port) m_ProxyURL.port = 80;
boost::asio::ip::tcp::resolver::query q(m_ProxyURL.host, std::to_string(m_ProxyURL.port)); if (m_ProxyURL.is_i2p())
m_proxy_resolver.async_resolve(q, std::bind(&HTTPReqHandler::HandleUpstreamProxyResolved, this, std::placeholders::_1, std::placeholders::_2, [&](boost::asio::ip::tcp::endpoint ep) { {
m_proxysock->async_connect(ep, std::bind(&HTTPReqHandler::HandleUpstreamHTTPProxyConnect, this, std::placeholders::_1)); m_send_buf = m_recv_buf;
})); GetOwner()->CreateStream (std::bind (&HTTPReqHandler::HandleStreamRequestComplete,
shared_from_this(), std::placeholders::_1), m_ProxyURL.host, m_ProxyURL.port);
}
else
{
boost::asio::ip::tcp::resolver::query q(m_ProxyURL.host, std::to_string(m_ProxyURL.port));
m_proxy_resolver.async_resolve(q, std::bind(&HTTPReqHandler::HandleUpstreamProxyResolved, this, std::placeholders::_1, std::placeholders::_2, [&](boost::asio::ip::tcp::endpoint ep) {
m_proxysock->async_connect(ep, std::bind(&HTTPReqHandler::HandleUpstreamHTTPProxyConnect, this, std::placeholders::_1));
}));
}
} else if (m_ProxyURL.schema == "socks") { } else if (m_ProxyURL.schema == "socks") {
// handle upstream socks proxy // handle upstream socks proxy
if (!m_ProxyURL.port) m_ProxyURL.port = 9050; // default to tor default if not specified if (!m_ProxyURL.port) m_ProxyURL.port = 9050; // default to tor default if not specified
@ -426,6 +464,37 @@ namespace proxy {
Terminate(); Terminate();
} }
void HTTPReqHandler::HTTPConnect(const std::string & host, uint16_t port)
{
LogPrint(eLogDebug, "HTTPProxy: CONNECT ",host, ":", port);
std::string hostname(host);
if(str_rmatch(hostname, ".i2p"))
GetOwner()->CreateStream (std::bind (&HTTPReqHandler::HandleHTTPConnectStreamRequestComplete,
shared_from_this(), std::placeholders::_1), host, port);
else
ForwardToUpstreamProxy();
}
void HTTPReqHandler::HandleHTTPConnectStreamRequestComplete(std::shared_ptr<i2p::stream::Stream> stream)
{
if(stream)
{
m_ClientResponse.code = 200;
m_ClientResponse.status = "OK";
m_send_buf = m_ClientResponse.to_string();
m_sock->send(boost::asio::buffer(m_send_buf));
auto connection = std::make_shared<i2p::client::I2PTunnelConnection>(GetOwner(), m_sock, stream);
GetOwner()->AddHandler(connection);
connection->I2PConnect();
m_sock = nullptr;
Terminate();
}
else
{
GenericProxyError("CONNECT error", "Failed to Connect");
}
}
void HTTPReqHandler::SocksProxySuccess() void HTTPReqHandler::SocksProxySuccess()
{ {
if(m_ClientRequest.method == "CONNECT") { if(m_ClientRequest.method == "CONNECT") {
@ -513,8 +582,9 @@ namespace proxy {
Done (shared_from_this()); Done (shared_from_this());
} }
HTTPProxy::HTTPProxy(const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination): HTTPProxy::HTTPProxy(const std::string& address, int port, const std::string & outproxy, std::shared_ptr<i2p::client::ClientDestination> localDestination):
TCPIPAcceptor(address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()) TCPIPAcceptor(address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()),
m_OutproxyUrl(outproxy)
{ {
} }

View file

@ -6,14 +6,20 @@ namespace proxy {
class HTTPProxy: public i2p::client::TCPIPAcceptor class HTTPProxy: public i2p::client::TCPIPAcceptor
{ {
public: public:
HTTPProxy(const std::string& address, int port, const std::string & outproxy, std::shared_ptr<i2p::client::ClientDestination> localDestination);
HTTPProxy(const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr); HTTPProxy(const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr) :
HTTPProxy(address, port, "", localDestination) {} ;
~HTTPProxy() {}; ~HTTPProxy() {};
std::string GetOutproxyURL() const { return m_OutproxyUrl; }
protected: protected:
// Implements TCPIPAcceptor // Implements TCPIPAcceptor
std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket); std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
const char* GetName() { return "HTTP Proxy"; } const char* GetName() { return "HTTP Proxy"; }
private:
std::string m_OutproxyUrl;
}; };
} // http } // http
} // i2p } // i2p

View file

@ -2,6 +2,7 @@
#include "Identity.h" #include "Identity.h"
#include "ClientContext.h" #include "ClientContext.h"
#include "I2PService.h" #include "I2PService.h"
#include <boost/asio/error.hpp>
namespace i2p namespace i2p
{ {
@ -11,13 +12,18 @@ namespace client
I2PService::I2PService (std::shared_ptr<ClientDestination> localDestination): I2PService::I2PService (std::shared_ptr<ClientDestination> localDestination):
m_LocalDestination (localDestination ? localDestination : m_LocalDestination (localDestination ? localDestination :
i2p::client::context.CreateNewLocalDestination (false, I2P_SERVICE_DEFAULT_KEY_TYPE)), isUpdated (true) i2p::client::context.CreateNewLocalDestination (false, I2P_SERVICE_DEFAULT_KEY_TYPE)),
m_ReadyTimer(m_LocalDestination->GetService()),
m_ConnectTimeout(0),
isUpdated (true)
{ {
m_LocalDestination->Acquire (); m_LocalDestination->Acquire ();
} }
I2PService::I2PService (i2p::data::SigningKeyType kt): I2PService::I2PService (i2p::data::SigningKeyType kt):
m_LocalDestination (i2p::client::context.CreateNewLocalDestination (false, kt)), m_LocalDestination (i2p::client::context.CreateNewLocalDestination (false, kt)),
m_ReadyTimer(m_LocalDestination->GetService()),
m_ConnectTimeout(0),
isUpdated (true) isUpdated (true)
{ {
m_LocalDestination->Acquire (); m_LocalDestination->Acquire ();
@ -31,17 +37,74 @@ namespace client
void I2PService::ClearHandlers () void I2PService::ClearHandlers ()
{ {
if(m_ConnectTimeout)
m_ReadyTimer.cancel();
std::unique_lock<std::mutex> l(m_HandlersMutex); std::unique_lock<std::mutex> l(m_HandlersMutex);
for (auto it: m_Handlers) for (auto it: m_Handlers)
it->Terminate (); it->Terminate ();
m_Handlers.clear(); m_Handlers.clear();
} }
void I2PService::SetConnectTimeout(uint32_t timeout)
{
if(timeout && !m_ConnectTimeout)
{
TriggerReadyCheckTimer();
}
else if (m_ConnectTimeout && !timeout)
{
m_ReadyTimer.cancel();
}
m_ConnectTimeout = timeout;
}
void I2PService::AddReadyCallback(ReadyCallback cb)
{
uint32_t now = i2p::util::GetSecondsSinceEpoch();
uint32_t tm = now + m_ConnectTimeout;
LogPrint(eLogDebug, "I2PService::AddReadyCallback() ", tm, " ", now);
m_ReadyCallbacks.push_back({cb, tm});
}
void I2PService::TriggerReadyCheckTimer()
{
m_ReadyTimer.expires_from_now(boost::posix_time::seconds (1));
m_ReadyTimer.async_wait(std::bind(&I2PService::HandleReadyCheckTimer, this, std::placeholders::_1));
}
void I2PService::HandleReadyCheckTimer(const boost::system::error_code &ec)
{
if(ec || m_LocalDestination->IsReady())
{
for(auto & itr : m_ReadyCallbacks)
itr.first(ec);
m_ReadyCallbacks.clear();
}
else if(!m_LocalDestination->IsReady())
{
// expire timed out requests
uint32_t now = i2p::util::GetSecondsSinceEpoch ();
auto itr = m_ReadyCallbacks.begin();
while(itr != m_ReadyCallbacks.end())
{
if(itr->second >= now)
{
itr->first(boost::asio::error::timed_out);
itr = m_ReadyCallbacks.erase(itr);
}
else
++itr;
}
}
if(!ec)
TriggerReadyCheckTimer();
}
void I2PService::CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port) { void I2PService::CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port) {
assert(streamRequestComplete); assert(streamRequestComplete);
i2p::data::IdentHash identHash; i2p::data::IdentHash identHash;
if (i2p::client::context.GetAddressBook ().GetIdentHash (dest, identHash)) if (i2p::client::context.GetAddressBook ().GetIdentHash (dest, identHash))
m_LocalDestination->CreateStream (streamRequestComplete, identHash, port); CreateStream(streamRequestComplete, identHash, port);
else else
{ {
LogPrint (eLogWarning, "I2PService: Remote destination not found: ", dest); LogPrint (eLogWarning, "I2PService: Remote destination not found: ", dest);
@ -49,6 +112,29 @@ namespace client
} }
} }
void I2PService::CreateStream(StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash & identHash, int port)
{
if(m_ConnectTimeout)
{
if(m_LocalDestination->IsReady())
m_LocalDestination->CreateStream (streamRequestComplete, identHash, port);
else
{
AddReadyCallback([this, streamRequestComplete, identHash, port] (const boost::system::error_code & ec) {
if(ec)
{
LogPrint(eLogWarning, "I2PService::CeateStream() ", ec.message());
streamRequestComplete(nullptr);
}
else
this->m_LocalDestination->CreateStream(streamRequestComplete, identHash, port);
});
}
}
else
m_LocalDestination->CreateStream(streamRequestComplete, identHash, port);
}
TCPIPPipe::TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream) TCPIPPipe::TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream)
{ {
boost::asio::socket_base::receive_buffer_size option(TCP_IP_PIPE_BUFFER_SIZE); boost::asio::socket_base::receive_buffer_size option(TCP_IP_PIPE_BUFFER_SIZE);
@ -70,16 +156,16 @@ namespace client
void TCPIPPipe::Terminate() void TCPIPPipe::Terminate()
{ {
if(Kill()) return; if(Kill()) return;
if (m_up) { if (m_up)
if (m_up->is_open()) { {
if (m_up->is_open())
m_up->close(); m_up->close();
}
m_up = nullptr; m_up = nullptr;
} }
if (m_down) { if (m_down)
if (m_down->is_open()) { {
if (m_down->is_open())
m_down->close(); m_down->close();
}
m_down = nullptr; m_down = nullptr;
} }
Done(shared_from_this()); Done(shared_from_this());
@ -87,103 +173,106 @@ namespace client
void TCPIPPipe::AsyncReceiveUpstream() void TCPIPPipe::AsyncReceiveUpstream()
{ {
if (m_up) { if (m_up)
{
m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, TCP_IP_PIPE_BUFFER_SIZE), m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, TCP_IP_PIPE_BUFFER_SIZE),
std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(), std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(),
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2));
} else {
LogPrint(eLogError, "TCPIPPipe: upstream receive: no socket");
} }
else
LogPrint(eLogError, "TCPIPPipe: upstream receive: no socket");
} }
void TCPIPPipe::AsyncReceiveDownstream() void TCPIPPipe::AsyncReceiveDownstream()
{ {
if (m_down) { if (m_down) {
m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, TCP_IP_PIPE_BUFFER_SIZE), m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, TCP_IP_PIPE_BUFFER_SIZE),
std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(), std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(),
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2));
} else {
LogPrint(eLogError, "TCPIPPipe: downstream receive: no socket");
} }
else
LogPrint(eLogError, "TCPIPPipe: downstream receive: no socket");
} }
void TCPIPPipe::UpstreamWrite(size_t len) void TCPIPPipe::UpstreamWrite(size_t len)
{ {
if (m_up) { if (m_up)
{
LogPrint(eLogDebug, "TCPIPPipe: upstream: ", (int) len, " bytes written"); LogPrint(eLogDebug, "TCPIPPipe: upstream: ", (int) len, " bytes written");
boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len), boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len),
boost::asio::transfer_all(), boost::asio::transfer_all(),
std::bind(&TCPIPPipe::HandleUpstreamWrite, std::bind(&TCPIPPipe::HandleUpstreamWrite,
shared_from_this(), shared_from_this(),
std::placeholders::_1) std::placeholders::_1));
);
} else {
LogPrint(eLogError, "TCPIPPipe: upstream write: no socket");
} }
else
LogPrint(eLogError, "TCPIPPipe: upstream write: no socket");
} }
void TCPIPPipe::DownstreamWrite(size_t len) void TCPIPPipe::DownstreamWrite(size_t len)
{ {
if (m_down) { if (m_down)
{
LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) len, " bytes written"); LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) len, " bytes written");
boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len), boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len),
boost::asio::transfer_all(), boost::asio::transfer_all(),
std::bind(&TCPIPPipe::HandleDownstreamWrite, std::bind(&TCPIPPipe::HandleDownstreamWrite,
shared_from_this(), shared_from_this(),
std::placeholders::_1) std::placeholders::_1));
);
} else {
LogPrint(eLogError, "TCPIPPipe: downstream write: no socket");
} }
else
LogPrint(eLogError, "TCPIPPipe: downstream write: no socket");
} }
void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
{ {
LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) bytes_transfered, " bytes received"); LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) bytes_transfered, " bytes received");
if (ecode) { if (ecode)
{
LogPrint(eLogError, "TCPIPPipe: downstream read error:" , ecode.message()); LogPrint(eLogError, "TCPIPPipe: downstream read error:" , ecode.message());
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
Terminate(); Terminate();
} else { } else {
if (bytes_transfered > 0 ) { if (bytes_transfered > 0 )
memcpy(m_upstream_buf, m_downstream_to_up_buf, bytes_transfered); memcpy(m_upstream_buf, m_downstream_to_up_buf, bytes_transfered);
}
UpstreamWrite(bytes_transfered); UpstreamWrite(bytes_transfered);
} }
} }
void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) { void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) {
if (ecode) { if (ecode)
{
LogPrint(eLogError, "TCPIPPipe: downstream write error:" , ecode.message()); LogPrint(eLogError, "TCPIPPipe: downstream write error:" , ecode.message());
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
Terminate(); Terminate();
} else {
AsyncReceiveUpstream();
} }
else
AsyncReceiveUpstream();
} }
void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) { void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) {
if (ecode) { if (ecode)
{
LogPrint(eLogError, "TCPIPPipe: upstream write error:" , ecode.message()); LogPrint(eLogError, "TCPIPPipe: upstream write error:" , ecode.message());
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
Terminate(); Terminate();
} else {
AsyncReceiveDownstream();
} }
else
AsyncReceiveDownstream();
} }
void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
{ {
LogPrint(eLogDebug, "TCPIPPipe: upstream ", (int)bytes_transfered, " bytes received"); LogPrint(eLogDebug, "TCPIPPipe: upstream ", (int)bytes_transfered, " bytes received");
if (ecode) { if (ecode)
{
LogPrint(eLogError, "TCPIPPipe: upstream read error:" , ecode.message()); LogPrint(eLogError, "TCPIPPipe: upstream read error:" , ecode.message());
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
Terminate(); Terminate();
} else { } else {
if (bytes_transfered > 0 ) { if (bytes_transfered > 0 )
memcpy(m_downstream_buf, m_upstream_to_down_buf, bytes_transfered); memcpy(m_downstream_buf, m_upstream_to_down_buf, bytes_transfered);
}
DownstreamWrite(bytes_transfered); DownstreamWrite(bytes_transfered);
} }
} }

View file

@ -14,8 +14,11 @@ namespace i2p
namespace client namespace client
{ {
class I2PServiceHandler; class I2PServiceHandler;
class I2PService class I2PService : std::enable_shared_from_this<I2PService>
{ {
public:
typedef std::function<void(const boost::system::error_code &)> ReadyCallback;
public: public:
I2PService (std::shared_ptr<ClientDestination> localDestination = nullptr); I2PService (std::shared_ptr<ClientDestination> localDestination = nullptr);
I2PService (i2p::data::SigningKeyType kt); I2PService (i2p::data::SigningKeyType kt);
@ -33,22 +36,38 @@ namespace client
} }
void ClearHandlers (); void ClearHandlers ();
void SetConnectTimeout(uint32_t timeout);
void AddReadyCallback(ReadyCallback cb);
inline std::shared_ptr<ClientDestination> GetLocalDestination () { return m_LocalDestination; } inline std::shared_ptr<ClientDestination> GetLocalDestination () { return m_LocalDestination; }
inline std::shared_ptr<const ClientDestination> GetLocalDestination () const { return m_LocalDestination; } inline std::shared_ptr<const ClientDestination> GetLocalDestination () const { return m_LocalDestination; }
inline void SetLocalDestination (std::shared_ptr<ClientDestination> dest) { m_LocalDestination = dest; } inline void SetLocalDestination (std::shared_ptr<ClientDestination> dest)
{
if (m_LocalDestination) m_LocalDestination->Release ();
if (dest) dest->Acquire ();
m_LocalDestination = dest;
}
void CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port = 0); void CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port = 0);
void CreateStream(StreamRequestComplete complete, const i2p::data::IdentHash & ident, int port);
inline boost::asio::io_service& GetService () { return m_LocalDestination->GetService (); } inline boost::asio::io_service& GetService () { return m_LocalDestination->GetService (); }
virtual void Start () = 0; virtual void Start () = 0;
virtual void Stop () = 0; virtual void Stop () = 0;
virtual const char* GetName() { return "Generic I2P Service"; } virtual const char* GetName() { return "Generic I2P Service"; }
private:
private:
void TriggerReadyCheckTimer();
void HandleReadyCheckTimer(const boost::system::error_code & ec);
private:
std::shared_ptr<ClientDestination> m_LocalDestination; std::shared_ptr<ClientDestination> m_LocalDestination;
std::unordered_set<std::shared_ptr<I2PServiceHandler> > m_Handlers; std::unordered_set<std::shared_ptr<I2PServiceHandler> > m_Handlers;
std::mutex m_HandlersMutex; std::mutex m_HandlersMutex;
std::vector<std::pair<ReadyCallback, uint32_t> > m_ReadyCallbacks;
boost::asio::deadline_timer m_ReadyTimer;
uint32_t m_ConnectTimeout;
public: public:
bool isUpdated; // transient, used during reload only bool isUpdated; // transient, used during reload only
@ -74,6 +93,7 @@ namespace client
inline void Done (std::shared_ptr<I2PServiceHandler> me) { if(m_Service) m_Service->RemoveHandler(me); } inline void Done (std::shared_ptr<I2PServiceHandler> me) { if(m_Service) m_Service->RemoveHandler(me); }
// Call to talk with the owner // Call to talk with the owner
inline I2PService * GetOwner() { return m_Service; } inline I2PService * GetOwner() { return m_Service; }
private: private:
I2PService *m_Service; I2PService *m_Service;
std::atomic<bool> m_Dead; //To avoid cleaning up multiple times std::atomic<bool> m_Dead; //To avoid cleaning up multiple times
@ -82,25 +102,28 @@ namespace client
const size_t TCP_IP_PIPE_BUFFER_SIZE = 8192 * 8; const size_t TCP_IP_PIPE_BUFFER_SIZE = 8192 * 8;
// bidirectional pipe for 2 tcp/ip sockets // bidirectional pipe for 2 tcp/ip sockets
class TCPIPPipe: public I2PServiceHandler, public std::enable_shared_from_this<TCPIPPipe> { class TCPIPPipe: public I2PServiceHandler, public std::enable_shared_from_this<TCPIPPipe>
public: {
TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream); public:
~TCPIPPipe(); TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream);
void Start(); ~TCPIPPipe();
protected: void Start();
void Terminate();
void AsyncReceiveUpstream(); protected:
void AsyncReceiveDownstream(); void Terminate();
void HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred); void AsyncReceiveUpstream();
void HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred); void AsyncReceiveDownstream();
void HandleUpstreamWrite(const boost::system::error_code & ecode); void HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred);
void HandleDownstreamWrite(const boost::system::error_code & ecode); void HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred);
void UpstreamWrite(size_t len); void HandleUpstreamWrite(const boost::system::error_code & ecode);
void DownstreamWrite(size_t len); void HandleDownstreamWrite(const boost::system::error_code & ecode);
private: void UpstreamWrite(size_t len);
uint8_t m_upstream_to_down_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[TCP_IP_PIPE_BUFFER_SIZE]; void DownstreamWrite(size_t len);
uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE];
std::shared_ptr<boost::asio::ip::tcp::socket> m_up, m_down; private:
uint8_t m_upstream_to_down_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[TCP_IP_PIPE_BUFFER_SIZE];
uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE];
std::shared_ptr<boost::asio::ip::tcp::socket> m_up, m_down;
}; };
/* TODO: support IPv6 too */ /* TODO: support IPv6 too */
@ -124,10 +147,11 @@ namespace client
const boost::asio::ip::tcp::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; }; const boost::asio::ip::tcp::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; };
virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; } virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; }
protected: protected:
virtual std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket) = 0; virtual std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket) = 0;
private: private:
void Accept(); void Accept();
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket); void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket);

View file

@ -29,14 +29,14 @@ namespace client
} }
I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, I2PTunnelConnection::I2PTunnelConnection (I2PService * owner,
std::shared_ptr<boost::asio::ip::tcp::socket> socket, std::shared_ptr<i2p::stream::Stream> stream): std::shared_ptr<boost::asio::ip::tcp::socket> socket, std::shared_ptr<i2p::stream::Stream> stream):
I2PServiceHandler(owner), m_Socket (socket), m_Stream (stream), I2PServiceHandler(owner), m_Socket (socket), m_Stream (stream),
m_RemoteEndpoint (socket->remote_endpoint ()), m_IsQuiet (true) m_RemoteEndpoint (socket->remote_endpoint ()), m_IsQuiet (true)
{ {
} }
I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream, I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
std::shared_ptr<boost::asio::ip::tcp::socket> socket, const boost::asio::ip::tcp::endpoint& target, bool quiet): std::shared_ptr<boost::asio::ip::tcp::socket> socket, const boost::asio::ip::tcp::endpoint& target, bool quiet):
I2PServiceHandler(owner), m_Socket (socket), m_Stream (stream), I2PServiceHandler(owner), m_Socket (socket), m_Stream (stream),
m_RemoteEndpoint (target), m_IsQuiet (quiet) m_RemoteEndpoint (target), m_IsQuiet (quiet)
{ {
@ -137,7 +137,7 @@ namespace client
auto s = shared_from_this (); auto s = shared_from_this ();
m_Stream->AsyncSend (m_Buffer, bytes_transferred, m_Stream->AsyncSend (m_Buffer, bytes_transferred,
[s](const boost::system::error_code& ecode) [s](const boost::system::error_code& ecode)
{ {
if (!ecode) if (!ecode)
s->Receive (); s->Receive ();
else else
@ -164,7 +164,7 @@ namespace client
if (m_Stream) if (m_Stream)
{ {
if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew || if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew ||
m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular
{ {
m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE),
std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (), std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (),
@ -207,7 +207,7 @@ namespace client
void I2PTunnelConnection::Write (const uint8_t * buf, size_t len) void I2PTunnelConnection::Write (const uint8_t * buf, size_t len)
{ {
boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, len), boost::asio::transfer_all (), boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, len), boost::asio::transfer_all (),
std::bind (&I2PTunnelConnection::HandleWrite, shared_from_this (), std::placeholders::_1)); std::bind (&I2PTunnelConnection::HandleWrite, shared_from_this (), std::placeholders::_1));
} }
void I2PTunnelConnection::HandleConnect (const boost::system::error_code& ecode) void I2PTunnelConnection::HandleConnect (const boost::system::error_code& ecode)
@ -339,48 +339,48 @@ namespace client
} }
I2PTunnelConnectionIRC::I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream, I2PTunnelConnectionIRC::I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
std::shared_ptr<boost::asio::ip::tcp::socket> socket, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint& target, const std::string& webircpass): const boost::asio::ip::tcp::endpoint& target, const std::string& webircpass):
I2PTunnelConnection (owner, stream, socket, target), m_From (stream->GetRemoteIdentity ()), I2PTunnelConnection (owner, stream, socket, target), m_From (stream->GetRemoteIdentity ()),
m_NeedsWebIrc (webircpass.length() ? true : false), m_WebircPass (webircpass) m_NeedsWebIrc (webircpass.length() ? true : false), m_WebircPass (webircpass)
{ {
} }
void I2PTunnelConnectionIRC::Write (const uint8_t * buf, size_t len) void I2PTunnelConnectionIRC::Write (const uint8_t * buf, size_t len)
{ {
m_OutPacket.str (""); m_OutPacket.str ("");
if (m_NeedsWebIrc) if (m_NeedsWebIrc)
{ {
m_NeedsWebIrc = false; m_NeedsWebIrc = false;
m_OutPacket << "WEBIRC " << m_WebircPass << " cgiirc " << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()) << " " << GetSocket ()->local_endpoint ().address () << std::endl; m_OutPacket << "WEBIRC " << m_WebircPass << " cgiirc " << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()) << " " << GetSocket ()->local_endpoint ().address () << std::endl;
} }
m_InPacket.clear (); m_InPacket.clear ();
m_InPacket.write ((const char *)buf, len); m_InPacket.write ((const char *)buf, len);
while (!m_InPacket.eof () && !m_InPacket.fail ()) while (!m_InPacket.eof () && !m_InPacket.fail ())
{ {
std::string line; std::string line;
std::getline (m_InPacket, line); std::getline (m_InPacket, line);
if (line.length () == 0 && m_InPacket.eof ()) if (line.length () == 0 && m_InPacket.eof ())
m_InPacket.str (""); m_InPacket.str ("");
auto pos = line.find ("USER"); auto pos = line.find ("USER");
if (!pos) // start of line if (!pos) // start of line
{ {
pos = line.find (" "); pos = line.find (" ");
pos++; pos++;
pos = line.find (" ", pos); pos = line.find (" ", pos);
pos++; pos++;
auto nextpos = line.find (" ", pos); auto nextpos = line.find (" ", pos);
m_OutPacket << line.substr (0, pos); m_OutPacket << line.substr (0, pos);
m_OutPacket << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()); m_OutPacket << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ());
m_OutPacket << line.substr (nextpos) << '\n'; m_OutPacket << line.substr (nextpos) << '\n';
} }
else else
m_OutPacket << line << '\n'; m_OutPacket << line << '\n';
} }
I2PTunnelConnection::Write ((uint8_t *)m_OutPacket.str ().c_str (), m_OutPacket.str ().length ()); I2PTunnelConnection::Write ((uint8_t *)m_OutPacket.str ().c_str (), m_OutPacket.str ().length ());
} }
/* This handler tries to stablish a connection with the desired server and dies if it fails to do so */ /* This handler tries to stablish a connection with the desired server and dies if it fails to do so */
@ -402,7 +402,7 @@ namespace client
void I2PClientTunnelHandler::Handle() void I2PClientTunnelHandler::Handle()
{ {
GetOwner()->GetLocalDestination ()->CreateStream ( GetOwner()->CreateStream (
std::bind (&I2PClientTunnelHandler::HandleStreamRequestComplete, shared_from_this(), std::placeholders::_1), std::bind (&I2PClientTunnelHandler::HandleStreamRequestComplete, shared_from_this(), std::placeholders::_1),
m_DestinationIdentHash, m_DestinationPort); m_DestinationIdentHash, m_DestinationPort);
} }
@ -437,7 +437,7 @@ namespace client
} }
I2PClientTunnel::I2PClientTunnel (const std::string& name, const std::string& destination, I2PClientTunnel::I2PClientTunnel (const std::string& name, const std::string& destination,
const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination, int destinationPort): const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination, int destinationPort):
TCPIPAcceptor (address, port, localDestination), m_Name (name), m_Destination (destination), TCPIPAcceptor (address, port, localDestination), m_Name (name), m_Destination (destination),
m_DestinationIdentHash (nullptr), m_DestinationPort (destinationPort) m_DestinationIdentHash (nullptr), m_DestinationPort (destinationPort)
{ {
@ -481,7 +481,7 @@ namespace client
} }
I2PServerTunnel::I2PServerTunnel (const std::string& name, const std::string& address, I2PServerTunnel::I2PServerTunnel (const std::string& name, const std::string& address,
int port, std::shared_ptr<ClientDestination> localDestination, int inport, bool gzip): int port, std::shared_ptr<ClientDestination> localDestination, int inport, bool gzip):
I2PService (localDestination), m_IsUniqueLocal(true), m_Name (name), m_Address (address), m_Port (port), m_IsAccessList (false) I2PService (localDestination), m_IsUniqueLocal(true), m_Name (name), m_Address (address), m_Port (port), m_IsAccessList (false)
{ {
m_PortDestination = localDestination->CreateStreamingDestination (inport > 0 ? inport : port, gzip); m_PortDestination = localDestination->CreateStreamingDestination (inport > 0 ? inport : port, gzip);
@ -573,8 +573,8 @@ namespace client
} }
I2PServerTunnelHTTP::I2PServerTunnelHTTP (const std::string& name, const std::string& address, I2PServerTunnelHTTP::I2PServerTunnelHTTP (const std::string& name, const std::string& address,
int port, std::shared_ptr<ClientDestination> localDestination, int port, std::shared_ptr<ClientDestination> localDestination,
const std::string& host, int inport, bool gzip): const std::string& host, int inport, bool gzip):
I2PServerTunnel (name, address, port, localDestination, inport, gzip), I2PServerTunnel (name, address, port, localDestination, inport, gzip),
m_Host (host) m_Host (host)
{ {
@ -586,30 +586,30 @@ namespace client
std::make_shared<boost::asio::ip::tcp::socket> (GetService ()), GetEndpoint (), m_Host); std::make_shared<boost::asio::ip::tcp::socket> (GetService ()), GetEndpoint (), m_Host);
} }
I2PServerTunnelIRC::I2PServerTunnelIRC (const std::string& name, const std::string& address, I2PServerTunnelIRC::I2PServerTunnelIRC (const std::string& name, const std::string& address,
int port, std::shared_ptr<ClientDestination> localDestination, int port, std::shared_ptr<ClientDestination> localDestination,
const std::string& webircpass, int inport, bool gzip): const std::string& webircpass, int inport, bool gzip):
I2PServerTunnel (name, address, port, localDestination, inport, gzip), I2PServerTunnel (name, address, port, localDestination, inport, gzip),
m_WebircPass (webircpass) m_WebircPass (webircpass)
{ {
} }
std::shared_ptr<I2PTunnelConnection> I2PServerTunnelIRC::CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream) std::shared_ptr<I2PTunnelConnection> I2PServerTunnelIRC::CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream)
{ {
return std::make_shared<I2PTunnelConnectionIRC> (this, stream, std::make_shared<boost::asio::ip::tcp::socket> (GetService ()), GetEndpoint (), this->m_WebircPass); return std::make_shared<I2PTunnelConnectionIRC> (this, stream, std::make_shared<boost::asio::ip::tcp::socket> (GetService ()), GetEndpoint (), this->m_WebircPass);
} }
void I2PUDPServerTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) void I2PUDPServerTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
{ {
std::lock_guard<std::mutex> lock(m_SessionsMutex); std::lock_guard<std::mutex> lock(m_SessionsMutex);
auto session = ObtainUDPSession(from, toPort, fromPort); auto session = ObtainUDPSession(from, toPort, fromPort);
session->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint); session->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint);
session->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); session->LastActivity = i2p::util::GetMillisecondsSinceEpoch();
} }
void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) { void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) {
std::lock_guard<std::mutex> lock(m_SessionsMutex); std::lock_guard<std::mutex> lock(m_SessionsMutex);
uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); uint64_t now = i2p::util::GetMillisecondsSinceEpoch();
auto itr = m_Sessions.begin(); auto itr = m_Sessions.begin();
while(itr != m_Sessions.end()) { while(itr != m_Sessions.end()) {
if(now - (*itr)->LastActivity >= delta ) if(now - (*itr)->LastActivity >= delta )
@ -617,11 +617,11 @@ namespace client
else else
++itr; ++itr;
} }
} }
void I2PUDPClientTunnel::ExpireStale(const uint64_t delta) { void I2PUDPClientTunnel::ExpireStale(const uint64_t delta) {
std::lock_guard<std::mutex> lock(m_SessionsMutex); std::lock_guard<std::mutex> lock(m_SessionsMutex);
uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); uint64_t now = i2p::util::GetMillisecondsSinceEpoch();
std::vector<uint16_t> removePorts; std::vector<uint16_t> removePorts;
for (const auto & s : m_Sessions) { for (const auto & s : m_Sessions) {
if (now - s.second.second >= delta) if (now - s.second.second >= delta)
@ -630,20 +630,20 @@ namespace client
for(auto port : removePorts) { for(auto port : removePorts) {
m_Sessions.erase(port); m_Sessions.erase(port);
} }
} }
UDPSessionPtr I2PUDPServerTunnel::ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort) UDPSessionPtr I2PUDPServerTunnel::ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort)
{ {
auto ih = from.GetIdentHash(); auto ih = from.GetIdentHash();
for (auto & s : m_Sessions ) for (auto & s : m_Sessions )
{ {
if ( s->Identity == ih) if ( s->Identity == ih)
{ {
/** found existing session */ /** found existing session */
LogPrint(eLogDebug, "UDPServer: found session ", s->IPSocket.local_endpoint(), " ", ih.ToBase32()); LogPrint(eLogDebug, "UDPServer: found session ", s->IPSocket.local_endpoint(), " ", ih.ToBase32());
return s; return s;
} }
} }
boost::asio::ip::address addr; boost::asio::ip::address addr;
/** create new udp session */ /** create new udp session */
if(m_IsUniqueLocal && m_LocalAddress.is_loopback()) if(m_IsUniqueLocal && m_LocalAddress.is_loopback())
@ -654,16 +654,16 @@ namespace client
else else
addr = m_LocalAddress; addr = m_LocalAddress;
boost::asio::ip::udp::endpoint ep(addr, 0); boost::asio::ip::udp::endpoint ep(addr, 0);
m_Sessions.push_back(std::make_shared<UDPSession>(ep, m_LocalDest, m_RemoteEndpoint, &ih, localPort, remotePort)); m_Sessions.push_back(std::make_shared<UDPSession>(ep, m_LocalDest, m_RemoteEndpoint, &ih, localPort, remotePort));
auto & back = m_Sessions.back(); auto & back = m_Sessions.back();
return back; return back;
} }
UDPSession::UDPSession(boost::asio::ip::udp::endpoint localEndpoint, UDPSession::UDPSession(boost::asio::ip::udp::endpoint localEndpoint,
const std::shared_ptr<i2p::client::ClientDestination> & localDestination, const std::shared_ptr<i2p::client::ClientDestination> & localDestination,
boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash * to, boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash * to,
uint16_t ourPort, uint16_t theirPort) : uint16_t ourPort, uint16_t theirPort) :
m_Destination(localDestination->GetDatagramDestination()), m_Destination(localDestination->GetDatagramDestination()),
IPSocket(localDestination->GetService(), localEndpoint), IPSocket(localDestination->GetService(), localEndpoint),
SendEndpoint(endpoint), SendEndpoint(endpoint),
LastActivity(i2p::util::GetMillisecondsSinceEpoch()), LastActivity(i2p::util::GetMillisecondsSinceEpoch()),
@ -674,7 +674,6 @@ namespace client
Receive(); Receive();
} }
void UDPSession::Receive() { void UDPSession::Receive() {
LogPrint(eLogDebug, "UDPSession: Receive"); LogPrint(eLogDebug, "UDPSession: Receive");
IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU), IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU),
@ -694,8 +693,6 @@ namespace client
} }
} }
I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr<i2p::client::ClientDestination> localDestination, I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr<i2p::client::ClientDestination> localDestination,
boost::asio::ip::address localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port) : boost::asio::ip::address localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port) :
m_IsUniqueLocal(true), m_IsUniqueLocal(true),
@ -759,13 +756,11 @@ namespace client
{ {
auto dgram = m_LocalDest->CreateDatagramDestination(); auto dgram = m_LocalDest->CreateDatagramDestination();
dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this, dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4, std::placeholders::_3, std::placeholders::_4,
std::placeholders::_5)); std::placeholders::_5));
} }
void I2PUDPClientTunnel::Start() { void I2PUDPClientTunnel::Start() {
m_LocalDest->Start(); m_LocalDest->Start();
if (m_ResolveThread == nullptr) if (m_ResolveThread == nullptr)
@ -850,7 +845,6 @@ namespace client
} }
else else
LogPrint(eLogWarning, "UDP Client: unwarrented traffic from ", from.GetIdentHash().ToBase32()); LogPrint(eLogWarning, "UDP Client: unwarrented traffic from ", from.GetIdentHash().ToBase32());
} }
I2PUDPClientTunnel::~I2PUDPClientTunnel() { I2PUDPClientTunnel::~I2PUDPClientTunnel() {

View file

@ -29,7 +29,6 @@ namespace client
class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this<I2PTunnelConnection> class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this<I2PTunnelConnection>
{ {
public: public:
I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket, I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
std::shared_ptr<const i2p::data::LeaseSet> leaseSet, int port = 0); // to I2P std::shared_ptr<const i2p::data::LeaseSet> leaseSet, int port = 0); // to I2P
I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket, I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
@ -41,7 +40,6 @@ namespace client
void Connect (bool isUniqueLocal = true); void Connect (bool isUniqueLocal = true);
protected: protected:
void Terminate (); void Terminate ();
void Receive (); void Receive ();
@ -56,7 +54,6 @@ namespace client
std::shared_ptr<const boost::asio::ip::tcp::socket> GetSocket () const { return m_Socket; }; std::shared_ptr<const boost::asio::ip::tcp::socket> GetSocket () const { return m_Socket; };
private: private:
uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE]; uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE];
std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket; std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;
std::shared_ptr<i2p::stream::Stream> m_Stream; std::shared_ptr<i2p::stream::Stream> m_Stream;
@ -67,18 +64,15 @@ namespace client
class I2PClientTunnelConnectionHTTP: public I2PTunnelConnection class I2PClientTunnelConnectionHTTP: public I2PTunnelConnection
{ {
public: public:
I2PClientTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket, I2PClientTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
std::shared_ptr<i2p::stream::Stream> stream): std::shared_ptr<i2p::stream::Stream> stream):
I2PTunnelConnection (owner, socket, stream), m_HeaderSent (false), I2PTunnelConnection (owner, socket, stream), m_HeaderSent (false),
m_ConnectionSent (false), m_ProxyConnectionSent (false) {}; m_ConnectionSent (false), m_ProxyConnectionSent (false) {};
protected: protected:
void Write (const uint8_t * buf, size_t len); void Write (const uint8_t * buf, size_t len);
private: private:
std::stringstream m_InHeader, m_OutHeader; std::stringstream m_InHeader, m_OutHeader;
bool m_HeaderSent, m_ConnectionSent, m_ProxyConnectionSent; bool m_HeaderSent, m_ConnectionSent, m_ProxyConnectionSent;
}; };
@ -86,17 +80,14 @@ namespace client
class I2PServerTunnelConnectionHTTP: public I2PTunnelConnection class I2PServerTunnelConnectionHTTP: public I2PTunnelConnection
{ {
public: public:
I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream, I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
std::shared_ptr<boost::asio::ip::tcp::socket> socket, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint& target, const std::string& host); const boost::asio::ip::tcp::endpoint& target, const std::string& host);
protected: protected:
void Write (const uint8_t * buf, size_t len); void Write (const uint8_t * buf, size_t len);
private: private:
std::string m_Host; std::string m_Host;
std::stringstream m_InHeader, m_OutHeader; std::stringstream m_InHeader, m_OutHeader;
bool m_HeaderSent; bool m_HeaderSent;
@ -104,35 +95,30 @@ namespace client
}; };
class I2PTunnelConnectionIRC: public I2PTunnelConnection class I2PTunnelConnectionIRC: public I2PTunnelConnection
{ {
public: public:
I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass);
I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream, protected:
std::shared_ptr<boost::asio::ip::tcp::socket> socket, void Write (const uint8_t * buf, size_t len);
const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass);
protected: private:
std::shared_ptr<const i2p::data::IdentityEx> m_From;
void Write (const uint8_t * buf, size_t len); std::stringstream m_OutPacket, m_InPacket;
private:
std::shared_ptr<const i2p::data::IdentityEx> m_From;
std::stringstream m_OutPacket, m_InPacket;
bool m_NeedsWebIrc; bool m_NeedsWebIrc;
std::string m_WebircPass; std::string m_WebircPass;
}; };
class I2PClientTunnel: public TCPIPAcceptor class I2PClientTunnel: public TCPIPAcceptor
{ {
protected: protected:
// Implements TCPIPAcceptor // Implements TCPIPAcceptor
std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket); std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
public: public:
I2PClientTunnel (const std::string& name, const std::string& destination, I2PClientTunnel (const std::string& name, const std::string& destination,
const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination, int destinationPort = 0); const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination, int destinationPort = 0);
~I2PClientTunnel () {} ~I2PClientTunnel () {}
@ -143,11 +129,9 @@ namespace client
const char* GetName() { return m_Name.c_str (); } const char* GetName() { return m_Name.c_str (); }
private: private:
const i2p::data::IdentHash * GetIdentHash (); const i2p::data::IdentHash * GetIdentHash ();
private: private:
std::string m_Name, m_Destination; std::string m_Name, m_Destination;
const i2p::data::IdentHash * m_DestinationIdentHash; const i2p::data::IdentHash * m_DestinationIdentHash;
int m_DestinationPort; int m_DestinationPort;
@ -208,11 +192,11 @@ namespace client
/** server side udp tunnel, many i2p inbound to 1 ip outbound */ /** server side udp tunnel, many i2p inbound to 1 ip outbound */
class I2PUDPServerTunnel class I2PUDPServerTunnel
{ {
public: public:
I2PUDPServerTunnel(const std::string & name, I2PUDPServerTunnel(const std::string & name,
std::shared_ptr<i2p::client::ClientDestination> localDestination, std::shared_ptr<i2p::client::ClientDestination> localDestination,
boost::asio::ip::address localAddress, boost::asio::ip::address localAddress,
boost::asio::ip::udp::endpoint forwardTo, uint16_t port); boost::asio::ip::udp::endpoint forwardTo, uint16_t port);
~I2PUDPServerTunnel(); ~I2PUDPServerTunnel();
/** expire stale udp conversations */ /** expire stale udp conversations */
@ -225,7 +209,6 @@ namespace client
void SetUniqueLocal(bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; } void SetUniqueLocal(bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; }
private: private:
void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
UDPSessionPtr ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); UDPSessionPtr ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort);
@ -256,22 +239,22 @@ namespace client
void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT);
private: private:
typedef std::pair<boost::asio::ip::udp::endpoint, uint64_t> UDPConvo; typedef std::pair<boost::asio::ip::udp::endpoint, uint64_t> UDPConvo;
void RecvFromLocal(); void RecvFromLocal();
void HandleRecvFromLocal(const boost::system::error_code & e, std::size_t transferred); void HandleRecvFromLocal(const boost::system::error_code & e, std::size_t transferred);
void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
void TryResolving(); void TryResolving();
const std::string m_Name; const std::string m_Name;
std::mutex m_SessionsMutex; std::mutex m_SessionsMutex;
std::map<uint16_t, UDPConvo > m_Sessions; // maps i2p port -> local udp convo std::map<uint16_t, UDPConvo > m_Sessions; // maps i2p port -> local udp convo
const std::string m_RemoteDest; const std::string m_RemoteDest;
std::shared_ptr<i2p::client::ClientDestination> m_LocalDest; std::shared_ptr<i2p::client::ClientDestination> m_LocalDest;
const boost::asio::ip::udp::endpoint m_LocalEndpoint; const boost::asio::ip::udp::endpoint m_LocalEndpoint;
i2p::data::IdentHash * m_RemoteIdent; i2p::data::IdentHash * m_RemoteIdent;
std::thread * m_ResolveThread; std::thread * m_ResolveThread;
boost::asio::ip::udp::socket m_LocalSocket; boost::asio::ip::udp::socket m_LocalSocket;
boost::asio::ip::udp::endpoint m_RecvEndpoint; boost::asio::ip::udp::endpoint m_RecvEndpoint;
uint8_t m_RecvBuff[I2P_UDP_MAX_MTU]; uint8_t m_RecvBuff[I2P_UDP_MAX_MTU];
uint16_t RemotePort; uint16_t RemotePort;
bool m_cancel_resolve; bool m_cancel_resolve;
}; };
@ -279,7 +262,6 @@ namespace client
class I2PServerTunnel: public I2PService class I2PServerTunnel: public I2PService
{ {
public: public:
I2PServerTunnel (const std::string& name, const std::string& address, int port, I2PServerTunnel (const std::string& name, const std::string& address, int port,
std::shared_ptr<ClientDestination> localDestination, int inport = 0, bool gzip = true); std::shared_ptr<ClientDestination> localDestination, int inport = 0, bool gzip = true);
@ -298,10 +280,9 @@ namespace client
const char* GetName() { return m_Name.c_str (); } const char* GetName() { return m_Name.c_str (); }
void SetMaxConnsPerMinute(const uint32_t conns) { m_PortDestination->SetMaxConnsPerMinute(conns); } void SetMaxConnsPerMinute(const uint32_t conns) { m_PortDestination->SetMaxConnsPerMinute(conns); }
private:
private:
void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it, void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it,
std::shared_ptr<boost::asio::ip::tcp::resolver> resolver); std::shared_ptr<boost::asio::ip::tcp::resolver> resolver);
@ -310,7 +291,6 @@ namespace client
virtual std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream); virtual std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
private: private:
bool m_IsUniqueLocal; bool m_IsUniqueLocal;
std::string m_Name, m_Address; std::string m_Name, m_Address;
int m_Port; int m_Port;
@ -323,37 +303,30 @@ namespace client
class I2PServerTunnelHTTP: public I2PServerTunnel class I2PServerTunnelHTTP: public I2PServerTunnel
{ {
public: public:
I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port, I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port,
std::shared_ptr<ClientDestination> localDestination, const std::string& host, std::shared_ptr<ClientDestination> localDestination, const std::string& host,
int inport = 0, bool gzip = true); int inport = 0, bool gzip = true);
private: private:
std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream); std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
private: private:
std::string m_Host; std::string m_Host;
}; };
class I2PServerTunnelIRC: public I2PServerTunnel class I2PServerTunnelIRC: public I2PServerTunnel
{ {
public: public:
I2PServerTunnelIRC (const std::string& name, const std::string& address, int port,
std::shared_ptr<ClientDestination> localDestination, const std::string& webircpass,
int inport = 0, bool gzip = true);
I2PServerTunnelIRC (const std::string& name, const std::string& address, int port, private:
std::shared_ptr<ClientDestination> localDestination, const std::string& webircpass, std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
int inport = 0, bool gzip = true);
private:
std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
private:
std::string m_WebircPass;
};
private:
std::string m_WebircPass;
};
} }
} }

View file

@ -692,8 +692,9 @@ namespace client
} }
else else
{ {
boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, bytes_transferred), if (m_SocketType != eSAMSocketTypeTerminated) // check for possible race condition with Terminate()
std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, bytes_transferred),
std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1));
} }
} }

View file

@ -3,14 +3,15 @@
#include "SignatureTypeComboboxFactory.h" #include "SignatureTypeComboboxFactory.h"
#include "QVBoxLayout" #include "QVBoxLayout"
ClientTunnelPane::ClientTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ClientTunnelConfig* tunconf): ClientTunnelPane::ClientTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ClientTunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow):
TunnelPane(tunnelsPageUpdateListener, tunconf) {} TunnelPane(tunnelsPageUpdateListener, tunconf, wrongInputPane_, wrongInputLabel_, mainWindow) {}
void ClientTunnelPane::setGroupBoxTitle(const QString & title) { void ClientTunnelPane::setGroupBoxTitle(const QString & title) {
clientTunnelNameGroupBox->setTitle(title); clientTunnelNameGroupBox->setTitle(title);
} }
void ClientTunnelPane::deleteClientTunnelForm() { void ClientTunnelPane::deleteClientTunnelForm() {
TunnelPane::deleteTunnelForm();
delete clientTunnelNameGroupBox; delete clientTunnelNameGroupBox;
clientTunnelNameGroupBox=nullptr; clientTunnelNameGroupBox=nullptr;
@ -179,6 +180,9 @@ int ClientTunnelPane::appendClientTunnelForm(
QObject::connect(sigTypeComboBox, SIGNAL(currentIndexChanged(int)), QObject::connect(sigTypeComboBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(updated())); this, SLOT(updated()));
horizontalLayout_2->addWidget(sigTypeComboBox); horizontalLayout_2->addWidget(sigTypeComboBox);
QPushButton * lockButton2 = new QPushButton(gridLayoutWidget_2);
horizontalLayout_2->addWidget(lockButton2);
widgetlocks.add(new widgetlock(sigTypeComboBox, lockButton2));
QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_2->addItem(horizontalSpacer); horizontalLayout_2->addItem(horizontalSpacer);
tunnelGridLayout->addLayout(horizontalLayout_2); tunnelGridLayout->addLayout(horizontalLayout_2);

View file

@ -14,7 +14,7 @@ class TunnelPane;
class ClientTunnelPane : public TunnelPane { class ClientTunnelPane : public TunnelPane {
Q_OBJECT Q_OBJECT
public: public:
ClientTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ClientTunnelConfig* tunconf); ClientTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ClientTunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow);
virtual ~ClientTunnelPane(){} virtual ~ClientTunnelPane(){}
virtual ServerTunnelPane* asServerTunnelPane(); virtual ServerTunnelPane* asServerTunnelPane();
virtual ClientTunnelPane* asClientTunnelPane(); virtual ClientTunnelPane* asClientTunnelPane();
@ -68,6 +68,7 @@ private:
} }
protected: protected:
virtual bool applyDataFromUIToTunnelConfig() { virtual bool applyDataFromUIToTunnelConfig() {
QString cannotSaveSettings = QApplication::tr("Cannot save settings.");
bool ok=TunnelPane::applyDataFromUIToTunnelConfig(); bool ok=TunnelPane::applyDataFromUIToTunnelConfig();
if(!ok)return false; if(!ok)return false;
ClientTunnelConfig* ctc=tunnelConfig->asClientTunnelConfig(); ClientTunnelConfig* ctc=tunnelConfig->asClientTunnelConfig();
@ -78,16 +79,23 @@ protected:
auto portStr=portLineEdit->text(); auto portStr=portLineEdit->text();
int portInt=portStr.toInt(&ok); int portInt=portStr.toInt(&ok);
if(!ok)return false;
if(!ok){
highlightWrongInput(QApplication::tr("Bad port, must be int.")+" "+cannotSaveSettings,portLineEdit);
return false;
}
ctc->setport(portInt); ctc->setport(portInt);
ctc->setkeys(keysLineEdit->text().toStdString()); ctc->setkeys(keysLineEdit->text().toStdString());
ctc->setaddress(addressLineEdit->text().toStdString()); ctc->setaddress(addressLineEdit->text().toStdString());
auto dportStr=portLineEdit->text(); auto dportStr=destinationPortLineEdit->text();
int dportInt=dportStr.toInt(&ok); int dportInt=dportStr.toInt(&ok);
if(!ok)return false; if(!ok){
highlightWrongInput(QApplication::tr("Bad destinationPort, must be int.")+" "+cannotSaveSettings,destinationPortLineEdit);
return false;
}
ctc->setdestinationPort(dportInt); ctc->setdestinationPort(dportInt);
ctc->setsigType(readSigTypeComboboxUI(sigTypeComboBox)); ctc->setsigType(readSigTypeComboboxUI(sigTypeComboBox));

View file

@ -2,8 +2,8 @@
#include "ClientContext.h" #include "ClientContext.h"
#include "SignatureTypeComboboxFactory.h" #include "SignatureTypeComboboxFactory.h"
ServerTunnelPane::ServerTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ServerTunnelConfig* tunconf): ServerTunnelPane::ServerTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ServerTunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow):
TunnelPane(tunnelsPageUpdateListener, tunconf) {} TunnelPane(tunnelsPageUpdateListener, tunconf, wrongInputPane_, wrongInputLabel_, mainWindow) {}
void ServerTunnelPane::setGroupBoxTitle(const QString & title) { void ServerTunnelPane::setGroupBoxTitle(const QString & title) {
serverTunnelNameGroupBox->setTitle(title); serverTunnelNameGroupBox->setTitle(title);
@ -197,6 +197,9 @@ int ServerTunnelPane::appendServerTunnelForm(
QObject::connect(sigTypeComboBox, SIGNAL(currentIndexChanged(int)), QObject::connect(sigTypeComboBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(updated())); this, SLOT(updated()));
horizontalLayout_2->addWidget(sigTypeComboBox); horizontalLayout_2->addWidget(sigTypeComboBox);
QPushButton * lockButton2 = new QPushButton(gridLayoutWidget_2);
horizontalLayout_2->addWidget(lockButton2);
widgetlocks.add(new widgetlock(sigTypeComboBox, lockButton2));
QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_2->addItem(horizontalSpacer); horizontalLayout_2->addItem(horizontalSpacer);
tunnelGridLayout->addLayout(horizontalLayout_2); tunnelGridLayout->addLayout(horizontalLayout_2);
@ -263,6 +266,7 @@ int ServerTunnelPane::appendServerTunnelForm(
} }
void ServerTunnelPane::deleteServerTunnelForm() { void ServerTunnelPane::deleteServerTunnelForm() {
TunnelPane::deleteTunnelForm();
delete serverTunnelNameGroupBox;//->deleteLater(); delete serverTunnelNameGroupBox;//->deleteLater();
serverTunnelNameGroupBox=nullptr; serverTunnelNameGroupBox=nullptr;

View file

@ -1,9 +1,6 @@
#ifndef SERVERTUNNELPANE_H #ifndef SERVERTUNNELPANE_H
#define SERVERTUNNELPANE_H #define SERVERTUNNELPANE_H
#include "TunnelPane.h"
#include "TunnelsPageUpdateListener.h"
#include <QtCore/QVariant> #include <QtCore/QVariant>
#include <QtWidgets/QAction> #include <QtWidgets/QAction>
#include <QtWidgets/QApplication> #include <QtWidgets/QApplication>
@ -23,6 +20,9 @@
#include "assert.h" #include "assert.h"
#include "TunnelPane.h"
#include "TunnelsPageUpdateListener.h"
class ServerTunnelConfig; class ServerTunnelConfig;
class ClientTunnelPane; class ClientTunnelPane;
@ -31,7 +31,7 @@ class ServerTunnelPane : public TunnelPane {
Q_OBJECT Q_OBJECT
public: public:
ServerTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ServerTunnelConfig* tunconf); ServerTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ServerTunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow);
virtual ~ServerTunnelPane(){} virtual ~ServerTunnelPane(){}
virtual ServerTunnelPane* asServerTunnelPane(); virtual ServerTunnelPane* asServerTunnelPane();
@ -119,6 +119,7 @@ private:
protected: protected:
virtual bool applyDataFromUIToTunnelConfig() { virtual bool applyDataFromUIToTunnelConfig() {
QString cannotSaveSettings = QApplication::tr("Cannot save settings.");
bool ok=TunnelPane::applyDataFromUIToTunnelConfig(); bool ok=TunnelPane::applyDataFromUIToTunnelConfig();
if(!ok)return false; if(!ok)return false;
ServerTunnelConfig* stc=tunnelConfig->asServerTunnelConfig(); ServerTunnelConfig* stc=tunnelConfig->asServerTunnelConfig();
@ -127,14 +128,20 @@ protected:
auto portStr=portLineEdit->text(); auto portStr=portLineEdit->text();
int portInt=portStr.toInt(&ok); int portInt=portStr.toInt(&ok);
if(!ok)return false; if(!ok){
highlightWrongInput(QApplication::tr("Bad port, must be int.")+" "+cannotSaveSettings,portLineEdit);
return false;
}
stc->setport(portInt); stc->setport(portInt);
stc->setkeys(keysLineEdit->text().toStdString()); stc->setkeys(keysLineEdit->text().toStdString());
auto str=inPortLineEdit->text(); auto str=inPortLineEdit->text();
int inPortInt=str.toInt(&ok); int inPortInt=str.toInt(&ok);
if(!ok)return false; if(!ok){
highlightWrongInput(QApplication::tr("Bad inPort, must be int.")+" "+cannotSaveSettings,inPortLineEdit);
return false;
}
stc->setinPort(inPortInt); stc->setinPort(inPortInt);
stc->setaccessList(accessListLineEdit->text().toStdString()); stc->setaccessList(accessListLineEdit->text().toStdString());
@ -147,7 +154,10 @@ protected:
auto mcStr=maxConnsLineEdit->text(); auto mcStr=maxConnsLineEdit->text();
uint32_t mcInt=(uint32_t)mcStr.toInt(&ok); uint32_t mcInt=(uint32_t)mcStr.toInt(&ok);
if(!ok)return false; if(!ok){
highlightWrongInput(QApplication::tr("Bad maxConns, must be int.")+" "+cannotSaveSettings,maxConnsLineEdit);
return false;
}
stc->setmaxConns(mcInt); stc->setmaxConns(mcInt);
stc->setgzip(gzipCheckBox->isChecked()); stc->setgzip(gzipCheckBox->isChecked());

View file

@ -6,12 +6,25 @@ void TunnelConfig::saveHeaderToStringStream(std::stringstream& out) {
} }
void TunnelConfig::saveI2CPParametersToStringStream(std::stringstream& out) { void TunnelConfig::saveI2CPParametersToStringStream(std::stringstream& out) {
out << "inbound.length=" << i2cpParameters.getInbound_length().toStdString() << "\n" if (i2cpParameters.getInbound_length().toUShort() != i2p::client::DEFAULT_INBOUND_TUNNEL_LENGTH)
<< "outbound.length=" << i2cpParameters.getOutbound_length().toStdString() << "\n" out << i2p::client::I2CP_PARAM_INBOUND_TUNNEL_LENGTH << "="
<< "inbound.quantity=" << i2cpParameters.getInbound_quantity().toStdString() << "\n" << i2cpParameters.getInbound_length().toStdString() << "\n";
<< "outbound.quantity=" << i2cpParameters.getOutbound_quantity().toStdString() << "\n" if (i2cpParameters.getOutbound_length().toUShort() != i2p::client::DEFAULT_OUTBOUND_TUNNEL_LENGTH)
<< "crypto.tagsToSend=" << i2cpParameters.getCrypto_tagsToSend().toStdString() << "\n" out << i2p::client::I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH << "="
<< "explicitPeers=" << i2cpParameters.getExplicitPeers().toStdString() << "\n\n"; << i2cpParameters.getOutbound_length().toStdString() << "\n";
if (i2cpParameters.getInbound_quantity().toUShort() != i2p::client::DEFAULT_INBOUND_TUNNELS_QUANTITY)
out << i2p::client::I2CP_PARAM_INBOUND_TUNNELS_QUANTITY << "="
<< i2cpParameters.getInbound_quantity().toStdString() << "\n";
if (i2cpParameters.getOutbound_quantity().toUShort() != i2p::client::DEFAULT_OUTBOUND_TUNNELS_QUANTITY)
out << i2p::client::I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY << "="
<< i2cpParameters.getOutbound_quantity().toStdString() << "\n";
if (i2cpParameters.getCrypto_tagsToSend().toUShort() != i2p::client::DEFAULT_TAGS_TO_SEND)
out << i2p::client::I2CP_PARAM_TAGS_TO_SEND << "="
<< i2cpParameters.getCrypto_tagsToSend().toStdString() << "\n";
if (!i2cpParameters.getExplicitPeers().isEmpty()) //todo #947
out << i2p::client::I2CP_PARAM_EXPLICIT_PEERS << "="
<< i2cpParameters.getExplicitPeers().toStdString() << "\n";
out << "\n";
} }
void ClientTunnelConfig::saveToStringStream(std::stringstream& out) { void ClientTunnelConfig::saveToStringStream(std::stringstream& out) {

View file

@ -5,6 +5,7 @@
#include <string> #include <string>
#include "../../libi2pd_client/ClientContext.h" #include "../../libi2pd_client/ClientContext.h"
#include "../../libi2pd/Destination.h"
#include "TunnelsPageUpdateListener.h" #include "TunnelsPageUpdateListener.h"

View file

@ -1,8 +1,14 @@
#include "TunnelPane.h" #include "TunnelPane.h"
#include "QMessageBox"
TunnelPane::TunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener_, TunnelConfig* tunnelConfig_): #include "QMessageBox"
#include "mainwindow.h"
#include "ui_mainwindow.h"
TunnelPane::TunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener_, TunnelConfig* tunnelConfig_, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow_):
QObject(), QObject(),
mainWindow(mainWindow_),
wrongInputPane(wrongInputPane_),
wrongInputLabel(wrongInputLabel_),
tunnelConfig(tunnelConfig_), tunnelConfig(tunnelConfig_),
tunnelsPageUpdateListener(tunnelsPageUpdateListener_), tunnelsPageUpdateListener(tunnelsPageUpdateListener_),
gridLayoutWidget_2(nullptr) {} gridLayoutWidget_2(nullptr) {}
@ -65,6 +71,9 @@ void TunnelPane::setupTunnelPane(
typeLabel->setObjectName(QStringLiteral("typeLabel")); typeLabel->setObjectName(QStringLiteral("typeLabel"));
horizontalLayout_->addWidget(typeLabel); horizontalLayout_->addWidget(typeLabel);
horizontalLayout_->addWidget(tunnelTypeComboBox); horizontalLayout_->addWidget(tunnelTypeComboBox);
QPushButton * lockButton1 = new QPushButton(gridLayoutWidget_2);
horizontalLayout_->addWidget(lockButton1);
widgetlocks.add(new widgetlock(tunnelTypeComboBox, lockButton1));
this->tunnelTypeComboBox=tunnelTypeComboBox; this->tunnelTypeComboBox=tunnelTypeComboBox;
QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_->addItem(horizontalSpacer); horizontalLayout_->addItem(horizontalSpacer);
@ -176,7 +185,9 @@ void TunnelPane::appendControlsForI2CPParameters(I2CPParameters& i2cpParameters,
void TunnelPane::updated() { void TunnelPane::updated() {
std::string oldName=tunnelConfig->getName(); std::string oldName=tunnelConfig->getName();
if(!applyDataFromUIToTunnelConfig())return;//TODO visualise bad input //validate and show red if invalid
hideWrongInputLabel();
if(!mainWindow->applyTunnelsUiToConfigs())return;
tunnelsPageUpdateListener->updated(oldName, tunnelConfig); tunnelsPageUpdateListener->updated(oldName, tunnelConfig);
} }
@ -189,6 +200,7 @@ void TunnelPane::deleteButtonReleased() {
switch (ret) { switch (ret) {
case QMessageBox::Ok: case QMessageBox::Ok:
// OK was clicked // OK was clicked
hideWrongInputLabel();
tunnelsPageUpdateListener->needsDeleting(tunnelConfig->getName()); tunnelsPageUpdateListener->needsDeleting(tunnelConfig->getName());
break; break;
case QMessageBox::Cancel: case QMessageBox::Cancel:
@ -215,3 +227,23 @@ QString TunnelPane::readTunnelTypeComboboxData() {
i2p::data::SigningKeyType TunnelPane::readSigTypeComboboxUI(QComboBox* sigTypeComboBox) { i2p::data::SigningKeyType TunnelPane::readSigTypeComboboxUI(QComboBox* sigTypeComboBox) {
return (i2p::data::SigningKeyType) sigTypeComboBox->currentData().toInt(); return (i2p::data::SigningKeyType) sigTypeComboBox->currentData().toInt();
} }
void TunnelPane::deleteTunnelForm() {
widgetlocks.deleteListeners();
}
void TunnelPane::highlightWrongInput(QString warningText, QWidget* controlWithWrongInput) {
wrongInputPane->setVisible(true);
wrongInputLabel->setText(warningText);
mainWindow->adjustSizesAccordingToWrongLabel();
if(controlWithWrongInput){
mainWindow->ui->tunnelsScrollArea->ensureWidgetVisible(controlWithWrongInput);
controlWithWrongInput->setFocus();
}
mainWindow->showTunnelsPage();
}
void TunnelPane::hideWrongInputLabel() const {
wrongInputPane->setVisible(false);
mainWindow->adjustSizesAccordingToWrongLabel();
}

View file

@ -14,25 +14,39 @@
#include "TunnelConfig.h" #include "TunnelConfig.h"
#include <widgetlock.h>
#include <widgetlockregistry.h>
class ServerTunnelPane; class ServerTunnelPane;
class ClientTunnelPane; class ClientTunnelPane;
class TunnelConfig; class TunnelConfig;
class I2CPParameters; class I2CPParameters;
class MainWindow;
class TunnelPane : public QObject { class TunnelPane : public QObject {
Q_OBJECT Q_OBJECT
public: public:
TunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener_, TunnelConfig* tunconf); TunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener_, TunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow_);
virtual ~TunnelPane(){} virtual ~TunnelPane(){}
void deleteTunnelForm();
void hideWrongInputLabel() const;
void highlightWrongInput(QString warningText, QWidget* controlWithWrongInput);
virtual ServerTunnelPane* asServerTunnelPane()=0; virtual ServerTunnelPane* asServerTunnelPane()=0;
virtual ClientTunnelPane* asClientTunnelPane()=0; virtual ClientTunnelPane* asClientTunnelPane()=0;
protected: protected:
MainWindow* mainWindow;
QWidget * wrongInputPane;
QLabel* wrongInputLabel;
TunnelConfig* tunnelConfig; TunnelConfig* tunnelConfig;
widgetlockregistry widgetlocks;
TunnelsPageUpdateListener* tunnelsPageUpdateListener; TunnelsPageUpdateListener* tunnelsPageUpdateListener;
QVBoxLayout *tunnelGridLayout; QVBoxLayout *tunnelGridLayout;
QGroupBox *tunnelGroupBox; QGroupBox *tunnelGroupBox;
@ -78,6 +92,7 @@ protected:
//should be created by factory //should be created by factory
i2p::data::SigningKeyType readSigTypeComboboxUI(QComboBox* sigTypeComboBox); i2p::data::SigningKeyType readSigTypeComboboxUI(QComboBox* sigTypeComboBox);
public:
//returns false when invalid data at UI //returns false when invalid data at UI
virtual bool applyDataFromUIToTunnelConfig() { virtual bool applyDataFromUIToTunnelConfig() {
tunnelConfig->setName(nameLineEdit->text().toStdString()); tunnelConfig->setName(nameLineEdit->text().toStdString());
@ -90,7 +105,7 @@ protected:
i2cpParams.setCrypto_tagsToSend(crypto_tagsToSendLineEdit->text()); i2cpParams.setCrypto_tagsToSend(crypto_tagsToSendLineEdit->text());
return true; return true;
} }
protected:
void setupTunnelPane( void setupTunnelPane(
TunnelConfig* tunnelConfig, TunnelConfig* tunnelConfig,
QGroupBox *tunnelGroupBox, QGroupBox *tunnelGroupBox,

File diff suppressed because it is too large Load diff

View file

@ -87,7 +87,11 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \
../../daemon/i2pd.cpp \ ../../daemon/i2pd.cpp \
../../daemon/I2PControl.cpp \ ../../daemon/I2PControl.cpp \
../../daemon/UnixDaemon.cpp \ ../../daemon/UnixDaemon.cpp \
../../daemon/UPnP.cpp ../../daemon/UPnP.cpp \
textbrowsertweaked1.cpp \
pagewithbackbutton.cpp \
widgetlock.cpp \
widgetlockregistry.cpp
#qt creator does not handle this well #qt creator does not handle this well
#SOURCES += $$files(../../libi2pd/*.cpp) #SOURCES += $$files(../../libi2pd/*.cpp)
@ -166,7 +170,11 @@ HEADERS += DaemonQT.h mainwindow.h \
../../daemon/Daemon.h \ ../../daemon/Daemon.h \
../../daemon/HTTPServer.h \ ../../daemon/HTTPServer.h \
../../daemon/I2PControl.h \ ../../daemon/I2PControl.h \
../../daemon/UPnP.h ../../daemon/UPnP.h \
textbrowsertweaked1.h \
pagewithbackbutton.h \
widgetlock.h \
widgetlockregistry.h
INCLUDEPATH += ../../libi2pd INCLUDEPATH += ../../libi2pd
INCLUDEPATH += ../../libi2pd_client INCLUDEPATH += ../../libi2pd_client
@ -174,10 +182,31 @@ INCLUDEPATH += ../../daemon
INCLUDEPATH += . INCLUDEPATH += .
FORMS += mainwindow.ui \ FORMS += mainwindow.ui \
tunnelform.ui tunnelform.ui \
statusbuttons.ui \
routercommandswidget.ui \
generalsettingswidget.ui
LIBS += -lz LIBS += -lz
macx {
message("using mac os x target")
BREWROOT=/usr/local
BOOSTROOT=$$BREWROOT/opt/boost
SSLROOT=$$BREWROOT/opt/libressl
UPNPROOT=$$BREWROOT/opt/miniupnpc
INCLUDEPATH += $$BOOSTROOT/include
INCLUDEPATH += $$SSLROOT/include
INCLUDEPATH += $$UPNPROOT/include
LIBS += $$SSLROOT/lib/libcrypto.a
LIBS += $$SSLROOT/lib/libssl.a
LIBS += $$BOOSTROOT/lib/libboost_system.a
LIBS += $$BOOSTROOT/lib/libboost_date_time.a
LIBS += $$BOOSTROOT/lib/libboost_filesystem.a
LIBS += $$BOOSTROOT/lib/libboost_program_options.a
LIBS += $$UPNPROOT/lib/libminiupnpc.a
}
android { android {
message("Using Android settings") message("Using Android settings")
DEFINES += ANDROID=1 DEFINES += ANDROID=1

View file

@ -1,5 +1,12 @@
#include <fstream>
#include <assert.h>
#include "mainwindow.h" #include "mainwindow.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "ui_statusbuttons.h"
#include "ui_routercommandswidget.h"
#include "ui_generalsettingswidget.h"
#include <sstream>
#include <QScrollBar>
#include <QMessageBox> #include <QMessageBox>
#include <QTimer> #include <QTimer>
#include <QFile> #include <QFile>
@ -8,15 +15,15 @@
#include "Config.h" #include "Config.h"
#include "FS.h" #include "FS.h"
#include "Log.h" #include "Log.h"
#include "RouterContext.h"
#include "Transports.h"
#include "HTTPServer.h"
#ifndef ANDROID #ifndef ANDROID
# include <QtDebug> # include <QtDebug>
#endif #endif
#include <QScrollBar>
#include <fstream>
#include "DaemonQT.h" #include "DaemonQT.h"
#include "SignatureTypeComboboxFactory.h" #include "SignatureTypeComboboxFactory.h"
@ -27,7 +34,14 @@ MainWindow::MainWindow(QWidget *parent) :
#ifndef ANDROID #ifndef ANDROID
,quitting(false) ,quitting(false)
#endif #endif
,wasSelectingAtStatusMainPage(false)
,showHiddenInfoStatusMainPage(false)
,ui(new Ui::MainWindow) ,ui(new Ui::MainWindow)
,statusButtonsUI(new Ui::StatusButtonsForm)
,routerCommandsUI(new Ui::routerCommandsWidget)
,uiSettings(new Ui::GeneralSettingsContentsForm)
,routerCommandsParent(new QWidget(this))
,widgetlocks()
,i2pController(nullptr) ,i2pController(nullptr)
,configItems() ,configItems()
,datadir() ,datadir()
@ -37,21 +51,31 @@ MainWindow::MainWindow(QWidget *parent) :
{ {
ui->setupUi(this); ui->setupUi(this);
statusButtonsUI->setupUi(ui->statusButtonsPane);
routerCommandsUI->setupUi(routerCommandsParent);
uiSettings->setupUi(ui->settingsContents);
routerCommandsParent->hide();
ui->verticalLayout_2->addWidget(routerCommandsParent);
//,statusHtmlUI(new Ui::StatusHtmlPaneForm)
//statusHtmlUI->setupUi(lastStatusWidgetui->statusWidget);
ui->statusButtonsPane->setFixedSize(171,300);
ui->verticalLayout->setGeometry(QRect(0,0,171,ui->verticalLayout->geometry().height()));
//ui->statusButtonsPane->adjustSize();
//ui->centralWidget->adjustSize();
setWindowTitle(QApplication::translate("AppTitle","I2PD")); setWindowTitle(QApplication::translate("AppTitle","I2PD"));
//TODO handle resizes and change the below into resize() call //TODO handle resizes and change the below into resize() call
setFixedSize(width(), 480); setFixedHeight(550);
ui->centralWidget->setMinimumHeight(480); ui->centralWidget->setFixedHeight(550);
ui->centralWidget->setMaximumHeight(480);
onResize(); onResize();
ui->stackedWidget->setCurrentIndex(0); ui->stackedWidget->setCurrentIndex(0);
ui->settingsScrollArea->resize(ui->settingsContentsGridLayout->sizeHint().width()+10,380); ui->settingsScrollArea->resize(uiSettings->settingsContentsGridLayout->sizeHint().width()+10,380);
QScrollBar* const barSett = ui->settingsScrollArea->verticalScrollBar(); QScrollBar* const barSett = ui->settingsScrollArea->verticalScrollBar();
//QSize szSettContents = ui->settingsContentsGridLayout->minimumSize();
int w = 683; int w = 683;
int h = 3060; int h = 3060;
ui->settingsContents->setFixedSize(w, h); ui->settingsContents->setFixedSize(w, h);
ui->settingsContents->setGeometry(QRect(0,0,w,h));
/* /*
QPalette pal(palette()); QPalette pal(palette());
@ -59,17 +83,55 @@ MainWindow::MainWindow(QWidget *parent) :
ui->settingsContents->setAutoFillBackground(true); ui->settingsContents->setAutoFillBackground(true);
ui->settingsContents->setPalette(pal); ui->settingsContents->setPalette(pal);
*/ */
QPalette pal(palette());
pal.setColor(QPalette::Background, Qt::red);
ui->wrongInputLabel->setAutoFillBackground(true);
ui->wrongInputLabel->setPalette(pal);
ui->wrongInputLabel->setMaximumHeight(ui->wrongInputLabel->sizeHint().height());
ui->wrongInputLabel->setVisible(false);
//ui->settingsScrollArea->adjustSize(); settingsTitleLabelNominalHeight = ui->settingsTitleLabel->height();
/*ui->tunnelsScrollAreaWidgetContents->setFixedSize(
ui->tunnelsScrollArea->width() - barSett->width(), 0);*/
#ifndef ANDROID #ifndef ANDROID
createActions(); createActions();
createTrayIcon(); createTrayIcon();
#endif #endif
QObject::connect(ui->statusPagePushButton, SIGNAL(released()), this, SLOT(showStatusPage())); textBrowser = new TextBrowserTweaked1(this);
//textBrowser->setOpenExternalLinks(false);
textBrowser->setOpenLinks(false);
/*textBrowser->setTextInteractionFlags(textBrowser->textInteractionFlags()|
Qt::LinksAccessibleByMouse|Qt::LinksAccessibleByKeyboard|
Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard);*/
ui->verticalLayout_2->addWidget(textBrowser);
childTextBrowser = new TextBrowserTweaked1(this);
//childTextBrowser->setOpenExternalLinks(false);
childTextBrowser->setOpenLinks(false);
connect(textBrowser, SIGNAL(anchorClicked(const QUrl&)), this, SLOT(anchorClickedHandler(const QUrl&)));
pageWithBackButton = new PageWithBackButton(this, childTextBrowser);
ui->verticalLayout_2->addWidget(pageWithBackButton);
pageWithBackButton->hide();
connect(pageWithBackButton, SIGNAL(backReleased()), this, SLOT(backClickedFromChild()));
scheduleStatusPageUpdates();
QObject::connect(ui->statusPagePushButton, SIGNAL(released()), this, SLOT(showStatusMainPage()));
showStatusMainPage();
QObject::connect(statusButtonsUI->mainPagePushButton, SIGNAL(released()), this, SLOT(showStatusMainPage()));
QObject::connect(statusButtonsUI->routerCommandsPushButton, SIGNAL(released()), this, SLOT(showStatus_commands_Page()));
QObject::connect(statusButtonsUI->localDestinationsPushButton, SIGNAL(released()), this, SLOT(showStatus_local_destinations_Page()));
QObject::connect(statusButtonsUI->leasesetsPushButton, SIGNAL(released()), this, SLOT(showStatus_leasesets_Page()));
QObject::connect(statusButtonsUI->tunnelsPushButton, SIGNAL(released()), this, SLOT(showStatus_tunnels_Page()));
QObject::connect(statusButtonsUI->transitTunnelsPushButton, SIGNAL(released()), this, SLOT(showStatus_transit_tunnels_Page()));
QObject::connect(statusButtonsUI->transportsPushButton, SIGNAL(released()), this, SLOT(showStatus_transports_Page()));
QObject::connect(statusButtonsUI->i2pTunnelsPushButton, SIGNAL(released()), this, SLOT(showStatus_i2p_tunnels_Page()));
QObject::connect(statusButtonsUI->samSessionsPushButton, SIGNAL(released()), this, SLOT(showStatus_sam_sessions_Page()));
QObject::connect(textBrowser, SIGNAL(mouseReleased()), this, SLOT(statusHtmlPageMouseReleased()));
QObject::connect(textBrowser, SIGNAL(selectionChanged()), this, SLOT(statusHtmlPageSelectionChanged()));
QObject::connect(routerCommandsUI->runPeerTestPushButton, SIGNAL(released()), this, SLOT(runPeerTest()));
QObject::connect(routerCommandsUI->acceptTransitTunnelsPushButton, SIGNAL(released()), this, SLOT(enableTransit()));
QObject::connect(routerCommandsUI->declineTransitTunnelsPushButton, SIGNAL(released()), this, SLOT(disableTransit()));
QObject::connect(ui->settingsPagePushButton, SIGNAL(released()), this, SLOT(showSettingsPage())); QObject::connect(ui->settingsPagePushButton, SIGNAL(released()), this, SLOT(showSettingsPage()));
QObject::connect(ui->tunnelsPagePushButton, SIGNAL(released()), this, SLOT(showTunnelsPage())); QObject::connect(ui->tunnelsPagePushButton, SIGNAL(released()), this, SLOT(showTunnelsPage()));
@ -83,132 +145,145 @@ MainWindow::MainWindow(QWidget *parent) :
# define OPTION(section,option,defaultValueGetter) ConfigOption(QString(section),QString(option)) # define OPTION(section,option,defaultValueGetter) ConfigOption(QString(section),QString(option))
initFileChooser( OPTION("","conf",[](){return "";}), ui->configFileLineEdit, ui->configFileBrowsePushButton); initFileChooser( OPTION("","conf",[](){return "";}), uiSettings->configFileLineEdit, uiSettings->configFileBrowsePushButton);
initFolderChooser( OPTION("","datadir",[]{return "";}), ui->dataFolderLineEdit, ui->dataFolderBrowsePushButton); initFolderChooser( OPTION("","datadir",[]{return "";}), uiSettings->dataFolderLineEdit, uiSettings->dataFolderBrowsePushButton);
initFileChooser( OPTION("","tunconf",[](){return "";}), ui->tunnelsConfigFileLineEdit, ui->tunnelsConfigFileBrowsePushButton); initFileChooser( OPTION("","tunconf",[](){return "";}), uiSettings->tunnelsConfigFileLineEdit, uiSettings->tunnelsConfigFileBrowsePushButton);
initFileChooser( OPTION("","pidfile",[]{return "";}), ui->pidFileLineEdit, ui->pidFileBrowsePushButton); initFileChooser( OPTION("","pidfile",[]{return "";}), uiSettings->pidFileLineEdit, uiSettings->pidFileBrowsePushButton);
logOption=initNonGUIOption( OPTION("","log",[]{return "";}));
daemonOption=initNonGUIOption( OPTION("","daemon",[]{return "";})); daemonOption=initNonGUIOption( OPTION("","daemon",[]{return "";}));
serviceOption=initNonGUIOption( OPTION("","service",[]{return "";})); serviceOption=initNonGUIOption( OPTION("","service",[]{return "";}));
logFileNameOption=initFileChooser( OPTION("","logfile",[]{return "";}), ui->logFileLineEdit, ui->logFileBrowsePushButton); uiSettings->logDestinationComboBox->clear();
initLogLevelCombobox(OPTION("","loglevel",[]{return "";}), ui->logLevelComboBox); uiSettings->logDestinationComboBox->insertItems(0, QStringList()
<< QApplication::translate("MainWindow", "stdout", 0)
<< QApplication::translate("MainWindow", "file", 0)
);
initLogDestinationCombobox( OPTION("","log",[]{return "";}), uiSettings->logDestinationComboBox);
initIPAddressBox( OPTION("","host",[]{return "";}), ui->routerExternalHostLineEdit, tr("Router external address -> Host")); logFileNameOption=initFileChooser( OPTION("","logfile",[]{return "";}), uiSettings->logFileLineEdit, uiSettings->logFileBrowsePushButton);
initTCPPortBox( OPTION("","port",[]{return "";}), ui->routerExternalPortLineEdit, tr("Router external address -> Port")); initLogLevelCombobox(OPTION("","loglevel",[]{return "";}), uiSettings->logLevelComboBox);
initCheckBox( OPTION("","ipv6",[]{return "false";}), ui->ipv6CheckBox); initIPAddressBox( OPTION("","host",[]{return "";}), uiSettings->routerExternalHostLineEdit, tr("Router external address -> Host"));
initCheckBox( OPTION("","notransit",[]{return "false";}), ui->notransitCheckBox); initTCPPortBox( OPTION("","port",[]{return "";}), uiSettings->routerExternalPortLineEdit, tr("Router external address -> Port"));
initCheckBox( OPTION("","floodfill",[]{return "false";}), ui->floodfillCheckBox);
initStringBox( OPTION("","bandwidth",[]{return "";}), ui->bandwidthLineEdit); initCheckBox( OPTION("","ipv6",[]{return "false";}), uiSettings->ipv6CheckBox);
initStringBox( OPTION("","family",[]{return "";}), ui->familyLineEdit); initCheckBox( OPTION("","notransit",[]{return "false";}), uiSettings->notransitCheckBox);
initIntegerBox( OPTION("","netid",[]{return "2";}), ui->netIdLineEdit, tr("NetID")); initCheckBox( OPTION("","floodfill",[]{return "false";}), uiSettings->floodfillCheckBox);
initStringBox( OPTION("","bandwidth",[]{return "";}), uiSettings->bandwidthLineEdit);
initStringBox( OPTION("","family",[]{return "";}), uiSettings->familyLineEdit);
initIntegerBox( OPTION("","netid",[]{return "2";}), uiSettings->netIdLineEdit, tr("NetID"));
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
initCheckBox( OPTION("","insomnia",[]{return "";}), ui->insomniaCheckBox); initCheckBox( OPTION("","insomnia",[]{return "";}), uiSettings->insomniaCheckBox);
initNonGUIOption( OPTION("","svcctl",[]{return "";})); initNonGUIOption( OPTION("","svcctl",[]{return "";}));
initNonGUIOption( OPTION("","close",[]{return "";})); initNonGUIOption( OPTION("","close",[]{return "";}));
#else #else
ui->insomniaCheckBox->setEnabled(false); uiSettings->insomniaCheckBox->setEnabled(false);
#endif #endif
initCheckBox( OPTION("http","enabled",[]{return "true";}), ui->webconsoleEnabledCheckBox); initCheckBox( OPTION("http","enabled",[]{return "true";}), uiSettings->webconsoleEnabledCheckBox);
initIPAddressBox( OPTION("http","address",[]{return "";}), ui->webconsoleAddrLineEdit, tr("HTTP webconsole -> IP address")); initIPAddressBox( OPTION("http","address",[]{return "";}), uiSettings->webconsoleAddrLineEdit, tr("HTTP webconsole -> IP address"));
initTCPPortBox( OPTION("http","port",[]{return "7070";}), ui->webconsolePortLineEdit, tr("HTTP webconsole -> Port")); initTCPPortBox( OPTION("http","port",[]{return "7070";}), uiSettings->webconsolePortLineEdit, tr("HTTP webconsole -> Port"));
initCheckBox( OPTION("http","auth",[]{return "";}), ui->webconsoleBasicAuthCheckBox); initCheckBox( OPTION("http","auth",[]{return "";}), uiSettings->webconsoleBasicAuthCheckBox);
initStringBox( OPTION("http","user",[]{return "i2pd";}), ui->webconsoleUserNameLineEditBasicAuth); initStringBox( OPTION("http","user",[]{return "i2pd";}), uiSettings->webconsoleUserNameLineEditBasicAuth);
initStringBox( OPTION("http","pass",[]{return "";}), ui->webconsolePasswordLineEditBasicAuth); initStringBox( OPTION("http","pass",[]{return "";}), uiSettings->webconsolePasswordLineEditBasicAuth);
initCheckBox( OPTION("httpproxy","enabled",[]{return "";}), ui->httpProxyEnabledCheckBox); initCheckBox( OPTION("httpproxy","enabled",[]{return "";}), uiSettings->httpProxyEnabledCheckBox);
initIPAddressBox( OPTION("httpproxy","address",[]{return "";}), ui->httpProxyAddressLineEdit, tr("HTTP proxy -> IP address")); initIPAddressBox( OPTION("httpproxy","address",[]{return "";}), uiSettings->httpProxyAddressLineEdit, tr("HTTP proxy -> IP address"));
initTCPPortBox( OPTION("httpproxy","port",[]{return "4444";}), ui->httpProxyPortLineEdit, tr("HTTP proxy -> Port")); initTCPPortBox( OPTION("httpproxy","port",[]{return "4444";}), uiSettings->httpProxyPortLineEdit, tr("HTTP proxy -> Port"));
initFileChooser( OPTION("httpproxy","keys",[]{return "";}), ui->httpProxyKeyFileLineEdit, ui->httpProxyKeyFilePushButton); initFileChooser( OPTION("httpproxy","keys",[]{return "";}), uiSettings->httpProxyKeyFileLineEdit, uiSettings->httpProxyKeyFilePushButton);
initSignatureTypeCombobox(OPTION("httpproxy","signaturetype",[]{return "7";}), ui->comboBox_httpPorxySignatureType); initSignatureTypeCombobox(OPTION("httpproxy","signaturetype",[]{return "7";}), uiSettings->comboBox_httpPorxySignatureType);
initStringBox( OPTION("httpproxy","inbound.length",[]{return "3";}), ui->httpProxyInboundTunnelsLenLineEdit); initStringBox( OPTION("httpproxy","inbound.length",[]{return "3";}), uiSettings->httpProxyInboundTunnelsLenLineEdit);
initStringBox( OPTION("httpproxy","inbound.quantity",[]{return "5";}), ui->httpProxyInboundTunnQuantityLineEdit); initStringBox( OPTION("httpproxy","inbound.quantity",[]{return "5";}), uiSettings->httpProxyInboundTunnQuantityLineEdit);
initStringBox( OPTION("httpproxy","outbound.length",[]{return "3";}), ui->httpProxyOutBoundTunnLenLineEdit); initStringBox( OPTION("httpproxy","outbound.length",[]{return "3";}), uiSettings->httpProxyOutBoundTunnLenLineEdit);
initStringBox( OPTION("httpproxy","outbound.quantity",[]{return "5";}), ui->httpProxyOutboundTunnQuantityLineEdit); initStringBox( OPTION("httpproxy","outbound.quantity",[]{return "5";}), uiSettings->httpProxyOutboundTunnQuantityLineEdit);
initCheckBox( OPTION("socksproxy","enabled",[]{return "";}), ui->socksProxyEnabledCheckBox); initCheckBox( OPTION("socksproxy","enabled",[]{return "";}), uiSettings->socksProxyEnabledCheckBox);
initIPAddressBox( OPTION("socksproxy","address",[]{return "";}), ui->socksProxyAddressLineEdit, tr("Socks proxy -> IP address")); initIPAddressBox( OPTION("socksproxy","address",[]{return "";}), uiSettings->socksProxyAddressLineEdit, tr("Socks proxy -> IP address"));
initTCPPortBox( OPTION("socksproxy","port",[]{return "4447";}), ui->socksProxyPortLineEdit, tr("Socks proxy -> Port")); initTCPPortBox( OPTION("socksproxy","port",[]{return "4447";}), uiSettings->socksProxyPortLineEdit, tr("Socks proxy -> Port"));
initFileChooser( OPTION("socksproxy","keys",[]{return "";}), ui->socksProxyKeyFileLineEdit, ui->socksProxyKeyFilePushButton); initFileChooser( OPTION("socksproxy","keys",[]{return "";}), uiSettings->socksProxyKeyFileLineEdit, uiSettings->socksProxyKeyFilePushButton);
initSignatureTypeCombobox(OPTION("socksproxy","signaturetype",[]{return "7";}), ui->comboBox_socksProxySignatureType); initSignatureTypeCombobox(OPTION("socksproxy","signaturetype",[]{return "7";}), uiSettings->comboBox_socksProxySignatureType);
initStringBox( OPTION("socksproxy","inbound.length",[]{return "";}), ui->socksProxyInboundTunnelsLenLineEdit); initStringBox( OPTION("socksproxy","inbound.length",[]{return "";}), uiSettings->socksProxyInboundTunnelsLenLineEdit);
initStringBox( OPTION("socksproxy","inbound.quantity",[]{return "";}), ui->socksProxyInboundTunnQuantityLineEdit); initStringBox( OPTION("socksproxy","inbound.quantity",[]{return "";}), uiSettings->socksProxyInboundTunnQuantityLineEdit);
initStringBox( OPTION("socksproxy","outbound.length",[]{return "";}), ui->socksProxyOutBoundTunnLenLineEdit); initStringBox( OPTION("socksproxy","outbound.length",[]{return "";}), uiSettings->socksProxyOutBoundTunnLenLineEdit);
initStringBox( OPTION("socksproxy","outbound.quantity",[]{return "";}), ui->socksProxyOutboundTunnQuantityLineEdit); initStringBox( OPTION("socksproxy","outbound.quantity",[]{return "";}), uiSettings->socksProxyOutboundTunnQuantityLineEdit);
initIPAddressBox( OPTION("socksproxy","outproxy",[]{return "";}), ui->outproxyAddressLineEdit, tr("Socks proxy -> Outproxy address")); initIPAddressBox( OPTION("socksproxy","outproxy",[]{return "";}), uiSettings->outproxyAddressLineEdit, tr("Socks proxy -> Outproxy address"));
initTCPPortBox( OPTION("socksproxy","outproxyport",[]{return "";}), ui->outproxyPortLineEdit, tr("Socks proxy -> Outproxy port")); initTCPPortBox( OPTION("socksproxy","outproxyport",[]{return "";}), uiSettings->outproxyPortLineEdit, tr("Socks proxy -> Outproxy port"));
initCheckBox( OPTION("sam","enabled",[]{return "false";}), ui->samEnabledCheckBox); initCheckBox( OPTION("sam","enabled",[]{return "false";}), uiSettings->samEnabledCheckBox);
initIPAddressBox( OPTION("sam","address",[]{return "";}), ui->samAddressLineEdit, tr("SAM -> IP address")); initIPAddressBox( OPTION("sam","address",[]{return "";}), uiSettings->samAddressLineEdit, tr("SAM -> IP address"));
initTCPPortBox( OPTION("sam","port",[]{return "7656";}), ui->samPortLineEdit, tr("SAM -> Port")); initTCPPortBox( OPTION("sam","port",[]{return "7656";}), uiSettings->samPortLineEdit, tr("SAM -> Port"));
initCheckBox( OPTION("bob","enabled",[]{return "false";}), ui->bobEnabledCheckBox); initCheckBox( OPTION("bob","enabled",[]{return "false";}), uiSettings->bobEnabledCheckBox);
initIPAddressBox( OPTION("bob","address",[]{return "";}), ui->bobAddressLineEdit, tr("BOB -> IP address")); initIPAddressBox( OPTION("bob","address",[]{return "";}), uiSettings->bobAddressLineEdit, tr("BOB -> IP address"));
initTCPPortBox( OPTION("bob","port",[]{return "2827";}), ui->bobPortLineEdit, tr("BOB -> Port")); initTCPPortBox( OPTION("bob","port",[]{return "2827";}), uiSettings->bobPortLineEdit, tr("BOB -> Port"));
initCheckBox( OPTION("i2cp","enabled",[]{return "false";}), ui->i2cpEnabledCheckBox); initCheckBox( OPTION("i2cp","enabled",[]{return "false";}), uiSettings->i2cpEnabledCheckBox);
initIPAddressBox( OPTION("i2cp","address",[]{return "";}), ui->i2cpAddressLineEdit, tr("I2CP -> IP address")); initIPAddressBox( OPTION("i2cp","address",[]{return "";}), uiSettings->i2cpAddressLineEdit, tr("I2CP -> IP address"));
initTCPPortBox( OPTION("i2cp","port",[]{return "7654";}), ui->i2cpPortLineEdit, tr("I2CP -> Port")); initTCPPortBox( OPTION("i2cp","port",[]{return "7654";}), uiSettings->i2cpPortLineEdit, tr("I2CP -> Port"));
initCheckBox( OPTION("i2pcontrol","enabled",[]{return "false";}), ui->i2pControlEnabledCheckBox); initCheckBox( OPTION("i2pcontrol","enabled",[]{return "false";}), uiSettings->i2pControlEnabledCheckBox);
initIPAddressBox( OPTION("i2pcontrol","address",[]{return "";}), ui->i2pControlAddressLineEdit, tr("I2PControl -> IP address")); initIPAddressBox( OPTION("i2pcontrol","address",[]{return "";}), uiSettings->i2pControlAddressLineEdit, tr("I2PControl -> IP address"));
initTCPPortBox( OPTION("i2pcontrol","port",[]{return "7650";}), ui->i2pControlPortLineEdit, tr("I2PControl -> Port")); initTCPPortBox( OPTION("i2pcontrol","port",[]{return "7650";}), uiSettings->i2pControlPortLineEdit, tr("I2PControl -> Port"));
initStringBox( OPTION("i2pcontrol","password",[]{return "";}), ui->i2pControlPasswordLineEdit); initStringBox( OPTION("i2pcontrol","password",[]{return "";}), uiSettings->i2pControlPasswordLineEdit);
initFileChooser( OPTION("i2pcontrol","cert",[]{return "i2pcontrol.crt.pem";}), ui->i2pControlCertFileLineEdit, ui->i2pControlCertFileBrowsePushButton); initFileChooser( OPTION("i2pcontrol","cert",[]{return "i2pcontrol.crt.pem";}), uiSettings->i2pControlCertFileLineEdit, uiSettings->i2pControlCertFileBrowsePushButton);
initFileChooser( OPTION("i2pcontrol","key",[]{return "i2pcontrol.key.pem";}), ui->i2pControlKeyFileLineEdit, ui->i2pControlKeyFileBrowsePushButton); initFileChooser( OPTION("i2pcontrol","key",[]{return "i2pcontrol.key.pem";}), uiSettings->i2pControlKeyFileLineEdit, uiSettings->i2pControlKeyFileBrowsePushButton);
initCheckBox( OPTION("upnp","enabled",[]{return "true";}), ui->enableUPnPCheckBox); initCheckBox( OPTION("upnp","enabled",[]{return "true";}), uiSettings->enableUPnPCheckBox);
initStringBox( OPTION("upnp","name",[]{return "I2Pd";}), ui->upnpNameLineEdit); initStringBox( OPTION("upnp","name",[]{return "I2Pd";}), uiSettings->upnpNameLineEdit);
initCheckBox( OPTION("precomputation","elgamal",[]{return "false";}), ui->useElGamalPrecomputedTablesCheckBox); initCheckBox( OPTION("precomputation","elgamal",[]{return "false";}), uiSettings->useElGamalPrecomputedTablesCheckBox);
initCheckBox( OPTION("reseed","verify",[]{return "";}), ui->reseedVerifyCheckBox); initCheckBox( OPTION("reseed","verify",[]{return "";}), uiSettings->reseedVerifyCheckBox);
initFileChooser( OPTION("reseed","file",[]{return "";}), ui->reseedFileLineEdit, ui->reseedFileBrowsePushButton); initFileChooser( OPTION("reseed","file",[]{return "";}), uiSettings->reseedFileLineEdit, uiSettings->reseedFileBrowsePushButton);
initStringBox( OPTION("reseed","urls",[]{return "";}), ui->reseedURLsLineEdit); initStringBox( OPTION("reseed","urls",[]{return "";}), uiSettings->reseedURLsLineEdit);
initStringBox( OPTION("addressbook","defaulturl",[]{return "";}), ui->addressbookDefaultURLLineEdit); initStringBox( OPTION("addressbook","defaulturl",[]{return "";}), uiSettings->addressbookDefaultURLLineEdit);
initStringBox( OPTION("addressbook","subscriptions",[]{return "";}), ui->addressbookSubscriptionsURLslineEdit); initStringBox( OPTION("addressbook","subscriptions",[]{return "";}), uiSettings->addressbookSubscriptionsURLslineEdit);
initUInt16Box( OPTION("limits","transittunnels",[]{return "2500";}), ui->maxNumOfTransitTunnelsLineEdit, tr("maxNumberOfTransitTunnels")); initUInt16Box( OPTION("limits","transittunnels",[]{return "2500";}), uiSettings->maxNumOfTransitTunnelsLineEdit, tr("maxNumberOfTransitTunnels"));
initUInt16Box( OPTION("limits","openfiles",[]{return "0";}), ui->maxNumOfOpenFilesLineEdit, tr("maxNumberOfOpenFiles")); initUInt16Box( OPTION("limits","openfiles",[]{return "0";}), uiSettings->maxNumOfOpenFilesLineEdit, tr("maxNumberOfOpenFiles"));
initUInt32Box( OPTION("limits","coresize",[]{return "0";}), ui->coreFileMaxSizeNumberLineEdit, tr("coreFileMaxSize")); initUInt32Box( OPTION("limits","coresize",[]{return "0";}), uiSettings->coreFileMaxSizeNumberLineEdit, tr("coreFileMaxSize"));
initCheckBox( OPTION("trust","enabled",[]{return "false";}), ui->checkBoxTrustEnable); initCheckBox( OPTION("trust","enabled",[]{return "false";}), uiSettings->checkBoxTrustEnable);
initStringBox( OPTION("trust","family",[]{return "";}), ui->lineEditTrustFamily); initStringBox( OPTION("trust","family",[]{return "";}), uiSettings->lineEditTrustFamily);
initStringBox( OPTION("trust","routers",[]{return "";}), ui->lineEditTrustRouters); initStringBox( OPTION("trust","routers",[]{return "";}), uiSettings->lineEditTrustRouters);
initCheckBox( OPTION("trust","hidden",[]{return "false";}), ui->checkBoxTrustHidden); initCheckBox( OPTION("trust","hidden",[]{return "false";}), uiSettings->checkBoxTrustHidden);
initCheckBox( OPTION("websockets","enabled",[]{return "false";}), ui->checkBoxWebsocketsEnable); initCheckBox( OPTION("websockets","enabled",[]{return "false";}), uiSettings->checkBoxWebsocketsEnable);
initIPAddressBox( OPTION("websockets","address",[]{return "127.0.0.1";}), ui->lineEdit_webSock_addr, tr("Websocket server -> IP address")); initIPAddressBox( OPTION("websockets","address",[]{return "127.0.0.1";}), uiSettings->lineEdit_webSock_addr, tr("Websocket server -> IP address"));
initTCPPortBox( OPTION("websockets","port",[]{return "7666";}), ui->lineEdit_webSock_port, tr("Websocket server -> Port")); initTCPPortBox( OPTION("websockets","port",[]{return "7666";}), uiSettings->lineEdit_webSock_port, tr("Websocket server -> Port"));
# undef OPTION # undef OPTION
//widgetlocks.add(new widgetlock(widget,lockbtn));
widgetlocks.add(new widgetlock(uiSettings->logDestinationComboBox,uiSettings->logDestComboEditPushButton));
widgetlocks.add(new widgetlock(uiSettings->logLevelComboBox,uiSettings->logLevelComboEditPushButton));
widgetlocks.add(new widgetlock(uiSettings->comboBox_httpPorxySignatureType,uiSettings->httpProxySignTypeComboEditPushButton));
widgetlocks.add(new widgetlock(uiSettings->comboBox_socksProxySignatureType,uiSettings->socksProxySignTypeComboEditPushButton));
loadAllConfigs(); loadAllConfigs();
//tunnelsFormGridLayoutWidget = new QWidget(ui->tunnelsScrollAreaWidgetContents); QObject::connect(uiSettings->logDestinationComboBox, SIGNAL(currentIndexChanged(const QString &)),
//tunnelsFormGridLayoutWidget->setObjectName(QStringLiteral("tunnelsFormGridLayoutWidget")); this, SLOT(logDestinationComboBoxValueChanged(const QString &)));
//tunnelsFormGridLayoutWidget->setGeometry(QRect(0, 0, 621, 451)); logDestinationComboBoxValueChanged(uiSettings->logDestinationComboBox->currentText());
ui->tunnelsScrollAreaWidgetContents->setGeometry(QRect(0, 0, 621, 451)); ui->tunnelsScrollAreaWidgetContents->setGeometry(QRect(0, 0, 621, 451));
appendTunnelForms(""); appendTunnelForms("");
ui->configFileLineEdit->setEnabled(false); uiSettings->configFileLineEdit->setEnabled(false);
ui->configFileBrowsePushButton->setEnabled(false); uiSettings->configFileBrowsePushButton->setEnabled(false);
ui->configFileLineEdit->setText(confpath); uiSettings->configFileLineEdit->setText(confpath);
ui->tunnelsConfigFileLineEdit->setText(tunconfpath); uiSettings->tunnelsConfigFileLineEdit->setText(tunconfpath);
for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) { for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) {
MainWindowItem* item = *it; MainWindowItem* item = *it;
item->installListeners(this); item->installListeners(this);
} }
QObject::connect(ui->tunnelsConfigFileLineEdit, SIGNAL(textChanged(const QString &)), QObject::connect(uiSettings->tunnelsConfigFileLineEdit, SIGNAL(textChanged(const QString &)),
this, SLOT(reloadTunnelsConfigAndUI())); this, SLOT(reloadTunnelsConfigAndUI()));
QObject::connect(ui->addServerTunnelPushButton, SIGNAL(released()), this, SLOT(addServerTunnelPushButtonReleased())); QObject::connect(ui->addServerTunnelPushButton, SIGNAL(released()), this, SLOT(addServerTunnelPushButtonReleased()));
@ -226,11 +301,104 @@ MainWindow::MainWindow(QWidget *parent) :
//QMetaObject::connectSlotsByName(this); //QMetaObject::connectSlotsByName(this);
} }
void MainWindow::showStatusPage(){ui->stackedWidget->setCurrentIndex(0);} void MainWindow::logDestinationComboBoxValueChanged(const QString & text) {
void MainWindow::showSettingsPage(){ui->stackedWidget->setCurrentIndex(1);} bool stdout = text==QString("stdout");
void MainWindow::showTunnelsPage(){ui->stackedWidget->setCurrentIndex(2);} uiSettings->logFileLineEdit->setEnabled(!stdout);
void MainWindow::showRestartPage(){ui->stackedWidget->setCurrentIndex(3);} uiSettings->logFileBrowsePushButton->setEnabled(!stdout);
void MainWindow::showQuitPage(){ui->stackedWidget->setCurrentIndex(4);} }
void MainWindow::updateRouterCommandsButtons() {
bool acceptsTunnels = i2p::context.AcceptsTunnels ();
routerCommandsUI->declineTransitTunnelsPushButton->setEnabled(acceptsTunnels);
routerCommandsUI->acceptTransitTunnelsPushButton->setEnabled(!acceptsTunnels);
}
void MainWindow::showStatusPage(StatusPage newStatusPage){
ui->stackedWidget->setCurrentIndex(0);
setStatusButtonsVisible(true);
statusPage=newStatusPage;
showHiddenInfoStatusMainPage=false;
if(newStatusPage!=StatusPage::commands){
textBrowser->setHtml(getStatusPageHtml(false));
textBrowser->show();
routerCommandsParent->hide();
pageWithBackButton->hide();
}else{
routerCommandsParent->show();
textBrowser->hide();
pageWithBackButton->hide();
updateRouterCommandsButtons();
}
wasSelectingAtStatusMainPage=false;
}
void MainWindow::showSettingsPage(){ui->stackedWidget->setCurrentIndex(1);setStatusButtonsVisible(false);}
void MainWindow::showTunnelsPage(){ui->stackedWidget->setCurrentIndex(2);setStatusButtonsVisible(false);}
void MainWindow::showRestartPage(){ui->stackedWidget->setCurrentIndex(3);setStatusButtonsVisible(false);}
void MainWindow::showQuitPage(){ui->stackedWidget->setCurrentIndex(4);setStatusButtonsVisible(false);}
void MainWindow::setStatusButtonsVisible(bool visible) {
ui->statusButtonsPane->setVisible(visible);
}
// see also: HTTPServer.cpp
QString MainWindow::getStatusPageHtml(bool showHiddenInfo) {
std::stringstream s;
s << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">";
switch (statusPage) {
case main_page: i2p::http::ShowStatus(s, showHiddenInfo);break;
case commands: break;
case local_destinations: i2p::http::ShowLocalDestinations(s);break;
case leasesets: i2p::http::ShowLeasesSets(s); break;
case tunnels: i2p::http::ShowTunnels(s); break;
case transit_tunnels: i2p::http::ShowTransitTunnels(s); break;
case transports: i2p::http::ShowTransports(s); break;
case i2p_tunnels: i2p::http::ShowI2PTunnels(s); break;
case sam_sessions: i2p::http::ShowSAMSessions(s); break;
default: assert(false); break;
}
std::string str = s.str();
return QString::fromStdString(str);
}
void MainWindow::showStatusMainPage() { showStatusPage(StatusPage::main_page); }
void MainWindow::showStatus_commands_Page() { showStatusPage(StatusPage::commands); }
void MainWindow::showStatus_local_destinations_Page() { showStatusPage(StatusPage::local_destinations); }
void MainWindow::showStatus_leasesets_Page() { showStatusPage(StatusPage::leasesets); }
void MainWindow::showStatus_tunnels_Page() { showStatusPage(StatusPage::tunnels); }
void MainWindow::showStatus_transit_tunnels_Page() { showStatusPage(StatusPage::transit_tunnels); }
void MainWindow::showStatus_transports_Page() { showStatusPage(StatusPage::transports); }
void MainWindow::showStatus_i2p_tunnels_Page() { showStatusPage(StatusPage::i2p_tunnels); }
void MainWindow::showStatus_sam_sessions_Page() { showStatusPage(StatusPage::sam_sessions); }
void MainWindow::scheduleStatusPageUpdates() {
statusPageUpdateTimer = new QTimer(this);
connect(statusPageUpdateTimer, SIGNAL(timeout()), this, SLOT(updateStatusPage()));
statusPageUpdateTimer->start(10*1000/*millis*/);
}
void MainWindow::statusHtmlPageMouseReleased() {
if(wasSelectingAtStatusMainPage){
QString selection = textBrowser->textCursor().selectedText();
if(!selection.isEmpty()&&!selection.isNull())return;
}
showHiddenInfoStatusMainPage=!showHiddenInfoStatusMainPage;
textBrowser->setHtml(getStatusPageHtml(showHiddenInfoStatusMainPage));
}
void MainWindow::statusHtmlPageSelectionChanged() {
wasSelectingAtStatusMainPage=true;
}
void MainWindow::updateStatusPage() {
showHiddenInfoStatusMainPage=false;
textBrowser->setHtml(getStatusPageHtml(showHiddenInfoStatusMainPage));
}
//TODO //TODO
void MainWindow::resizeEvent(QResizeEvent *event) void MainWindow::resizeEvent(QResizeEvent *event)
@ -352,6 +520,7 @@ void MainWindow::handleGracefulQuitTimerEvent() {
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
qDebug("Destroying main window"); qDebug("Destroying main window");
delete statusPageUpdateTimer;
for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) { for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) {
MainWindowItem* item = *it; MainWindowItem* item = *it;
item->deleteLater(); item->deleteLater();
@ -376,6 +545,9 @@ void MainWindow::initFolderChooser(ConfigOption option, QLineEdit* folderLineEdi
configItems.append(new ComboBoxItem(option, comboBox)); configItems.append(new ComboBoxItem(option, comboBox));
QObject::connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(saveAllConfigs())); QObject::connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(saveAllConfigs()));
}*/ }*/
void MainWindow::initLogDestinationCombobox(ConfigOption option, QComboBox* comboBox){
configItems.append(new LogDestinationComboBoxItem(option, comboBox));
}
void MainWindow::initLogLevelCombobox(ConfigOption option, QComboBox* comboBox){ void MainWindow::initLogLevelCombobox(ConfigOption option, QComboBox* comboBox){
configItems.append(new LogLevelComboBoxItem(option, comboBox)); configItems.append(new LogLevelComboBoxItem(option, comboBox));
} }
@ -401,7 +573,7 @@ void MainWindow::initUInt16Box(ConfigOption option, QLineEdit* numberLineEdit, Q
configItems.append(new UInt16StringItem(option, numberLineEdit, fieldNameTranslated)); configItems.append(new UInt16StringItem(option, numberLineEdit, fieldNameTranslated));
} }
void MainWindow::initStringBox(ConfigOption option, QLineEdit* lineEdit){ void MainWindow::initStringBox(ConfigOption option, QLineEdit* lineEdit){
configItems.append(new BaseStringItem(option, lineEdit)); configItems.append(new BaseStringItem(option, lineEdit, QString()));
} }
NonGUIOptionItem* MainWindow::initNonGUIOption(ConfigOption option) { NonGUIOptionItem* MainWindow::initNonGUIOption(ConfigOption option) {
NonGUIOptionItem * retValue; NonGUIOptionItem * retValue;
@ -430,10 +602,7 @@ void MainWindow::loadAllConfigs(){
LogPrint(eLogWarning, "Daemon: please rename i2p.conf to i2pd.conf here: ", config); LogPrint(eLogWarning, "Daemon: please rename i2p.conf to i2pd.conf here: ", config);
} else { } else {
config = i2p::fs::DataDirPath("i2pd.conf"); config = i2p::fs::DataDirPath("i2pd.conf");
if (!i2p::fs::Exists (config)) { /*if (!i2p::fs::Exists (config)) {}*/
// use i2pd.conf only if exists
config = ""; /* reset */
}
} }
} }
@ -462,16 +631,20 @@ void MainWindow::loadAllConfigs(){
} }
/** returns false iff not valid items present and save was aborted */ /** returns false iff not valid items present and save was aborted */
bool MainWindow::saveAllConfigs(){ bool MainWindow::saveAllConfigs(){
QString cannotSaveSettings = QApplication::tr("Cannot save settings.");
programOptionsWriterCurrentSection=""; programOptionsWriterCurrentSection="";
if(!logFileNameOption->lineEdit->text().trimmed().isEmpty())logOption->optionValue=boost::any(std::string("file")); /*if(!logFileNameOption->lineEdit->text().trimmed().isEmpty())logOption->optionValue=boost::any(std::string("file"));
else logOption->optionValue=boost::any(std::string("stdout")); else logOption->optionValue=boost::any(std::string("stdout"));*/
daemonOption->optionValue=boost::any(false); daemonOption->optionValue=boost::any(false);
serviceOption->optionValue=boost::any(false); serviceOption->optionValue=boost::any(false);
std::stringstream out; std::stringstream out;
for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) { for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) {
MainWindowItem* item = *it; MainWindowItem* item = *it;
if(!item->isValid()) return false; if(!item->isValid()){
highlightWrongInput(QApplication::tr("Invalid value for")+" "+item->getConfigOption().section+"::"+item->getConfigOption().option+". "+item->getRequirementToBeValid()+" "+cannotSaveSettings, item->getWidgetToFocus());
return false;
}
} }
for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) { for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) {
@ -481,9 +654,10 @@ bool MainWindow::saveAllConfigs(){
using namespace std; using namespace std;
QString backup=confpath+"~"; QString backup=confpath+"~";
if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors
QFile::rename(confpath, backup);//TODO handle errors if(QFile::exists(confpath)) QFile::rename(confpath, backup);//TODO handle errors
ofstream outfile; ofstream outfile;
outfile.open(confpath.toStdString());//TODO handle errors outfile.open(confpath.toStdString());//TODO handle errors
outfile << out.str().c_str(); outfile << out.str().c_str();
@ -506,15 +680,22 @@ void FolderChooserItem::pushButtonReleased() {
} }
void BaseStringItem::installListeners(MainWindow *mainWindow) { void BaseStringItem::installListeners(MainWindow *mainWindow) {
QObject::connect(lineEdit, SIGNAL(textChanged(const QString &)), mainWindow, SLOT(saveAllConfigs())); QObject::connect(lineEdit, SIGNAL(textChanged(const QString &)), mainWindow, SLOT(updated()));
} }
void ComboBoxItem::installListeners(MainWindow *mainWindow) { void ComboBoxItem::installListeners(MainWindow *mainWindow) {
QObject::connect(comboBox, SIGNAL(currentIndexChanged(int)), mainWindow, SLOT(saveAllConfigs())); QObject::connect(comboBox, SIGNAL(currentIndexChanged(int)), mainWindow, SLOT(updated()));
} }
void CheckBoxItem::installListeners(MainWindow *mainWindow) { void CheckBoxItem::installListeners(MainWindow *mainWindow) {
QObject::connect(checkBox, SIGNAL(stateChanged(int)), mainWindow, SLOT(saveAllConfigs())); QObject::connect(checkBox, SIGNAL(stateChanged(int)), mainWindow, SLOT(updated()));
} }
void MainWindow::updated() {
ui->wrongInputLabel->setVisible(false);
adjustSizesAccordingToWrongLabel();
applyTunnelsUiToConfigs();
saveAllConfigs();
}
void MainWindowItem::installListeners(MainWindow *mainWindow) {} void MainWindowItem::installListeners(MainWindow *mainWindow) {}
@ -526,27 +707,33 @@ void MainWindow::appendTunnelForms(std::string tunnelNameToFocus) {
TunnelConfig* tunconf = it->second; TunnelConfig* tunconf = it->second;
ServerTunnelConfig* stc = tunconf->asServerTunnelConfig(); ServerTunnelConfig* stc = tunconf->asServerTunnelConfig();
if(stc){ if(stc){
ServerTunnelPane * tunnelPane=new ServerTunnelPane(&tunnelsPageUpdateListener, stc); ServerTunnelPane * tunnelPane=new ServerTunnelPane(&tunnelsPageUpdateListener, stc, ui->wrongInputLabel, ui->wrongInputLabel, this);
int h=tunnelPane->appendServerTunnelForm(stc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height); int h=tunnelPane->appendServerTunnelForm(stc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height);
height+=h; height+=h;
qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size(); //qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size();
tunnelPanes.push_back(tunnelPane); tunnelPanes.push_back(tunnelPane);
if(name==tunnelNameToFocus)tunnelPane->getNameLineEdit()->setFocus(); if(name==tunnelNameToFocus){
tunnelPane->getNameLineEdit()->setFocus();
ui->tunnelsScrollArea->ensureWidgetVisible(tunnelPane->getNameLineEdit());
}
continue; continue;
} }
ClientTunnelConfig* ctc = tunconf->asClientTunnelConfig(); ClientTunnelConfig* ctc = tunconf->asClientTunnelConfig();
if(ctc){ if(ctc){
ClientTunnelPane * tunnelPane=new ClientTunnelPane(&tunnelsPageUpdateListener, ctc); ClientTunnelPane * tunnelPane=new ClientTunnelPane(&tunnelsPageUpdateListener, ctc, ui->wrongInputLabel, ui->wrongInputLabel, this);
int h=tunnelPane->appendClientTunnelForm(ctc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height); int h=tunnelPane->appendClientTunnelForm(ctc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height);
height+=h; height+=h;
qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size(); //qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size();
tunnelPanes.push_back(tunnelPane); tunnelPanes.push_back(tunnelPane);
if(name==tunnelNameToFocus)tunnelPane->getNameLineEdit()->setFocus(); if(name==tunnelNameToFocus){
tunnelPane->getNameLineEdit()->setFocus();
ui->tunnelsScrollArea->ensureWidgetVisible(tunnelPane->getNameLineEdit());
}
continue; continue;
} }
throw "unknown TunnelConfig subtype"; throw "unknown TunnelConfig subtype";
} }
qDebug() << "tun.setting height:" << height; //qDebug() << "tun.setting height:" << height;
ui->tunnelsScrollAreaWidgetContents->setGeometry(QRect(0, 0, 621, height)); ui->tunnelsScrollAreaWidgetContents->setGeometry(QRect(0, 0, 621, height));
QList<QWidget*> childWidgets = ui->tunnelsScrollAreaWidgetContents->findChildren<QWidget*>(); QList<QWidget*> childWidgets = ui->tunnelsScrollAreaWidgetContents->findChildren<QWidget*>();
foreach(QWidget* widget, childWidgets) foreach(QWidget* widget, childWidgets)
@ -572,6 +759,14 @@ void MainWindow::deleteTunnelForms() {
tunnelPanes.clear(); tunnelPanes.clear();
} }
bool MainWindow::applyTunnelsUiToConfigs() {
for(std::list<TunnelPane*>::iterator it = tunnelPanes.begin(); it != tunnelPanes.end(); ++it) {
TunnelPane* tp = *it;
if(!tp->applyDataFromUIToTunnelConfig())return false;
}
return true;
}
void MainWindow::reloadTunnelsConfigAndUI(std::string tunnelNameToFocus) { void MainWindow::reloadTunnelsConfigAndUI(std::string tunnelNameToFocus) {
deleteTunnelForms(); deleteTunnelForms();
for (std::map<std::string,TunnelConfig*>::iterator it=tunnelConfigs.begin(); it!=tunnelConfigs.end(); ++it) { for (std::map<std::string,TunnelConfig*>::iterator it=tunnelConfigs.begin(); it!=tunnelConfigs.end(); ++it) {
@ -598,12 +793,14 @@ void MainWindow::SaveTunnelsConfig() {
QString backup=tunconfpath+"~"; QString backup=tunconfpath+"~";
if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors
QFile::rename(tunconfpath, backup);//TODO handle errors if(QFile::exists(tunconfpath)) QFile::rename(tunconfpath, backup);//TODO handle errors
ofstream outfile; ofstream outfile;
outfile.open(tunconfpath.toStdString());//TODO handle errors outfile.open(tunconfpath.toStdString());//TODO handle errors
outfile << out.str().c_str(); outfile << out.str().c_str();
outfile.close(); outfile.close();
i2p::client::context.ReloadConfig();
} }
void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::updated(std::string oldName, TunnelConfig* tunConf) { void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::updated(std::string oldName, TunnelConfig* tunConf) {
@ -613,7 +810,7 @@ void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::updated(std::string ol
if(it!=mainWindow->tunnelConfigs.end())mainWindow->tunnelConfigs.erase(it); if(it!=mainWindow->tunnelConfigs.end())mainWindow->tunnelConfigs.erase(it);
mainWindow->tunnelConfigs[tunConf->getName()]=tunConf; mainWindow->tunnelConfigs[tunConf->getName()]=tunConf;
} }
mainWindow->SaveTunnelsConfig(); mainWindow->saveAllConfigs();
} }
void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::needsDeleting(std::string oldName){ void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::needsDeleting(std::string oldName){
@ -631,3 +828,79 @@ void MainWindow::addClientTunnelPushButtonReleased() {
void MainWindow::setI2PController(i2p::qt::Controller* controller_) { void MainWindow::setI2PController(i2p::qt::Controller* controller_) {
this->i2pController = controller_; this->i2pController = controller_;
} }
void MainWindow::runPeerTest() {
i2p::transport::transports.PeerTest();
}
void MainWindow::enableTransit() {
i2p::context.SetAcceptsTunnels(true);
updateRouterCommandsButtons();
}
void MainWindow::disableTransit() {
i2p::context.SetAcceptsTunnels(false);
updateRouterCommandsButtons();
}
void MainWindow::anchorClickedHandler(const QUrl & link) {
QString debugStr=QString()+"anchorClicked: "+"\""+link.toString()+"\"";
qDebug()<<debugStr;
//QMessageBox::information(this, "", debugStr);
/* /?page=local_destination&b32=xx...xx */
QString str=link.toString();
#define LOCAL_DEST_B32_PREFIX "/?page=local_destination&b32="
static size_t LOCAL_DEST_B32_PREFIX_SZ=QString(LOCAL_DEST_B32_PREFIX).size();
if(str.startsWith(LOCAL_DEST_B32_PREFIX)) {
str = str.right(str.size()-LOCAL_DEST_B32_PREFIX_SZ);
qDebug () << "b32:" << str;
pageWithBackButton->show();
textBrowser->hide();
std::stringstream s;
i2p::http::ShowLocalDestination(s,str.toStdString());
childTextBrowser->setHtml(QString::fromStdString(s.str()));
}
}
void MainWindow::backClickedFromChild() {
showStatusPage(statusPage);
}
void MainWindow::adjustSizesAccordingToWrongLabel() {
if(ui->wrongInputLabel->isVisible()) {
int dh = ui->wrongInputLabel->height()+ui->verticalLayout_7->layout()->spacing();
ui->verticalLayout_7->invalidate();
ui->wrongInputLabel->adjustSize();
ui->stackedWidget->adjustSize();
ui->stackedWidget->setFixedHeight(531-dh);
ui->settingsPage->setFixedHeight(531-dh);
ui->verticalLayoutWidget_4->setGeometry(QRect(0, 0, 711, 531-dh));
ui->stackedWidget->setFixedHeight(531-dh);
ui->settingsScrollArea->setFixedHeight(531-dh-settingsTitleLabelNominalHeight-ui->verticalLayout_4->spacing());
ui->settingsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
ui->tunnelsScrollArea->setFixedHeight(531-dh-settingsTitleLabelNominalHeight-ui->horizontalLayout_42->geometry().height()-2*ui->verticalLayout_4->spacing());
ui->tunnelsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
}else{
ui->verticalLayout_7->invalidate();
ui->wrongInputLabel->adjustSize();
ui->stackedWidget->adjustSize();
ui->stackedWidget->setFixedHeight(531);
ui->settingsPage->setFixedHeight(531);
ui->verticalLayoutWidget_4->setGeometry(QRect(0, 0, 711, 531));
ui->stackedWidget->setFixedHeight(531);
ui->settingsScrollArea->setFixedHeight(531-settingsTitleLabelNominalHeight-ui->verticalLayout_4->spacing());
ui->settingsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
ui->tunnelsScrollArea->setFixedHeight(531-settingsTitleLabelNominalHeight-ui->horizontalLayout_42->geometry().height()-2*ui->verticalLayout_4->spacing());
ui->tunnelsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
}
}
void MainWindow::highlightWrongInput(QString warningText, QWidget* widgetToFocus) {
bool redVisible = ui->wrongInputLabel->isVisible();
ui->wrongInputLabel->setVisible(true);
ui->wrongInputLabel->setText(warningText);
if(!redVisible)adjustSizesAccordingToWrongLabel();
if(widgetToFocus){ui->settingsScrollArea->ensureWidgetVisible(widgetToFocus);widgetToFocus->setFocus();}
showSettingsPage();
}

View file

@ -24,6 +24,7 @@
#include <QtWidgets/QPushButton> #include <QtWidgets/QPushButton>
#include <QtWidgets/QSpacerItem> #include <QtWidgets/QSpacerItem>
#include "QVBoxLayout" #include "QVBoxLayout"
#include "QUrl"
#ifndef ANDROID #ifndef ANDROID
# include <QSystemTrayIcon> # include <QSystemTrayIcon>
@ -40,6 +41,7 @@
#include "ServerTunnelPane.h" #include "ServerTunnelPane.h"
#include "ClientTunnelPane.h" #include "ClientTunnelPane.h"
#include "TunnelConfig.h" #include "TunnelConfig.h"
#include "textbrowsertweaked1.h"
#include "Config.h" #include "Config.h"
#include "FS.h" #include "FS.h"
@ -53,6 +55,12 @@
#include "DaemonQT.h" #include "DaemonQT.h"
#include "SignatureTypeComboboxFactory.h" #include "SignatureTypeComboboxFactory.h"
#include "pagewithbackbutton.h"
#include <iostream>
#include "widgetlockregistry.h"
#include "widgetlock.h"
template<typename ValueType> template<typename ValueType>
bool isType(boost::any& a) { bool isType(boost::any& a) {
@ -85,8 +93,13 @@ class MainWindow;
class MainWindowItem : public QObject { class MainWindowItem : public QObject {
Q_OBJECT Q_OBJECT
ConfigOption option; ConfigOption option;
QWidget* widgetToFocus;
QString requirementToBeValid;
public: public:
MainWindowItem(ConfigOption option_) : option(option_) {} MainWindowItem(ConfigOption option_, QWidget* widgetToFocus_, QString requirementToBeValid_) : option(option_), widgetToFocus(widgetToFocus_), requirementToBeValid(requirementToBeValid_) {}
QWidget* getWidgetToFocus(){return widgetToFocus;}
QString& getRequirementToBeValid() { return requirementToBeValid; }
ConfigOption& getConfigOption() { return option; }
boost::any optionValue; boost::any optionValue;
virtual ~MainWindowItem(){} virtual ~MainWindowItem(){}
virtual void installListeners(MainWindow *mainWindow); virtual void installListeners(MainWindow *mainWindow);
@ -94,7 +107,7 @@ public:
std::string optName=""; std::string optName="";
if(!option.section.isEmpty())optName=option.section.toStdString()+std::string("."); if(!option.section.isEmpty())optName=option.section.toStdString()+std::string(".");
optName+=option.option.toStdString(); optName+=option.option.toStdString();
qDebug() << "loadFromConfigOption[" << optName.c_str() << "]"; //qDebug() << "loadFromConfigOption[" << optName.c_str() << "]";
boost::any programOption; boost::any programOption;
i2p::config::GetOptionAsAny(optName, programOption); i2p::config::GetOptionAsAny(optName, programOption);
optionValue=programOption.empty()?boost::any(std::string("")) optionValue=programOption.empty()?boost::any(std::string(""))
@ -137,7 +150,7 @@ public:
}; };
class NonGUIOptionItem : public MainWindowItem { class NonGUIOptionItem : public MainWindowItem {
public: public:
NonGUIOptionItem(ConfigOption option_) : MainWindowItem(option_) {}; NonGUIOptionItem(ConfigOption option_) : MainWindowItem(option_, nullptr, QString()) {};
virtual ~NonGUIOptionItem(){} virtual ~NonGUIOptionItem(){}
virtual bool isValid() { return true; } virtual bool isValid() { return true; }
}; };
@ -145,7 +158,7 @@ class BaseStringItem : public MainWindowItem {
Q_OBJECT Q_OBJECT
public: public:
QLineEdit* lineEdit; QLineEdit* lineEdit;
BaseStringItem(ConfigOption option_, QLineEdit* lineEdit_) : MainWindowItem(option_), lineEdit(lineEdit_){}; BaseStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString requirementToBeValid_) : MainWindowItem(option_, lineEdit_, requirementToBeValid_), lineEdit(lineEdit_){};
virtual ~BaseStringItem(){} virtual ~BaseStringItem(){}
virtual void installListeners(MainWindow *mainWindow); virtual void installListeners(MainWindow *mainWindow);
virtual QString toString(){ virtual QString toString(){
@ -167,7 +180,7 @@ class FileOrFolderChooserItem : public BaseStringItem {
public: public:
QPushButton* browsePushButton; QPushButton* browsePushButton;
FileOrFolderChooserItem(ConfigOption option_, QLineEdit* lineEdit_, QPushButton* browsePushButton_) : FileOrFolderChooserItem(ConfigOption option_, QLineEdit* lineEdit_, QPushButton* browsePushButton_) :
BaseStringItem(option_, lineEdit_), browsePushButton(browsePushButton_) {} BaseStringItem(option_, lineEdit_, QString()), browsePushButton(browsePushButton_) {}
virtual ~FileOrFolderChooserItem(){} virtual ~FileOrFolderChooserItem(){}
}; };
class FileChooserItem : public FileOrFolderChooserItem { class FileChooserItem : public FileOrFolderChooserItem {
@ -193,13 +206,30 @@ public:
class ComboBoxItem : public MainWindowItem { class ComboBoxItem : public MainWindowItem {
public: public:
QComboBox* comboBox; QComboBox* comboBox;
ComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : MainWindowItem(option_), comboBox(comboBox_){}; ComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : MainWindowItem(option_,comboBox_,QString()), comboBox(comboBox_){};
virtual ~ComboBoxItem(){} virtual ~ComboBoxItem(){}
virtual void installListeners(MainWindow *mainWindow); virtual void installListeners(MainWindow *mainWindow);
virtual void loadFromConfigOption()=0; virtual void loadFromConfigOption()=0;
virtual void saveToStringStream(std::stringstream& out)=0; virtual void saveToStringStream(std::stringstream& out)=0;
virtual bool isValid() { return true; } virtual bool isValid() { return true; }
}; };
class LogDestinationComboBoxItem : public ComboBoxItem {
public:
LogDestinationComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : ComboBoxItem(option_, comboBox_) {};
virtual ~LogDestinationComboBoxItem(){}
virtual void loadFromConfigOption(){
MainWindowItem::loadFromConfigOption();
const char * ld = boost::any_cast<std::string>(optionValue).c_str();
comboBox->setCurrentText(QString(ld));
}
virtual void saveToStringStream(std::stringstream& out){
std::string logDest = comboBox->currentText().toStdString();
if(logDest==std::string("stdout"))logDest="";
optionValue=logDest;
MainWindowItem::saveToStringStream(out);
}
virtual bool isValid() { return true; }
};
class LogLevelComboBoxItem : public ComboBoxItem { class LogLevelComboBoxItem : public ComboBoxItem {
public: public:
LogLevelComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : ComboBoxItem(option_, comboBox_) {}; LogLevelComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : ComboBoxItem(option_, comboBox_) {};
@ -235,7 +265,7 @@ public:
class CheckBoxItem : public MainWindowItem { class CheckBoxItem : public MainWindowItem {
public: public:
QCheckBox* checkBox; QCheckBox* checkBox;
CheckBoxItem(ConfigOption option_, QCheckBox* checkBox_) : MainWindowItem(option_), checkBox(checkBox_){}; CheckBoxItem(ConfigOption option_, QCheckBox* checkBox_) : MainWindowItem(option_,checkBox_,QString()), checkBox(checkBox_){};
virtual ~CheckBoxItem(){} virtual ~CheckBoxItem(){}
virtual void installListeners(MainWindow *mainWindow); virtual void installListeners(MainWindow *mainWindow);
virtual void loadFromConfigOption(){ virtual void loadFromConfigOption(){
@ -251,62 +281,84 @@ public:
class BaseFormattedStringItem : public BaseStringItem { class BaseFormattedStringItem : public BaseStringItem {
public: public:
QString fieldNameTranslated; QString fieldNameTranslated;
BaseFormattedStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) : BaseFormattedStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_, QString requirementToBeValid_) :
BaseStringItem(option_, lineEdit_), fieldNameTranslated(fieldNameTranslated_) {}; BaseStringItem(option_, lineEdit_, requirementToBeValid_), fieldNameTranslated(fieldNameTranslated_) {};
virtual ~BaseFormattedStringItem(){} virtual ~BaseFormattedStringItem(){}
virtual bool isValid()=0; virtual bool isValid()=0;
}; };
class IntegerStringItem : public BaseFormattedStringItem { class IntegerStringItem : public BaseFormattedStringItem {
public: public:
IntegerStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) : IntegerStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_) {}; BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be a valid integer.")) {};
virtual ~IntegerStringItem(){} virtual ~IntegerStringItem(){}
virtual bool isValid(){return true;} virtual bool isValid(){
auto str=lineEdit->text();
bool ok;
str.toInt(&ok);
return ok;
}
virtual QString toString(){return QString::number(boost::any_cast<int>(optionValue));} virtual QString toString(){return QString::number(boost::any_cast<int>(optionValue));}
virtual boost::any fromString(QString s){return boost::any(std::stoi(s.toStdString()));} virtual boost::any fromString(QString s){return boost::any(std::stoi(s.toStdString()));}
}; };
class UShortStringItem : public BaseFormattedStringItem { class UShortStringItem : public BaseFormattedStringItem {
public: public:
UShortStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) : UShortStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_) {}; BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be unsigned short integer.")) {};
virtual ~UShortStringItem(){} virtual ~UShortStringItem(){}
virtual bool isValid(){return true;} virtual bool isValid(){
auto str=lineEdit->text();
bool ok;
str.toUShort(&ok);
return ok;
}
virtual QString toString(){return QString::number(boost::any_cast<unsigned short>(optionValue));} virtual QString toString(){return QString::number(boost::any_cast<unsigned short>(optionValue));}
virtual boost::any fromString(QString s){return boost::any((unsigned short)std::stoi(s.toStdString()));} virtual boost::any fromString(QString s){return boost::any((unsigned short)std::stoi(s.toStdString()));}
}; };
class UInt32StringItem : public BaseFormattedStringItem { class UInt32StringItem : public BaseFormattedStringItem {
public: public:
UInt32StringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) : UInt32StringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_) {}; BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be unsigned 32-bit integer.")) {};
virtual ~UInt32StringItem(){} virtual ~UInt32StringItem(){}
virtual bool isValid(){return true;} virtual bool isValid(){
auto str=lineEdit->text();
bool ok;
str.toUInt(&ok);
return ok;
}
virtual QString toString(){return QString::number(boost::any_cast<uint32_t>(optionValue));} virtual QString toString(){return QString::number(boost::any_cast<uint32_t>(optionValue));}
virtual boost::any fromString(QString s){return boost::any((uint32_t)std::stoi(s.toStdString()));} virtual boost::any fromString(QString s){return boost::any((uint32_t)std::stoi(s.toStdString()));}
}; };
class UInt16StringItem : public BaseFormattedStringItem { class UInt16StringItem : public BaseFormattedStringItem {
public: public:
UInt16StringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) : UInt16StringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_) {}; BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be unsigned 16-bit integer.")) {};
virtual ~UInt16StringItem(){} virtual ~UInt16StringItem(){}
virtual bool isValid(){return true;} virtual bool isValid(){
auto str=lineEdit->text();
bool ok;
str.toUShort(&ok);
return ok;
}
virtual QString toString(){return QString::number(boost::any_cast<uint16_t>(optionValue));} virtual QString toString(){return QString::number(boost::any_cast<uint16_t>(optionValue));}
virtual boost::any fromString(QString s){return boost::any((uint16_t)std::stoi(s.toStdString()));} virtual boost::any fromString(QString s){return boost::any((uint16_t)std::stoi(s.toStdString()));}
}; };
class IPAddressStringItem : public BaseFormattedStringItem { class IPAddressStringItem : public BaseFormattedStringItem {
public: public:
IPAddressStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) : IPAddressStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_) {}; BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be an IPv4 address")) {};
virtual bool isValid(){return true;} virtual bool isValid(){return true;}//todo
}; };
class TCPPortStringItem : public UShortStringItem { class TCPPortStringItem : public UShortStringItem {
public: public:
TCPPortStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) : TCPPortStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
UShortStringItem(option_, lineEdit_, fieldNameTranslated_) {}; UShortStringItem(option_, lineEdit_, fieldNameTranslated_) {};
virtual bool isValid(){return true;}
}; };
namespace Ui { namespace Ui {
class MainWindow; class MainWindow;
class StatusButtonsForm;
class routerCommandsWidget;
class GeneralSettingsContentsForm;
} }
using namespace i2p::client; using namespace i2p::client;
@ -326,13 +378,20 @@ public:
void setI2PController(i2p::qt::Controller* controller_); void setI2PController(i2p::qt::Controller* controller_);
void highlightWrongInput(QString warningText, QWidget* widgetToFocus);
//typedef std::function<QString ()> DefaultValueGetter; //typedef std::function<QString ()> DefaultValueGetter;
//#ifndef ANDROID //#ifndef ANDROID
// void setVisible(bool visible); // void setVisible(bool visible);
//#endif //#endif
private:
enum StatusPage {main_page, commands, local_destinations, leasesets, tunnels, transit_tunnels,
transports, i2p_tunnels, sam_sessions};
private slots: private slots:
void updated();
void handleQuitButton(); void handleQuitButton();
void handleGracefulQuitButton(); void handleGracefulQuitButton();
void handleDoRestartButton(); void handleDoRestartButton();
@ -342,13 +401,37 @@ private slots:
void iconActivated(QSystemTrayIcon::ActivationReason reason); void iconActivated(QSystemTrayIcon::ActivationReason reason);
void toggleVisibilitySlot(); void toggleVisibilitySlot();
#endif #endif
void showStatusPage(); void scheduleStatusPageUpdates();
void statusHtmlPageMouseReleased();
void statusHtmlPageSelectionChanged();
void updateStatusPage();
void showStatusMainPage();
void showStatus_commands_Page();
void runPeerTest();
void enableTransit();
void disableTransit();
public slots:
void showStatus_local_destinations_Page();
void showStatus_leasesets_Page();
void showStatus_tunnels_Page();
void showStatus_transit_tunnels_Page();
void showStatus_transports_Page();
void showStatus_i2p_tunnels_Page();
void showStatus_sam_sessions_Page();
void showSettingsPage(); void showSettingsPage();
void showTunnelsPage(); void showTunnelsPage();
void showRestartPage(); void showRestartPage();
void showQuitPage(); void showQuitPage();
private: private:
StatusPage statusPage;
QTimer * statusPageUpdateTimer;
bool wasSelectingAtStatusMainPage;
bool showHiddenInfoStatusMainPage;
void showStatusPage(StatusPage newStatusPage);
#ifndef ANDROID #ifndef ANDROID
void createActions(); void createActions();
void createTrayIcon(); void createTrayIcon();
@ -358,26 +441,48 @@ private:
QMenu *trayIconMenu; QMenu *trayIconMenu;
#endif #endif
public:
Ui::MainWindow* ui; Ui::MainWindow* ui;
Ui::StatusButtonsForm* statusButtonsUI;
Ui::routerCommandsWidget* routerCommandsUI;
Ui::GeneralSettingsContentsForm* uiSettings;
void adjustSizesAccordingToWrongLabel();
bool applyTunnelsUiToConfigs();
private:
int settingsTitleLabelNominalHeight;
TextBrowserTweaked1 * textBrowser;
QWidget * routerCommandsParent;
PageWithBackButton * pageWithBackButton;
TextBrowserTweaked1 * childTextBrowser;
widgetlockregistry widgetlocks;
i2p::qt::Controller* i2pController; i2p::qt::Controller* i2pController;
protected: protected:
void updateRouterCommandsButtons();
#ifndef ANDROID #ifndef ANDROID
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
#endif #endif
void resizeEvent(QResizeEvent* event); void resizeEvent(QResizeEvent* event);
void onResize(); void onResize();
void setStatusButtonsVisible(bool visible);
QString getStatusPageHtml(bool showHiddenInfo);
QList<MainWindowItem*> configItems; QList<MainWindowItem*> configItems;
NonGUIOptionItem* logOption;
NonGUIOptionItem* daemonOption; NonGUIOptionItem* daemonOption;
NonGUIOptionItem* serviceOption; NonGUIOptionItem* serviceOption;
//LogDestinationComboBoxItem* logOption;
FileChooserItem* logFileNameOption; FileChooserItem* logFileNameOption;
FileChooserItem* initFileChooser(ConfigOption option, QLineEdit* fileNameLineEdit, QPushButton* fileBrowsePushButton); FileChooserItem* initFileChooser(ConfigOption option, QLineEdit* fileNameLineEdit, QPushButton* fileBrowsePushButton);
void initFolderChooser(ConfigOption option, QLineEdit* folderLineEdit, QPushButton* folderBrowsePushButton); void initFolderChooser(ConfigOption option, QLineEdit* folderLineEdit, QPushButton* folderBrowsePushButton);
//void initCombobox(ConfigOption option, QComboBox* comboBox); //void initCombobox(ConfigOption option, QComboBox* comboBox);
void initLogDestinationCombobox(ConfigOption option, QComboBox* comboBox);
void initLogLevelCombobox(ConfigOption option, QComboBox* comboBox); void initLogLevelCombobox(ConfigOption option, QComboBox* comboBox);
void initSignatureTypeCombobox(ConfigOption option, QComboBox* comboBox); void initSignatureTypeCombobox(ConfigOption option, QComboBox* comboBox);
void initIPAddressBox(ConfigOption option, QLineEdit* addressLineEdit, QString fieldNameTranslated); void initIPAddressBox(ConfigOption option, QLineEdit* addressLineEdit, QString fieldNameTranslated);
@ -402,6 +507,11 @@ public slots:
void addServerTunnelPushButtonReleased(); void addServerTunnelPushButtonReleased();
void addClientTunnelPushButtonReleased(); void addClientTunnelPushButtonReleased();
void anchorClickedHandler(const QUrl & link);
void backClickedFromChild();
void logDestinationComboBoxValueChanged(const QString & text);
private: private:
QString datadir; QString datadir;
QString confpath; QString confpath;
@ -466,9 +576,9 @@ private:
TunnelConfig* tc=it->second; TunnelConfig* tc=it->second;
tunnelConfigs.erase(it); tunnelConfigs.erase(it);
delete tc; delete tc;
SaveTunnelsConfig();
reloadTunnelsConfigAndUI("");
} }
saveAllConfigs();
reloadTunnelsConfigAndUI("");
} }
std::string GenerateNewTunnelName() { std::string GenerateNewTunnelName() {
@ -503,7 +613,7 @@ private:
destinationPort, destinationPort,
sigType); sigType);
SaveTunnelsConfig(); saveAllConfigs();
reloadTunnelsConfigAndUI(name); reloadTunnelsConfigAndUI(name);
} }
@ -542,7 +652,7 @@ private:
isUniqueLocal); isUniqueLocal);
SaveTunnelsConfig(); saveAllConfigs();
reloadTunnelsConfigAndUI(name); reloadTunnelsConfigAndUI(name);
} }
@ -584,13 +694,17 @@ private:
{ {
// mandatory params // mandatory params
std::string dest; std::string dest;
if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT || type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT || type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) {
dest = section.second.get<std::string> (I2P_CLIENT_TUNNEL_DESTINATION); dest = section.second.get<std::string> (I2P_CLIENT_TUNNEL_DESTINATION);
std::cout << "had read tunnel dest: " << dest << std::endl;
}
int port = section.second.get<int> (I2P_CLIENT_TUNNEL_PORT); int port = section.second.get<int> (I2P_CLIENT_TUNNEL_PORT);
std::cout << "had read tunnel port: " << port << std::endl;
// optional params // optional params
std::string keys = section.second.get (I2P_CLIENT_TUNNEL_KEYS, ""); std::string keys = section.second.get (I2P_CLIENT_TUNNEL_KEYS, "");
std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1"); std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1");
int destinationPort = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0); int destinationPort = section.second.get<int>(I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0);
std::cout << "had read tunnel destinationPort: " << destinationPort << std::endl;
i2p::data::SigningKeyType sigType = section.second.get (I2P_CLIENT_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256); i2p::data::SigningKeyType sigType = section.second.get (I2P_CLIENT_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256);
// I2CP // I2CP
std::map<std::string, std::string> options; std::map<std::string, std::string> options;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,24 @@
#include "pagewithbackbutton.h"
#include "QVBoxLayout"
#include "QHBoxLayout"
#include "QPushButton"
PageWithBackButton::PageWithBackButton(QWidget *parent, QWidget* child) : QWidget(parent)
{
QVBoxLayout * layout = new QVBoxLayout();
setLayout(layout);
QWidget * topBar = new QWidget();
QHBoxLayout * topBarLayout = new QHBoxLayout();
topBar->setLayout(topBarLayout);
layout->addWidget(topBar);
layout->addWidget(child);
QPushButton * backButton = new QPushButton(topBar);
backButton->setText("< Back");
topBarLayout->addWidget(backButton);
connect(backButton, SIGNAL(released()), this, SLOT(backReleasedSlot()));
}
void PageWithBackButton::backReleasedSlot() {
emit backReleased();
}

View file

@ -0,0 +1,21 @@
#ifndef PAGEWITHBACKBUTTON_H
#define PAGEWITHBACKBUTTON_H
#include <QWidget>
class PageWithBackButton : public QWidget
{
Q_OBJECT
public:
explicit PageWithBackButton(QWidget *parent, QWidget* child);
signals:
void backReleased();
private slots:
void backReleasedSlot();
};
#endif // PAGEWITHBACKBUTTON_H

View file

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>routerCommandsWidget</class>
<widget class="QWidget" name="routerCommandsWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>711</width>
<height>300</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>711</width>
<height>301</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Router Commands</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="runPeerTestPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Run peer test</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="declineTransitTunnelsPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Decline transit tunnels</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="acceptTransitTunnelsPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Accept transit tunnels</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancelGracefulQuitPushButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Cancel graceful quit</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

163
qt/i2pd_qt/statusbuttons.ui Normal file
View file

@ -0,0 +1,163 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>StatusButtonsForm</class>
<widget class="QWidget" name="StatusButtonsForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>171</width>
<height>295</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>171</width>
<height>295</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
<x>21</x>
<y>0</y>
<width>171</width>
<height>300</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QPushButton" name="mainPagePushButton">
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Main page</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="routerCommandsPushButton">
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Router commands</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="localDestinationsPushButton">
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Local destinations</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="leasesetsPushButton">
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Leasesets</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="tunnelsPushButton">
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Tunnels</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="transitTunnelsPushButton">
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Transit tunnels</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="transportsPushButton">
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Transports</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="i2pTunnelsPushButton">
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>I2P tunnels</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="samSessionsPushButton">
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>SAM sessions</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,9 @@
#include "textbrowsertweaked1.h"
TextBrowserTweaked1::TextBrowserTweaked1(QWidget * parent): QTextBrowser(parent)
{
}
/*void TextBrowserTweaked1::setSource(const QUrl & url) {
emit navigatedTo(url);
}*/

View file

@ -0,0 +1,26 @@
#ifndef TEXTBROWSERTWEAKED1_H
#define TEXTBROWSERTWEAKED1_H
#include <QTextBrowser>
#include <QUrl>
class TextBrowserTweaked1 : public QTextBrowser
{
Q_OBJECT
public:
TextBrowserTweaked1(QWidget * parent);
//virtual void setSource(const QUrl & url);
signals:
void mouseReleased();
//void navigatedTo(const QUrl & link);
protected:
void mouseReleaseEvent(QMouseEvent *event) {
QTextBrowser::mouseReleaseEvent(event);
emit mouseReleased();
}
};
#endif // TEXTBROWSERTWEAKED1_H

View file

@ -0,0 +1 @@
#include "widgetlock.h"

35
qt/i2pd_qt/widgetlock.h Normal file
View file

@ -0,0 +1,35 @@
#ifndef WIDGETLOCK_H
#define WIDGETLOCK_H
#include <QWidget>
#include <QObject>
#include <QPushButton>
#include <QApplication>
class widgetlock : public QObject {
Q_OBJECT
private:
QWidget* widget;
QPushButton* lockButton;
public slots:
void lockButtonClicked(bool) {
bool wasEnabled = widget->isEnabled();
widget->setEnabled(!wasEnabled);
lockButton->setText(widget->isEnabled()?lockButton->tr("Lock"):lockButton->tr("Edit"));
}
public:
widgetlock(QWidget* widget_, QPushButton* lockButton_): widget(widget_),lockButton(lockButton_) {
widget->setEnabled(false);
lockButton->setText(lockButton->tr("Edit"));
QObject::connect(lockButton,SIGNAL(clicked(bool)), this, SLOT(lockButtonClicked(bool)));
}
virtual ~widgetlock() {}
void deleteListener() {
QObject::disconnect(lockButton,SIGNAL(clicked(bool)), this, SLOT(lockButtonClicked(bool)));
}
};
#endif // WIDGETLOCK_H

View file

@ -0,0 +1,2 @@
#include "widgetlockregistry.h"

View file

@ -0,0 +1,27 @@
#ifndef WIDGETLOCKREGISTRY_H
#define WIDGETLOCKREGISTRY_H
#include <vector>
#include <widgetlock.h>
class widgetlockregistry {
std::vector<widgetlock*> locks;
public:
widgetlockregistry() : locks() {}
virtual ~widgetlockregistry() {}
void add(widgetlock* lock) {
locks.push_back(lock);
}
void deleteListeners() {
while(!locks.empty()) {
widgetlock* lock = locks.back();
lock->deleteListener();
delete lock;
locks.pop_back();
}
}
};
#endif // WIDGETLOCKREGISTRY_H