diff options
-rw-r--r-- | src/anytun.cpp | 22 | ||||
-rw-r--r-- | src/posix/signalHandler.hpp | 2 | ||||
-rw-r--r-- | src/signalController.cpp | 19 | ||||
-rw-r--r-- | src/signalController.h | 11 | ||||
-rw-r--r-- | src/win32/signalHandler.hpp | 2 | ||||
-rw-r--r-- | src/win32/signalServiceHandler.hpp | 47 | ||||
-rw-r--r-- | src/win32/winService.cpp | 88 | ||||
-rw-r--r-- | src/win32/winService.h | 22 |
8 files changed, 109 insertions, 104 deletions
diff --git a/src/anytun.cpp b/src/anytun.cpp index e30443a..2e1e49c 100644 --- a/src/anytun.cpp +++ b/src/anytun.cpp @@ -353,14 +353,13 @@ int main(int argc, char* argv[]) } } -int real_main(int argc, char* argv[]) -#else -int main(int argc, char* argv[]) -#endif +int real_main(int argc, char* argv[], WinService& service) { -#ifdef WIN_SERVICE bool daemonized=true; #else +int main(int argc, char* argv[]) +{ + DaemonService service; bool daemonized=false; #endif try @@ -425,7 +424,7 @@ int main(int argc, char* argv[]) #endif #if !defined(__FreeBSD_kernel__) // this has to be called before the first thread is started - gSignalController.init(); + gSignalController.init(service); #endif gResolver.init(); #ifndef NO_EXEC @@ -469,12 +468,7 @@ int main(int argc, char* argv[]) // to be still able to process signals while waiting boost::thread(boost::bind(startSendRecvThreads, &dev, src)); -#if defined(WIN_SERVICE) - int ret = 0; - gWinService.waitForStop(); -#else int ret = gSignalController.run(); -#endif // TODO: stop all threads and cleanup // @@ -483,9 +477,6 @@ int main(int argc, char* argv[]) // if(connTo) // delete connTo; -#if defined(WIN_SERVICE) - gWinService.stop(); -#endif return ret; } catch(std::runtime_error& e) @@ -500,9 +491,6 @@ int main(int argc, char* argv[]) if(!daemonized) std::cout << "uncaught exception, exiting: " << e.what() << std::endl; } -#if defined(WIN_SERVICE) - gWinService.stop(); -#endif return -1; } diff --git a/src/posix/signalHandler.hpp b/src/posix/signalHandler.hpp index d52b4d6..b56f43c 100644 --- a/src/posix/signalHandler.hpp +++ b/src/posix/signalHandler.hpp @@ -92,7 +92,7 @@ void handleSignal() } } -void registerSignalHandler(SignalController& ctrl) +void registerSignalHandler(SignalController& ctrl, DaemonService& /*service*/) { sigset_t signal_set; diff --git a/src/signalController.cpp b/src/signalController.cpp index f0191fe..ca6d044 100644 --- a/src/signalController.cpp +++ b/src/signalController.cpp @@ -64,12 +64,23 @@ int SigErrorHandler(const SigNum& /*sig*/, const std::string& msg) #ifndef _MSC_VER #include "signalHandler.hpp" #else -#include "win32/signalHandler.hpp" + #ifdef WIN_SERVICE + #include "win32/signalServiceHandler.hpp" + #else + #include "win32/signalHandler.hpp" + #endif #endif void SignalController::init() { - registerSignalHandler(*this); + DaemonService service; + registerSignalHandler(*this, service); + handler[SIGERROR] = boost::bind(SigErrorHandler, _1, _2); +} + +void SignalController::init(DaemonService& service) +{ + registerSignalHandler(*this, service); handler[SIGERROR] = boost::bind(SigErrorHandler, _1, _2); } @@ -86,7 +97,7 @@ int SignalController::run() { for(CallbackMap::iterator it = callbacks.begin(); it != callbacks.end(); ++it) if(it->first == CALLB_RUNNING) - it->second(CALLB_RUNNING); + it->second(); int ret = 0; while(1) { @@ -112,7 +123,7 @@ int SignalController::run() for(CallbackMap::iterator it = callbacks.begin(); it != callbacks.end(); ++it) if(it->first == CALLB_STOPPING) - it->second(CALLB_STOPPING); + it->second(); return ret; } diff --git a/src/signalController.h b/src/signalController.h index 2602cc0..f872888 100644 --- a/src/signalController.h +++ b/src/signalController.h @@ -38,13 +38,19 @@ #include <boost/function.hpp> #include "threadUtils.hpp" +#ifdef WIN_SERVICE +#include "win32/winService.h" +typedef WinService DaemonService; +#else +typedef int DaemonService; +#endif #define SIGERROR -1 typedef int SigNum; typedef boost::function<int (SigNum const&, std::string const&)> SignalHandler; typedef enum { CALLB_RUNNING, CALLB_STOPPING } CallbackType; -typedef boost::function<void (CallbackType const&)> ServiceCallback; +typedef boost::function<void ()> ServiceCallback; class SignalController { @@ -52,6 +58,7 @@ public: static SignalController& instance(); void init(); + void init(DaemonService& service); int run(); void inject(int sig, const std::string& msg = ""); @@ -81,7 +88,7 @@ private: typedef std::map<CallbackType, ServiceCallback> CallbackMap; CallbackMap callbacks; - friend void registerSignalHandler(SignalController& ctrl); + friend void registerSignalHandler(SignalController& ctrl, DaemonService& service); }; extern SignalController& gSignalController; diff --git a/src/win32/signalHandler.hpp b/src/win32/signalHandler.hpp index f5b79e1..a961621 100644 --- a/src/win32/signalHandler.hpp +++ b/src/win32/signalHandler.hpp @@ -71,7 +71,7 @@ bool handleSignal(DWORD ctrlType) return true; } -void registerSignalHandler(SignalController& ctrl) +void registerSignalHandler(SignalController& ctrl, DaemonService& /*service*/) { if(!SetConsoleCtrlHandler((PHANDLER_ROUTINE)handleSignal, true)) AnytunError::throwErr() << "Error on SetConsoleCtrlhandler: " << AnytunErrno(GetLastError()); diff --git a/src/win32/signalServiceHandler.hpp b/src/win32/signalServiceHandler.hpp new file mode 100644 index 0000000..3c6be7e --- /dev/null +++ b/src/win32/signalServiceHandler.hpp @@ -0,0 +1,47 @@ +/* + * anytun + * + * The secure anycast tunneling protocol (satp) defines a protocol used + * for communication between any combination of unicast and anycast + * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel + * mode and allows tunneling of every ETHER TYPE protocol (e.g. + * ethernet, ip, arp ...). satp directly includes cryptography and + * message authentication based on the methodes used by SRTP. It is + * intended to deliver a generic, scaleable and secure solution for + * tunneling and relaying of packets of any protocol. + * + * + * Copyright (C) 2007-2009 Othmar Gsenger, Erwin Nindl, + * Christian Pointner <satp@wirdorange.org> + * + * This file is part of Anytun. + * + * Anytun is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * Anytun is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with anytun. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ANYTUN_signalServiceHandler_h_INCLUDED +#define ANYTUN_signalServiceHandler_h_INCLUDED + +#include "winService.h" + +void registerSignalHandler(SignalController& ctrl, WinService& service) +{ + ctrl.handler[SERVICE_CONTROL_STOP] = boost::bind(WinService::handleCtrlSignal, &service, _1, _2); + ctrl.handler[SERVICE_CONTROL_INTERROGATE] = boost::bind(WinService::handleCtrlSignal, &service, _1, _2); + + ctrl.callbacks.insert(SignalController::CallbackMap::value_type(CALLB_RUNNING, boost::bind(&WinService::reportStatus, &service, SERVICE_RUNNING, NO_ERROR))); + ctrl.callbacks.insert(SignalController::CallbackMap::value_type(CALLB_STOPPING, boost::bind(&WinService::reportStatus, &service, SERVICE_STOP_PENDING, NO_ERROR))); +} + +#endif diff --git a/src/win32/winService.cpp b/src/win32/winService.cpp index 1b7c9f8..feb1aab 100644 --- a/src/win32/winService.cpp +++ b/src/win32/winService.cpp @@ -41,26 +41,6 @@ #include "../anytunError.h"
#include "../threadUtils.hpp"
-WinService* WinService::inst = NULL;
-Mutex WinService::instMutex;
-WinService& gWinService = WinService::instance();
-
-WinService& WinService::instance()
-{
- Lock lock(instMutex);
- static instanceCleaner c;
- if(!inst)
- inst = new WinService();
-
- return *inst;
-}
-
-WinService::~WinService()
-{
- if(started_)
- CloseHandle(stop_event_);
-}
-
void WinService::install()
{
SC_HANDLE schSCManager;
@@ -125,75 +105,61 @@ void WinService::start() AnytunError::throwErr() << "Error on StartServiceCtrlDispatcher: " << AnytunErrno(GetLastError());
}
-void WinService::waitForStop()
-{
- if(!started_)
- AnytunError::throwErr() << "Service not started correctly";
-
- reportStatus(SERVICE_RUNNING, NO_ERROR);
- WaitForSingleObject(stop_event_, INFINITE);
- reportStatus(SERVICE_STOP_PENDING, NO_ERROR);
- cLog.msg(Log::PRIO_NOTICE) << "WinService received stop signal, exitting";
-}
-
-void WinService::stop()
-{
- if(!started_)
- AnytunError::throwErr() << "Service not started correctly";
-
- reportStatus(SERVICE_STOPPED, NO_ERROR);
-}
-
-int real_main(int argc, char* argv[]);
+int real_main(int argc, char* argv[], WinService& service);
VOID WINAPI WinService::main(DWORD dwArgc, LPTSTR *lpszArgv)
{
- if(gWinService.started_) {
- cLog.msg(Log::PRIO_ERROR) << "Service is already running";
- return;
- }
+ WinService service;
- gWinService.status_handle_ = RegisterServiceCtrlHandlerA(SVC_NAME, WinService::ctrlHandler);
- if(!gWinService.status_handle_) {
+ service.status_handle_ = RegisterServiceCtrlHandlerA(SVC_NAME, WinService::ctrlHandler);
+ if(!service.status_handle_) {
cLog.msg(Log::PRIO_ERROR) << "Error on RegisterServiceCtrlHandler: " << AnytunErrno(GetLastError());
return;
}
- gWinService.status_.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
- gWinService.status_.dwServiceSpecificExitCode = 0;
- gWinService.reportStatus(SERVICE_START_PENDING, NO_ERROR);
- gWinService.started_ = true;
+ service.status_.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ service.status_.dwServiceSpecificExitCode = 0;
+ service.reportStatus(SERVICE_START_PENDING, NO_ERROR);
- gWinService.stop_event_ = CreateEvent(NULL, true, false, NULL);
- if(!gWinService.stop_event_) {
+ service.stop_event_ = CreateEvent(NULL, true, false, NULL);
+ if(!service.stop_event_) {
cLog.msg(Log::PRIO_ERROR) << "WinService Error on CreateEvent: " << AnytunErrno(GetLastError());
- gWinService.reportStatus(SERVICE_STOPPED, -1);
+ service.reportStatus(SERVICE_STOPPED, -1);
return;
}
- real_main(dwArgc, lpszArgv);
+ real_main(dwArgc, lpszArgv, service);
+
+ service.reportStatus(SERVICE_STOPPED, NO_ERROR);
}
VOID WINAPI WinService::ctrlHandler(DWORD dwCtrl)
{
- switch(dwCtrl) {
+ gSignalController.inject(ctrlType);
+ return true;
+}
+
+int handleCtrlSignal(const SigNum& sig, const std::string& msg)
+{
+ switch(sig) {
case SERVICE_CONTROL_STOP: {
- gWinService.reportStatus(SERVICE_STOP_PENDING, NO_ERROR);
- SetEvent(gWinService.stop_event_);
- return;
+ reportStatus(SERVICE_STOP_PENDING, NO_ERROR);
+ return 1;
}
case SERVICE_CONTROL_INTERROGATE: break;
default: break;
}
- gWinService.reportStatus(gWinService.status_.dwCurrentState, NO_ERROR);
+ reportStatus(gWinService.status_.dwCurrentState, NO_ERROR);
+
+ return 0;
}
-void WinService::reportStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
+void WinService::reportStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode)
{
static DWORD dwCheckPoint = 1;
status_.dwCurrentState = dwCurrentState;
status_.dwWin32ExitCode = dwWin32ExitCode;
- status_.dwWaitHint = dwWaitHint;
+ status_.dwWaitHint = 0;
if((dwCurrentState == SERVICE_START_PENDING) ||
(dwCurrentState == SERVICE_STOP_PENDING))
diff --git a/src/win32/winService.h b/src/win32/winService.h index 6867c7c..e2bab90 100644 --- a/src/win32/winService.h +++ b/src/win32/winService.h @@ -40,39 +40,25 @@ class WinService { public: - static WinService& instance(); #define SVC_NAME "anytun" static void install(); static void uninstall(); static void start(); - void waitForStop(); - void stop(); - static VOID WINAPI main(DWORD dwArgc, LPTSTR *lpszArgv); static VOID WINAPI ctrlHandler(DWORD dwCtrl); + + void reportStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode); + int handleCtrlSignal(const SigNum& sig, const std::string& msg); + private: WinService() : started_(false) {}; ~WinService(); WinService(const WinService &w); void operator=(const WinService &w); - void reportStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint=0); - - static WinService* inst; - static Mutex instMutex; - class instanceCleaner { - public: ~instanceCleaner() { - if(WinService::inst != NULL) - delete WinService::inst; - } - }; - friend class instanceCleaner; - - bool started_; SERVICE_STATUS status_; SERVICE_STATUS_HANDLE status_handle_; - HANDLE stop_event_; }; extern WinService& gWinService; |