summaryrefslogtreecommitdiff
path: root/windows/ZeroTierOne
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@zerotier.com>2014-02-06 22:06:27 -0800
committerAdam Ierymenko <adam.ierymenko@zerotier.com>2014-02-06 22:06:27 -0800
commit8a7486577afb259c19b82e4e73cb8b508cd2f162 (patch)
treedc36ac222fecb598972ad4a1e47454fa9099fb3a /windows/ZeroTierOne
parent6d17993eb69455a8a47013e9c6f110863f7dbb35 (diff)
downloadinfinitytier-8a7486577afb259c19b82e4e73cb8b508cd2f162.tar.gz
infinitytier-8a7486577afb259c19b82e4e73cb8b508cd2f162.zip
Windows service work, remove old installer... not sure exactly what we're going to use.
Diffstat (limited to 'windows/ZeroTierOne')
-rw-r--r--windows/ZeroTierOne/ServiceInstaller.cpp43
-rw-r--r--windows/ZeroTierOne/ServiceInstaller.h7
-rw-r--r--windows/ZeroTierOne/ZeroTierOneService.cpp62
-rw-r--r--windows/ZeroTierOne/ZeroTierOneService.h18
4 files changed, 95 insertions, 35 deletions
diff --git a/windows/ZeroTierOne/ServiceInstaller.cpp b/windows/ZeroTierOne/ServiceInstaller.cpp
index 9d7b22c7..5945ecdf 100644
--- a/windows/ZeroTierOne/ServiceInstaller.cpp
+++ b/windows/ZeroTierOne/ServiceInstaller.cpp
@@ -42,20 +42,21 @@
// NOTE: If the function fails to install the service, it prints the error
// in the standard output stream for users to diagnose the problem.
//
-void InstallService(PSTR pszServiceName,
+std::string InstallService(PSTR pszServiceName,
PSTR pszDisplayName,
DWORD dwStartType,
PSTR pszDependencies,
PSTR pszAccount,
PSTR pszPassword)
{
+ std::string ret;
char szPath[MAX_PATH];
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)) == 0)
{
- wprintf(L"GetModuleFileName failed w/err 0x%08lx\n", GetLastError());
+ ret = "GetModuleFileName failed, unable to get path to self";
goto Cleanup;
}
@@ -64,7 +65,7 @@ void InstallService(PSTR pszServiceName,
SC_MANAGER_CREATE_SERVICE);
if (schSCManager == NULL)
{
- wprintf(L"OpenSCManager failed w/err 0x%08lx\n", GetLastError());
+ ret = "OpenSCManager failed";
goto Cleanup;
}
@@ -86,12 +87,10 @@ void InstallService(PSTR pszServiceName,
);
if (schService == NULL)
{
- wprintf(L"CreateService failed w/err 0x%08lx\n", GetLastError());
+ ret = "CreateService failed";
goto Cleanup;
}
- wprintf(L"%s is installed.\n", pszServiceName);
-
Cleanup:
// Centralized cleanup for all allocated resources.
if (schSCManager)
@@ -104,6 +103,8 @@ Cleanup:
CloseServiceHandle(schService);
schService = NULL;
}
+
+ return ret;
}
@@ -119,8 +120,9 @@ Cleanup:
// NOTE: If the function fails to uninstall the service, it prints the
// error in the standard output stream for users to diagnose the problem.
//
-void UninstallService(PSTR pszServiceName)
+std::string UninstallService(PSTR pszServiceName)
{
+ std::string ret;
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
SERVICE_STATUS ssSvcStatus = {};
@@ -129,7 +131,7 @@ void UninstallService(PSTR pszServiceName)
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (schSCManager == NULL)
{
- wprintf(L"OpenSCManager failed w/err 0x%08lx\n", GetLastError());
+ ret = "OpenSCManager failed";
goto Cleanup;
}
@@ -138,45 +140,32 @@ void UninstallService(PSTR pszServiceName)
SERVICE_QUERY_STATUS | DELETE);
if (schService == NULL)
{
- wprintf(L"OpenService failed w/err 0x%08lx\n", GetLastError());
+ ret = "OpenService failed (is service installed?)";
goto Cleanup;
}
// Try to stop the service
if (ControlService(schService, SERVICE_CONTROL_STOP, &ssSvcStatus))
{
- wprintf(L"Stopping %s.", pszServiceName);
- Sleep(1000);
+ Sleep(500);
while (QueryServiceStatus(schService, &ssSvcStatus))
{
if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING)
{
- wprintf(L".");
- Sleep(1000);
+ Sleep(500);
}
else break;
}
-
- if (ssSvcStatus.dwCurrentState == SERVICE_STOPPED)
- {
- wprintf(L"\n%s is stopped.\n", pszServiceName);
- }
- else
- {
- wprintf(L"\n%s failed to stop.\n", pszServiceName);
- }
}
// Now remove the service by calling DeleteService.
if (!DeleteService(schService))
{
- wprintf(L"DeleteService failed w/err 0x%08lx\n", GetLastError());
+ ret = "DeleteService failed (is service running?)";
goto Cleanup;
}
- wprintf(L"%s is removed.\n", pszServiceName);
-
Cleanup:
// Centralized cleanup for all allocated resources.
if (schSCManager)
@@ -189,4 +178,6 @@ Cleanup:
CloseServiceHandle(schService);
schService = NULL;
}
-} \ No newline at end of file
+
+ return ret;
+}
diff --git a/windows/ZeroTierOne/ServiceInstaller.h b/windows/ZeroTierOne/ServiceInstaller.h
index 1f007c05..ee9856df 100644
--- a/windows/ZeroTierOne/ServiceInstaller.h
+++ b/windows/ZeroTierOne/ServiceInstaller.h
@@ -16,6 +16,7 @@
#pragma once
+#include <string>
//
// FUNCTION: InstallService
@@ -38,7 +39,8 @@
// NOTE: If the function fails to install the service, it prints the error
// in the standard output stream for users to diagnose the problem.
//
-void InstallService(PSTR pszServiceName,
+// modified for ZT1 to return an error or empty string on success
+std::string InstallService(PSTR pszServiceName,
PSTR pszDisplayName,
DWORD dwStartType,
PSTR pszDependencies,
@@ -58,4 +60,5 @@ void InstallService(PSTR pszServiceName,
// NOTE: If the function fails to uninstall the service, it prints the
// error in the standard output stream for users to diagnose the problem.
//
-void UninstallService(PSTR pszServiceName); \ No newline at end of file
+// Also modified to return rather than print errors
+std::string UninstallService(PSTR pszServiceName);
diff --git a/windows/ZeroTierOne/ZeroTierOneService.cpp b/windows/ZeroTierOne/ZeroTierOneService.cpp
index 0a89e80a..b8277436 100644
--- a/windows/ZeroTierOne/ZeroTierOneService.cpp
+++ b/windows/ZeroTierOne/ZeroTierOneService.cpp
@@ -27,29 +27,81 @@
#pragma region Includes
#include "ZeroTierOneService.h"
+#include "../../node/Node.hpp"
+#include "../../node/Defaults.hpp"
+#include "../../node/Thread.hpp"
#pragma endregion
+using namespace ZeroTier;
+
ZeroTierOneService::ZeroTierOneService() :
- CServiceBase(ZT_SERVICE_NAME,TRUE,TRUE,TRUE)
+ CServiceBase(ZT_SERVICE_NAME,TRUE,TRUE,FALSE),
+ _thread(new Thread()),
+ _node((Node *)0)
{
}
ZeroTierOneService::~ZeroTierOneService(void)
{
+ delete _thread;
+ delete _node;
}
-void ZeroTierOneService::OnStart(DWORD dwArgc, LPSTR *lpszArgv)
+void ZeroTierOneService::threadMain()
+ throw()
{
+ try {
+ // Since Windows doesn't auto-restart services, we'll restart the node
+ // on normal termination.
+ for(;;) {
+ switch(_node->run()) {
+ case Node::NODE_NORMAL_TERMINATION:
+ delete _node;
+ _node = new Node(ZT_DEFAULTS.defaultHomePath.c_str(),0,0);
+ break; // restart
+ case Node::NODE_RESTART_FOR_UPGRADE: {
+ } return; // terminate thread
+ case Node::NODE_UNRECOVERABLE_ERROR: {
+ std::string err("unrecoverable error: ");
+ const char *r = _node->reasonForTermination;
+ if (r)
+ err.append(r);
+ else err.append("(unknown error)");
+ WriteEventLogEntry(const_cast <PSTR>(err.c_str()),EVENTLOG_ERROR_TYPE);
+ } return; // terminate thread
+ default:
+ break;
+ }
+ }
+ } catch ( ... ) {
+ WriteEventLogEntry("unexpected exception in Node::run() or during restart",EVENTLOG_ERROR_TYPE);
+ }
}
-void ZeroTierOneService::OnStop()
+void ZeroTierOneService::OnStart(DWORD dwArgc, LPSTR *lpszArgv)
{
+ try {
+ _node = new Node(ZT_DEFAULTS.defaultHomePath.c_str(),0,0);
+ *_thread = Thread::start(this);
+ } catch ( ... ) {
+ // shouldn't happen unless something weird occurs like out of memory...
+ throw (DWORD)ERROR_EXCEPTION_IN_SERVICE;
+ }
}
-void ZeroTierOneService::OnPause()
+void ZeroTierOneService::OnStop()
{
+ Node *n = _node;
+ _node = (Node *)0;
+ if (n) {
+ n->terminate(Node::NODE_NORMAL_TERMINATION,"Service Shutdown");
+ Thread::join(*_thread);
+ delete n;
+ }
}
-void ZeroTierOneService::OnContinue()
+void ZeroTierOneService::OnShutdown()
{
+ // make sure it's stopped
+ OnStop();
}
diff --git a/windows/ZeroTierOne/ZeroTierOneService.h b/windows/ZeroTierOne/ZeroTierOneService.h
index 4bfc60b2..776446b0 100644
--- a/windows/ZeroTierOne/ZeroTierOneService.h
+++ b/windows/ZeroTierOne/ZeroTierOneService.h
@@ -36,15 +36,29 @@
#define ZT_SERVICE_ACCOUNT "NT AUTHORITY\\LocalService"
#define ZT_SERVICE_PASSWORD NULL
+namespace ZeroTier {
+class Node;
+class Thread;
+} // namespace ZeroTier
+
class ZeroTierOneService : public CServiceBase
{
public:
ZeroTierOneService();
virtual ~ZeroTierOneService(void);
+ /**
+ * Thread main method; do not call elsewhere
+ */
+ void threadMain()
+ throw();
+
protected:
virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
virtual void OnStop();
- virtual void OnPause();
- virtual void OnContinue();
+ virtual void OnShutdown();
+
+private:
+ ZeroTier::Node *volatile _node;
+ ZeroTier::Thread *volatile _thread;
};