fixed Windows build error
[public/netxms.git] / src / server / core / main.cpp
CommitLineData
d9177dd1 1/*
5039dede 2** NetXMS - Network Management System
302bb0af 3** Copyright (C) 2003-2017 Raden Solutions
5039dede
AK
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19** File: main.cpp
20**
21**/
22
23#include "nxcore.h"
24#include <netxmsdb.h>
fdbee7f8 25#include <netxms_mt.h>
6fad8870 26#include <hdlink.h>
5039dede 27
b847803c 28#if !defined(_WIN32) && HAVE_READLINE_READLINE_H && HAVE_READLINE && !defined(UNICODE)
0322eed7
VK
29#include <readline/readline.h>
30#include <readline/history.h>
31#define USE_READLINE 1
5039dede
AK
32#endif
33
34#ifdef _WIN32
a23d8e0d
VK
35#include <errno.h>
36#include <psapi.h>
7bdb43c3 37#include <conio.h>
5039dede 38#else
a23d8e0d
VK
39#include <signal.h>
40#include <sys/wait.h>
5039dede
AK
41#endif
42
4ef60905
AK
43#ifdef WITH_ZMQ
44#include "zeromq.h"
45#endif
46
3a82d5ae
VK
47/**
48 * Messages generated by mc.pl (for UNIX version only)
49 */
5039dede
AK
50#ifndef _WIN32
51extern unsigned int g_dwNumMessages;
52extern const TCHAR *g_szMessages[];
53#endif
54
8f99849c
VK
55/**
56 * Shutdown reasons
57 */
030a0779
VK
58#define SHUTDOWN_DEFAULT 0
59#define SHUTDOWN_FROM_CONSOLE 1
60#define SHUTDOWN_BY_SIGNAL 2
5039dede 61
8f99849c
VK
62/**
63 * Externals
64 */
d140955e 65extern Queue g_dciCacheLoaderQueue;
5039dede 66
36e44abe 67void InitClientListeners();
534e1b83 68void InitMobileDeviceListeners();
36e44abe 69void InitCertificates();
cce82c3a 70bool LoadServerCertificate(RSA **serverKey);
ab185583
VK
71void InitUsers();
72void CleanupUsers();
8fd95c92 73void LoadPerfDataStorageDrivers();
03b96461 74void ImportLocalConfiguration();
288a0046 75void RegisterPredictionEngines();
cf4260a7 76void ExecuteStartupScripts();
bf306af3 77void CloseAgentTunnels();
ec13a467
VK
78
79void ExecuteScheduledScript(const ScheduledTaskParameters *param);
80void MaintenanceModeEnter(const ScheduledTaskParameters *params);
81void MaintenanceModeLeave(const ScheduledTaskParameters *params);
82deb2d7
TD
82void ScheduleDeployPolicy(const ScheduledTaskParameters *params);
83void ScheduleUninstallPolicy(const ScheduledTaskParameters * params);
058bf6fc 84
0de31ec3
VK
85void InitCountryList();
86void InitCurrencyList();
87
058bf6fc 88#if XMPP_SUPPORTED
098ef635 89void StartXMPPConnector();
244c65ef 90void StopXMPPConnector();
058bf6fc 91#endif
5039dede 92
534e1b83 93/**
af4a09df
VK
94 * Syslog server control
95 */
96void StartSyslogServer();
97void StopSyslogServer();
98
99/**
534e1b83
VK
100 * Thread functions
101 */
534e1b83
VK
102THREAD_RESULT THREAD_CALL Syncer(void *);
103THREAD_RESULT THREAD_CALL NodePoller(void *);
104THREAD_RESULT THREAD_CALL PollManager(void *);
105THREAD_RESULT THREAD_CALL EventProcessor(void *);
106THREAD_RESULT THREAD_CALL WatchdogThread(void *);
107THREAD_RESULT THREAD_CALL ClientListener(void *);
108THREAD_RESULT THREAD_CALL ClientListenerIPv6(void *);
109THREAD_RESULT THREAD_CALL MobileDeviceListener(void *);
110THREAD_RESULT THREAD_CALL MobileDeviceListenerIPv6(void *);
111THREAD_RESULT THREAD_CALL ISCListener(void *);
112THREAD_RESULT THREAD_CALL LocalAdminListener(void *);
113THREAD_RESULT THREAD_CALL SNMPTrapReceiver(void *);
534e1b83
VK
114THREAD_RESULT THREAD_CALL BeaconPoller(void *);
115THREAD_RESULT THREAD_CALL JobManagerThread(void *);
116THREAD_RESULT THREAD_CALL UptimeCalculator(void *);
d75003e1 117THREAD_RESULT THREAD_CALL ReportingServerConnector(void *);
bf306af3 118THREAD_RESULT THREAD_CALL TunnelListener(void *arg);
058bf6fc 119
534e1b83
VK
120/**
121 * Global variables
122 */
1039d7ee 123TCHAR NXCORE_EXPORTABLE g_szConfigFile[MAX_PATH] = _T("{search}");
5039dede 124TCHAR NXCORE_EXPORTABLE g_szLogFile[MAX_PATH] = DEFAULT_LOG_FILE;
458b5d2b
VK
125UINT32 g_logRotationMode = NXLOG_ROTATION_BY_SIZE;
126UINT64 g_maxLogSize = 16384 * 1024;
127UINT32 g_logHistorySize = 4;
4f8998ca 128TCHAR g_szDailyLogFileSuffix[64] = _T("");
5039dede 129TCHAR NXCORE_EXPORTABLE g_szDumpDir[MAX_PATH] = DEFAULT_DUMP_DIR;
29dc8792 130char g_szCodePage[256] = ICONV_DEFAULT_CODEPAGE;
5f6e8d09 131TCHAR NXCORE_EXPORTABLE g_szListenAddress[MAX_PATH] = _T("*");
5039dede 132#ifndef _WIN32
b07c50cc 133TCHAR NXCORE_EXPORTABLE g_szPIDFile[MAX_PATH] = _T("/var/run/netxmsd.pid");
5039dede 134#endif
967893bb
VK
135UINT32 g_dwDiscoveryPollingInterval;
136UINT32 g_dwStatusPollingInterval;
137UINT32 g_dwConfigurationPollingInterval;
138UINT32 g_dwRoutingTableUpdateInterval;
139UINT32 g_dwTopologyPollingInterval;
140UINT32 g_dwConditionPollingInterval;
805171de 141UINT32 g_instancePollingInterval;
c59466d2
VK
142UINT32 g_icmpPingSize;
143UINT32 g_icmpPingTimeout = 1500; // ICMP ping timeout (milliseconds)
144UINT32 g_auditFlags;
145UINT32 g_slmPollingInterval;
f6456d80 146UINT32 g_offlineDataRelevanceTime = 86400;
db6a6b45
VK
147TCHAR NXCORE_EXPORTABLE g_netxmsdDataDir[MAX_PATH] = _T("");
148TCHAR NXCORE_EXPORTABLE g_netxmsdLibDir[MAX_PATH] = _T("");
2a964810 149int g_dbSyntax = DB_SYNTAX_UNKNOWN;
967893bb 150UINT32 NXCORE_EXPORTABLE g_processAffinityMask = DEFAULT_AFFINITY_MASK;
e9902466 151UINT64 g_serverId = 0;
5039dede 152RSA *g_pServerKey = NULL;
c59466d2
VK
153time_t g_serverStartTime = 0;
154UINT32 g_lockTimeout = 60000; // Default timeout for acquiring mutex
155UINT32 g_agentCommandTimeout = 4000; // Default timeout for requests to agent
156UINT32 g_thresholdRepeatInterval = 0; // Disabled by default
157int g_requiredPolls = 1;
b8c1ec69 158DB_DRIVER g_dbDriver = NULL;
1ef6170e 159ThreadPool NXCORE_EXPORTABLE *g_mainThreadPool = NULL;
9708eff4 160INT16 g_defaultAgentCacheMode = AGENT_CACHE_OFF;
fbd0079b 161InetAddressList g_peerNodeAddrList;
4a64a795 162Condition g_dbPasswordReady(true);
5039dede 163
f375019e
VK
164/**
165 * Static data
166 */
5039dede
AK
167static CONDITION m_condShutdown = INVALID_CONDITION_HANDLE;
168static THREAD m_thPollManager = INVALID_THREAD_HANDLE;
5039dede 169static THREAD m_thSyncer = INVALID_THREAD_HANDLE;
bf306af3 170static THREAD s_tunnelListenerThread = INVALID_THREAD_HANDLE;
5039dede 171static int m_nShutdownReason = SHUTDOWN_DEFAULT;
4fd0b7ca 172static StringSet s_components;
5039dede
AK
173
174#ifndef _WIN32
175static pthread_t m_signalHandlerThread;
176#endif
177
496390c2 178/**
4fd0b7ca
VK
179 * Register component
180 */
181void NXCORE_EXPORTABLE RegisterComponent(const TCHAR *id)
182{
183 s_components.add(id);
184}
185
186/**
187 * Check if component with given ID is registered
188 */
189bool NXCORE_EXPORTABLE IsComponentRegistered(const TCHAR *id)
190{
191 return s_components.contains(id);
192}
193
194/**
195 * Fill NXCP message with components data
196 */
197void FillComponentsMessage(NXCPMessage *msg)
198{
199 msg->setField(VID_NUM_COMPONENTS, (INT32)s_components.size());
200 UINT32 fieldId = VID_COMPONENT_LIST_BASE;
201 Iterator<const TCHAR> *it = s_components.iterator();
202 while(it->hasNext())
203 {
204 msg->setField(fieldId++, it->next());
205 }
206 delete it;
207}
208
209/**
496390c2
VK
210 * Sleep for specified number of seconds or until system shutdown arrives
211 * Function will return TRUE if shutdown event occurs
212 *
213 * @param seconds seconds to sleep
214 * @return true if server is shutting down
215 */
400e55c4 216bool NXCORE_EXPORTABLE SleepAndCheckForShutdown(int seconds)
5039dede 217{
496390c2 218 return ConditionWait(m_condShutdown, seconds * 1000);
5039dede
AK
219}
220
496390c2
VK
221/**
222 * Disconnect from database (exportable function for startup module)
223 */
73869331 224void NXCORE_EXPORTABLE ShutdownDB()
5039dede 225{
9bd1bace 226 DBConnectionPoolShutdown();
b8c1ec69 227 DBUnloadDriver(g_dbDriver);
5039dede
AK
228}
229
496390c2
VK
230/**
231 * Check data directory for existence
232 */
35f836fe 233static BOOL CheckDataDir()
5039dede 234{
35f836fe 235 TCHAR szBuffer[MAX_PATH];
5039dede 236
db6a6b45 237 if (_tchdir(g_netxmsdDataDir) == -1)
5039dede 238 {
db6a6b45 239 nxlog_write(MSG_INVALID_DATA_DIR, EVENTLOG_ERROR_TYPE, "s", g_netxmsdDataDir);
5039dede
AK
240 return FALSE;
241 }
242
243#ifdef _WIN32
35f836fe 244#define MKDIR(name) _tmkdir(name)
5039dede 245#else
35f836fe 246#define MKDIR(name) _tmkdir(name, 0700)
5039dede
AK
247#endif
248
5039dede 249 // Create directory for package files if it doesn't exist
db6a6b45 250 _tcscpy(szBuffer, g_netxmsdDataDir);
35f836fe 251 _tcscat(szBuffer, DDIR_PACKAGES);
5039dede
AK
252 if (MKDIR(szBuffer) == -1)
253 if (errno != EEXIST)
254 {
255 nxlog_write(MSG_ERROR_CREATING_DATA_DIR, EVENTLOG_ERROR_TYPE, "s", szBuffer);
256 return FALSE;
257 }
258
4d0c32f3 259 // Create directory for map background images if it doesn't exist
db6a6b45 260 _tcscpy(szBuffer, g_netxmsdDataDir);
35f836fe 261 _tcscat(szBuffer, DDIR_BACKGROUNDS);
4d0c32f3
VK
262 if (MKDIR(szBuffer) == -1)
263 if (errno != EEXIST)
264 {
265 nxlog_write(MSG_ERROR_CREATING_DATA_DIR, EVENTLOG_ERROR_TYPE, "s", szBuffer);
266 return FALSE;
267 }
268
e6b9439a 269 // Create directory for image library is if does't exists
db6a6b45 270 _tcscpy(szBuffer, g_netxmsdDataDir);
e6b9439a
AK
271 _tcscat(szBuffer, DDIR_IMAGES);
272 if (MKDIR(szBuffer) == -1)
273 {
274 if (errno != EEXIST)
275 {
276 nxlog_write(MSG_ERROR_CREATING_DATA_DIR, EVENTLOG_ERROR_TYPE, "s", szBuffer);
277 return FALSE;
278 }
279 }
280
619e5c9b 281 // Create directory for file store if does't exists
db6a6b45 282 _tcscpy(szBuffer, g_netxmsdDataDir);
619e5c9b
VK
283 _tcscat(szBuffer, DDIR_FILES);
284 if (MKDIR(szBuffer) == -1)
285 {
286 if (errno != EEXIST)
287 {
288 nxlog_write(MSG_ERROR_CREATING_DATA_DIR, EVENTLOG_ERROR_TYPE, "s", szBuffer);
57fef75c
VK
289 return FALSE;
290 }
291 }
292
5039dede
AK
293#undef MKDIR
294
295 return TRUE;
296}
297
496390c2
VK
298/**
299 * Load global configuration parameters
300 */
5039dede
AK
301static void LoadGlobalConfig()
302{
35f836fe
VK
303 g_dwDiscoveryPollingInterval = ConfigReadInt(_T("DiscoveryPollingInterval"), 900);
304 g_dwStatusPollingInterval = ConfigReadInt(_T("StatusPollingInterval"), 60);
305 g_dwConfigurationPollingInterval = ConfigReadInt(_T("ConfigurationPollingInterval"), 3600);
805171de 306 g_instancePollingInterval = ConfigReadInt(_T("InstancePollingInterval"), 600);
35f836fe 307 g_dwRoutingTableUpdateInterval = ConfigReadInt(_T("RoutingTableUpdateInterval"), 300);
040c45fa 308 g_dwTopologyPollingInterval = ConfigReadInt(_T("TopologyPollingInterval"), 1800);
35f836fe 309 g_dwConditionPollingInterval = ConfigReadInt(_T("ConditionPollingInterval"), 60);
c59466d2 310 g_slmPollingInterval = ConfigReadInt(_T("SlmPollingInterval"), 60);
90e3031f
VK
311 DCObject::m_defaultPollingInterval = ConfigReadInt(_T("DefaultDCIPollingInterval"), 60);
312 DCObject::m_defaultRetentionTime = ConfigReadInt(_T("DefaultDCIRetentionTime"), 30);
9708eff4 313 g_defaultAgentCacheMode = (INT16)ConfigReadInt(_T("DefaultAgentCacheMode"), AGENT_CACHE_OFF);
e9902466
VK
314 if ((g_defaultAgentCacheMode != AGENT_CACHE_ON) && (g_defaultAgentCacheMode != AGENT_CACHE_OFF))
315 {
316 DbgPrintf(1, _T("Invalid value %d of DefaultAgentCacheMode: reset to %d (OFF)"), g_defaultAgentCacheMode, AGENT_CACHE_OFF);
317 ConfigWriteInt(_T("DefaultAgentCacheMode"), AGENT_CACHE_OFF, true, true, true);
c1f07289 318 g_defaultAgentCacheMode = AGENT_CACHE_OFF;
e9902466 319 }
35f836fe 320 if (ConfigReadInt(_T("DeleteEmptySubnets"), 1))
c8076b19 321 g_flags |= AF_DELETE_EMPTY_SUBNETS;
35f836fe 322 if (ConfigReadInt(_T("EnableSNMPTraps"), 1))
c8076b19
VK
323 g_flags |= AF_ENABLE_SNMP_TRAPD;
324 if (ConfigReadInt(_T("ProcessTrapsFromUnmanagedNodes"), 0))
325 g_flags |= AF_TRAPS_FROM_UNMANAGED_NODES;
35f836fe 326 if (ConfigReadInt(_T("EnableZoning"), 0))
c8076b19 327 g_flags |= AF_ENABLE_ZONING;
549f48b3 328 if (ConfigReadInt(_T("EnableObjectTransactions"), 0))
c8076b19 329 g_flags |= AF_ENABLE_OBJECT_TRANSACTIONS;
35f836fe 330 if (ConfigReadInt(_T("RunNetworkDiscovery"), 0))
c8076b19 331 g_flags |= AF_ENABLE_NETWORK_DISCOVERY;
35f836fe 332 if (ConfigReadInt(_T("ActiveNetworkDiscovery"), 0))
c8076b19 333 g_flags |= AF_ACTIVE_NETWORK_DISCOVERY;
e02953a4 334 if (ConfigReadInt(_T("UseSNMPTrapsForDiscovery"), 0))
c8076b19 335 g_flags |= AF_SNMP_TRAP_DISCOVERY;
727b90ff
VK
336 if (ConfigReadInt(_T("UseSyslogForDiscovery"), 0))
337 g_flags |= AF_SYSLOG_DISCOVERY;
35f836fe 338 if (ConfigReadInt(_T("ResolveNodeNames"), 1))
c8076b19 339 g_flags |= AF_RESOLVE_NODE_NAMES;
35f836fe 340 if (ConfigReadInt(_T("SyncNodeNamesWithDNS"), 0))
c8076b19 341 g_flags |= AF_SYNC_NODE_NAMES_WITH_DNS;
35f836fe 342 if (ConfigReadInt(_T("CheckTrustedNodes"), 1))
c8076b19 343 g_flags |= AF_CHECK_TRUSTED_NODES;
3bbc7435 344 if (ConfigReadInt(_T("EnableNXSLContainerFunctions"), 1))
c8076b19 345 g_flags |= AF_ENABLE_NXSL_CONTAINER_FUNCS;
f31c22b3 346 if (ConfigReadInt(_T("UseFQDNForNodeNames"), 1))
c8076b19 347 g_flags |= AF_USE_FQDN_FOR_NODE_NAMES;
098ef635 348 if (ConfigReadInt(_T("ApplyDCIFromTemplateToDisabledDCI"), 1))
c8076b19 349 g_flags |= AF_APPLY_TO_DISABLED_DCI_FROM_TEMPLATE;
4553d424 350 if (ConfigReadInt(_T("ResolveDNSToIPOnStatusPoll"), 0))
385b1f20 351 g_flags |= AF_RESOLVE_IP_FOR_EACH_STATUS_POLL;
8a1519ce
VK
352 if (ConfigReadInt(_T("CaseInsensitiveLoginNames"), 0))
353 g_flags |= AF_CASE_INSENSITIVE_LOGINS;
0eff2ce4
VK
354 if (ConfigReadInt(_T("TrapSourcesInAllZones"), 0))
355 g_flags |= AF_TRAP_SOURCES_IN_ALL_ZONES;
fc958888 356
db6a6b45 357 if (g_netxmsdDataDir[0] == 0)
f31c22b3 358 {
1039d7ee
VK
359 GetNetXMSDirectory(nxDirData, g_netxmsdDataDir);
360 DbgPrintf(1, _T("Data directory set to %s"), g_netxmsdDataDir);
f31c22b3
VK
361 }
362 else
363 {
db6a6b45 364 DbgPrintf(1, _T("Using data directory %s"), g_netxmsdDataDir);
f31c22b3 365 }
d96bd4c7 366
c59466d2
VK
367 g_icmpPingTimeout = ConfigReadInt(_T("IcmpPingTimeout"), 1500);
368 g_icmpPingSize = ConfigReadInt(_T("IcmpPingSize"), 46);
369 g_lockTimeout = ConfigReadInt(_T("LockTimeout"), 60000);
c59466d2
VK
370 g_agentCommandTimeout = ConfigReadInt(_T("AgentCommandTimeout"), 4000);
371 g_thresholdRepeatInterval = ConfigReadInt(_T("ThresholdRepeatInterval"), 0);
372 g_requiredPolls = ConfigReadInt(_T("PollCountForStatusChange"), 1);
f6456d80 373 g_offlineDataRelevanceTime = ConfigReadInt(_T("OfflineDataRelevanceTime"), 86400);
296ae03d 374
014fbefc 375 UINT32 snmpTimeout = ConfigReadInt(_T("SNMPRequestTimeout"), 1500);
296ae03d 376 SnmpSetDefaultTimeout(snmpTimeout);
5039dede
AK
377}
378
fdbee7f8
VK
379/**
380 * Initialize cryptografic functions
381 */
cce82c3a 382static bool InitCryptografy()
5039dede
AK
383{
384#ifdef _WITH_ENCRYPTION
cce82c3a 385 bool success = false;
5039dede 386
2df047f4 387 if (!InitCryptoLib(ConfigReadULong(_T("AllowedCiphers"), 0x7F)))
5039dede 388 return FALSE;
2df047f4 389 nxlog_debug(4, _T("Supported ciphers: %s"), (const TCHAR *)NXCPGetSupportedCiphersAsText());
5039dede 390
958a9397 391 SSL_library_init();
0fd5c0a1 392 SSL_load_error_strings();
958a9397 393
cce82c3a
VK
394 if (LoadServerCertificate(&g_pServerKey))
395 {
396 nxlog_debug(1, _T("Server certificate loaded"));
397 }
398 if (g_pServerKey != NULL)
399 {
400 nxlog_debug(1, _T("Using server certificate key"));
401 success = true;
402 }
403 else
404 {
405 TCHAR szKeyFile[MAX_PATH];
406 _tcscpy(szKeyFile, g_netxmsdDataDir);
407 _tcscat(szKeyFile, DFILE_KEYS);
408 g_pServerKey = LoadRSAKeys(szKeyFile);
409 if (g_pServerKey == NULL)
410 {
411 nxlog_debug(1, _T("Generating RSA key pair..."));
3b89a4c1 412 g_pServerKey = RSA_generate_key(NETXMS_RSA_KEYLEN, 17, NULL, NULL);
cce82c3a
VK
413 if (g_pServerKey != NULL)
414 {
415 int fd = _topen(szKeyFile, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, 0600);
416 if (fd != -1)
417 {
418 UINT32 dwLen = i2d_RSAPublicKey(g_pServerKey, NULL);
419 dwLen += i2d_RSAPrivateKey(g_pServerKey, NULL);
420 BYTE *pKeyBuffer = (BYTE *)malloc(dwLen);
421
422 BYTE *pBufPos = pKeyBuffer;
423 i2d_RSAPublicKey(g_pServerKey, &pBufPos);
424 i2d_RSAPrivateKey(g_pServerKey, &pBufPos);
425 _write(fd, &dwLen, sizeof(UINT32));
426 _write(fd, pKeyBuffer, dwLen);
427
428 BYTE hash[SHA1_DIGEST_SIZE];
429 CalculateSHA1Hash(pKeyBuffer, dwLen, hash);
430 _write(fd, hash, SHA1_DIGEST_SIZE);
431
432 _close(fd);
433 free(pKeyBuffer);
434 success = true;
435 }
436 else
437 {
438 nxlog_debug(0, _T("Failed to open %s for writing"), szKeyFile);
439 }
440 }
2df047f4
VK
441 else
442 {
cce82c3a 443 nxlog_debug(0, _T("Failed to generate RSA key"));
2df047f4 444 }
cce82c3a 445 }
c578be51
AK
446 else
447 {
cce82c3a 448 success = true;
c578be51 449 }
cce82c3a 450 }
5039dede 451
a3ef278b 452 int iPolicy = ConfigReadInt(_T("DefaultEncryptionPolicy"), 1);
5039dede
AK
453 if ((iPolicy < 0) || (iPolicy > 3))
454 iPolicy = 1;
455 SetAgentDEP(iPolicy);
456
cce82c3a 457 return success;
5039dede
AK
458#else
459 return TRUE;
460#endif
461}
462
496390c2
VK
463/**
464 * Check if process with given PID exists and is a NetXMS server process
465 */
fbd0079b 466static bool IsNetxmsdProcess(UINT32 pid)
5039dede
AK
467{
468#ifdef _WIN32
fbd0079b
VK
469 bool result = false;
470 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
5039dede
AK
471 if (hProcess != NULL)
472 {
fbd0079b 473 TCHAR szExtModule[MAX_PATH], szIntModule[MAX_PATH];
5039dede 474 if ((GetModuleBaseName(hProcess, NULL, szExtModule, MAX_PATH) > 0) &&
fbd0079b 475 (GetModuleBaseName(GetCurrentProcess(), NULL, szIntModule, MAX_PATH) > 0))
5039dede 476 {
fbd0079b 477 result = (_tcsicmp(szExtModule, szIntModule) == 0);
5039dede
AK
478 }
479 else
480 {
481 // Cannot read process name, for safety assume that it's a server process
fbd0079b 482 result = true;
5039dede
AK
483 }
484 CloseHandle(hProcess);
485 }
fbd0079b 486 return result;
5039dede 487#else
fbd0079b 488 return kill((pid_t)pid, 0) != -1;
5039dede
AK
489#endif
490}
491
496390c2 492/**
fbd0079b
VK
493 * Check if remote netxmsd is running
494 */
495static bool PeerNodeIsRunning(const InetAddress& addr)
496{
497 bool result = false;
498
499 TCHAR keyFile[MAX_PATH];
500 _tcscpy(keyFile, g_netxmsdDataDir);
501 _tcscat(keyFile, DFILE_KEYS);
502 RSA *key = LoadRSAKeys(keyFile);
503
504 AgentConnection *ac = new AgentConnection(addr);
505 if (ac->connect(key))
506 {
507 TCHAR result[MAX_RESULT_LENGTH];
508#ifdef _WIN32
509 UINT32 rcc = ac->getParameter(_T("Process.Count(netxmsd.exe)"), MAX_RESULT_LENGTH, result);
510#else
511 UINT32 rcc = ac->getParameter(_T("Process.Count(netxmsd)"), MAX_RESULT_LENGTH, result);
512#endif
513 ac->decRefCount();
514 if (key != NULL)
515 RSA_free(key);
516 if (rcc == ERR_SUCCESS)
517 {
518 return _tcstol(result, NULL, 10) > 0;
519 }
520 }
521 else
522 {
523 ac->decRefCount();
524 if (key != NULL)
525 RSA_free(key);
526 }
527
528 UINT16 port = (UINT16)ConfigReadInt(_T("ClientListenerPort"), SERVER_LISTEN_PORT_FOR_CLIENTS);
529 SOCKET s = ConnectToHost(addr, port, 5000);
530 if (s != INVALID_SOCKET)
531 {
532 shutdown(s, SHUT_RDWR);
533 closesocket(s);
534 result = true;
535 }
536 return result;
537}
538
539/**
496390c2
VK
540 * Database event handler
541 */
526ae8b8 542static void DBEventHandler(DWORD dwEvent, const WCHAR *pszArg1, const WCHAR *pszArg2, bool connLost, void *userArg)
5039dede 543{
c8076b19 544 if (!(g_flags & AF_SERVER_INITIALIZED))
5039dede
AK
545 return; // Don't try to do anything if server is not ready yet
546
547 switch(dwEvent)
548 {
549 case DBEVENT_CONNECTION_LOST:
550 PostEvent(EVENT_DB_CONNECTION_LOST, g_dwMgmtNode, NULL);
c8076b19 551 g_flags |= AF_DB_CONNECTION_LOST;
5039dede
AK
552 NotifyClientSessions(NX_NOTIFY_DBCONN_STATUS, FALSE);
553 break;
554 case DBEVENT_CONNECTION_RESTORED:
555 PostEvent(EVENT_DB_CONNECTION_RESTORED, g_dwMgmtNode, NULL);
c8076b19 556 g_flags &= ~AF_DB_CONNECTION_LOST;
5039dede
AK
557 NotifyClientSessions(NX_NOTIFY_DBCONN_STATUS, TRUE);
558 break;
4d0c32f3 559 case DBEVENT_QUERY_FAILED:
526ae8b8 560 PostEvent(EVENT_DB_QUERY_FAILED, g_dwMgmtNode, "uud", pszArg1, pszArg2, connLost ? 1 : 0);
4d0c32f3 561 break;
5039dede
AK
562 default:
563 break;
564 }
565}
566
496390c2
VK
567/**
568 * Send console message to session with open console
569 */
f669df41
VK
570static void SendConsoleMessage(ClientSession *session, void *arg)
571{
572 if (session->isConsoleOpen())
573 {
b368969c 574 NXCPMessage msg;
f669df41 575
b368969c
VK
576 msg.setCode(CMD_ADM_MESSAGE);
577 msg.setField(VID_MESSAGE, (TCHAR *)arg);
d3a7cf4c 578 session->postMessage(&msg);
f669df41
VK
579 }
580}
581
d6217efa
VK
582/**
583 * Console writer
584 */
f669df41
VK
585static void LogConsoleWriter(const TCHAR *format, ...)
586{
587 TCHAR buffer[8192];
588 va_list args;
589
590 va_start(args, format);
591 _vsntprintf(buffer, 8192, format, args);
592 buffer[8191] = 0;
593 va_end(args);
594
595 WriteToTerminal(buffer);
596
597 EnumerateClientSessions(SendConsoleMessage, buffer);
598}
599
fdbee7f8 600/**
b6aff59d
VK
601 * Oracle session init callback
602 */
603static void OracleSessionInitCallback(DB_HANDLE hdb)
604{
605 DBQuery(hdb, _T("ALTER SESSION SET DDL_LOCK_TIMEOUT = 60"));
606}
607
608/**
4a64a795
VK
609 * Get database password
610 */
611static void GetDatabasePassword()
612{
613 if (_tcscmp(g_szDbPassword, _T("?")))
614 return;
615
616 nxlog_write(MSG_WAITING_FOR_DB_PASSWORD, NXLOG_INFO, NULL);
617 g_dbPasswordReady.wait(INFINITE);
618 nxlog_debug(1, _T("Database password received"));
619}
620
621/**
fdbee7f8
VK
622 * Server initialization
623 */
bc980b27 624BOOL NXCORE_EXPORTABLE Initialize()
5039dede 625{
4fd0b7ca 626 s_components.add(_T("CORE"));
5039dede 627
c59466d2
VK
628 g_serverStartTime = time(NULL);
629 srand((unsigned int)g_serverStartTime);
4f8998ca 630
c8076b19 631 if (!(g_flags & AF_USE_SYSLOG))
4f8998ca 632 {
458b5d2b 633 if (!nxlog_set_rotation_policy((int)g_logRotationMode, g_maxLogSize, (int)g_logHistorySize, g_szDailyLogFileSuffix))
c8076b19 634 if (!(g_flags & AF_DAEMON))
4f8998ca
VK
635 _tprintf(_T("WARNING: cannot set log rotation policy; using default values\n"));
636 }
c8076b19 637 if (!nxlog_open((g_flags & AF_USE_SYSLOG) ? NETXMSD_SYSLOG_NAME : g_szLogFile,
2589cc10 638 ((g_flags & AF_USE_SYSLOG) ? NXLOG_USE_SYSLOG : 0) |
639 ((g_flags & AF_BACKGROUND_LOG_WRITER) ? NXLOG_BACKGROUND_WRITER : 0) |
4e0e77e6 640 ((g_flags & AF_DAEMON) ? 0 : NXLOG_PRINT_TO_STDOUT),
9d381279 641 _T("LIBNXSRV.DLL"),
5039dede 642#ifdef _WIN32
7615283c 643 0, NULL, MSG_DEBUG, MSG_OTHER))
5039dede 644#else
90a9e65e 645 g_dwNumMessages, g_szMessages, MSG_DEBUG, MSG_OTHER))
5039dede 646#endif
9d381279
VK
647 {
648 _ftprintf(stderr, _T("FATAL ERROR: Cannot open log file\n"));
649 return FALSE;
650 }
f669df41 651 nxlog_set_console_writer(LogConsoleWriter);
5039dede 652
2df047f4
VK
653 if (g_netxmsdLibDir[0] == 0)
654 {
655 GetNetXMSDirectory(nxDirLib, g_netxmsdLibDir);
656 nxlog_debug(1, _T("LIB directory set to %s"), g_netxmsdLibDir);
657 }
658
5039dede
AK
659 // Set code page
660#ifndef _WIN32
661 if (SetDefaultCodepage(g_szCodePage))
662 {
f5797a09 663 DbgPrintf(1, _T("Code page set to %hs"), g_szCodePage);
5039dede
AK
664 }
665 else
666 {
f375019e 667 nxlog_write(MSG_CODEPAGE_ERROR, EVENTLOG_WARNING_TYPE, "m", g_szCodePage);
5039dede
AK
668 }
669#endif
670
73869331
VK
671 // Set process affinity mask
672 if (g_processAffinityMask != DEFAULT_AFFINITY_MASK)
673 {
674#ifdef _WIN32
675 if (SetProcessAffinityMask(GetCurrentProcess(), g_processAffinityMask))
2df047f4 676 nxlog_debug(1, _T("Process affinity mask set to 0x%08X"), g_processAffinityMask);
73869331
VK
677#else
678 nxlog_write(MSG_SET_PROCESS_AFFINITY_NOT_SUPPORTED, EVENTLOG_WARNING_TYPE, NULL);
679#endif
680 }
681
5039dede
AK
682#ifdef _WIN32
683 WSADATA wsaData;
1ddf3f0c
VK
684 int wrc = WSAStartup(MAKEWORD(2, 2), &wsaData);
685 if (wrc != 0)
686 {
687 nxlog_write(MSG_WSASTARTUP_FAILED, EVENTLOG_ERROR_TYPE, "e", wrc);
688 return FALSE;
689 }
5039dede
AK
690#endif
691
692 InitLocalNetInfo();
296ae03d 693 SnmpSetMessageIds(MSG_OID_PARSE_ERROR, MSG_SNMP_UNKNOWN_TYPE, MSG_SNMP_GET_ERROR);
5039dede
AK
694
695 // Create queue for delayed SQL queries
76fcb995
VK
696 g_dbWriterQueue = new Queue(256, 64);
697 g_dciDataWriterQueue = new Queue(1024, 1024);
698 g_dciRawDataWriterQueue = new Queue(1024, 1024);
5039dede
AK
699
700 // Initialize database driver and connect to database
c8076b19 701 if (!DBInit(MSG_OTHER, (g_flags & AF_LOG_SQL_ERRORS) ? MSG_SQL_ERROR : 0))
b8c1ec69 702 return FALSE;
2df047f4 703 g_dbDriver = DBLoadDriver(g_szDbDriver, g_szDbDrvParams, (nxlog_get_debug_level() >= 9), DBEventHandler, NULL);
b8c1ec69 704 if (g_dbDriver == NULL)
5039dede
AK
705 return FALSE;
706
4a64a795
VK
707 // Start local administrative interface listener if required
708 if (g_flags & AF_ENABLE_LOCAL_CONSOLE)
709 ThreadCreate(LocalAdminListener, 0, NULL);
710
711 // Wait for database password if needed
712 GetDatabasePassword();
713
5039dede 714 // Connect to database
9bd1bace 715 DB_HANDLE hdbBootstrap = NULL;
465b3f2d 716 TCHAR errorText[DBDRV_MAX_ERROR_TEXT];
4fd0b7ca 717 for(int i = 0; ; i++)
5039dede 718 {
9bd1bace
VK
719 hdbBootstrap = DBConnect(g_dbDriver, g_szDbServer, g_szDbName, g_szDbLogin, g_szDbPassword, g_szDbSchema, errorText);
720 if ((hdbBootstrap != NULL) || (i == 5))
5039dede
AK
721 break;
722 ThreadSleep(5);
723 }
9bd1bace 724 if (hdbBootstrap == NULL)
5039dede 725 {
465b3f2d 726 nxlog_write(MSG_DB_CONNFAIL, EVENTLOG_ERROR_TYPE, "s", errorText);
5039dede
AK
727 return FALSE;
728 }
2df047f4 729 nxlog_debug(1, _T("Successfully connected to database %s@%s"), g_szDbName, g_szDbServer);
5039dede 730
4fd0b7ca
VK
731 // Check database schema version
732 int schemaVersion = DBGetSchemaVersion(hdbBootstrap);
733 if (schemaVersion != DB_FORMAT_VERSION)
5039dede 734 {
4fd0b7ca 735 nxlog_write(MSG_WRONG_DB_VERSION, EVENTLOG_ERROR_TYPE, "dd", schemaVersion, DB_FORMAT_VERSION);
9bd1bace 736 DBDisconnect(hdbBootstrap);
5039dede
AK
737 return FALSE;
738 }
739
b6aff59d 740 // Read database syntax
9bd1bace 741 g_dbSyntax = DBGetSyntax(hdbBootstrap);
b6aff59d
VK
742 if (g_dbSyntax == DB_SYNTAX_ORACLE)
743 {
744 DBSetSessionInitCallback(OracleSessionInitCallback);
745 }
746
9bd1bace
VK
747 int baseSize = ConfigReadIntEx(hdbBootstrap, _T("DBConnectionPoolBaseSize"), 10);
748 int maxSize = ConfigReadIntEx(hdbBootstrap, _T("DBConnectionPoolMaxSize"), 30);
749 int cooldownTime = ConfigReadIntEx(hdbBootstrap, _T("DBConnectionPoolCooldownTime"), 300);
750 int ttl = ConfigReadIntEx(hdbBootstrap, _T("DBConnectionPoolMaxLifetime"), 14400);
751
752 DBDisconnect(hdbBootstrap);
753
754 if (!DBConnectionPoolStartup(g_dbDriver, g_szDbServer, g_szDbName, g_szDbLogin, g_szDbPassword, g_szDbSchema, baseSize, maxSize, cooldownTime, ttl))
755 {
756 nxlog_write(MSG_DBCONNPOOL_INIT_FAILED, EVENTLOG_ERROR_TYPE, NULL);
757 return FALSE;
758 }
f727d089 759
58f1f627
VK
760 UINT32 lrt = ConfigReadULong(_T("LongRunningQueryThreshold"), 0);
761 if (lrt != 0)
762 DBSetLongRunningThreshold(lrt);
763
0fdb37c6
VK
764 MetaDataPreLoad();
765
5039dede 766 // Read server ID
4fd0b7ca
VK
767 TCHAR buffer[256];
768 MetaDataReadStr(_T("ServerID"), buffer, 256, _T(""));
769 StrStrip(buffer);
770 if (buffer[0] != 0)
5039dede 771 {
4fd0b7ca 772 g_serverId = _tcstoull(buffer, NULL, 16);
5039dede
AK
773 }
774 else
775 {
776 // Generate new ID
e9902466 777 g_serverId = ((UINT64)time(NULL) << 31) | (UINT64)((UINT32)rand() & 0x7FFFFFFF);
4fd0b7ca
VK
778 _sntprintf(buffer, 256, UINT64X_FMT(_T("016")), g_serverId);
779 MetaDataWriteStr(_T("ServerID"), buffer);
5039dede 780 }
2df047f4 781 nxlog_debug(1, _T("Server ID ") UINT64X_FMT(_T("016")), g_serverId);
5039dede
AK
782
783 // Initialize locks
784retry_db_lock:
c30c0c0f 785 InetAddress addr;
4fd0b7ca 786 if (!InitLocks(&addr, buffer))
5039dede 787 {
fbd0079b 788 if (addr.isValidUnicast()) // Database already locked by another server instance
5039dede
AK
789 {
790 // Check for lock from crashed/terminated local process
c30c0c0f 791 if (GetLocalIpAddr().equals(addr))
5039dede 792 {
fbd0079b
VK
793 UINT32 pid = ConfigReadULong(_T("DBLockPID"), 0);
794 if (!IsNetxmsdProcess(pid) || (pid == GetCurrentProcessId()))
5039dede
AK
795 {
796 UnlockDB();
797 nxlog_write(MSG_DB_LOCK_REMOVED, EVENTLOG_INFORMATION_TYPE, NULL);
798 goto retry_db_lock;
799 }
800 }
fbd0079b
VK
801 else if (g_peerNodeAddrList.hasAddress(addr))
802 {
803 if (!PeerNodeIsRunning(addr))
804 {
805 UnlockDB();
806 nxlog_write(MSG_DB_LOCK_REMOVED, EVENTLOG_INFORMATION_TYPE, NULL);
807 goto retry_db_lock;
808 }
809 }
d94ada36 810 nxlog_write(MSG_DB_LOCKED, EVENTLOG_ERROR_TYPE, "Is", &addr, buffer);
5039dede 811 }
fbd0079b
VK
812 else
813 {
814 nxlog_write(MSG_INIT_LOCKS_FAILED, EVENTLOG_ERROR_TYPE, NULL);
815 }
5039dede
AK
816 return FALSE;
817 }
c8076b19 818 g_flags |= AF_DB_LOCKED;
5039dede
AK
819
820 // Load global configuration parameters
821 LoadGlobalConfig();
958a9397 822 CASReadSettings();
2df047f4 823 nxlog_debug(1, _T("Global configuration loaded"));
5039dede
AK
824
825 // Check data directory
826 if (!CheckDataDir())
827 return FALSE;
828
829 // Initialize cryptografy
830 if (!InitCryptografy())
831 {
832 nxlog_write(MSG_INIT_CRYPTO_FAILED, EVENTLOG_ERROR_TYPE, NULL);
833 return FALSE;
834 }
835
836 // Initialize certificate store and CA
837 InitCertificates();
838
5039dede
AK
839 // Create synchronization stuff
840 m_condShutdown = ConditionCreate(TRUE);
841
5d3459af 842 // Create thread pools
2df047f4 843 nxlog_debug(2, _T("Creating thread pools"));
5d3459af 844 g_mainThreadPool = ThreadPoolCreate(8, 256, _T("MAIN"));
1693f955 845 g_agentConnectionThreadPool = ThreadPoolCreate(4, 256, _T("AGENT"));
5d3459af 846
5039dede
AK
847 // Setup unique identifiers table
848 if (!InitIdTable())
849 return FALSE;
2df047f4 850 nxlog_debug(2, _T("ID table created"));
5039dede 851
0de31ec3
VK
852 InitCountryList();
853 InitCurrencyList();
854
24dc5346 855 // Update status for unfinished jobs in job history
9bd1bace
VK
856 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
857 DBQuery(hdb, _T("UPDATE job_history SET status=4,failure_message='Aborted due to server shutdown or crash' WHERE status NOT IN (3,4,5)"));
858 DBConnectionPoolReleaseConnection(hdb);
24dc5346 859
5039dede
AK
860 // Load and compile scripts
861 LoadScripts();
862
00420032 863 // Initialize persistent storage
864 PersistentStorageInit();
865
f7e4c50e
VK
866 // Initialize watchdog
867 WatchdogInit();
868
53d2de79 869 // Load modules
890478d8
VK
870 if (!LoadNetXMSModules())
871 return FALSE; // Mandatory module not loaded
288a0046 872 RegisterPredictionEngines();
53d2de79 873
5039dede
AK
874 // Initialize mailer and SMS sender
875 InitMailer();
876 InitSMSSender();
877
878 // Load users from database
ab185583 879 InitUsers();
5039dede
AK
880 if (!LoadUsers())
881 {
882 nxlog_write(MSG_ERROR_LOADING_USERS, EVENTLOG_ERROR_TYPE, NULL);
883 return FALSE;
884 }
2df047f4 885 nxlog_debug(2, _T("User accounts loaded"));
5039dede
AK
886
887 // Initialize audit
888 InitAuditLog();
889
da84c57a
VK
890 // Initialize event handling subsystem
891 if (!InitEventSubsystem())
892 return FALSE;
893
894 // Initialize alarms
e30c2442 895 LoadAlarmCategories();
da84c57a
VK
896 if (!InitAlarmManager())
897 return FALSE;
898
5039dede 899 // Initialize objects infrastructure and load objects from database
9796ce45 900 LoadNetworkDeviceDrivers();
5039dede
AK
901 ObjectsInit();
902 if (!LoadObjects())
903 return FALSE;
2df047f4 904 nxlog_debug(1, _T("Objects loaded and initialized"));
d9177dd1 905
5039dede
AK
906 // Initialize and load event actions
907 if (!InitActions())
908 {
909 nxlog_write(MSG_ACTION_INIT_ERROR, EVENTLOG_ERROR_TYPE, NULL);
910 return FALSE;
911 }
912
6fad8870
VK
913 // Initialize helpdesk link
914 SetHDLinkEntryPoints(ResolveAlarmByHDRef, TerminateAlarmByHDRef);
915 LoadHelpDeskLink();
916
5039dede 917 // Initialize data collection subsystem
8fd95c92 918 LoadPerfDataStorageDrivers();
5039dede
AK
919 if (!InitDataCollector())
920 return FALSE;
921
e05b1945 922 InitLogAccess();
d77baddd 923 FileUploadJob::init();
fdbee7f8 924 InitMappingTables();
e05b1945 925
03b96461
VK
926 InitClientListeners();
927 if (ConfigReadInt(_T("ImportConfigurationOnStartup"), 1))
928 ImportLocalConfiguration();
929
5039dede
AK
930 // Check if management node object presented in database
931 CheckForMgmtNode();
932 if (g_dwMgmtNode == 0)
933 {
934 nxlog_write(MSG_CANNOT_FIND_SELF, EVENTLOG_ERROR_TYPE, NULL);
935 return FALSE;
936 }
937
938 // Start threads
939 ThreadCreate(WatchdogThread, 0, NULL);
940 ThreadCreate(NodePoller, 0, NULL);
3929b1ca 941 ThreadCreate(JobManagerThread, 0, NULL);
5039dede 942 m_thSyncer = ThreadCreateEx(Syncer, 0, NULL);
5039dede
AK
943 m_thPollManager = ThreadCreateEx(PollManager, 0, NULL);
944
a64c346b
VK
945 StartHouseKeeper();
946
5039dede
AK
947 // Start event processor
948 ThreadCreate(EventProcessor, 0, NULL);
949
950 // Start SNMP trapper
951 InitTraps();
35f836fe 952 if (ConfigReadInt(_T("EnableSNMPTraps"), 1))
5039dede
AK
953 ThreadCreate(SNMPTrapReceiver, 0, NULL);
954
955 // Start built-in syslog daemon
685508a7 956 StartSyslogServer();
5039dede 957
35f836fe 958 // Start database _T("lazy") write thread
5039dede
AK
959 StartDBWriter();
960
5039dede
AK
961 // Start beacon host poller
962 ThreadCreate(BeaconPoller, 0, NULL);
963
964 // Start inter-server communication listener
35f836fe 965 if (ConfigReadInt(_T("EnableISCListener"), 0))
5039dede
AK
966 ThreadCreate(ISCListener, 0, NULL);
967
d75003e1
AK
968 // Start reporting server connector
969 if (ConfigReadInt(_T("EnableReportingServer"), 0))
970 ThreadCreate(ReportingServerConnector, 0, NULL);
971
d9177dd1 972 //Start ldap synchronization
973 if (ConfigReadInt(_T("LdapSyncInterval"), 0))
974 ThreadCreate(SyncLDAPUsers, 0, NULL);
975
ec13a467
VK
976 RegisterSchedulerTaskHandler(_T("Execute.Script"), ExecuteScheduledScript, SYSTEM_ACCESS_SCHEDULE_SCRIPT);
977 RegisterSchedulerTaskHandler(_T("Maintenance.Enter"), MaintenanceModeEnter, SYSTEM_ACCESS_SCHEDULE_MAINTENANCE);
978 RegisterSchedulerTaskHandler(_T("Maintenance.Leave"), MaintenanceModeLeave, SYSTEM_ACCESS_SCHEDULE_MAINTENANCE);
82deb2d7
TD
979 RegisterSchedulerTaskHandler(_T("Policy.Deploy"), ScheduleDeployPolicy, 0); //No access right beacause it will be used only by server
980 RegisterSchedulerTaskHandler(_T("Policy.Uninstall"), ScheduleUninstallPolicy, 0); //No access right beacause it will be used only by server
ed0a30ba 981 RegisterSchedulerTaskHandler(ALARM_SUMMARY_EMAIL_TASK_ID, SendAlarmSummaryEmail, 0); //No access right beacause it will be used only by server
0a145c10 982 InitializeTaskScheduler();
983
f14e669f
EJ
984 // Send summary emails
985 if (ConfigReadInt(_T("EnableAlarmSummaryEmails"), 0))
986 EnableAlarmSummaryEmails();
987 else
ed0a30ba 988 RemoveScheduledTaskByHandlerId(ALARM_SUMMARY_EMAIL_TASK_ID);
f14e669f 989
5039dede
AK
990 // Allow clients to connect
991 ThreadCreate(ClientListener, 0, NULL);
36e44abe
VK
992#ifdef WITH_IPV6
993 ThreadCreate(ClientListenerIPv6, 0, NULL);
994#endif
5039dede 995
534e1b83
VK
996 // Allow mobile devices to connect
997 InitMobileDeviceListeners();
998 ThreadCreate(MobileDeviceListener, 0, NULL);
999#ifdef WITH_IPV6
1000 ThreadCreate(MobileDeviceListenerIPv6, 0, NULL);
1001#endif
1002
bf306af3
VK
1003 // Agent tunnels
1004 s_tunnelListenerThread = ThreadCreateEx(TunnelListener, 0, NULL);
1005
86457857
AK
1006 // Start uptime calculator for SLM
1007 ThreadCreate(UptimeCalculator, 0, NULL);
1008
2df047f4 1009 nxlog_debug(2, _T("LIBDIR: %s"), g_netxmsdLibDir);
712dd47d 1010
1b42a673 1011 // Call startup functions for the modules
a0efa7b5 1012 CALL_ALL_MODULES(pfServerStarted, ());
53d2de79 1013
058bf6fc 1014#if XMPP_SUPPORTED
244c65ef
VK
1015 if (ConfigReadInt(_T("EnableXMPPConnector"), 1))
1016 {
098ef635 1017 StartXMPPConnector();
244c65ef 1018 }
058bf6fc 1019#endif
244c65ef 1020
9df36f62
AK
1021#if WITH_ZMQ
1022 StartZMQConnector();
1023#endif
1024
cf4260a7
VK
1025 ExecuteStartupScripts();
1026
c8076b19 1027 g_flags |= AF_SERVER_INITIALIZED;
2df047f4 1028 nxlog_debug(1, _T("Server initialization completed"));
5039dede
AK
1029 return TRUE;
1030}
1031
371d9c60
VK
1032/**
1033 * Server shutdown
1034 */
035a4d73 1035void NXCORE_EXPORTABLE Shutdown()
5039dede 1036{
5039dede
AK
1037 // Notify clients
1038 NotifyClientSessions(NX_NOTIFY_SHUTDOWN, 0);
1039
1040 nxlog_write(MSG_SERVER_STOPPED, EVENTLOG_INFORMATION_TYPE, NULL);
c8076b19 1041 g_flags |= AF_SHUTDOWN; // Set shutdown flag
5039dede
AK
1042 ConditionSet(m_condShutdown);
1043
0a145c10 1044 CloseTaskScheduler();
1045
d140955e 1046 // Stop DCI cache loading thread
19dbc8ef 1047 g_dciCacheLoaderQueue.setShutdownMode();
d140955e 1048
058bf6fc 1049#if XMPP_SUPPORTED
244c65ef 1050 StopXMPPConnector();
058bf6fc 1051#endif
244c65ef 1052
9df36f62
AK
1053#if WITH_ZMQ
1054 StopZMQConnector();
1055#endif
1056
19dbc8ef
VK
1057 g_pEventQueue->clear();
1058 g_pEventQueue->put(INVALID_POINTER_VALUE);
5039dede
AK
1059
1060 ShutdownMailer();
1061 ShutdownSMSSender();
1062
1063 ThreadSleep(1); // Give other threads a chance to terminate in a safe way
2df047f4 1064 nxlog_debug(2, _T("All threads was notified, continue with shutdown"));
5039dede 1065
af4a09df 1066 StopSyslogServer();
a64c346b 1067 StopHouseKeeper();
af4a09df 1068
5039dede 1069 // Wait for critical threads
5039dede
AK
1070 ThreadJoin(m_thPollManager);
1071 ThreadJoin(m_thSyncer);
bf306af3
VK
1072 ThreadJoin(s_tunnelListenerThread);
1073
1074 CloseAgentTunnels();
5039dede 1075
a0efa7b5
VK
1076 // Call shutdown functions for the modules
1077 // CALL_ALL_MODULES cannot be used here because it checks for shutdown flag
1078 for(UINT32 i = 0; i < g_dwNumModules; i++)
1079 {
1080 if (g_pModuleList[i].pfShutdown != NULL)
1081 g_pModuleList[i].pfShutdown();
1082 }
1083
9bd1bace 1084 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
83b1c107 1085 SaveObjects(hdb, INVALID_INDEX);
2df047f4 1086 nxlog_debug(2, _T("All objects saved to database"));
83b1c107 1087 SaveUsers(hdb, INVALID_INDEX);
2df047f4 1088 nxlog_debug(2, _T("All users saved to database"));
76d77587 1089 UpdatePStorageDatabase(hdb, INVALID_INDEX);
1090 nxlog_debug(2, _T("All persistent storage values saved"));
9bd1bace
VK
1091 DBConnectionPoolReleaseConnection(hdb);
1092
5039dede 1093 StopDBWriter();
2df047f4 1094 nxlog_debug(1, _T("Database writer stopped"));
5039dede 1095
ab185583 1096 CleanupUsers();
7b45b90d 1097 PersistentStorageDestroy();
ab185583 1098
5039dede
AK
1099 // Remove database lock
1100 UnlockDB();
1101
7a7dfb3e 1102 DBConnectionPoolShutdown();
b8c1ec69 1103 DBUnloadDriver(g_dbDriver);
2df047f4 1104 nxlog_debug(1, _T("Database driver unloaded"));
5039dede
AK
1105
1106 CleanupActions();
1107 ShutdownEventSubsystem();
da84c57a 1108 ShutdownAlarmManager();
2df047f4 1109 nxlog_debug(1, _T("Event processing stopped"));
5039dede 1110
1693f955 1111 ThreadPoolDestroy(g_agentConnectionThreadPool);
5d3459af 1112 ThreadPoolDestroy(g_mainThreadPool);
d87ddcc2 1113 MsgWaitQueue::shutdown();
83b1c107 1114 WatchdogShutdown();
5d3459af 1115
2df047f4 1116 nxlog_debug(1, _T("Server shutdown complete"));
5039dede
AK
1117 nxlog_close();
1118
1119 // Remove PID file
1120#ifndef _WIN32
dda7c270 1121 _tremove(g_szPIDFile);
5039dede
AK
1122#endif
1123
1124 // Terminate process
1125#ifdef _WIN32
c8076b19 1126 if (!(g_flags & AF_DAEMON))
5039dede
AK
1127 ExitProcess(0);
1128#else
1129 exit(0);
1130#endif
1131}
1132
371d9c60
VK
1133/**
1134 * Fast server shutdown - normally called only by Windows service on system shutdown
1135 */
f669df41 1136void NXCORE_EXPORTABLE FastShutdown()
5039dede 1137{
bc9263d1
VK
1138 DbgPrintf(1, _T("Using fast shutdown procedure"));
1139
c8076b19 1140 g_flags |= AF_SHUTDOWN; // Set shutdown flag
5039dede
AK
1141 ConditionSet(m_condShutdown);
1142
9bd1bace 1143 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
83b1c107 1144 SaveObjects(hdb, INVALID_INDEX);
35f836fe 1145 DbgPrintf(2, _T("All objects saved to database"));
83b1c107 1146 SaveUsers(hdb, INVALID_INDEX);
35f836fe 1147 DbgPrintf(2, _T("All users saved to database"));
76d77587 1148 UpdatePStorageDatabase(hdb, INVALID_INDEX);
1149 DbgPrintf(2, _T("All persistent storage values saved"));
9bd1bace 1150 DBConnectionPoolReleaseConnection(hdb);
5039dede 1151
9bd1bace 1152 // Remove database lock first, because we have a chance to lose DB connection
5039dede
AK
1153 UnlockDB();
1154
1155 // Stop database writers
1156 StopDBWriter();
35f836fe 1157 DbgPrintf(1, _T("Database writer stopped"));
5039dede 1158
bc9263d1 1159 DbgPrintf(1, _T("Server shutdown complete"));
5039dede
AK
1160 nxlog_close();
1161}
1162
fdbee7f8 1163/**
fdbee7f8
VK
1164 * Signal handler for UNIX platforms
1165 */
5039dede
AK
1166#ifndef _WIN32
1167
1168void SignalHandlerStub(int nSignal)
1169{
1170 // should be unused, but JIC...
1171 if (nSignal == SIGCHLD)
1172 {
1173 while (waitpid(-1, NULL, WNOHANG) > 0)
1174 ;
1175 }
1176}
1177
1178THREAD_RESULT NXCORE_EXPORTABLE THREAD_CALL SignalHandler(void *pArg)
1179{
1180 sigset_t signals;
1181 int nSignal;
5039dede
AK
1182
1183 m_signalHandlerThread = pthread_self();
1184
1185 // default for SIGCHLD: ignore
1186 signal(SIGCHLD, &SignalHandlerStub);
1187
1188 sigemptyset(&signals);
1189 sigaddset(&signals, SIGTERM);
1190 sigaddset(&signals, SIGINT);
5039dede
AK
1191 sigaddset(&signals, SIGSEGV);
1192 sigaddset(&signals, SIGCHLD);
1193 sigaddset(&signals, SIGHUP);
1194 sigaddset(&signals, SIGUSR1);
1195 sigaddset(&signals, SIGUSR2);
95e2329a
VK
1196#if !defined(__sun) && !defined(_AIX) && !defined(__hpux)
1197 sigaddset(&signals, SIGPIPE);
1198#endif
5039dede
AK
1199
1200 sigprocmask(SIG_BLOCK, &signals, NULL);
1201
1202 while(1)
1203 {
1204 if (sigwait(&signals, &nSignal) == 0)
1205 {
1206 switch(nSignal)
1207 {
1208 case SIGTERM:
1209 case SIGINT:
bc9263d1
VK
1210 // avoid repeat Shutdown() call
1211 if (!(g_flags & AF_SHUTDOWN))
1212 {
1213 m_nShutdownReason = SHUTDOWN_BY_SIGNAL;
1214 if (IsStandalone())
1215 Shutdown(); // will never return
1216 else
1217 ConditionSet(m_condShutdown);
1218 }
1219 break;
5039dede
AK
1220 case SIGSEGV:
1221 abort();
1222 break;
1223 case SIGCHLD:
1224 while (waitpid(-1, NULL, WNOHANG) > 0)
1225 ;
1226 break;
1227 case SIGUSR1:
c8076b19 1228 if (g_flags & AF_SHUTDOWN)
5039dede
AK
1229 goto stop_handler;
1230 break;
1231 default:
1232 break;
1233 }
1234 }
1235 else
1236 {
1237 ThreadSleepMs(100);
1238 }
1239 }
1240
1241stop_handler:
1242 sigprocmask(SIG_UNBLOCK, &signals, NULL);
5039dede
AK
1243 return THREAD_OK;
1244}
1245
1246#endif
1247
fdbee7f8
VK
1248/**
1249 * Common main()
1250 */
5039dede
AK
1251THREAD_RESULT NXCORE_EXPORTABLE THREAD_CALL Main(void *pArg)
1252{
1253 nxlog_write(MSG_SERVER_STARTED, EVENTLOG_INFORMATION_TYPE, NULL);
1254
7bdb43c3
VK
1255 if (IsStandalone())
1256 {
c8076b19 1257 if (!(g_flags & AF_DEBUG_CONSOLE_DISABLED))
7bdb43c3
VK
1258 {
1259 char *ptr, szCommand[256];
1260 struct __console_ctx ctx;
35f836fe 1261#ifdef UNICODE
7bdb43c3 1262 WCHAR wcCommand[256];
35f836fe 1263#endif
5039dede 1264
7bdb43c3
VK
1265 ctx.hSocket = -1;
1266 ctx.socketMutex = INVALID_MUTEX_HANDLE;
1267 ctx.pMsg = NULL;
1268 ctx.session = NULL;
1269 ctx.output = NULL;
8e17001f 1270 WriteToTerminal(_T("\nNetXMS Server V") NETXMS_VERSION_STRING _T(" Build ") NETXMS_VERSION_BUILD_STRING IS_UNICODE_BUILD_STRING _T(" Ready\n")
7bdb43c3
VK
1271 _T("Enter \"\x1b[1mhelp\x1b[0m\" for command list or \"\x1b[1mdown\x1b[0m\" for server shutdown\n")
1272 _T("System Console\n\n"));
5039dede
AK
1273
1274#if USE_READLINE
7bdb43c3
VK
1275 // Initialize readline library if we use it
1276 rl_bind_key('\t', RL_INSERT_CAST rl_insert);
5039dede
AK
1277#endif
1278
7bdb43c3
VK
1279 while(1)
1280 {
5039dede 1281#if USE_READLINE
7bdb43c3 1282 ptr = readline("\x1b[33mnetxmsd:\x1b[0m ");
5039dede 1283#else
7bdb43c3
VK
1284 WriteToTerminal(_T("\x1b[33mnetxmsd:\x1b[0m "));
1285 fflush(stdout);
1286 if (fgets(szCommand, 255, stdin) == NULL)
1287 break; // Error reading stdin
1288 ptr = strchr(szCommand, '\n');
1289 if (ptr != NULL)
1290 *ptr = 0;
1291 ptr = szCommand;
5039dede
AK
1292#endif
1293
7bdb43c3
VK
1294 if (ptr != NULL)
1295 {
35f836fe 1296#ifdef UNICODE
fe8ea784
VK
1297#if HAVE_MBSTOWCS
1298 mbstowcs(wcCommand, ptr, 255);
1299#else
7bdb43c3 1300 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, ptr, -1, wcCommand, 256);
fe8ea784 1301#endif
7bdb43c3
VK
1302 wcCommand[255] = 0;
1303 StrStrip(wcCommand);
1304 if (wcCommand[0] != 0)
1305 {
1306 if (ProcessConsoleCommand(wcCommand, &ctx) == CMD_EXIT_SHUTDOWN)
35f836fe 1307#else
7bdb43c3
VK
1308 StrStrip(ptr);
1309 if (*ptr != 0)
1310 {
1311 if (ProcessConsoleCommand(ptr, &ctx) == CMD_EXIT_SHUTDOWN)
35f836fe 1312#endif
7bdb43c3 1313 break;
5039dede 1314#if USE_READLINE
7bdb43c3 1315 add_history(ptr);
5039dede 1316#endif
7bdb43c3 1317 }
5039dede 1318#if USE_READLINE
7bdb43c3 1319 free(ptr);
5039dede 1320#endif
7bdb43c3
VK
1321 }
1322 else
1323 {
1324 _tprintf(_T("\n"));
1325 }
1326 }
5039dede
AK
1327
1328#if USE_READLINE
7bdb43c3 1329 free(ptr);
5039dede 1330#endif
bc9263d1
VK
1331 if (!(g_flags & AF_SHUTDOWN))
1332 {
1333 m_nShutdownReason = SHUTDOWN_FROM_CONSOLE;
1334 Shutdown();
1335 }
7bdb43c3
VK
1336 }
1337 else
1338 {
1339 // standalone with debug console disabled
1340#ifdef _WIN32
1341 _tprintf(_T("Server running. Press ESC to shutdown.\n"));
1342 while(1)
1343 {
1344 if (_getch() == 27)
1345 break;
1346 }
1347 _tprintf(_T("Server shutting down...\n"));
1348 Shutdown();
1349#else
1350 _tprintf(_T("Server running. Press Ctrl+C to shutdown.\n"));
1351 // Shutdown will be called from signal handler
1352 ConditionWait(m_condShutdown, INFINITE);
1353#endif
1354 }
5039dede
AK
1355 }
1356 else
1357 {
1358 ConditionWait(m_condShutdown, INFINITE);
1359 // On Win32, Shutdown() will be called by service control handler
1360#ifndef _WIN32
1361 Shutdown();
1362#endif
1363 }
1364 return THREAD_OK;
1365}
1366
fdbee7f8
VK
1367/**
1368 * Initiate server shutdown
1369 */
035a4d73 1370void InitiateShutdown()
5039dede
AK
1371{
1372#ifdef _WIN32
1373 Shutdown();
1374#else
1375 if (IsStandalone())
1376 {
1377 Shutdown();
1378 }
1379 else
1380 {
1381 pthread_kill(m_signalHandlerThread, SIGTERM);
1382 }
1383#endif
1384}
1385
fdbee7f8
VK
1386/**
1387 *DLL Entry point
1388 */
5039dede
AK
1389#ifdef _WIN32
1390
1391BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
1392{
1393 if (dwReason == DLL_PROCESS_ATTACH)
1394 DisableThreadLibraryCalls(hInstance);
1395 return TRUE;
1396}
1397
1398#endif