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