1 /*
2 * Copyright (c)2019 ZeroTier, Inc.
3 *
4 * Use of this software is governed by the Business Source License included
5 * in the LICENSE.TXT file in the project's root directory.
6 *
7 * Change Date: 2025-01-01
8 *
9 * On the date above, in accordance with the Business Source License, use
10 * of this software will be governed by version 2.0 of the Apache License.
11 */
12 /****/
13
14 #pragma region Includes
15
16 #if defined(_WIN32) || defined(_WIN64)
17
18 #include <WinSock2.h>
19 #include <Windows.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #include "ZeroTierOneService.h"
24
25 #include "../../version.h"
26 #include "../../include/ZeroTierOne.h"
27
28 #include "../../node/Constants.hpp"
29 #include "../../node/Utils.hpp"
30 #include "../../osdep/OSUtils.hpp"
31 #include "../../service/OneService.hpp"
32
33 #pragma endregion // Includes
34
35 #ifdef ZT_DEBUG_SERVICE
36 FILE *SVCDBGfile = (FILE *)0;
37 ZeroTier::Mutex SVCDBGfile_m;
38 #endif
39
ZeroTierOneService()40 ZeroTierOneService::ZeroTierOneService() :
41 CServiceBase(ZT_SERVICE_NAME,TRUE,TRUE,FALSE),
42 _service((ZeroTier::OneService *)0)
43 {
44 #ifdef ZT_DEBUG_SERVICE
45 SVCDBGfile_m.lock();
46 if (!SVCDBGfile)
47 SVCDBGfile = fopen(ZT_DEBUG_SERVICE,"a");
48 SVCDBGfile_m.unlock();
49 #endif
50
51 ZT_SVCDBG("ZeroTierOneService::ZeroTierOneService()\r\n");
52 }
53
~ZeroTierOneService(void)54 ZeroTierOneService::~ZeroTierOneService(void)
55 {
56 ZT_SVCDBG("ZeroTierOneService::~ZeroTierOneService()\r\n");
57
58 #ifdef ZT_DEBUG_SERVICE
59 SVCDBGfile_m.lock();
60 if (SVCDBGfile) {
61 fclose(SVCDBGfile);
62 SVCDBGfile = (FILE *)0;
63 }
64 SVCDBGfile_m.unlock();
65 #endif
66 }
67
threadMain()68 void ZeroTierOneService::threadMain()
69 throw()
70 {
71 ZT_SVCDBG("ZeroTierOneService::threadMain()\r\n");
72
73 restart_node:
74 try {
75 {
76 ZeroTier::Mutex::Lock _l(_lock);
77 delete _service;
78 _service = (ZeroTier::OneService *)0; // in case newInstance() fails
79 _service = ZeroTier::OneService::newInstance(_path.c_str(), ZT_DEFAULT_PORT);
80 }
81 switch(_service->run()) {
82 case ZeroTier::OneService::ONE_UNRECOVERABLE_ERROR: {
83 std::string err("ZeroTier One encountered an unrecoverable error: ");
84 err.append(_service->fatalErrorMessage());
85 err.append(" (restarting in 5 seconds)");
86 WriteEventLogEntry(const_cast <PSTR>(err.c_str()),EVENTLOG_ERROR_TYPE);
87 Sleep(5000);
88 } goto restart_node;
89
90 case ZeroTier::OneService::ONE_IDENTITY_COLLISION: {
91 std::string homeDir(ZeroTier::OneService::platformDefaultHomePath());
92 delete _service;
93 _service = (ZeroTier::OneService *)0;
94 std::string oldid;
95 ZeroTier::OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(),oldid);
96 if (oldid.length()) {
97 ZeroTier::OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret.saved_after_collision").c_str(),oldid);
98 ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str());
99 ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.public").c_str());
100 }
101 } goto restart_node;
102
103 default: // normal termination
104 break;
105 }
106 } catch ( ... ) {
107 // sanity check, shouldn't happen since Node::run() should catch all its own errors
108 // could also happen if we're out of memory though!
109 WriteEventLogEntry("unexpected exception (out of memory?) (trying again in 5 seconds)",EVENTLOG_ERROR_TYPE);
110 Sleep(5000);
111 goto restart_node;
112 }
113
114 {
115 ZeroTier::Mutex::Lock _l(_lock);
116 delete _service;
117 _service = (ZeroTier::OneService *)0;
118 }
119 }
120
OnStart(DWORD dwArgc,PSTR * lpszArgv)121 void ZeroTierOneService::OnStart(DWORD dwArgc, PSTR *lpszArgv)
122 {
123 ZT_SVCDBG("ZeroTierOneService::OnStart()\r\n");
124
125 if ((dwArgc > 1)&&(lpszArgv[1])&&(strlen(lpszArgv[1]) > 0)) {
126 this->_path = lpszArgv[1];
127 } else {
128 this->_path = ZeroTier::OneService::platformDefaultHomePath();
129 }
130
131 try {
132 _thread = ZeroTier::Thread::start(this);
133 } catch ( ... ) {
134 throw (DWORD)ERROR_EXCEPTION_IN_SERVICE;
135 }
136 }
137
OnStop()138 void ZeroTierOneService::OnStop()
139 {
140 ZT_SVCDBG("ZeroTierOneService::OnStop()\r\n");
141
142 _lock.lock();
143 ZeroTier::OneService *s = _service;
144 _lock.unlock();
145
146 if (s) {
147 s->terminate();
148 ZeroTier::Thread::join(_thread);
149 }
150 }
151
OnShutdown()152 void ZeroTierOneService::OnShutdown()
153 {
154 ZT_SVCDBG("ZeroTierOneService::OnShutdown()\r\n");
155
156 // stop thread on system shutdown (if it hasn't happened already)
157 OnStop();
158 }
159
160 #endif
161