IBR-DTNSuite  0.12
NTService.cpp
Go to the documentation of this file.
1 /*
2  * NTService.cpp
3  *
4  * Copyright (C) 2012 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
22 #include "config.h"
23 #include "Configuration.h"
24 #include <ibrcommon/Logger.h>
25 #include <ibrcommon/data/File.h>
26 
27 #include <windows.h>
28 
29 #include <string.h>
30 #include <csignal>
31 #include <set>
32 
33 #include <sys/types.h>
34 #include <unistd.h>
35 
36 #include "NativeDaemon.h"
37 
38 // marker if the shutdown was called
40 bool _shutdown = false;
41 
42 // daemon instance
44 
45 // key for registry access
46 const char* _subkey = "Software\\IBR-DTN";
47 
48 SERVICE_STATUS ServiceStatus;
49 SERVICE_STATUS_HANDLE hStatus;
50 
52  ibrcommon::MutexLock l(_shutdown_cond);
53  _shutdown = true;
54  _shutdown_cond.signal(true);
55 }
56 
57 int InitService() {
58  bool error = false;
59 
60  // enable ring-buffer
62 
63  // enable asynchronous logging feature (thread-safe)
65 
66  // load the configuration file
67  _dtnd.setLogging("DTNEngine", 1);
68 
69  // read configuration from registry
70  HKEY hKey = 0;
71  char buf[255] = {0};
72  DWORD dwType = 0;
73  DWORD dwBufSize = sizeof(buf);
74  DWORD dwValue = 0;
75 
76  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _subkey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
77  {
78  int logLevel = 1;
79 
80  dwType = REG_DWORD;
81  dwBufSize = sizeof(dwValue);
82  if ( RegQueryValueEx(hKey, "loglevel", NULL, &dwType, (LPBYTE)&dwValue, &dwBufSize) == ERROR_SUCCESS )
83  {
84  logLevel = dwValue;
85  }
86  else
87  {
88  error = true;
89  }
90 
91  dwType = REG_DWORD;
92  dwBufSize = sizeof(dwValue);
93  if ( RegQueryValueEx(hKey, "debuglevel", NULL, &dwType, (LPBYTE)&dwValue, &dwBufSize) == ERROR_SUCCESS )
94  {
95  _dtnd.setDebug(dwValue);
96  }
97  else
98  {
99  error = true;
100  }
101 
102  dwType = REG_SZ;
103  dwBufSize = sizeof(buf);
104  if ( RegQueryValueEx(hKey, "logfile", NULL, &dwType, (BYTE*)buf, &dwBufSize) == ERROR_SUCCESS )
105  {
106  _dtnd.setLogFile(buf, logLevel);
107  }
108  else
109  {
110  error = true;
111  }
112 
113  dwType = REG_SZ;
114  dwBufSize = sizeof(buf);
115  if ( RegQueryValueEx(hKey, "configfile", NULL, &dwType, (BYTE*)buf, &dwBufSize) == ERROR_SUCCESS )
116  {
117  _dtnd.setConfigFile(buf);
118  }
119  else
120  {
121  error = true;
122  }
123 
124  RegCloseKey(hKey);
125  }
126  else
127  {
128  // can not open registry
129  error = true;
130  }
131 
132  if (error) return -1;
133  return 0;
134 
135  // return -1 on failure
136  // return -1;
137 }
138 
139 void ControlHandler(DWORD request)
140 {
141  switch(request)
142  {
143  case SERVICE_CONTROL_STOP:
145  return;
146 
147  case SERVICE_CONTROL_SHUTDOWN:
149  return;
150 
151  default:
152  break;
153  }
154 
155  // Report current status
156  SetServiceStatus (hStatus, &ServiceStatus);
157 
158  return;
159 }
160 
161 void ServiceMain(int argc, char** argv) {
162  int error = 0;
163 
164  ServiceStatus.dwServiceType = SERVICE_WIN32;
165  ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
166  ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
167  ServiceStatus.dwWin32ExitCode = 0;
168  ServiceStatus.dwServiceSpecificExitCode = 0;
169  ServiceStatus.dwCheckPoint = 0;
170  ServiceStatus.dwWaitHint = 0;
171 
172  hStatus = RegisterServiceCtrlHandler("DtnStack", (LPHANDLER_FUNCTION)ControlHandler);
173 
174  if (hStatus == (SERVICE_STATUS_HANDLE)0)
175  {
176  // Registering Control Handler failed
177  return;
178  }
179 
180  // initialize the service
181  error = InitService();
182 
183  if (error)
184  {
185  // Initialization failed; we stop the service
186  ServiceStatus.dwCurrentState = SERVICE_STOPPED;
187  ServiceStatus.dwWin32ExitCode = error;
188  SetServiceStatus(hStatus, &ServiceStatus);
189 
190  // exit ServiceMain
191  return;
192  }
193 
194  // initialize the daemon up to runlevel "Routing Extensions"
196 
197  // We report the running status to SCM.
198  ServiceStatus.dwCurrentState = SERVICE_RUNNING;
199  SetServiceStatus (hStatus, &ServiceStatus);
200 
201  ibrcommon::MutexLock l(_shutdown_cond);
202  while (!_shutdown) _shutdown_cond.wait();
203 
205 
206  // stop the asynchronous logger
208 
209  // report the stop of the service to SCM
210  ServiceStatus.dwWin32ExitCode = 0;
211  ServiceStatus.dwCurrentState = SERVICE_STOPPED;
212  SetServiceStatus (hStatus, &ServiceStatus);
213 }
214 
215 int main()
216 {
217  SERVICE_TABLE_ENTRY ServiceTable[2];
218  ServiceTable[0].lpServiceName = LPSTR("IBR-DTN");
219  ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
220 
221  ServiceTable[1].lpServiceName = NULL;
222  ServiceTable[1].lpServiceProc = NULL;
223 
224  // Start the control dispatcher thread for our service
225  StartServiceCtrlDispatcher(ServiceTable);
226  return 0;
227 }
228