summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@anytun.org>2010-01-20 07:38:36 +0000
committerChristian Pointner <equinox@anytun.org>2010-01-20 07:38:36 +0000
commit91b4dfa446e352f5d9c7d0ef58da1ceee9ce7b34 (patch)
treebcc677584cbec7bedf9b6f112fd14a78d0e06f82
parentupdated windows signal handler (diff)
integrated winservice into signal controller
-rw-r--r--src/anytun.cpp22
-rw-r--r--src/posix/signalHandler.hpp2
-rw-r--r--src/signalController.cpp19
-rw-r--r--src/signalController.h11
-rw-r--r--src/win32/signalHandler.hpp2
-rw-r--r--src/win32/signalServiceHandler.hpp47
-rw-r--r--src/win32/winService.cpp88
-rw-r--r--src/win32/winService.h22
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;