diff --git a/Daemon.h b/Daemon.h index e755e3e9..4f31b2dc 100644 --- a/Daemon.h +++ b/Daemon.h @@ -20,6 +20,7 @@ namespace i2p virtual bool init(int argc, char* argv[]); virtual bool start(); virtual bool stop(); + virtual void run () {}; bool isLogging; bool isDaemon; @@ -61,8 +62,10 @@ namespace i2p return instance; } - virtual bool start(); - virtual bool stop(); + bool start(); + bool stop(); +; void run (); + private: std::string pidfile; int pidFH; diff --git a/DaemonLinux.cpp b/DaemonLinux.cpp index 2ccbfe38..53d9f61e 100644 --- a/DaemonLinux.cpp +++ b/DaemonLinux.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -118,6 +119,14 @@ namespace i2p return Daemon_Singleton::stop(); } + + void DaemonLinux::run () + { + while (running) + { + std::this_thread::sleep_for (std::chrono::seconds(1)); + } + } } } diff --git a/DaemonWin32.cpp b/DaemonWin32.cpp index 4ab65040..bf5f938c 100644 --- a/DaemonWin32.cpp +++ b/DaemonWin32.cpp @@ -68,7 +68,14 @@ namespace i2p SetConsoleOutputCP(1251); setlocale(LC_ALL, "Russian"); - return Daemon_Singleton::start(); + bool ret = Daemon_Singleton::start(); + if (ret && IsLogToFile ()) + { + // TODO: find out where this garbage to console comes from + SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE); + SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE); + } + return ret; } bool DaemonWin32::stop() diff --git a/Log.h b/Log.h index 5b07e2c9..363a23b5 100644 --- a/Log.h +++ b/Log.h @@ -45,6 +45,7 @@ class Log: public i2p::util::MsgQueue std::shared_ptr GetLogStream () const { return m_LogStream; }; const std::string& GetTimestamp (); LogLevel GetLogLevel () { return m_MinLevel; }; + const std::string& GetFullFilePath () const { return m_FullFilePath; }; private: @@ -110,6 +111,11 @@ inline void ReopenLogFile () g_Log->ReopenLogFile (); } +inline bool IsLogToFile () +{ + return g_Log ? !g_Log->GetFullFilePath ().empty () : false; +} + template void LogPrint (std::stringstream& s, TValue arg) { diff --git a/Makefile b/Makefile index 09cf2ace..2a0baaba 100644 --- a/Makefile +++ b/Makefile @@ -1,95 +1,91 @@ -UNAME := $(shell uname -s) -SHLIB := libi2pd.so -ARLIB := libi2pd.a -SHLIB_CLIENT := libi2pdclient.so -ARLIB_CLIENT := libi2pdclient.a -I2PD := i2pd -GREP := fgrep -DEPS := obj/make.dep - -include filelist.mk - -USE_AESNI := yes -USE_STATIC := no - -ifeq ($(UNAME),Darwin) - DAEMON_SRC += DaemonLinux.cpp - include Makefile.osx -else ifeq ($(shell echo $(UNAME) | $(GREP) -c FreeBSD),1) - DAEMON_SRC += DaemonLinux.cpp - include Makefile.bsd -else ifeq ($(UNAME),Linux) - DAEMON_SRC += DaemonLinux.cpp - include Makefile.linux -else # win32 mingw - DAEMON_SRC += DaemonWin32.cpp Win32/Win32Service.cpp - WINDIR := True - include Makefile.mingw -endif - -all: mk_build_dir $(ARLIB) $(ARLIB_CLIENT) $(I2PD) - -mk_build_dir: - mkdir -p obj - ifeq ($(WINDIR),True) - mkdir -p obj/Win32 - endif - -api: mk_build_dir $(SHLIB) $(ARLIB) -api_client: mk_build_dir $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) - -## NOTE: The NEEDED_CXXFLAGS are here so that CXXFLAGS can be specified at build time -## **without** overwriting the CXXFLAGS which we need in order to build. -## For example, when adding 'hardening flags' to the build -## (e.g. -fstack-protector-strong -Wformat -Werror=format-security), we do not want to remove -## -std=c++11. If you want to remove this variable please do so in a way that allows setting -## custom FLAGS to work at build-time. - -deps: - @mkdir -p obj - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) -MM *.cpp > $(DEPS) - @sed -i -e '/\.o:/ s/^/obj\//' $(DEPS) - -obj/%.o : %.cpp - @mkdir -p obj - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(CPU_FLAGS) -c -o $@ $< - -# '-' is 'ignore if missing' on first run --include $(DEPS) - -$(I2PD): $(patsubst %.cpp,obj/%.o,$(DAEMON_SRC)) $(ARLIB) $(ARLIB_CLIENT) - $(CXX) -o $@ $^ $(LDLIBS) $(LDFLAGS) - -$(SHLIB): $(patsubst %.cpp,obj/%.o,$(LIB_SRC)) -ifneq ($(USE_STATIC),yes) - $(CXX) $(LDFLAGS) $(LDLIBS) -shared -o $@ $^ -endif - -$(SHLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC)) - $(CXX) $(LDFLAGS) $(LDLIBS) -shared -o $@ $^ - -$(ARLIB): $(patsubst %.cpp,obj/%.o,$(LIB_SRC)) - ar -r $@ $^ - -$(ARLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC)) - ar -r $@ $^ - -clean: - rm -rf obj - $(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) - -strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB) - strip $^ - -LATEST_TAG=$(shell git describe --tags --abbrev=0 master) -dist: - git archive --format=tar.gz -9 --worktree-attributes \ - --prefix=i2pd_$(LATEST_TAG)/ $(LATEST_TAG) -o i2pd_$(LATEST_TAG).tar.gz - -.PHONY: all -.PHONY: clean -.PHONY: deps -.PHONY: dist -.PHONY: api -.PHONY: api_client -.PHONY: mk_build_dir +UNAME := $(shell uname -s) +SHLIB := libi2pd.so +ARLIB := libi2pd.a +SHLIB_CLIENT := libi2pdclient.so +ARLIB_CLIENT := libi2pdclient.a +I2PD := i2pd +GREP := fgrep +DEPS := obj/make.dep + +include filelist.mk + +USE_AESNI := yes +USE_STATIC := no + +ifeq ($(UNAME),Darwin) + DAEMON_SRC += DaemonLinux.cpp + include Makefile.osx +else ifeq ($(shell echo $(UNAME) | $(GREP) -c FreeBSD),1) + DAEMON_SRC += DaemonLinux.cpp + include Makefile.bsd +else ifeq ($(UNAME),Linux) + DAEMON_SRC += DaemonLinux.cpp + include Makefile.linux +else # win32 mingw + DAEMON_SRC += DaemonWin32.cpp Win32/Win32Service.cpp Win32/Win32App.cpp + include Makefile.mingw +endif + +all: mk_obj_dir $(ARLIB) $(ARLIB_CLIENT) $(I2PD) + +mk_obj_dir: + @mkdir -p obj + @mkdir -p obj/Win32 + +api: mk_obj_dir $(SHLIB) $(ARLIB) +api_client: mk_obj_dir $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) + +## NOTE: The NEEDED_CXXFLAGS are here so that CXXFLAGS can be specified at build time +## **without** overwriting the CXXFLAGS which we need in order to build. +## For example, when adding 'hardening flags' to the build +## (e.g. -fstack-protector-strong -Wformat -Werror=format-security), we do not want to remove +## -std=c++11. If you want to remove this variable please do so in a way that allows setting +## custom FLAGS to work at build-time. + +deps: mk_obj_dir + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) -MM *.cpp > $(DEPS) + @sed -i -e '/\.o:/ s/^/obj\//' $(DEPS) + +obj/%.o: %.cpp + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(CPU_FLAGS) -c -o $@ $< + +# '-' is 'ignore if missing' on first run +-include $(DEPS) + +DAEMON_OBJS += $(patsubst %.cpp,obj/%.o,$(DAEMON_SRC)) +$(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) + $(CXX) -o $@ $^ $(LDLIBS) $(LDFLAGS) + +$(SHLIB): $(patsubst %.cpp,obj/%.o,$(LIB_SRC)) +ifneq ($(USE_STATIC),yes) + $(CXX) $(LDFLAGS) $(LDLIBS) -shared -o $@ $^ +endif + +$(SHLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC)) + $(CXX) $(LDFLAGS) $(LDLIBS) -shared -o $@ $^ + +$(ARLIB): $(patsubst %.cpp,obj/%.o,$(LIB_SRC)) + ar -r $@ $^ + +$(ARLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC)) + ar -r $@ $^ + +clean: + rm -rf obj + $(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) + +strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB) + strip $^ + +LATEST_TAG=$(shell git describe --tags --abbrev=0 master) +dist: + git archive --format=tar.gz -9 --worktree-attributes \ + --prefix=i2pd_$(LATEST_TAG)/ $(LATEST_TAG) -o i2pd_$(LATEST_TAG).tar.gz + +.PHONY: all +.PHONY: clean +.PHONY: deps +.PHONY: dist +.PHONY: api +.PHONY: api_client +.PHONY: mk_obj_dir diff --git a/Makefile.mingw b/Makefile.mingw index 24f33a11..ba741918 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -1,13 +1,38 @@ CXX = g++ +WINDRES = windres CXXFLAGS = -O2 -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN NEEDED_CXXFLAGS = -std=c++11 BOOST_SUFFIX = -mt INCFLAGS = -I/usr/include/ -I/usr/local/include/ -LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -L/c/dev/openssl -L/c/dev/boost/lib -LDLIBS = -Wl,-Bstatic -lboost_system$(BOOST_SUFFIX) -Wl,-Bstatic -lboost_date_time$(BOOST_SUFFIX) -Wl,-Bstatic -lboost_filesystem$(BOOST_SUFFIX) -Wl,-Bstatic -lboost_regex$(BOOST_SUFFIX) -Wl,-Bstatic -lboost_program_options$(BOOST_SUFFIX) -Wl,-Bstatic -lssl -Wl,-Bstatic -lcrypto -Wl,-Bstatic -lz -Wl,-Bstatic -lwsock32 -Wl,-Bstatic -lws2_32 -Wl,-Bstatic -lgdi32 -Wl,-Bstatic -liphlpapi -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -Wl,-Bstatic -lpthread +LDFLAGS = -mwindows -Wl,-rpath,/usr/local/lib \ + -L/usr/local/lib \ + -L/c/dev/openssl \ + -L/c/dev/boost/lib +LDLIBS = \ + -Wl,-Bstatic -lboost_system$(BOOST_SUFFIX) \ + -Wl,-Bstatic -lboost_date_time$(BOOST_SUFFIX) \ + -Wl,-Bstatic -lboost_filesystem$(BOOST_SUFFIX) \ + -Wl,-Bstatic -lboost_regex$(BOOST_SUFFIX) \ + -Wl,-Bstatic -lboost_program_options$(BOOST_SUFFIX) \ + -Wl,-Bstatic -lssl \ + -Wl,-Bstatic -lcrypto \ + -Wl,-Bstatic -lz \ + -Wl,-Bstatic -lwsock32 \ + -Wl,-Bstatic -lws2_32 \ + -Wl,-Bstatic -lgdi32 \ + -Wl,-Bstatic -liphlpapi \ + -static-libgcc -static-libstdc++ \ + -Wl,-Bstatic -lstdc++ \ + -Wl,-Bstatic -lpthread +DAEMON_RC += Win32/Resource.rc +DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC)) ifeq ($(USE_AESNI),1) CPU_FLAGS = -maes -DAESNI else CPU_FLAGS = -msse endif + +obj/%.o : %.rc + $(WINDRES) -i $< -o $@ + diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 0ac2e74b..2584f584 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -25,7 +25,6 @@ namespace transport m_TerminationTimer (m_Server.GetService ()), m_IsEstablished (false), m_IsTerminated (false), m_ReceiveBufferOffset (0), m_NextMessage (nullptr), m_IsSending (false) { - m_DHKeysPair = transports.GetNextDHKeysPair (); m_Establisher = new Establisher; } diff --git a/Win32/Resource.rc b/Win32/Resource.rc index c8643e8d..56868181 100644 --- a/Win32/Resource.rc +++ b/Win32/Resource.rc @@ -53,7 +53,7 @@ END // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. MAINICON ICON "ictoopie.ico" - +IDI_ICON1 ICON "ictoopie_16.ico" #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp new file mode 100644 index 00000000..c356aec5 --- /dev/null +++ b/Win32/Win32App.cpp @@ -0,0 +1,157 @@ +#include +#include +#include +//#include "../Daemon.h" +#include "resource.h" +#include "Win32App.h" + +#define ID_ABOUT 2000 +#define ID_EXIT 2001 + +#define ID_TRAY_ICON 2050 +#define WM_TRAYICON (WM_USER + 1) + +void ShowPopupMenu (HWND hWnd, POINT *curpos, int wDefaultItem) +{ + HMENU hPopup = CreatePopupMenu(); + InsertMenu (hPopup, 0, MF_BYPOSITION | MF_STRING, ID_ABOUT, "About..."); + InsertMenu (hPopup, 1, MF_BYPOSITION | MF_STRING, ID_EXIT , "Exit"); + SetMenuDefaultItem (hPopup, ID_ABOUT, FALSE); + SetFocus (hWnd); + SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0); + + POINT p; + if (!curpos) + { + GetCursorPos (&p); + curpos = &p; + } + + WORD cmd = TrackPopupMenu (hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, curpos->x, curpos->y, 0, hWnd, NULL); + SendMessage (hWnd, WM_COMMAND, cmd, 0); + + DestroyMenu(hPopup); +} + +void AddTrayIcon (HWND hWnd) +{ + NOTIFYICONDATA nid; + memset(&nid, 0, sizeof(nid)); + nid.cbSize = sizeof(nid); + nid.hWnd = hWnd; + nid.uID = ID_TRAY_ICON; + nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; + nid.uCallbackMessage = WM_TRAYICON; + nid.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE (IDI_ICON1)); + strcpy (nid.szTip, "i2pd"); + Shell_NotifyIcon(NIM_ADD, &nid ); +} + +void RemoveTrayIcon (HWND hWnd) +{ + NOTIFYICONDATA nid; + nid.hWnd = hWnd; + nid.uID = ID_TRAY_ICON; + Shell_NotifyIcon (NIM_DELETE, &nid); +} + +static LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_CREATE: + { + AddTrayIcon (hWnd); + break; + } + case WM_CLOSE: + { + RemoveTrayIcon (hWnd); + PostQuitMessage (0); + break; + } + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case ID_ABOUT: + { + MessageBox( hWnd, TEXT("i2pd"), TEXT("About"), MB_ICONINFORMATION | MB_OK ); + return 0; + } + case ID_EXIT: + { + PostMessage (hWnd, WM_CLOSE, 0, 0); + return 0; + } + } + break; + } + case WM_TRAYICON: + { + SetForegroundWindow (hWnd); + switch (lParam) + { + case WM_RBUTTONUP: + { + SetForegroundWindow (hWnd); + ShowPopupMenu(hWnd, NULL, -1); + PostMessage (hWnd, WM_APP + 1, 0, 0); + break; + } + } + break; + } + } + return DefWindowProc( hWnd, uMsg, wParam, lParam); +} + + int WINAPI WinMain (HINSTANCE hInst, HINSTANCE prev, LPSTR cmdline, int show) + { + // check if tunning already + if (FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"))) + { + MessageBox(NULL, TEXT("I2Pd is running already"), TEXT("Warning"), MB_OK); + return 0; + } + // register main window + WNDCLASSEX wclx; + memset (&wclx, 0, sizeof(wclx)); + wclx.cbSize = sizeof(wclx); + wclx.style = 0; + wclx.lpfnWndProc = WndProc; + wclx.cbClsExtra = 0; + wclx.cbWndExtra = 0; + wclx.hInstance = hInst; + wclx.hIcon = LoadIcon (hInst, IDI_APPLICATION); + wclx.hIconSm = LoadIcon (hInst, IDI_APPLICATION); + wclx.hCursor = LoadCursor (NULL, IDC_ARROW); + wclx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); + wclx.lpszMenuName = NULL; + wclx.lpszClassName = I2PD_WIN32_CLASSNAME; + RegisterClassEx (&wclx); + // create new window + if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 150, NULL, NULL, hInst, NULL)) + { + MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST); + return 1; + } + + /* // init + char * argv[] = { (char *)"i2pd" }; + Daemon.init(sizeof (argv)/sizeof (argv[0]), argv); + // start + Daemon.start ();*/ + // main loop + MSG msg; + while (GetMessage (&msg, NULL, 0, 0 )) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + /* // atop + Daemon.stop ();*/ + // terminate + UnregisterClass (I2PD_WIN32_CLASSNAME, hInst); + return msg.wParam; + } diff --git a/Win32/Win32App.h b/Win32/Win32App.h new file mode 100644 index 00000000..8b14ae1b --- /dev/null +++ b/Win32/Win32App.h @@ -0,0 +1,6 @@ +#ifndef WIN32APP_H__ +#define WIN32APP_H__ + +#define I2PD_WIN32_CLASSNAME "i2pd main window" + +#endif // WIN32APP_H__ diff --git a/Win32/ictoopie_16.ico b/Win32/ictoopie_16.ico new file mode 100644 index 00000000..525646c3 Binary files /dev/null and b/Win32/ictoopie_16.ico differ diff --git a/i2pd.cpp b/i2pd.cpp index 32749d16..6167f10e 100644 --- a/i2pd.cpp +++ b/i2pd.cpp @@ -1,4 +1,3 @@ -#include #include #include "Daemon.h" @@ -6,12 +5,7 @@ int main( int argc, char* argv[] ) { Daemon.init(argc, argv); if (Daemon.start()) - { - while (Daemon.running) - { - std::this_thread::sleep_for (std::chrono::seconds(1)); - } - } + Daemon.run (); Daemon.stop(); return EXIT_SUCCESS; }