condTimedWait fixed
[public/netxms.git] / src / server / core / session.cpp
CommitLineData
21e4b6f0
VK
1/*
2** NetXMS - Network Management System
3** Copyright (C) 2003, 2004 Victor Kirhenshtein
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** $module: session.cpp
20**
21**/
22
a551fe4d 23#include "nxcore.h"
21e4b6f0 24
693119d6
VK
25#ifndef _WIN32
26#include <dirent.h>
06e7be2f
VK
27#endif
28
21e4b6f0 29
693119d6
VK
30//
31// Constants
32//
33
34#define TRAP_CREATE 1
35#define TRAP_UPDATE 2
36#define TRAP_DELETE 3
37
257defd7
VK
38#define RAW_MSG_SIZE 262144
39
693119d6 40
ccdbbb52
VK
41//
42// Externals
43//
44
45void UnregisterSession(DWORD dwIndex);
46
47
d966d18a
VK
48//
49// Node poller start data
50//
51
52typedef struct
53{
54 ClientSession *pSession;
55 Node *pNode;
56 int iPollType;
57 DWORD dwRqId;
58} POLLER_START_DATA;
59
60
2d5c8ac8
VK
61//
62// Fill CSCP message with user data
63//
64
65static void FillUserInfoMessage(CSCPMessage *pMsg, NMS_USER *pUser)
66{
67 pMsg->SetVariable(VID_USER_ID, pUser->dwId);
68 pMsg->SetVariable(VID_USER_NAME, pUser->szName);
69 pMsg->SetVariable(VID_USER_FLAGS, pUser->wFlags);
70 pMsg->SetVariable(VID_USER_SYS_RIGHTS, pUser->wSystemRights);
71 pMsg->SetVariable(VID_USER_FULL_NAME, pUser->szFullName);
72 pMsg->SetVariable(VID_USER_DESCRIPTION, pUser->szDescription);
73}
74
75
76//
77// Fill CSCP message with user group data
78//
79
80static void FillGroupInfoMessage(CSCPMessage *pMsg, NMS_USER_GROUP *pGroup)
81{
82 DWORD i, dwId;
83
84 pMsg->SetVariable(VID_USER_ID, pGroup->dwId);
85 pMsg->SetVariable(VID_USER_NAME, pGroup->szName);
86 pMsg->SetVariable(VID_USER_FLAGS, pGroup->wFlags);
87 pMsg->SetVariable(VID_USER_SYS_RIGHTS, pGroup->wSystemRights);
88 pMsg->SetVariable(VID_USER_DESCRIPTION, pGroup->szDescription);
89 pMsg->SetVariable(VID_NUM_MEMBERS, pGroup->dwNumMembers);
90 for(i = 0, dwId = VID_GROUP_MEMBER_BASE; i < pGroup->dwNumMembers; i++, dwId++)
91 pMsg->SetVariable(dwId, pGroup->pMembers[i]);
92}
93
94
ccdbbb52
VK
95//
96// Client communication read thread starter
97//
98
99THREAD_RESULT THREAD_CALL ClientSession::ReadThreadStarter(void *pArg)
100{
101 ((ClientSession *)pArg)->ReadThread();
102
103 // When ClientSession::ReadThread exits, all other session
104 // threads are already stopped, so we can safely destroy
105 // session object
106 UnregisterSession(((ClientSession *)pArg)->GetIndex());
107 delete (ClientSession *)pArg;
108 return THREAD_OK;
109}
110
111
112//
113// Client communication write thread starter
114//
115
116THREAD_RESULT THREAD_CALL ClientSession::WriteThreadStarter(void *pArg)
117{
118 ((ClientSession *)pArg)->WriteThread();
119 return THREAD_OK;
120}
121
122
123//
124// Received message processing thread starter
125//
126
127THREAD_RESULT THREAD_CALL ClientSession::ProcessingThreadStarter(void *pArg)
128{
129 ((ClientSession *)pArg)->ProcessingThread();
130 return THREAD_OK;
131}
132
133
134//
135// Information update processing thread starter
136//
137
138THREAD_RESULT THREAD_CALL ClientSession::UpdateThreadStarter(void *pArg)
139{
140 ((ClientSession *)pArg)->UpdateThread();
141 return THREAD_OK;
142}
143
144
d966d18a
VK
145//
146// Forced node poll thread starter
147//
148
149THREAD_RESULT THREAD_CALL ClientSession::PollerThreadStarter(void *pArg)
150{
151 ((POLLER_START_DATA *)pArg)->pSession->PollerThread(
152 ((POLLER_START_DATA *)pArg)->pNode,
153 ((POLLER_START_DATA *)pArg)->iPollType,
154 ((POLLER_START_DATA *)pArg)->dwRqId);
155 free(pArg);
156 return THREAD_OK;
157}
158
159
21e4b6f0
VK
160//
161// Client session class constructor
162//
163
b54b2b11 164ClientSession::ClientSession(SOCKET hSocket, DWORD dwHostAddr)
21e4b6f0
VK
165{
166 m_pSendQueue = new Queue;
167 m_pMessageQueue = new Queue;
62f5857f 168 m_pUpdateQueue = new Queue;
21e4b6f0
VK
169 m_hSocket = hSocket;
170 m_dwIndex = INVALID_INDEX;
cb7ec554 171 m_iState = SESSION_STATE_INIT;
21e4b6f0 172 m_pMsgBuffer = (CSCP_BUFFER *)malloc(sizeof(CSCP_BUFFER));
ccdbbb52
VK
173 m_hWriteThread = INVALID_THREAD_HANDLE;
174 m_hProcessingThread = INVALID_THREAD_HANDLE;
175 m_hUpdateThread = INVALID_THREAD_HANDLE;
03482383
VK
176 m_mutexSendEvents = MutexCreate();
177 m_mutexSendObjects = MutexCreate();
178 m_mutexSendAlarms = MutexCreate();
c9363772 179 m_mutexSendActions = MutexCreate();
d966d18a 180 m_mutexPollerInit = MutexCreate();
b54b2b11
VK
181 m_dwFlags = 0;
182 m_dwHostAddr = dwHostAddr;
183 strcpy(m_szUserName, "<not logged in>");
984542f8 184 m_dwUserId = INVALID_INDEX;
338493a0
VK
185 m_dwOpenDCIListSize = 0;
186 m_pOpenDCIList = NULL;
8f7e2482 187 m_ppEPPRuleList = NULL;
257defd7
VK
188 m_hCurrFile = -1;
189 m_dwFileRqId = 0;
21e4b6f0
VK
190}
191
192
193//
194// Destructor
195//
196
197ClientSession::~ClientSession()
198{
199 shutdown(m_hSocket, 2);
200 closesocket(m_hSocket);
201 delete m_pSendQueue;
202 delete m_pMessageQueue;
62f5857f 203 delete m_pUpdateQueue;
338493a0 204 safe_free(m_pMsgBuffer);
03482383
VK
205 MutexDestroy(m_mutexSendEvents);
206 MutexDestroy(m_mutexSendObjects);
207 MutexDestroy(m_mutexSendAlarms);
c9363772 208 MutexDestroy(m_mutexSendActions);
d966d18a 209 MutexDestroy(m_mutexPollerInit);
338493a0 210 safe_free(m_pOpenDCIList);
8f7e2482
VK
211 if (m_ppEPPRuleList != NULL)
212 {
213 DWORD i;
214
215 if (m_dwFlags & CSF_EPP_UPLOAD) // Aborted in the middle of EPP transfer
216 for(i = 0; i < m_dwRecordsUploaded; i++)
217 delete m_ppEPPRuleList[i];
218 free(m_ppEPPRuleList);
219 }
21e4b6f0
VK
220}
221
222
ccdbbb52
VK
223//
224// Start all threads
225//
226
227void ClientSession::Run(void)
228{
229 m_hWriteThread = ThreadCreateEx(WriteThreadStarter, 0, this);
230 m_hProcessingThread = ThreadCreateEx(ProcessingThreadStarter, 0, this);
231 m_hUpdateThread = ThreadCreateEx(UpdateThreadStarter, 0, this);
232 ThreadCreate(ReadThreadStarter, 0, this);
233}
234
235
21e4b6f0
VK
236//
237// Print debug information
238//
239
240void ClientSession::DebugPrintf(char *szFormat, ...)
241{
242 if ((g_dwFlags & AF_STANDALONE) && (g_dwFlags & AF_DEBUG_CSCP))
243 {
244 va_list args;
245
246 printf("*CSCP(%d)* ", m_dwIndex);
247 va_start(args, szFormat);
248 vprintf(szFormat, args);
249 va_end(args);
250 }
251}
252
253
21e4b6f0
VK
254//
255// ReadThread()
256//
257
258void ClientSession::ReadThread(void)
259{
260 CSCP_MESSAGE *pRawMsg;
261 CSCPMessage *pMsg;
257defd7 262 TCHAR szBuffer[256];
21e4b6f0 263 int iErr;
338493a0
VK
264 DWORD i;
265 NetObj *pObject;
257defd7 266 WORD wFlags;
21e4b6f0
VK
267
268 // Initialize raw message receiving function
a933a2bf 269 RecvCSCPMessage(0, NULL, m_pMsgBuffer, 0);
21e4b6f0 270
257defd7 271 pRawMsg = (CSCP_MESSAGE *)malloc(RAW_MSG_SIZE);
21e4b6f0
VK
272 while(1)
273 {
257defd7 274 if ((iErr = RecvCSCPMessage(m_hSocket, pRawMsg, m_pMsgBuffer, RAW_MSG_SIZE)) <= 0)
21e4b6f0
VK
275 break;
276
a933a2bf
VK
277 // Check if message is too large
278 if (iErr == 1)
257defd7
VK
279 {
280 DebugPrintf("Received message %s is too large (%d bytes)\n",
281 CSCPMessageCodeName(ntohs(pRawMsg->wCode), szBuffer),
282 ntohl(pRawMsg->dwSize));
a933a2bf 283 continue;
257defd7 284 }
a933a2bf 285
21e4b6f0 286 // Check that actual received packet size is equal to encoded in packet
6159a875 287 if ((int)ntohl(pRawMsg->dwSize) != iErr)
21e4b6f0 288 {
6159a875 289 DebugPrintf("Actual message size doesn't match wSize value (%d,%d)\n", iErr, ntohl(pRawMsg->dwSize));
21e4b6f0
VK
290 continue; // Bad packet, wait for next
291 }
292
257defd7
VK
293 // Special handling for raw messages
294 wFlags = ntohs(pRawMsg->wFlags);
295 if (wFlags & MF_BINARY)
296 {
297 // Convert message header to host format
298 pRawMsg->dwId = ntohl(pRawMsg->dwId);
299 pRawMsg->wCode = ntohs(pRawMsg->wCode);
300 pRawMsg->dwNumVars = ntohl(pRawMsg->dwNumVars);
301 DebugPrintf("Received raw message %s\n", CSCPMessageCodeName(pRawMsg->wCode, szBuffer));
302
303 if ((pRawMsg->wCode == CMD_FILE_DATA) ||
304 (pRawMsg->wCode == CMD_ABORT_FILE_TRANSFER))
305 {
306 if ((m_hCurrFile != -1) && (m_dwFileRqId == pRawMsg->dwId))
307 {
308 if (pRawMsg->wCode == CMD_FILE_DATA)
309 {
310 if (write(m_hCurrFile, pRawMsg->df, pRawMsg->dwNumVars) == (int)pRawMsg->dwNumVars)
311 {
312 if (wFlags & MF_EOF)
313 {
314 CSCPMessage msg;
315
316 close(m_hCurrFile);
317 m_hCurrFile = -1;
318
319 msg.SetCode(CMD_REQUEST_COMPLETED);
320 msg.SetId(pRawMsg->dwId);
321 msg.SetVariable(VID_RCC, RCC_SUCCESS);
322 SendMessage(&msg);
323
324 OnFileUpload(TRUE);
325 }
326 }
327 else
328 {
329 // I/O error
330 CSCPMessage msg;
331
332 close(m_hCurrFile);
333 m_hCurrFile = -1;
334
335 msg.SetCode(CMD_REQUEST_COMPLETED);
336 msg.SetId(pRawMsg->dwId);
337 msg.SetVariable(VID_RCC, RCC_IO_ERROR);
338 SendMessage(&msg);
339
340 OnFileUpload(FALSE);
341 }
342 }
343 else
344 {
345 // Abort current file transfer because of client's problem
346 close(m_hCurrFile);
347 m_hCurrFile = -1;
348
349 OnFileUpload(FALSE);
350 }
351 }
352 else
353 {
354 DebugPrintf("Out of state message (ID: %d)\n", pRawMsg->dwId);
355 }
356 }
357 }
358 else
359 {
360 // Create message object from raw message
361 pMsg = new CSCPMessage(pRawMsg);
362 m_pMessageQueue->Put(pMsg);
363 }
21e4b6f0
VK
364 }
365 if (iErr < 0)
366 WriteLog(MSG_SESSION_CLOSED, EVENTLOG_WARNING_TYPE, "e", WSAGetLastError());
367 free(pRawMsg);
368
369 // Notify other threads to exit
d09b1909 370 m_pSendQueue->Clear();
ecb7e1ee 371 m_pSendQueue->Put(INVALID_POINTER_VALUE);
d09b1909 372 m_pMessageQueue->Clear();
ecb7e1ee 373 m_pMessageQueue->Put(INVALID_POINTER_VALUE);
d09b1909 374 m_pUpdateQueue->Clear();
8f7e2482 375 m_pUpdateQueue->Put(INVALID_POINTER_VALUE);
ecb7e1ee
VK
376
377 // Wait for other threads to finish
ccdbbb52
VK
378 ThreadJoin(m_hWriteThread);
379 ThreadJoin(m_hProcessingThread);
380 ThreadJoin(m_hUpdateThread);
54abbe0e 381
257defd7
VK
382 // Abort current file upload operation, if any
383 if (m_hCurrFile != -1)
384 {
385 close(m_hCurrFile);
386 m_hCurrFile = -1;
387 OnFileUpload(FALSE);
388 }
389
54abbe0e
VK
390 // Remove all locks created by this session
391 RemoveAllSessionLocks(m_dwIndex);
338493a0
VK
392 for(i = 0; i < m_dwOpenDCIListSize; i++)
393 {
394 pObject = FindObjectById(m_pOpenDCIList[i]);
395 if (pObject != NULL)
396 if (pObject->Type() == OBJECT_NODE)
397 ((Node *)pObject)->UnlockDCIList(m_dwIndex);
398 }
8f7e2482
VK
399
400 DebugPrintf("Session closed\n");
21e4b6f0
VK
401}
402
403
404//
405// WriteThread()
406//
407
408void ClientSession::WriteThread(void)
409{
410 CSCP_MESSAGE *pMsg;
7ac0c0a8 411 char szBuffer[128];
21e4b6f0
VK
412
413 while(1)
414 {
415 pMsg = (CSCP_MESSAGE *)m_pSendQueue->GetOrBlock();
ecb7e1ee 416 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
21e4b6f0
VK
417 break;
418
6159a875 419 DebugPrintf("Sending message %s\n", CSCPMessageCodeName(ntohs(pMsg->wCode), szBuffer));
1216cc73 420 if (SendEx(m_hSocket, (const char *)pMsg, ntohl(pMsg->dwSize), 0) <= 0)
21e4b6f0 421 {
9d72bde1 422 safe_free(pMsg);
80de4676 423 closesocket(m_hSocket);
21e4b6f0
VK
424 break;
425 }
9d72bde1 426 safe_free(pMsg);
21e4b6f0 427 }
8f7e2482
VK
428}
429
430
431//
432// Update processing thread
433//
434
435void ClientSession::UpdateThread(void)
436{
437 UPDATE_INFO *pUpdate;
438 CSCPMessage msg;
439
8f7e2482
VK
440 while(1)
441 {
442 pUpdate = (UPDATE_INFO *)m_pUpdateQueue->GetOrBlock();
443 if (pUpdate == INVALID_POINTER_VALUE) // Session termination indicator
444 break;
445
446 switch(pUpdate->dwCategory)
447 {
448 case INFO_CAT_EVENT:
03482383 449 MutexLock(m_mutexSendEvents, INFINITE);
8f7e2482 450 m_pSendQueue->Put(CreateRawCSCPMessage(CMD_EVENT, 0, sizeof(NXC_EVENT), pUpdate->pData, NULL));
03482383 451 MutexUnlock(m_mutexSendEvents);
8f7e2482
VK
452 free(pUpdate->pData);
453 break;
454 case INFO_CAT_OBJECT_CHANGE:
03482383 455 MutexLock(m_mutexSendObjects, INFINITE);
8f7e2482 456 msg.SetCode(CMD_OBJECT_UPDATE);
03482383 457 msg.SetId(0);
8f7e2482
VK
458 ((NetObj *)pUpdate->pData)->CreateMessage(&msg);
459 SendMessage(&msg);
03482383 460 MutexUnlock(m_mutexSendObjects);
8f7e2482
VK
461 msg.DeleteAllVariables();
462 ((NetObj *)pUpdate->pData)->DecRefCount();
463 break;
03482383
VK
464 case INFO_CAT_ALARM:
465 MutexLock(m_mutexSendAlarms, INFINITE);
466 msg.SetCode(CMD_ALARM_UPDATE);
467 msg.SetId(0);
c9363772 468 msg.SetVariable(VID_NOTIFICATION_CODE, pUpdate->dwCode);
b900a78b 469 FillAlarmInfoMessage(&msg, (NXC_ALARM *)pUpdate->pData);
49dde062 470 SendMessage(&msg);
03482383
VK
471 MutexUnlock(m_mutexSendAlarms);
472 msg.DeleteAllVariables();
c9363772
VK
473 free(pUpdate->pData);
474 break;
475 case INFO_CAT_ACTION:
476 MutexLock(m_mutexSendActions, INFINITE);
477 msg.SetCode(CMD_ACTION_DB_UPDATE);
478 msg.SetId(0);
479 msg.SetVariable(VID_NOTIFICATION_CODE, pUpdate->dwCode);
480 msg.SetVariable(VID_ACTION_ID, ((NXC_ACTION *)pUpdate->pData)->dwId);
e91cb822
VK
481 if (pUpdate->dwCode != NX_NOTIFY_ACTION_DELETED)
482 FillActionInfoMessage(&msg, (NXC_ACTION *)pUpdate->pData);
c9363772
VK
483 SendMessage(&msg);
484 MutexUnlock(m_mutexSendActions);
485 msg.DeleteAllVariables();
486 free(pUpdate->pData);
03482383 487 break;
8f7e2482
VK
488 default:
489 break;
490 }
491
492 free(pUpdate);
493 }
21e4b6f0
VK
494}
495
496
497//
498// Message processing thread
499//
500
501void ClientSession::ProcessingThread(void)
502{
3421c063 503 CSCPMessage *pMsg;
74a5aa17 504 char szBuffer[128];
cb7ec554 505 DWORD i;
21e4b6f0
VK
506
507 while(1)
508 {
509 pMsg = (CSCPMessage *)m_pMessageQueue->GetOrBlock();
ecb7e1ee 510 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
21e4b6f0
VK
511 break;
512
74a5aa17 513 DebugPrintf("Received message %s\n", CSCPMessageCodeName(pMsg->GetCode(), szBuffer));
cb7ec554 514 if (!(m_dwFlags & CSF_AUTHENTICATED) &&
693119d6 515 (pMsg->GetCode() != CMD_LOGIN) && (pMsg->GetCode() != CMD_GET_SERVER_INFO))
21e4b6f0
VK
516 {
517 delete pMsg;
518 continue;
519 }
520
cb7ec554
VK
521 m_wCurrentCmd = pMsg->GetCode();
522 m_iState = SESSION_STATE_PROCESSING;
523 switch(m_wCurrentCmd)
21e4b6f0
VK
524 {
525 case CMD_LOGIN:
e100f091 526 Login(pMsg);
21e4b6f0 527 break;
693119d6
VK
528 case CMD_GET_SERVER_INFO:
529 SendServerInfo(pMsg->GetId());
530 break;
21e4b6f0 531 case CMD_GET_OBJECTS:
e100f091 532 SendAllObjects(pMsg->GetId());
21e4b6f0
VK
533 break;
534 case CMD_GET_EVENTS:
74a5aa17 535 SendAllEvents(pMsg->GetId());
21e4b6f0
VK
536 break;
537 case CMD_GET_CONFIG_VARLIST:
538 SendAllConfigVars();
539 break;
37c4d6aa 540 case CMD_LOAD_EVENT_DB:
b54b2b11
VK
541 SendEventDB(pMsg->GetId());
542 break;
37c4d6aa
VK
543 case CMD_LOCK_EVENT_DB:
544 LockEventDB(pMsg->GetId());
545 break;
546 case CMD_UNLOCK_EVENT_DB:
547 UnlockEventDB(pMsg->GetId());
b54b2b11 548 break;
605d2931
VK
549 case CMD_SET_EVENT_INFO:
550 SetEventInfo(pMsg);
551 break;
37c4d6aa
VK
552 case CMD_DELETE_EVENT_TEMPLATE:
553 DeleteEventTemplate(pMsg);
554 break;
c19b2871
VK
555 case CMD_GENERATE_EVENT_CODE:
556 GenerateEventCode(pMsg->GetId());
37c4d6aa 557 break;
24156e90
VK
558 case CMD_MODIFY_OBJECT:
559 ModifyObject(pMsg);
560 break;
c1c39152
VK
561 case CMD_SET_OBJECT_MGMT_STATUS:
562 ChangeObjectMgmtStatus(pMsg);
563 break;
23a32988
VK
564 case CMD_LOAD_USER_DB:
565 SendUserDB(pMsg->GetId());
566 break;
ff550544
VK
567 case CMD_CREATE_USER:
568 CreateUser(pMsg);
569 break;
570 case CMD_UPDATE_USER:
571 UpdateUser(pMsg);
572 break;
573 case CMD_DELETE_USER:
574 DeleteUser(pMsg);
575 break;
576 case CMD_LOCK_USER_DB:
577 LockUserDB(pMsg->GetId(), TRUE);
578 break;
579 case CMD_UNLOCK_USER_DB:
580 LockUserDB(pMsg->GetId(), FALSE);
581 break;
017e1e13
VK
582 case CMD_SET_PASSWORD:
583 SetPassword(pMsg);
584 break;
7257eb7d
VK
585 case CMD_GET_NODE_DCI_LIST:
586 OpenNodeDCIList(pMsg);
587 break;
588 case CMD_UNLOCK_NODE_DCI_LIST:
589 CloseNodeDCIList(pMsg);
590 break;
9ed4eaff
VK
591 case CMD_CREATE_NEW_DCI:
592 case CMD_MODIFY_NODE_DCI:
593 case CMD_DELETE_NODE_DCI:
594 ModifyNodeDCI(pMsg);
595 break;
5b9a1c7b
VK
596 case CMD_SET_DCI_STATUS:
597 ChangeDCIStatus(pMsg);
598 break;
933aee5c
VK
599 case CMD_COPY_DCI:
600 CopyDCI(pMsg);
601 break;
ebebc8ea
VK
602 case CMD_GET_DCI_DATA:
603 GetCollectedData(pMsg);
604 break;
06e7be2f
VK
605 case CMD_OPEN_EPP:
606 OpenEPP(pMsg->GetId());
607 break;
608 case CMD_CLOSE_EPP:
609 CloseEPP(pMsg->GetId());
610 break;
611 case CMD_SAVE_EPP:
612 SaveEPP(pMsg);
613 break;
8f7e2482
VK
614 case CMD_EPP_RECORD:
615 ProcessEPPRecord(pMsg);
06e7be2f
VK
616 break;
617 case CMD_GET_MIB_LIST:
618 SendMIBList(pMsg->GetId());
619 break;
620 case CMD_GET_MIB:
621 SendMIB(pMsg);
622 break;
ef44d5ea
VK
623 case CMD_CREATE_OBJECT:
624 CreateObject(pMsg);
625 break;
e6b958c4
VK
626 case CMD_BIND_OBJECT:
627 ChangeObjectBinding(pMsg, TRUE);
628 break;
629 case CMD_UNBIND_OBJECT:
630 ChangeObjectBinding(pMsg, FALSE);
631 break;
f70fc197 632 case CMD_GET_IMAGE_LIST:
aa3743b2 633 SendImageCatalogue(this, pMsg->GetId(), pMsg->GetVariableShort(VID_IMAGE_FORMAT));
f70fc197
VK
634 break;
635 case CMD_LOAD_IMAGE_FILE:
aa3743b2
VK
636 SendImageFile(this, pMsg->GetId(), pMsg->GetVariableLong(VID_IMAGE_ID),
637 pMsg->GetVariableShort(VID_IMAGE_FORMAT));
8bff53f6
VK
638 break;
639 case CMD_GET_DEFAULT_IMAGE_LIST:
640 SendDefaultImageList(this, pMsg->GetId());
f70fc197 641 break;
03482383
VK
642 case CMD_GET_ALL_ALARMS:
643 SendAllAlarms(pMsg->GetId(), pMsg->GetVariableShort(VID_IS_ACK));
644 break;
645 case CMD_GET_ALARM:
646 break;
647 case CMD_ACK_ALARM:
ee20e615
VK
648 AcknowlegeAlarm(pMsg);
649 break;
650 case CMD_DELETE_ALARM:
ae3a55d9 651 DeleteAlarm(pMsg);
03482383 652 break;
c9363772
VK
653 case CMD_LOCK_ACTION_DB:
654 LockActionDB(pMsg->GetId(), TRUE);
655 break;
656 case CMD_UNLOCK_ACTION_DB:
657 LockActionDB(pMsg->GetId(), FALSE);
658 break;
659 case CMD_CREATE_ACTION:
660 CreateAction(pMsg);
661 break;
662 case CMD_MODIFY_ACTION:
663 UpdateAction(pMsg);
664 break;
665 case CMD_DELETE_ACTION:
666 DeleteAction(pMsg);
667 break;
e91cb822
VK
668 case CMD_LOAD_ACTIONS:
669 SendAllActions(pMsg->GetId());
670 break;
6849d9be
VK
671 case CMD_GET_CONTAINER_CAT_LIST:
672 SendContainerCategories(pMsg->GetId());
673 break;
88039e6c
VK
674 case CMD_DELETE_OBJECT:
675 DeleteObject(pMsg);
676 break;
0b89f5fb
VK
677 case CMD_POLL_NODE:
678 ForcedNodePoll(pMsg);
679 break;
b562fca8
VK
680 case CMD_TRAP:
681 OnTrap(pMsg);
682 break;
ed1140dc
VK
683 case CMD_WAKEUP_NODE:
684 OnWakeUpNode(pMsg);
685 break;
b4895bbe
VK
686 case CMD_LOCK_TRAP_CFG:
687 LockTrapCfg(pMsg->GetId(), TRUE);
688 break;
689 case CMD_UNLOCK_TRAP_CFG:
690 LockTrapCfg(pMsg->GetId(), FALSE);
691 break;
692 case CMD_CREATE_TRAP:
693119d6 693 EditTrap(TRAP_CREATE, pMsg);
b4895bbe
VK
694 break;
695 case CMD_MODIFY_TRAP:
693119d6 696 EditTrap(TRAP_UPDATE, pMsg);
b4895bbe
VK
697 break;
698 case CMD_DELETE_TRAP:
693119d6 699 EditTrap(TRAP_DELETE, pMsg);
b4895bbe 700 break;
840eb902 701 case CMD_LOAD_TRAP_CFG:
b4895bbe
VK
702 SendAllTraps(pMsg->GetId());
703 break;
80de4676
VK
704 case CMD_QUERY_PARAMETER:
705 QueryParameter(pMsg);
706 break;
5be45ff2
VK
707 case CMD_LOCK_PACKAGE_DB:
708 LockPackageDB(pMsg->GetId(), TRUE);
709 break;
710 case CMD_UNLOCK_PACKAGE_DB:
711 LockPackageDB(pMsg->GetId(), FALSE);
712 break;
1c8b8363
VK
713 case CMD_GET_PACKAGE_LIST:
714 SendAllPackages(pMsg->GetId());
715 break;
257defd7
VK
716 case CMD_INSTALL_PACKAGE:
717 InstallPackage(pMsg);
718 break;
f6aa542e
VK
719 case CMD_REMOVE_PACKAGE:
720 RemovePackage(pMsg);
721 break;
89235715
VK
722 case CMD_GET_PARAMETER_LIST:
723 SendParametersList(pMsg);
724 break;
21e4b6f0 725 default:
ded831ac
VK
726 // Pass message to loaded modules
727 for(i = 0; i < g_dwNumModules; i++)
cb7ec554 728 if (g_pModuleList[i].pfCommandHandler(m_wCurrentCmd, pMsg, this))
ded831ac
VK
729 break; // Message was processed by the module
730 if (i == g_dwNumModules)
37c4d6aa
VK
731 {
732 CSCPMessage responce;
733
734 responce.SetId(pMsg->GetId());
735 responce.SetCode(CMD_REQUEST_COMPLETED);
736 responce.SetVariable(VID_RCC, RCC_NOT_IMPLEMENTED);
737 SendMessage(&responce);
738 }
21e4b6f0
VK
739 break;
740 }
741 delete pMsg;
cb7ec554 742 m_iState = (m_dwFlags & CSF_AUTHENTICATED) ? SESSION_STATE_IDLE : SESSION_STATE_INIT;
21e4b6f0
VK
743 }
744}
745
746
257defd7
VK
747//
748// Process received file
749//
750
751void ClientSession::OnFileUpload(BOOL bSuccess)
752{
753 // Do processing specific to command initiated file upload
754 switch(m_dwUploadCommand)
755 {
756 case CMD_INSTALL_PACKAGE:
757 if (!bSuccess)
758 {
759 TCHAR szQuery[256];
760
761 _sntprintf(szQuery, 256, _T("DELETE FROM agent_pkg WHERE pkg_id=%ld"), m_dwUploadData);
762 DBQuery(g_hCoreDB, szQuery);
763 }
764 break;
765 default:
766 break;
767 }
768
769 // Remove received file in case of failure
770 if (!bSuccess)
771 _tunlink(m_szCurrFileName);
772}
773
774
693119d6
VK
775//
776// Send server information to client
777//
778
779void ClientSession::SendServerInfo(DWORD dwRqId)
780{
781 CSCPMessage msg;
782
783 // Prepare responce message
784 msg.SetCode(CMD_REQUEST_COMPLETED);
785 msg.SetId(dwRqId);
786
787 // Fill message with server info
788 msg.SetVariable(VID_RCC, RCC_SUCCESS);
789 msg.SetVariable(VID_SERVER_VERSION, NETXMS_VERSION_STRING);
790 msg.SetVariable(VID_SUPPORTED_ENCRYPTION, (DWORD)0);
791
792 // Send responce
793 SendMessage(&msg);
794}
795
796
e100f091
VK
797//
798// Authenticate client
799//
800
801void ClientSession::Login(CSCPMessage *pRequest)
802{
803 CSCPMessage msg;
6528a4d7 804 BYTE szPassword[SHA1_DIGEST_SIZE];
e100f091
VK
805 char szLogin[MAX_USER_NAME], szBuffer[32];
806
807 // Prepare responce message
808 msg.SetCode(CMD_LOGIN_RESP);
809 msg.SetId(pRequest->GetId());
810
cb7ec554 811 if (!(m_dwFlags & CSF_AUTHENTICATED))
e100f091
VK
812 {
813
814 pRequest->GetVariableStr(VID_LOGIN_NAME, szLogin, MAX_USER_NAME);
6528a4d7 815 pRequest->GetVariableBinary(VID_PASSWORD, szPassword, SHA1_DIGEST_SIZE);
e100f091
VK
816
817 if (AuthenticateUser(szLogin, szPassword, &m_dwUserId, &m_dwSystemAccess))
818 {
cb7ec554 819 m_dwFlags |= CSF_AUTHENTICATED;
e100f091
VK
820 sprintf(m_szUserName, "%s@%s", szLogin, IpToStr(m_dwHostAddr, szBuffer));
821 msg.SetVariable(VID_RCC, RCC_SUCCESS);
822 DebugPrintf("User %s authenticated\n", m_szUserName);
823 }
824 else
825 {
826 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
827 }
828 }
829 else
830 {
831 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
832 }
833
834 // Send responce
835 SendMessage(&msg);
836}
837
838
b54b2b11
VK
839//
840// Send event configuration to client
841//
842
843void ClientSession::SendEventDB(DWORD dwRqId)
844{
845 DB_ASYNC_RESULT hResult;
846 CSCPMessage msg;
847 char szBuffer[1024];
848
849 // Prepare responce message
3a5042fd 850 msg.SetCode(CMD_REQUEST_COMPLETED);
b54b2b11
VK
851 msg.SetId(dwRqId);
852
b8bad201
VK
853 if (!CheckSysAccessRights(SYSTEM_ACCESS_VIEW_EVENT_DB))
854 {
855 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
856 SendMessage(&msg);
857 }
b54b2b11
VK
858 else
859 {
b54b2b11
VK
860 msg.SetVariable(VID_RCC, RCC_SUCCESS);
861 SendMessage(&msg);
862 msg.DeleteAllVariables();
863
864 // Prepare data message
865 msg.SetCode(CMD_EVENT_DB_RECORD);
866 msg.SetId(dwRqId);
867
c19b2871 868 hResult = DBAsyncSelect(g_hCoreDB, "SELECT event_code,event_name,severity,flags,message,description FROM event_cfg");
ebebc8ea 869 if (hResult != NULL)
b54b2b11 870 {
ebebc8ea
VK
871 while(DBFetch(hResult))
872 {
c19b2871 873 msg.SetVariable(VID_EVENT_CODE, DBGetFieldAsyncULong(hResult, 0));
ebebc8ea
VK
874 msg.SetVariable(VID_NAME, DBGetFieldAsync(hResult, 1, szBuffer, 1024));
875 msg.SetVariable(VID_SEVERITY, DBGetFieldAsyncULong(hResult, 2));
876 msg.SetVariable(VID_FLAGS, DBGetFieldAsyncULong(hResult, 3));
8f7e2482
VK
877
878 DBGetFieldAsync(hResult, 4, szBuffer, 1024);
879 DecodeSQLString(szBuffer);
880 msg.SetVariable(VID_MESSAGE, szBuffer);
881
882 DBGetFieldAsync(hResult, 5, szBuffer, 1024);
883 DecodeSQLString(szBuffer);
884 msg.SetVariable(VID_DESCRIPTION, szBuffer);
885
ebebc8ea
VK
886 SendMessage(&msg);
887 msg.DeleteAllVariables();
888 }
889 DBFreeAsyncResult(hResult);
b54b2b11 890 }
3a5042fd
VK
891
892 // Send end-of-list indicator
c19b2871 893 msg.SetVariable(VID_EVENT_CODE, (DWORD)0);
3a5042fd 894 SendMessage(&msg);
b54b2b11
VK
895 }
896}
897
898
37c4d6aa
VK
899//
900// Lock event configuration database
901//
902
903void ClientSession::LockEventDB(DWORD dwRqId)
904{
905 CSCPMessage msg;
906 char szBuffer[1024];
907
908 // Prepare responce message
909 msg.SetCode(CMD_REQUEST_COMPLETED);
910 msg.SetId(dwRqId);
911
912 if (!CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
913 {
914 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
915 }
916 else if (!LockComponent(CID_EVENT_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
917 {
918 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
919 msg.SetVariable(VID_LOCKED_BY, szBuffer);
920 }
921 else
922 {
923 m_dwFlags |= CSF_EVENT_DB_LOCKED;
924 m_dwFlags &= ~CSF_EVENT_DB_MODIFIED;
925
926 msg.SetVariable(VID_RCC, RCC_SUCCESS);
927 }
928 SendMessage(&msg);
929}
930
931
3421c063
VK
932//
933// Close event configuration database
934//
935
37c4d6aa 936void ClientSession::UnlockEventDB(DWORD dwRqId)
3421c063
VK
937{
938 CSCPMessage msg;
939
940 msg.SetCode(CMD_REQUEST_COMPLETED);
941 msg.SetId(dwRqId);
942
943 if (m_dwFlags & CSF_EVENT_DB_LOCKED)
944 {
945 // Check if event configuration DB has been modified
946 if (m_dwFlags & CSF_EVENT_DB_MODIFIED)
947 {
948 ReloadEvents();
949
950 // Notify clients on event database change
951 EnumerateClientSessions(NotifyClient, (void *)NX_NOTIFY_EVENTDB_CHANGED);
952 }
953 UnlockComponent(CID_EVENT_DB);
954 m_dwFlags &= ~CSF_EVENT_DB_LOCKED;
955 msg.SetVariable(VID_RCC, RCC_SUCCESS);
956 }
957 else
958 {
959 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
960 }
961 SendMessage(&msg);
962}
963
964
37c4d6aa
VK
965//
966// Update event template
967//
968
969void ClientSession::SetEventInfo(CSCPMessage *pRequest)
970{
971 CSCPMessage msg;
972
973 // Prepare reply message
974 msg.SetCode(CMD_REQUEST_COMPLETED);
975 msg.SetId(pRequest->GetId());
976
977 // Check if we have event configuration database opened
978 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
979 {
980 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
981 }
982 else
983 {
984 // Check access rights
985 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
986 {
987 char szQuery[4096], szName[MAX_EVENT_NAME];
c19b2871 988 DWORD dwEventCode;
37c4d6aa
VK
989 BOOL bEventExist = FALSE;
990 DB_RESULT hResult;
991
c19b2871
VK
992 // Check if event with specific code exists
993 dwEventCode = pRequest->GetVariableLong(VID_EVENT_CODE);
994 sprintf(szQuery, "SELECT event_code FROM event_cfg WHERE event_code=%ld", dwEventCode);
37c4d6aa
VK
995 hResult = DBSelect(g_hCoreDB, szQuery);
996 if (hResult != NULL)
997 {
998 if (DBGetNumRows(hResult) > 0)
999 bEventExist = TRUE;
1000 DBFreeResult(hResult);
1001 }
1002
1003 // Check that we are not trying to create event below 100000
c19b2871 1004 if (bEventExist || (dwEventCode >= FIRST_USER_EVENT_ID))
37c4d6aa
VK
1005 {
1006 // Prepare and execute SQL query
1007 pRequest->GetVariableStr(VID_NAME, szName, MAX_EVENT_NAME);
1008 if (IsValidObjectName(szName))
1009 {
1010 char szMessage[MAX_DB_STRING], *pszDescription, *pszEscMsg, *pszEscDescr;
1011
1012 pRequest->GetVariableStr(VID_MESSAGE, szMessage, MAX_DB_STRING);
1013 pszEscMsg = EncodeSQLString(szMessage);
1014
1015 pszDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
1016 pszEscDescr = EncodeSQLString(pszDescription);
1017 safe_free(pszDescription);
1018
1019 if (bEventExist)
1020 {
c19b2871 1021 sprintf(szQuery, "UPDATE event_cfg SET event_name='%s',severity=%ld,flags=%ld,message='%s',description='%s' WHERE event_code=%ld",
37c4d6aa 1022 szName, pRequest->GetVariableLong(VID_SEVERITY), pRequest->GetVariableLong(VID_FLAGS),
c19b2871 1023 pszEscMsg, pszEscDescr, dwEventCode);
37c4d6aa
VK
1024 }
1025 else
1026 {
c19b2871 1027 sprintf(szQuery, "INSERT INTO event_cfg (event_code,event_name,severity,flags,"
37c4d6aa 1028 "message,description) VALUES (%ld,'%s',%ld,%ld,'%s','%s')",
c19b2871 1029 dwEventCode, szName, pRequest->GetVariableLong(VID_SEVERITY),
37c4d6aa
VK
1030 pRequest->GetVariableLong(VID_FLAGS), pszEscMsg, pszEscDescr);
1031 }
1032
1033 free(pszEscMsg);
1034 free(pszEscDescr);
1035
1036 if (DBQuery(g_hCoreDB, szQuery))
1037 {
1038 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1039 m_dwFlags |= CSF_EVENT_DB_MODIFIED;
1040 }
1041 else
1042 {
1043 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
1044 }
1045 }
1046 else
1047 {
1048 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
1049 }
1050 }
1051 else
1052 {
1053 msg.SetVariable(VID_RCC, RCC_INVALID_EVENT_CODE);
1054 }
1055 }
1056 else
1057 {
1058 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1059 }
1060 }
1061
1062 // Send responce
1063 SendMessage(&msg);
1064}
1065
1066
1067//
1068// Delete event template
1069//
1070
1071void ClientSession::DeleteEventTemplate(CSCPMessage *pRequest)
1072{
1073 CSCPMessage msg;
c19b2871 1074 DWORD dwEventCode;
37c4d6aa
VK
1075
1076 // Prepare reply message
1077 msg.SetCode(CMD_REQUEST_COMPLETED);
1078 msg.SetId(pRequest->GetId());
1079
1080 // Check if we have event configuration database opened
1081 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
1082 {
1083 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1084 }
1085 else
1086 {
c19b2871 1087 dwEventCode = pRequest->GetVariableLong(VID_EVENT_CODE);
37c4d6aa
VK
1088
1089 // Check access rights
c19b2871 1090 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB) && (dwEventCode >= FIRST_USER_EVENT_ID))
37c4d6aa
VK
1091 {
1092 TCHAR szQuery[256];
1093
c19b2871 1094 _stprintf(szQuery, _T("DELETE FROM event_cfg WHERE event_code=%ld"), dwEventCode);
37c4d6aa
VK
1095 if (DBQuery(g_hCoreDB, szQuery))
1096 {
1097 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1098 m_dwFlags |= CSF_EVENT_DB_LOCKED;
1099 }
1100 else
1101 {
1102 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
1103 }
1104 }
1105 else
1106 {
1107 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1108 }
1109 }
1110
1111 // Send responce
1112 SendMessage(&msg);
1113}
1114
1115
1116//
1117// Generate ID for new event template
1118//
1119
c19b2871 1120void ClientSession::GenerateEventCode(DWORD dwRqId)
37c4d6aa
VK
1121{
1122 CSCPMessage msg;
1123
1124 // Prepare reply message
1125 msg.SetCode(CMD_REQUEST_COMPLETED);
1126 msg.SetId(dwRqId);
1127
1128 // Check if we have event configuration database opened
1129 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
1130 {
1131 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1132 }
1133 else
1134 {
1135 // Check access rights
1136 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
1137 {
c19b2871 1138 msg.SetVariable(VID_EVENT_CODE, CreateUniqueId(IDG_EVENT));
37c4d6aa
VK
1139 }
1140 else
1141 {
1142 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1143 }
1144 }
1145
1146 // Send responce
1147 SendMessage(&msg);
1148}
1149
1150
21e4b6f0
VK
1151//
1152// Send all objects to client
1153//
1154
e100f091 1155void ClientSession::SendAllObjects(DWORD dwRqId)
21e4b6f0
VK
1156{
1157 DWORD i;
1158 CSCPMessage msg;
1159
e100f091
VK
1160 // Send confirmation message
1161 msg.SetCode(CMD_REQUEST_COMPLETED);
1162 msg.SetId(dwRqId);
1163 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1164 SendMessage(&msg);
1165 msg.DeleteAllVariables();
1166
03482383 1167 MutexLock(m_mutexSendObjects, INFINITE);
53512272 1168
21e4b6f0
VK
1169 // Prepare message
1170 msg.SetCode(CMD_OBJECT);
1171
1172 // Send objects, one per message
4e839863 1173 RWLockReadLock(g_rwlockIdIndex, INFINITE);
21e4b6f0 1174 for(i = 0; i < g_dwIdIndexSize; i++)
24156e90
VK
1175 if (g_pIndexById[i].pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1176 {
1177 g_pIndexById[i].pObject->CreateMessage(&msg);
1178 SendMessage(&msg);
1179 msg.DeleteAllVariables();
1180 }
4e839863 1181 RWLockUnlock(g_rwlockIdIndex);
21e4b6f0
VK
1182
1183 // Send end of list notification
1184 msg.SetCode(CMD_OBJECT_LIST_END);
1185 SendMessage(&msg);
53512272 1186
03482383 1187 MutexUnlock(m_mutexSendObjects);
21e4b6f0
VK
1188}
1189
1190
1191//
1192// Send all events to client
1193//
1194
74a5aa17 1195void ClientSession::SendAllEvents(DWORD dwRqId)
21e4b6f0 1196{
21e4b6f0 1197 CSCPMessage msg;
20177e8e 1198 DB_ASYNC_RESULT hResult;
9c36ef66 1199 NXC_EVENT event;
babb8280
VK
1200#ifndef UNICODE
1201 char szBuffer[MAX_EVENT_MSG_LENGTH];
1202#endif
21e4b6f0 1203
74a5aa17
VK
1204 // Send confirmation message
1205 msg.SetCode(CMD_REQUEST_COMPLETED);
1206 msg.SetId(dwRqId);
1207 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1208 SendMessage(&msg);
1209 msg.DeleteAllVariables();
1210
03482383 1211 MutexLock(m_mutexSendEvents, INFINITE);
62f5857f 1212
21e4b6f0 1213 // Retrieve events from database
0c6014e4 1214 hResult = DBAsyncSelect(g_hCoreDB, "SELECT event_id,event_code,event_timestamp,event_source,"
31115ff9
VK
1215 "event_severity,event_message FROM event_log "
1216 "ORDER BY event_timestamp");
21e4b6f0
VK
1217 if (hResult != NULL)
1218 {
1219 // Send events, one per message
20177e8e 1220 while(DBFetch(hResult))
21e4b6f0 1221 {
0c6014e4
VK
1222 event.qwEventId = htonq(DBGetFieldAsyncUInt64(hResult, 0));
1223 event.dwEventCode = htonl(DBGetFieldAsyncULong(hResult, 1));
1224 event.dwTimeStamp = htonl(DBGetFieldAsyncULong(hResult, 2));
1225 event.dwSourceId = htonl(DBGetFieldAsyncULong(hResult, 3));
1226 event.dwSeverity = htonl(DBGetFieldAsyncULong(hResult, 4));
babb8280 1227#ifdef UNICODE
0c6014e4 1228 DBGetFieldAsync(hResult, 5, event.szMessage, MAX_EVENT_MSG_LENGTH);
8f7e2482 1229 DecodeSQLString(event.szMessage);
babb8280
VK
1230#else
1231 DBGetFieldAsync(hResult, 5, szBuffer, MAX_EVENT_MSG_LENGTH);
1232 DecodeSQLString(szBuffer);
1233 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szBuffer, -1,
1234 (WCHAR *)event.szMessage, MAX_EVENT_MSG_LENGTH);
1235#endif
1236 SwapWideString((WCHAR *)event.szMessage);
74a5aa17 1237 m_pSendQueue->Put(CreateRawCSCPMessage(CMD_EVENT, dwRqId, sizeof(NXC_EVENT), &event, NULL));
9c36ef66 1238 }
20177e8e 1239 DBFreeAsyncResult(hResult);
21e4b6f0
VK
1240 }
1241
1242 // Send end of list notification
1243 msg.SetCode(CMD_EVENT_LIST_END);
1244 SendMessage(&msg);
62f5857f 1245
03482383 1246 MutexUnlock(m_mutexSendEvents);
21e4b6f0
VK
1247}
1248
1249
1250//
1251// Send all configuration variables to client
1252//
1253
1254void ClientSession::SendAllConfigVars(void)
1255{
1256 DWORD i, dwNumRecords;
1257 CSCPMessage msg;
1258 DB_RESULT hResult;
1259
1260 // Check user rights
11363a86 1261 if ((m_dwUserId != 0) && ((m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG) == 0))
21e4b6f0
VK
1262 {
1263 // Access denied
1264 msg.SetCode(CMD_CONFIG_VARLIST_END);
a5f8dbb8 1265 msg.SetVariable(VID_ERROR, (DWORD)1);
21e4b6f0
VK
1266 SendMessage(&msg);
1267 }
1268 else
1269 {
1270 // Prepare message
1271 msg.SetCode(CMD_CONFIG_VARIABLE);
1272
1273 // Retrieve configuration variables from database
44375123 1274 hResult = DBSelect(g_hCoreDB, "SELECT var_name,var_value FROM config WHERE is_visible=1");
21e4b6f0
VK
1275 if (hResult != NULL)
1276 {
1277 // Send events, one per message
1278 dwNumRecords = DBGetNumRows(hResult);
1279 for(i = 0; i < dwNumRecords; i++)
1280 {
a5f8dbb8
VK
1281 msg.SetVariable(VID_NAME, DBGetField(hResult, i, 0));
1282 msg.SetVariable(VID_VALUE, DBGetField(hResult, i, 1));
21e4b6f0
VK
1283 SendMessage(&msg);
1284 msg.DeleteAllVariables();
1285 }
20177e8e 1286 DBFreeResult(hResult);
21e4b6f0
VK
1287 }
1288
1289 // Send end of list notification
1290 msg.SetCode(CMD_CONFIG_VARLIST_END);
a5f8dbb8 1291 msg.SetVariable(VID_ERROR, (DWORD)0);
21e4b6f0
VK
1292 SendMessage(&msg);
1293 }
1294}
20177e8e
VK
1295
1296
1297//
1298// Close session forcibly
1299//
1300
1301void ClientSession::Kill(void)
1302{
1303 // We shutdown socket connection, which will cause
1304 // read thread to stop, and other threads will follow
1305 shutdown(m_hSocket, 2);
1306}
62f5857f
VK
1307
1308
1309//
1310// Handler for new events
1311//
1312
1313void ClientSession::OnNewEvent(Event *pEvent)
1314{
1315 UPDATE_INFO *pUpdate;
1316
cb7ec554 1317 if (IsAuthenticated())
984542f8
VK
1318 {
1319 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
1320 pUpdate->dwCategory = INFO_CAT_EVENT;
1321 pUpdate->pData = malloc(sizeof(NXC_EVENT));
1322 pEvent->PrepareMessage((NXC_EVENT *)pUpdate->pData);
1323 m_pUpdateQueue->Put(pUpdate);
1324 }
62f5857f
VK
1325}
1326
1327
1328//
1329// Handler for object changes
1330//
1331
53512272 1332void ClientSession::OnObjectChange(NetObj *pObject)
62f5857f 1333{
53512272
VK
1334 UPDATE_INFO *pUpdate;
1335
cb7ec554 1336 if (IsAuthenticated())
984542f8
VK
1337 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1338 {
1339 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
1340 pUpdate->dwCategory = INFO_CAT_OBJECT_CHANGE;
1341 pUpdate->pData = pObject;
984542f8 1342 pObject->IncRefCount();
333ece94 1343 m_pUpdateQueue->Put(pUpdate);
984542f8 1344 }
62f5857f
VK
1345}
1346
1347
83f0529c
VK
1348//
1349// Send notification message to server
1350//
1351
4de204a3 1352void ClientSession::Notify(DWORD dwCode, DWORD dwData)
83f0529c
VK
1353{
1354 CSCPMessage msg;
1355
1356 msg.SetCode(CMD_NOTIFY);
1357 msg.SetVariable(VID_NOTIFICATION_CODE, dwCode);
4de204a3 1358 msg.SetVariable(VID_NOTIFICATION_DATA, dwData);
83f0529c
VK
1359 SendMessage(&msg);
1360}
605d2931
VK
1361
1362
24156e90
VK
1363//
1364// Modify object
1365//
1366
1367void ClientSession::ModifyObject(CSCPMessage *pRequest)
1368{
ff550544 1369 DWORD dwObjectId, dwResult = RCC_SUCCESS;
24156e90
VK
1370 NetObj *pObject;
1371 CSCPMessage msg;
1372
1373 // Prepare reply message
1374 msg.SetCode(CMD_REQUEST_COMPLETED);
1375 msg.SetId(pRequest->GetId());
1376
1377 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1378 pObject = FindObjectById(dwObjectId);
1379 if (pObject != NULL)
1380 {
1381 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1382 {
ff550544
VK
1383 // If user attempts to change object's ACL, check
1384 // if he has OBJECT_ACCESS_CONTROL permission
1385 if (pRequest->IsVariableExist(VID_ACL_SIZE))
1386 if (!pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CONTROL))
1387 dwResult = RCC_ACCESS_DENIED;
1388
1389 // If allowed, change object and set completion code
1390 if (dwResult != RCC_ACCESS_DENIED)
1391 dwResult = pObject->ModifyFromMessage(pRequest);
24156e90
VK
1392 msg.SetVariable(VID_RCC, dwResult);
1393 }
1394 else
1395 {
1396 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1397 }
1398 }
1399 else
1400 {
1401 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1402 }
1403
1404 // Send responce
1405 SendMessage(&msg);
1406}
23a32988
VK
1407
1408
1409//
1410// Send users database to client
1411//
1412
1413void ClientSession::SendUserDB(DWORD dwRqId)
1414{
1415 CSCPMessage msg;
2d5c8ac8 1416 DWORD i;
23a32988
VK
1417
1418 // Prepare responce message
1419 msg.SetCode(CMD_REQUEST_COMPLETED);
1420 msg.SetId(dwRqId);
1421 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1422 SendMessage(&msg);
1423
1424 // Send users
1425 msg.SetCode(CMD_USER_DATA);
1426 for(i = 0; i < g_dwNumUsers; i++)
1427 {
2d5c8ac8 1428 FillUserInfoMessage(&msg, &g_pUserList[i]);
23a32988
VK
1429 SendMessage(&msg);
1430 msg.DeleteAllVariables();
1431 }
1432
1433 // Send groups
1434 msg.SetCode(CMD_GROUP_DATA);
1435 for(i = 0; i < g_dwNumGroups; i++)
1436 {
2d5c8ac8 1437 FillGroupInfoMessage(&msg, &g_pGroupList[i]);
23a32988
VK
1438 SendMessage(&msg);
1439 msg.DeleteAllVariables();
1440 }
1441
1442 // Send end-of-database notification
1443 msg.SetCode(CMD_USER_DB_EOF);
1444 SendMessage(&msg);
1445}
ff550544
VK
1446
1447
1448//
1449// Create new user
1450//
1451
1452void ClientSession::CreateUser(CSCPMessage *pRequest)
1453{
1454 CSCPMessage msg;
1455
1456 // Prepare responce message
1457 msg.SetCode(CMD_REQUEST_COMPLETED);
1458 msg.SetId(pRequest->GetId());
1459
1460 // Check user rights
1461 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
1462 {
1463 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1464 }
1465 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1466 {
1467 // User database have to be locked before any
1468 // changes to user database can be made
1469 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1470 }
1471 else
1472 {
984542f8 1473 DWORD dwResult, dwUserId;
ff550544
VK
1474 BOOL bIsGroup;
1475 char szUserName[MAX_USER_NAME];
1476
1477 pRequest->GetVariableStr(VID_USER_NAME, szUserName, MAX_USER_NAME);
8f7e2482
VK
1478 if (IsValidObjectName(szUserName))
1479 {
1480 bIsGroup = pRequest->GetVariableShort(VID_IS_GROUP);
1481 dwResult = CreateNewUser(szUserName, bIsGroup, &dwUserId);
1482 msg.SetVariable(VID_RCC, dwResult);
1483 if (dwResult == RCC_SUCCESS)
1484 msg.SetVariable(VID_USER_ID, dwUserId); // Send id of new user to client
1485 }
1486 else
1487 {
1488 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
1489 }
ff550544
VK
1490 }
1491
1492 // Send responce
1493 SendMessage(&msg);
1494}
1495
1496
1497//
1498// Update existing user's data
1499//
1500
1501void ClientSession::UpdateUser(CSCPMessage *pRequest)
1502{
612d43dc
VK
1503 CSCPMessage msg;
1504
1505 // Prepare responce message
1506 msg.SetCode(CMD_REQUEST_COMPLETED);
1507 msg.SetId(pRequest->GetId());
1508
1509 // Check user rights
1510 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
1511 {
1512 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1513 }
1514 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1515 {
1516 // User database have to be locked before any
1517 // changes to user database can be made
1518 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1519 }
1520 else
1521 {
86f31e8f 1522 DWORD dwUserId, dwResult;
612d43dc
VK
1523
1524 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1525 if (dwUserId & GROUP_FLAG)
1526 {
1527 NMS_USER_GROUP group;
2d5c8ac8 1528 DWORD i, dwId;
86f31e8f
VK
1529
1530 group.dwId = dwUserId;
2d5c8ac8
VK
1531 pRequest->GetVariableStr(VID_USER_DESCRIPTION, group.szDescription, MAX_USER_DESCR);
1532 pRequest->GetVariableStr(VID_USER_NAME, group.szName, MAX_USER_NAME);
1533 group.wFlags = pRequest->GetVariableShort(VID_USER_FLAGS);
1534 group.wSystemRights = pRequest->GetVariableShort(VID_USER_SYS_RIGHTS);
1535 group.dwNumMembers = pRequest->GetVariableLong(VID_NUM_MEMBERS);
1536 group.pMembers = (DWORD *)malloc(sizeof(DWORD) * group.dwNumMembers);
1537 for(i = 0, dwId = VID_GROUP_MEMBER_BASE; i < group.dwNumMembers; i++, dwId++)
1538 group.pMembers[i] = pRequest->GetVariableLong(dwId);
86f31e8f 1539 dwResult = ModifyGroup(&group);
2d5c8ac8 1540 safe_free(group.pMembers);
612d43dc
VK
1541 }
1542 else
1543 {
1544 NMS_USER user;
1545
1546 user.dwId = dwUserId;
1547 pRequest->GetVariableStr(VID_USER_DESCRIPTION, user.szDescription, MAX_USER_DESCR);
1548 pRequest->GetVariableStr(VID_USER_FULL_NAME, user.szFullName, MAX_USER_FULLNAME);
1549 pRequest->GetVariableStr(VID_USER_NAME, user.szName, MAX_USER_NAME);
1550 user.wFlags = pRequest->GetVariableShort(VID_USER_FLAGS);
86f31e8f
VK
1551 user.wSystemRights = pRequest->GetVariableShort(VID_USER_SYS_RIGHTS);
1552 dwResult = ModifyUser(&user);
612d43dc 1553 }
86f31e8f 1554 msg.SetVariable(VID_RCC, dwResult);
612d43dc
VK
1555 }
1556
1557 // Send responce
1558 SendMessage(&msg);
ff550544
VK
1559}
1560
1561
1562//
1563// Delete user
1564//
1565
1566void ClientSession::DeleteUser(CSCPMessage *pRequest)
1567{
1568 CSCPMessage msg;
1569 DWORD dwUserId;
1570
1571 // Prepare responce message
1572 msg.SetCode(CMD_REQUEST_COMPLETED);
1573 msg.SetId(pRequest->GetId());
1574
612d43dc
VK
1575 // Check user rights
1576 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
ff550544 1577 {
612d43dc
VK
1578 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1579 }
1580 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1581 {
1582 // User database have to be locked before any
1583 // changes to user database can be made
1584 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1585 }
1586 else
1587 {
1588 // Get Id of user to be deleted
1589 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1590
1591 if (dwUserId != 0)
ff550544 1592 {
c9363772 1593 DWORD dwResult;
612d43dc 1594
c9363772
VK
1595 dwResult = DeleteUserFromDB(dwUserId);
1596 msg.SetVariable(VID_RCC, dwResult);
ff550544
VK
1597 }
1598 else
1599 {
612d43dc
VK
1600 // Nobody can delete system administrator account
1601 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
ff550544
VK
1602 }
1603 }
ff550544
VK
1604
1605 // Send responce
1606 SendMessage(&msg);
1607}
1608
1609
1610//
1611// Lock/unlock user database
1612//
1613
1614void ClientSession::LockUserDB(DWORD dwRqId, BOOL bLock)
1615{
1616 CSCPMessage msg;
1617 char szBuffer[256];
1618
1619 // Prepare responce message
1620 msg.SetCode(CMD_REQUEST_COMPLETED);
1621 msg.SetId(dwRqId);
1622
1623 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS)
1624 {
1625 if (bLock)
1626 {
1627 if (!LockComponent(CID_USER_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
1628 {
1629 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
1630 msg.SetVariable(VID_LOCKED_BY, szBuffer);
1631 }
1632 else
1633 {
1634 m_dwFlags |= CSF_USER_DB_LOCKED;
1635 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1636 }
1637 }
1638 else
1639 {
1640 if (m_dwFlags & CSF_USER_DB_LOCKED)
1641 {
1642 UnlockComponent(CID_USER_DB);
1643 m_dwFlags &= ~CSF_USER_DB_LOCKED;
1644 }
1645 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1646 }
1647 }
1648 else
1649 {
1650 // Current user has no rights for user account management
1651 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1652 }
1653
1654 // Send responce
1655 SendMessage(&msg);
1656}
984542f8
VK
1657
1658
1659//
1660// Notify client on user database update
1661//
1662
1663void ClientSession::OnUserDBUpdate(int iCode, DWORD dwUserId, NMS_USER *pUser, NMS_USER_GROUP *pGroup)
1664{
1665 CSCPMessage msg;
1666
cb7ec554 1667 if (IsAuthenticated())
984542f8
VK
1668 {
1669 msg.SetCode(CMD_USER_DB_UPDATE);
1670 msg.SetId(0);
1671 msg.SetVariable(VID_UPDATE_TYPE, (WORD)iCode);
984542f8
VK
1672
1673 switch(iCode)
1674 {
1675 case USER_DB_CREATE:
2d5c8ac8 1676 msg.SetVariable(VID_USER_ID, dwUserId);
984542f8 1677 if (dwUserId & GROUP_FLAG)
984542f8 1678 msg.SetVariable(VID_USER_NAME, pGroup->szName);
984542f8 1679 else
984542f8 1680 msg.SetVariable(VID_USER_NAME, pUser->szName);
2d5c8ac8
VK
1681 break;
1682 case USER_DB_MODIFY:
1683 if (dwUserId & GROUP_FLAG)
1684 FillGroupInfoMessage(&msg, pGroup);
1685 else
1686 FillUserInfoMessage(&msg, pUser);
984542f8
VK
1687 break;
1688 default:
2d5c8ac8 1689 msg.SetVariable(VID_USER_ID, dwUserId);
984542f8
VK
1690 break;
1691 }
1692
1693 SendMessage(&msg);
1694 }
1695}
017e1e13
VK
1696
1697
9ed4eaff
VK
1698//
1699// Change management status for the object
1700//
1701
1702void ClientSession::ChangeObjectMgmtStatus(CSCPMessage *pRequest)
1703{
1704 CSCPMessage msg;
1705 DWORD dwObjectId;
1706 NetObj *pObject;
1707
1708 // Prepare responce message
1709 msg.SetCode(CMD_REQUEST_COMPLETED);
1710 msg.SetId(pRequest->GetId());
1711
1712 // Get object id and check access rights
1713 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1714 pObject = FindObjectById(dwObjectId);
1715 if (pObject != NULL)
1716 {
1717 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1718 {
1719 BOOL bIsManaged;
1720
1721 bIsManaged = (BOOL)pRequest->GetVariableShort(VID_MGMT_STATUS);
1722 pObject->SetMgmtStatus(bIsManaged);
1723 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1724 }
1725 else
1726 {
1727 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1728 }
1729 }
1730 else
1731 {
1732 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1733 }
1734
1735 // Send responce
1736 SendMessage(&msg);
1737}
1738
1739
017e1e13
VK
1740//
1741// Set user's password
1742//
1743
1744void ClientSession::SetPassword(CSCPMessage *pRequest)
1745{
1746 CSCPMessage msg;
1747 DWORD dwUserId;
1748
1749 // Prepare responce message
1750 msg.SetCode(CMD_REQUEST_COMPLETED);
1751 msg.SetId(pRequest->GetId());
1752
1753 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1754
1755 if (((m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS) &&
1756 !((dwUserId == 0) && (m_dwUserId != 0))) || // Only administrator can change password for UID 0
1757 (dwUserId == m_dwUserId)) // User can change password for itself
1758 {
1759 DWORD dwResult;
6528a4d7 1760 BYTE szPassword[SHA1_DIGEST_SIZE];
017e1e13 1761
6528a4d7 1762 pRequest->GetVariableBinary(VID_PASSWORD, szPassword, SHA1_DIGEST_SIZE);
017e1e13
VK
1763 dwResult = SetUserPassword(dwUserId, szPassword);
1764 msg.SetVariable(VID_RCC, dwResult);
1765 }
1766 else
1767 {
1768 // Current user has no rights to change password for specific user
1769 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1770 }
1771
1772 // Send responce
1773 SendMessage(&msg);
1774}
7257eb7d
VK
1775
1776
1777//
1778// Send node's DCIs to client and lock data collection settings
1779//
1780
1781void ClientSession::OpenNodeDCIList(CSCPMessage *pRequest)
1782{
1783 CSCPMessage msg;
3c55b85d
VK
1784 DWORD dwObjectId;
1785 NetObj *pObject;
1786 BOOL bSuccess = FALSE;
7257eb7d
VK
1787
1788 // Prepare responce message
1789 msg.SetCode(CMD_REQUEST_COMPLETED);
1790 msg.SetId(pRequest->GetId());
1791
3c55b85d
VK
1792 // Get node id and check object class and access rights
1793 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1794 pObject = FindObjectById(dwObjectId);
1795 if (pObject != NULL)
1796 {
62d11997
VK
1797 if ((pObject->Type() == OBJECT_NODE) ||
1798 (pObject->Type() == OBJECT_TEMPLATE))
3c55b85d
VK
1799 {
1800 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1801 {
1802 // Try to lock DCI list
62d11997 1803 bSuccess = ((Template *)pObject)->LockDCIList(m_dwIndex);
3c55b85d 1804 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_COMPONENT_LOCKED);
338493a0
VK
1805
1806 // Modify list of open nodes DCI lists
1807 if (bSuccess)
1808 {
1809 m_pOpenDCIList = (DWORD *)realloc(m_pOpenDCIList, sizeof(DWORD) * (m_dwOpenDCIListSize + 1));
1810 m_pOpenDCIList[m_dwOpenDCIListSize] = dwObjectId;
1811 m_dwOpenDCIListSize++;
1812 }
3c55b85d
VK
1813 }
1814 else
1815 {
1816 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1817 }
1818 }
1819 else
1820 {
1821 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1822 }
1823 }
1824 else
1825 {
1826 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1827 }
7257eb7d
VK
1828
1829 // Send responce
1830 SendMessage(&msg);
3c55b85d
VK
1831
1832 // If DCI list was successfully locked, send it to client
1833 if (bSuccess)
62d11997 1834 ((Template *)pObject)->SendItemsToClient(this, pRequest->GetId());
7257eb7d
VK
1835}
1836
1837
1838//
1839// Unlock node's data collection settings
1840//
1841
1842void ClientSession::CloseNodeDCIList(CSCPMessage *pRequest)
1843{
1844 CSCPMessage msg;
3c55b85d
VK
1845 DWORD dwObjectId;
1846 NetObj *pObject;
7257eb7d
VK
1847
1848 // Prepare responce message
1849 msg.SetCode(CMD_REQUEST_COMPLETED);
1850 msg.SetId(pRequest->GetId());
1851
3c55b85d
VK
1852 // Get node id and check object class and access rights
1853 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1854 pObject = FindObjectById(dwObjectId);
1855 if (pObject != NULL)
1856 {
62d11997
VK
1857 if ((pObject->Type() == OBJECT_NODE) ||
1858 (pObject->Type() == OBJECT_TEMPLATE))
3c55b85d
VK
1859 {
1860 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1861 {
1862 BOOL bSuccess;
1863
1864 // Try to unlock DCI list
62d11997 1865 bSuccess = ((Template *)pObject)->UnlockDCIList(m_dwIndex);
3c55b85d 1866 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_OUT_OF_STATE_REQUEST);
338493a0
VK
1867
1868 // Modify list of open nodes DCI lists
1869 if (bSuccess)
1870 {
1871 DWORD i;
1872
1873 for(i = 0; i < m_dwOpenDCIListSize; i++)
1874 if (m_pOpenDCIList[i] == dwObjectId)
1875 {
1876 m_dwOpenDCIListSize--;
1877 memmove(&m_pOpenDCIList[i], &m_pOpenDCIList[i + 1],
1878 sizeof(DWORD) * (m_dwOpenDCIListSize - i));
1879 break;
1880 }
1881 }
3c55b85d
VK
1882 }
1883 else
1884 {
1885 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1886 }
1887 }
1888 else
1889 {
1890 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1891 }
1892 }
1893 else
1894 {
1895 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1896 }
1897
7257eb7d
VK
1898 // Send responce
1899 SendMessage(&msg);
1900}
c1c39152
VK
1901
1902
1903//
9ed4eaff 1904// Create, modify, or delete data collection item for node
c1c39152
VK
1905//
1906
9ed4eaff 1907void ClientSession::ModifyNodeDCI(CSCPMessage *pRequest)
c1c39152
VK
1908{
1909 CSCPMessage msg;
1910 DWORD dwObjectId;
1911 NetObj *pObject;
1912
1913 // Prepare responce message
1914 msg.SetCode(CMD_REQUEST_COMPLETED);
1915 msg.SetId(pRequest->GetId());
1916
9ed4eaff 1917 // Get node id and check object class and access rights
c1c39152
VK
1918 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1919 pObject = FindObjectById(dwObjectId);
1920 if (pObject != NULL)
1921 {
62d11997
VK
1922 if ((pObject->Type() == OBJECT_NODE) ||
1923 (pObject->Type() == OBJECT_TEMPLATE))
c1c39152 1924 {
62d11997 1925 if (((Template *)pObject)->IsLockedBySession(m_dwIndex))
9ed4eaff
VK
1926 {
1927 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1928 {
07a45e04 1929 DWORD i, dwItemId, dwNumMaps, *pdwMapId, *pdwMapIndex;
9ed4eaff
VK
1930 DCItem *pItem;
1931 BOOL bSuccess;
1932
1933 switch(pRequest->GetCode())
1934 {
1935 case CMD_CREATE_NEW_DCI:
1936 // Create dummy DCI
1937 pItem = new DCItem(CreateUniqueId(IDG_ITEM), "no name", DS_INTERNAL,
0ae741b9 1938 DCI_DT_INT, 60, 30, (Node *)pObject);
9ed4eaff 1939 pItem->SetStatus(ITEM_STATUS_DISABLED);
62d11997 1940 if (((Template *)pObject)->AddItem(pItem))
9ed4eaff
VK
1941 {
1942 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1943 // Return new item id to client
1944 msg.SetVariable(VID_DCI_ID, pItem->Id());
1945 }
1946 else // Unable to add item to node
1947 {
1948 delete pItem;
1949 msg.SetVariable(VID_RCC, RCC_DUPLICATE_DCI);
1950 }
1951 break;
1952 case CMD_MODIFY_NODE_DCI:
1953 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
62d11997
VK
1954 bSuccess = ((Template *)pObject)->UpdateItem(dwItemId, pRequest, &dwNumMaps,
1955 &pdwMapIndex, &pdwMapId);
07a45e04
VK
1956 if (bSuccess)
1957 {
1958 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1959
1960 // Send index to id mapping for newly created thresholds to client
1961 msg.SetVariable(VID_DCI_NUM_MAPS, dwNumMaps);
1962 for(i = 0; i < dwNumMaps; i++)
1963 {
1964 pdwMapId[i] = htonl(pdwMapId[i]);
1965 pdwMapIndex[i] = htonl(pdwMapIndex[i]);
1966 }
1967 msg.SetVariable(VID_DCI_MAP_IDS, (BYTE *)pdwMapId, sizeof(DWORD) * dwNumMaps);
1968 msg.SetVariable(VID_DCI_MAP_INDEXES, (BYTE *)pdwMapIndex, sizeof(DWORD) * dwNumMaps);
7247842d
VK
1969 safe_free(pdwMapId);
1970 safe_free(pdwMapIndex);
07a45e04
VK
1971 }
1972 else
1973 {
1974 msg.SetVariable(VID_RCC, RCC_INVALID_DCI_ID);
1975 }
9ed4eaff
VK
1976 break;
1977 case CMD_DELETE_NODE_DCI:
1978 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
62d11997 1979 bSuccess = ((Template *)pObject)->DeleteItem(dwItemId);
9ed4eaff
VK
1980 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_INVALID_DCI_ID);
1981 break;
1982 }
70573ffe
VK
1983 if (bSuccess)
1984 ((Template *)pObject)->SetDCIModificationFlag();
9ed4eaff
VK
1985 }
1986 else // User doesn't have MODIFY rights on object
1987 {
1988 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1989 }
1990 }
1991 else // Nodes DCI list not locked by this session
1992 {
1993 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1994 }
c1c39152 1995 }
9ed4eaff 1996 else // Object is not a node
c1c39152 1997 {
9ed4eaff 1998 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
5b9a1c7b
VK
1999 }
2000 }
2001 else // No object with given ID
2002 {
2003 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2004 }
2005
2006 // Send responce
2007 SendMessage(&msg);
2008}
2009
2010
2011//
2012// Change status for one or more DCIs
2013//
2014
2015void ClientSession::ChangeDCIStatus(CSCPMessage *pRequest)
2016{
2017 CSCPMessage msg;
2018 NetObj *pObject;
2019
2020 // Prepare responce message
2021 msg.SetCode(CMD_REQUEST_COMPLETED);
2022 msg.SetId(pRequest->GetId());
2023
2024 // Get node id and check object class and access rights
2025 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
2026 if (pObject != NULL)
2027 {
2028 if ((pObject->Type() == OBJECT_NODE) ||
2029 (pObject->Type() == OBJECT_TEMPLATE))
2030 {
2031 if (((Template *)pObject)->IsLockedBySession(m_dwIndex))
2032 {
2033 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
2034 {
2185f431
VK
2035 DWORD dwNumItems, *pdwItemList;
2036 int iStatus;
2037
2038 iStatus = pRequest->GetVariableShort(VID_DCI_STATUS);
2039 dwNumItems = pRequest->GetVariableLong(VID_NUM_ITEMS);
2040 pdwItemList = (DWORD *)malloc(sizeof(DWORD) * dwNumItems);
2041 pRequest->GetVariableInt32Array(VID_ITEM_LIST, dwNumItems, pdwItemList);
2042 if (((Template *)pObject)->SetItemStatus(dwNumItems, pdwItemList, iStatus))
2043 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2044 else
2045 msg.SetVariable(VID_RCC, RCC_INVALID_DCI_ID);
2046 free(pdwItemList);
5b9a1c7b
VK
2047 }
2048 else // User doesn't have MODIFY rights on object
2049 {
2050 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2051 }
2052 }
2053 else // Nodes DCI list not locked by this session
2054 {
2055 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2056 }
2057 }
2058 else // Object is not a node
2059 {
2060 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
c1c39152
VK
2061 }
2062 }
9ed4eaff 2063 else // No object with given ID
c1c39152
VK
2064 {
2065 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2066 }
2067
2068 // Send responce
2069 SendMessage(&msg);
2070}
ebebc8ea
VK
2071
2072
933aee5c 2073//
62d11997 2074// Copy DCI from one node or template to another
933aee5c
VK
2075//
2076
2077void ClientSession::CopyDCI(CSCPMessage *pRequest)
2078{
2079 CSCPMessage msg;
2080 NetObj *pSource, *pDestination;
2081
2082 // Prepare responce message
2083 msg.SetCode(CMD_REQUEST_COMPLETED);
2084 msg.SetId(pRequest->GetId());
2085
2086 // Get source and destination
2087 pSource = FindObjectById(pRequest->GetVariableLong(VID_SOURCE_OBJECT_ID));
2088 pDestination = FindObjectById(pRequest->GetVariableLong(VID_DESTINATION_OBJECT_ID));
2089 if ((pSource != NULL) && (pDestination != NULL))
2090 {
2091 // Check object types
62d11997
VK
2092 if (((pSource->Type() == OBJECT_NODE) || (pSource->Type() == OBJECT_TEMPLATE)) &&
2093 (pDestination->Type() == OBJECT_NODE))
933aee5c 2094 {
62d11997 2095 if (((Template *)pSource)->IsLockedBySession(m_dwIndex))
933aee5c
VK
2096 {
2097 // Check access rights
2098 if ((pSource->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ)) &&
2099 (pDestination->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)))
2100 {
2101 // Attempt to lock destination's DCI list
079c3851
VK
2102 if ((pDestination->Id() == pSource->Id()) ||
2103 (((Template *)pDestination)->LockDCIList(m_dwIndex)))
933aee5c
VK
2104 {
2105 DWORD i, *pdwItemList, dwNumItems;
2106 const DCItem *pSrcItem;
2107 DCItem *pDstItem;
2108 int iErrors = 0;
2109
2110 // Get list of items to be copied
2111 dwNumItems = pRequest->GetVariableLong(VID_NUM_ITEMS);
2112 pdwItemList = (DWORD *)malloc(sizeof(DWORD) * dwNumItems);
2113 pRequest->GetVariableInt32Array(VID_ITEM_LIST, dwNumItems, pdwItemList);
2114
2115 // Copy items
2116 for(i = 0; i < dwNumItems; i++)
2117 {
62d11997 2118 pSrcItem = ((Template *)pSource)->GetItemById(pdwItemList[i]);
933aee5c
VK
2119 if (pSrcItem != NULL)
2120 {
2121 pDstItem = new DCItem(pSrcItem);
2122 pDstItem->SetId(CreateUniqueId(IDG_ITEM));
2123 pDstItem->SetStatus(ITEM_STATUS_ACTIVE);
8f3374c9 2124 pDstItem->BindToNode((Template *)pDestination);
62d11997 2125 if (!((Template *)pDestination)->AddItem(pDstItem))
933aee5c
VK
2126 {
2127 delete pDstItem;
2128 iErrors++;
2129 }
2130 }
2131 else
2132 {
2133 iErrors++;
2134 }
2135 }
2136
2137 // Cleanup
2138 free(pdwItemList);
079c3851
VK
2139 if (pDestination->Id() != pSource->Id())
2140 ((Template *)pDestination)->UnlockDCIList(m_dwIndex);
933aee5c
VK
2141 msg.SetVariable(VID_RCC, (iErrors == 0) ? RCC_SUCCESS : RCC_DCI_COPY_ERRORS);
2142 }
2143 else // Destination's DCI list already locked by someone else
2144 {
2145 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
2146 }
2147 }
2148 else // User doesn't have enough rights on object(s)
2149 {
2150 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2151 }
2152 }
2153 else // Source node DCI list not locked by this session
2154 {
2155 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2156 }
2157 }
2158 else // Object(s) is not a node
2159 {
2160 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2161 }
2162 }
2163 else // No object(s) with given ID
2164 {
2165 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2166 }
2167
2168 // Send responce
2169 SendMessage(&msg);
2170}
2171
2172
ebebc8ea
VK
2173//
2174// Get collected data
2175//
2176
2177void ClientSession::GetCollectedData(CSCPMessage *pRequest)
2178{
2179 CSCPMessage msg;
2180 DWORD dwObjectId;
2181 NetObj *pObject;
6159a875 2182 BOOL bSuccess = FALSE;
2b9c1c41 2183 static DWORD m_dwRowSize[] = { 8, 8, 12, 12, 260, 12 };
ebebc8ea
VK
2184
2185 // Prepare responce message
2186 msg.SetCode(CMD_REQUEST_COMPLETED);
2187 msg.SetId(pRequest->GetId());
2188
2189 // Get node id and check object class and access rights
2190 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
2191 pObject = FindObjectById(dwObjectId);
2192 if (pObject != NULL)
2193 {
2194 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
2195 {
2196 DB_ASYNC_RESULT hResult;
2197 DWORD dwItemId, dwMaxRows, dwTimeFrom, dwTimeTo;
6159a875 2198 DWORD dwAllocatedRows = 100, dwNumRows = 0;
bdce7422
VK
2199 char szQuery[512], szCond[256];
2200 int iPos = 0, iType;
2201 DCI_DATA_HEADER *pData = NULL;
6159a875 2202 DCI_DATA_ROW *pCurr;
bdce7422
VK
2203
2204 // Send CMD_REQUEST_COMPLETED message
2205 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2206 SendMessage(&msg);
ebebc8ea
VK
2207
2208 // Get request parameters
2209 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
2210 dwMaxRows = pRequest->GetVariableLong(VID_MAX_ROWS);
2211 dwTimeFrom = pRequest->GetVariableLong(VID_TIME_FROM);
2212 dwTimeTo = pRequest->GetVariableLong(VID_TIME_TO);
2213
9f20696e 2214 szCond[0] = 0;
bdce7422
VK
2215 if (dwTimeFrom != 0)
2216 {
1dc90d86 2217 sprintf(szCond, " AND idata_timestamp>=%d", dwTimeFrom);
bdce7422
VK
2218 iPos = strlen(szCond);
2219 }
2220 if (dwTimeTo != 0)
2221 {
1dc90d86 2222 sprintf(&szCond[iPos], " AND idata_timestamp<=%d", dwTimeTo);
bdce7422
VK
2223 }
2224
4e839863
VK
2225 // Get item's data type to determine actual row size
2226 iType = ((Node *)pObject)->GetItemType(dwItemId);
2227
31115ff9 2228 sprintf(szQuery, "SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC",
bdce7422 2229 dwObjectId, dwItemId, szCond);
ebebc8ea
VK
2230 hResult = DBAsyncSelect(g_hCoreDB, szQuery);
2231 if (hResult != NULL)
2232 {
6159a875
VK
2233 // Allocate initial memory block and prepare data header
2234 pData = (DCI_DATA_HEADER *)malloc(dwAllocatedRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER));
2235 pData->dwDataType = htonl((DWORD)iType);
2236 pData->dwItemId = htonl(dwItemId);
2237
2238 // Fill memory block with records
2239 pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER));
ebebc8ea
VK
2240 while(DBFetch(hResult))
2241 {
6159a875 2242 if ((dwMaxRows > 0) && (dwNumRows >= dwMaxRows))
bdce7422 2243 break;
6159a875
VK
2244
2245 // Extend buffer if we are at the end
2246 if (dwNumRows == dwAllocatedRows)
2247 {
2248 dwAllocatedRows += 50;
2249 pData = (DCI_DATA_HEADER *)realloc(pData,
2250 dwAllocatedRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER));
2251 pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER) + m_dwRowSize[iType] * dwNumRows);
2252 }
2253
2254 dwNumRows++;
2255
2256 pCurr->dwTimeStamp = htonl(DBGetFieldAsyncULong(hResult, 0));
2257 switch(iType)
2258 {
0ae741b9
VK
2259 case DCI_DT_INT:
2260 case DCI_DT_UINT:
9f20696e
VK
2261 pCurr->value.dwInteger = htonl(DBGetFieldAsyncULong(hResult, 1));
2262 break;
0ae741b9
VK
2263 case DCI_DT_INT64:
2264 case DCI_DT_UINT64:
0c6014e4 2265 pCurr->value.qwInt64 = htonq(DBGetFieldAsyncUInt64(hResult, 1));
0ae741b9 2266 break;
42d7ed00 2267 case DCI_DT_FLOAT:
9f20696e 2268 pCurr->value.dFloat = htond(DBGetFieldAsyncDouble(hResult, 1));
6159a875 2269 break;
42d7ed00 2270 case DCI_DT_STRING:
6159a875
VK
2271 DBGetFieldAsync(hResult, 1, pCurr->value.szString, MAX_DCI_STRING_VALUE);
2272 break;
2273 }
2274 pCurr = (DCI_DATA_ROW *)(((char *)pCurr) + m_dwRowSize[iType]);
ebebc8ea
VK
2275 }
2276 DBFreeAsyncResult(hResult);
9f20696e 2277 pData->dwNumRows = htonl(dwNumRows);
6159a875
VK
2278
2279 // Prepare and send raw message with fetched data
2280 m_pSendQueue->Put(
2281 CreateRawCSCPMessage(CMD_DCI_DATA, pRequest->GetId(),
2282 dwNumRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER),
2283 pData, NULL));
2284 free(pData);
2285 bSuccess = TRUE;
ebebc8ea 2286 }
62d11997
VK
2287 else
2288 {
2289 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
2290 }
ebebc8ea
VK
2291 }
2292 else
2293 {
2294 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2295 }
2296 }
2297 else // No object with given ID
2298 {
2299 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2300 }
2301
2302 // Send responce
6159a875
VK
2303 if (!bSuccess)
2304 SendMessage(&msg);
ebebc8ea 2305}
06e7be2f
VK
2306
2307
2308//
2309// Open event processing policy
2310//
2311
2312void ClientSession::OpenEPP(DWORD dwRqId)
2313{
2314 CSCPMessage msg;
2315 char szBuffer[256];
2316 BOOL bSuccess = FALSE;
2317
2318 // Prepare responce message
2319 msg.SetCode(CMD_REQUEST_COMPLETED);
2320 msg.SetId(dwRqId);
2321
2322 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
2323 {
2324 if (!LockComponent(CID_EPP, m_dwIndex, m_szUserName, NULL, szBuffer))
2325 {
2326 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
2327 msg.SetVariable(VID_LOCKED_BY, szBuffer);
2328 }
2329 else
2330 {
2331 m_dwFlags |= CSF_EPP_LOCKED;
2332 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2333 msg.SetVariable(VID_NUM_RULES, g_pEventPolicy->NumRules());
2334 bSuccess = TRUE;
2335 }
2336 }
2337 else
2338 {
2339 // Current user has no rights for event policy management
2340 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2341 }
2342
2343 // Send responce
2344 SendMessage(&msg);
2345
2346 // Send policy to client
2347 if (bSuccess)
2348 g_pEventPolicy->SendToClient(this, dwRqId);
2349}
2350
2351
2352//
2353// Close event processing policy
2354//
2355
2356void ClientSession::CloseEPP(DWORD dwRqId)
2357{
2358 CSCPMessage msg;
2359
2360 // Prepare responce message
2361 msg.SetCode(CMD_REQUEST_COMPLETED);
2362 msg.SetId(dwRqId);
2363
2364 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
2365 {
2366 if (m_dwFlags & CSF_EPP_LOCKED)
2367 {
2368 UnlockComponent(CID_EPP);
2369 m_dwFlags &= ~CSF_EPP_LOCKED;
2370 }
2371 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2372 }
2373 else
2374 {
2375 // Current user has no rights for event policy management
2376 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2377 }
2378
2379 // Send responce
2380 SendMessage(&msg);
2381}
2382
2383
2384//
2385// Save event processing policy
2386//
2387
8f7e2482 2388void ClientSession::SaveEPP(CSCPMessage *pRequest)
06e7be2f 2389{
8f7e2482
VK
2390 CSCPMessage msg;
2391
2392 // Prepare responce message
2393 msg.SetCode(CMD_REQUEST_COMPLETED);
2394 msg.SetId(pRequest->GetId());
2395
2396 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
2397 {
2398 if (m_dwFlags & CSF_EPP_LOCKED)
2399 {
2400 msg.SetVariable(VID_RCC, RCC_SUCCESS);
8f7e2482
VK
2401 m_dwNumRecordsToUpload = pRequest->GetVariableLong(VID_NUM_RULES);
2402 m_dwRecordsUploaded = 0;
043fe1ec
VK
2403 if (m_dwNumRecordsToUpload == 0)
2404 {
2405 g_pEventPolicy->ReplacePolicy(0, NULL);
2406 g_pEventPolicy->SaveToDB();
2407 }
2408 else
2409 {
2410 m_dwFlags |= CSF_EPP_UPLOAD;
2411 m_ppEPPRuleList = (EPRule **)malloc(sizeof(EPRule *) * m_dwNumRecordsToUpload);
2412 memset(m_ppEPPRuleList, 0, sizeof(EPRule *) * m_dwNumRecordsToUpload);
2413 }
8f7e2482
VK
2414 DebugPrintf("Accepted EPP upload request for %d rules\n", m_dwNumRecordsToUpload);
2415 }
2416 else
2417 {
2418 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2419 }
2420 }
2421 else
2422 {
2423 // Current user has no rights for event policy management
2424 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2425 }
2426
2427 // Send responce
2428 SendMessage(&msg);
06e7be2f
VK
2429}
2430
2431
2432//
8f7e2482 2433// Process EPP rule received from client
06e7be2f
VK
2434//
2435
8f7e2482 2436void ClientSession::ProcessEPPRecord(CSCPMessage *pRequest)
06e7be2f 2437{
8f7e2482
VK
2438 if (!(m_dwFlags & CSF_EPP_LOCKED))
2439 {
2440 CSCPMessage msg;
2441
2442 msg.SetCode(CMD_REQUEST_COMPLETED);
2443 msg.SetId(pRequest->GetId());
2444 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2445 SendMessage(&msg);
2446 }
2447 else
2448 {
2449 if (m_dwRecordsUploaded < m_dwNumRecordsToUpload)
2450 {
2451 m_ppEPPRuleList[m_dwRecordsUploaded] = new EPRule(pRequest);
2452 m_dwRecordsUploaded++;
2453 if (m_dwRecordsUploaded == m_dwNumRecordsToUpload)
2454 {
2455 CSCPMessage msg;
2456
2457 // All records received, replace event policy...
2458 DebugPrintf("Replacing event processing policy with a new one at %p (%d rules)\n",
2459 m_ppEPPRuleList, m_dwNumRecordsToUpload);
2460 g_pEventPolicy->ReplacePolicy(m_dwNumRecordsToUpload, m_ppEPPRuleList);
043fe1ec 2461 g_pEventPolicy->SaveToDB();
8f7e2482
VK
2462 m_ppEPPRuleList = NULL;
2463
2464 // ... and send final confirmation
2465 msg.SetCode(CMD_REQUEST_COMPLETED);
2466 msg.SetId(pRequest->GetId());
2467 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2468 SendMessage(&msg);
2469
2470 m_dwFlags &= ~CSF_EPP_UPLOAD;
2471 }
2472 }
2473 }
06e7be2f
VK
2474}
2475
2476
2477//
2478// Send list of available MIB files to client
2479//
2480
2481void ClientSession::SendMIBList(DWORD dwRqId)
2482{
2483 CSCPMessage msg;
2484 DWORD dwId1, dwId2, dwNumFiles;
2485 DIR *dir;
2486 int iBufPos;
c9ccd685 2487 struct dirent *dptr;
06e7be2f
VK
2488 char szBuffer[MAX_PATH];
2489 BYTE md5Hash[MD5_DIGEST_SIZE];
2490
2491 // Prepare responce message
2492 msg.SetCode(CMD_MIB_LIST);
2493 msg.SetId(dwRqId);
2494
2495 // Read directory
2496 dwNumFiles = 0;
2497 strcpy(szBuffer, g_szDataDir);
2498 strcat(szBuffer, DDIR_MIBS);
2499 dir = opendir(szBuffer);
2500 if (dir != NULL)
2501 {
06f6e54c 2502 strcat(szBuffer, FS_PATH_SEPARATOR);
06e7be2f
VK
2503 iBufPos = strlen(szBuffer);
2504 dwId1 = VID_MIB_NAME_BASE;
2505 dwId2 = VID_MIB_HASH_BASE;
2506 while((dptr = readdir(dir)) != NULL)
2507 {
06f6e54c
VK
2508 if (dptr->d_name[0] == '.')
2509 continue;
2510
06e7be2f
VK
2511 strcpy(&szBuffer[iBufPos], dptr->d_name);
2512 if (CalculateFileMD5Hash(szBuffer, md5Hash))
2513 {
2514 msg.SetVariable(dwId1++, dptr->d_name);
2515 msg.SetVariable(dwId2++, md5Hash, MD5_DIGEST_SIZE);
2516 dwNumFiles++;
2517 }
2518 }
2519 closedir(dir);
2520 }
2521
2522 msg.SetVariable(VID_NUM_MIBS, dwNumFiles);
2523
2524 // Send responce
2525 SendMessage(&msg);
2526}
2527
2528
2529//
2530// Send requested MIB file to client
2531//
2532
2533void ClientSession::SendMIB(CSCPMessage *pRequest)
2534{
2535 CSCPMessage msg;
2536 BYTE *pFile;
2537 DWORD dwFileSize;
2538 char szBuffer[MAX_PATH], szMIB[MAX_PATH];
2539
2540 // Prepare responce message
2541 msg.SetCode(CMD_MIB);
2542 msg.SetId(pRequest->GetId());
2543
2544 // Get name of the requested file
2545 pRequest->GetVariableStr(VID_MIB_NAME, szMIB, MAX_PATH);
2546
2547 // Load file into memory
2548 strcpy(szBuffer, g_szDataDir);
2549 strcat(szBuffer, DDIR_MIBS);
2550#ifdef _WIN32
2551 strcat(szBuffer, "\\");
2552#else
2553 strcat(szBuffer, "/");
2554#endif
2555 strcat(szBuffer, szMIB);
2556 pFile = LoadFile(szBuffer, &dwFileSize);
2557 if (pFile != NULL)
2558 {
2559 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2560 msg.SetVariable(VID_MIB_FILE_SIZE, dwFileSize);
2561 msg.SetVariable(VID_MIB_FILE, pFile, dwFileSize);
2562 free(pFile);
2563 }
2564 else
2565 {
2566 msg.SetVariable(VID_RCC, RCC_SYSTEM_FAILURE);
2567 }
2568
2569 // Send responce
2570 SendMessage(&msg);
3421c063
VK
2571}
2572
2573
ef44d5ea
VK
2574//
2575// Create new object
2576//
2577
2578void ClientSession::CreateObject(CSCPMessage *pRequest)
2579{
e6b958c4
VK
2580 CSCPMessage msg;
2581 NetObj *pObject, *pParent;
b61fe31e
VK
2582 int iClass, iServiceType;
2583 TCHAR *pDescription, szObjectName[MAX_OBJECT_NAME];
2584 TCHAR *pszRequest, *pszResponce;
b688074e 2585 DWORD dwIpAddr;
b61fe31e 2586 WORD wIpProto, wIpPort;
b688074e 2587 BOOL bParentAlwaysValid = FALSE;
e6b958c4
VK
2588
2589 // Prepare responce message
2590 msg.SetCode(CMD_REQUEST_COMPLETED);
2591 msg.SetId(pRequest->GetId());
2592
b688074e
VK
2593 iClass = pRequest->GetVariableShort(VID_OBJECT_CLASS);
2594
e6b958c4
VK
2595 // Find parent object
2596 pParent = FindObjectById(pRequest->GetVariableLong(VID_PARENT_ID));
7cbe553e 2597 if (iClass == OBJECT_NODE)
b688074e
VK
2598 {
2599 dwIpAddr = pRequest->GetVariableLong(VID_IP_ADDRESS);
7cbe553e
VK
2600 if ((pParent == NULL) && (dwIpAddr != 0))
2601 {
2602 pParent = FindSubnetForNode(dwIpAddr);
2603 bParentAlwaysValid = TRUE;
2604 }
b688074e
VK
2605 }
2606 if ((pParent != NULL) || (iClass == OBJECT_NODE))
e6b958c4
VK
2607 {
2608 // User should have create access to parent object
b688074e
VK
2609 if ((pParent != NULL) ?
2610 pParent->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CREATE) :
2611 g_pEntireNet->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CREATE))
e6b958c4 2612 {
62d11997 2613 // Parent object should be of valid type
b688074e 2614 if (bParentAlwaysValid || IsValidParentClass(iClass, (pParent != NULL) ? pParent->Type() : -1))
e6b958c4 2615 {
e6b958c4 2616 pRequest->GetVariableStr(VID_OBJECT_NAME, szObjectName, MAX_OBJECT_NAME);
8f7e2482 2617 if (IsValidObjectName(szObjectName))
e6b958c4 2618 {
62d11997
VK
2619 // Create new object
2620 switch(iClass)
e6b958c4 2621 {
62d11997 2622 case OBJECT_NODE:
b688074e 2623 pObject = PollNewNode(dwIpAddr, pRequest->GetVariableLong(VID_IP_NETMASK),
62d11997
VK
2624 DF_DEFAULT, szObjectName);
2625 break;
2626 case OBJECT_CONTAINER:
2627 pDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
2628 pObject = new Container(szObjectName,
2629 pRequest->GetVariableLong(VID_CATEGORY),
2630 pDescription);
2631 safe_free(pDescription);
2632 NetObjInsert(pObject, TRUE);
2633 break;
2634 case OBJECT_TEMPLATEGROUP:
2635 pDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
2636 pObject = new TemplateGroup(szObjectName, pDescription);
2637 safe_free(pDescription);
2638 NetObjInsert(pObject, TRUE);
2639 break;
2640 case OBJECT_TEMPLATE:
2641 pObject = new Template;
2642 pObject->SetName(szObjectName);
2643 NetObjInsert(pObject, TRUE);
2644 break;
b61fe31e
VK
2645 case OBJECT_NETWORKSERVICE:
2646 iServiceType = (int)pRequest->GetVariableShort(VID_SERVICE_TYPE);
2647 wIpProto = pRequest->GetVariableShort(VID_IP_PROTO);
2648 wIpPort = pRequest->GetVariableShort(VID_IP_PORT);
2649 pszRequest = pRequest->GetVariableStr(VID_SERVICE_REQUEST);
2650 pszResponce = pRequest->GetVariableStr(VID_SERVICE_RESPONCE);
2651 pObject = new NetworkService(iServiceType, wIpProto, wIpPort,
2652 pszRequest, pszResponce, (Node *)pParent);
2653 pObject->SetName(szObjectName);
2654 NetObjInsert(pObject, TRUE);
2655 break;
62d11997 2656 }
917aa2e6 2657
62d11997
VK
2658 // If creation was successful do binding
2659 if (pObject != NULL)
2660 {
7cbe553e
VK
2661 if (pParent != NULL) // parent can be NULL for nodes
2662 {
2663 pParent->AddChild(pObject);
2664 pObject->AddParent(pParent);
b61fe31e 2665 pParent->CalculateCompoundStatus();
7cbe553e 2666 }
62d11997
VK
2667 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2668 msg.SetVariable(VID_OBJECT_ID, pObject->Id());
917aa2e6
VK
2669 }
2670 else
2671 {
62d11997 2672 msg.SetVariable(VID_RCC, RCC_OBJECT_CREATION_FAILED);
917aa2e6 2673 }
e6b958c4
VK
2674 }
2675 else
2676 {
8f7e2482 2677 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
e6b958c4
VK
2678 }
2679 }
2680 else
2681 {
2682 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2683 }
2684 }
2685 else
2686 {
2687 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2688 }
2689 }
2690 else
2691 {
2692 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2693 }
2694
2695 // Send responce
2696 SendMessage(&msg);
2697}
2698
2699
2700//
2701// Bind/unbind object
2702//
2703
2704void ClientSession::ChangeObjectBinding(CSCPMessage *pRequest, BOOL bBind)
2705{
2706 CSCPMessage msg;
2707 NetObj *pParent, *pChild;
2708
2709 // Prepare responce message
2710 msg.SetCode(CMD_REQUEST_COMPLETED);
2711 msg.SetId(pRequest->GetId());
2712
2713 // Get parent and child objects
2714 pParent = FindObjectById(pRequest->GetVariableLong(VID_PARENT_ID));
2715 pChild = FindObjectById(pRequest->GetVariableLong(VID_CHILD_ID));
2716
2717 // Check access rights and change binding
2718 if ((pParent != NULL) && (pChild != NULL))
2719 {
2720 // User should have modify access to both objects
2721 if ((pParent->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)) &&
2722 (pChild->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)))
2723 {
2724 // Parent object should be container or service root
2725 if ((pParent->Type() == OBJECT_CONTAINER) ||
2726 (pParent->Type() == OBJECT_SERVICEROOT))
2727 {
2728 if (bBind)
2729 {
917aa2e6
VK
2730 // Prevent loops
2731 if (!pChild->IsChild(pParent->Id()))
2732 {
2733 pParent->AddChild(pChild);
2734 pChild->AddParent(pParent);
b61fe31e 2735 pParent->CalculateCompoundStatus();
917aa2e6
VK
2736 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2737 }
2738 else
2739 {
2740 msg.SetVariable(VID_RCC, RCC_OBJECT_LOOP);
2741 }
e6b958c4
VK
2742 }
2743 else
2744 {
2745 pParent->DeleteChild(pChild);
2746 pChild->DeleteParent(pParent);
917aa2e6 2747 msg.SetVariable(VID_RCC, RCC_SUCCESS);
e6b958c4 2748 }
e6b958c4
VK
2749 }
2750 else
2751 {
2752 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2753 }
2754 }
2755 else
2756 {
2757 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2758 }
2759 }
2760 else
2761 {
2762 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2763 }
2764
2765 // Send responce
2766 SendMessage(&msg);
ef44d5ea 2767}
03482383
VK
2768
2769
88039e6c
VK
2770//
2771// Delete object
2772//
2773
2774void ClientSession::DeleteObject(CSCPMessage *pRequest)
2775{
2776 CSCPMessage msg;
2777 NetObj *pObject;
2778
2779 // Prepare responce message
2780 msg.SetCode(CMD_REQUEST_COMPLETED);
2781 msg.SetId(pRequest->GetId());
2782
2783 // Find object to be deleted
2784 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
2785 if (pObject != NULL)
2786 {
2787 // Check if it is a built-in object, like "Entire Network"
2788 if (pObject->Id() >= 10)
2789 {
2790 // Check access rights
2791 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_DELETE))
2792 {
9a029be8 2793 pObject->Delete(FALSE);
88039e6c
VK
2794 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2795 }
2796 else
2797 {
2798 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2799 }
2800 }
2801 else
2802 {
2803 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2804 }
2805 }
2806 else
2807 {
2808 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2809 }
2810
2811 // Send responce
2812 SendMessage(&msg);
2813}
2814
2815
03482383
VK
2816//
2817// Process changes in alarms
2818//
2819
2820void ClientSession::OnAlarmUpdate(DWORD dwCode, NXC_ALARM *pAlarm)
2821{
2822 UPDATE_INFO *pUpdate;
2823 NetObj *pObject;
2824
cb7ec554 2825 if (IsAuthenticated())
03482383
VK
2826 {
2827 pObject = FindObjectById(pAlarm->dwSourceObject);
2828 if (pObject != NULL)
2829 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ_ALARMS))
2830 {
2831 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
2832 pUpdate->dwCategory = INFO_CAT_ALARM;
c9363772
VK
2833 pUpdate->dwCode = dwCode;
2834 pUpdate->pData = nx_memdup(pAlarm, sizeof(NXC_ALARM));
03482383
VK
2835 m_pUpdateQueue->Put(pUpdate);
2836 }
2837 }
2838}
2839
2840
2841//
2842// Send all alarms to client
2843//
2844
2845void ClientSession::SendAllAlarms(DWORD dwRqId, BOOL bIncludeAck)
2846{
2847 MutexLock(m_mutexSendAlarms, INFINITE);
2848 g_alarmMgr.SendAlarmsToClient(dwRqId, bIncludeAck, this);
2849 MutexUnlock(m_mutexSendAlarms);
2850}
ee20e615
VK
2851
2852
2853//
2854// Acknowlege alarm
2855//
2856
2857void ClientSession::AcknowlegeAlarm(CSCPMessage *pRequest)
2858{
2859 CSCPMessage msg;
2860 NetObj *pObject;
2861 DWORD dwAlarmId;
2862
2863 // Prepare responce message
2864 msg.SetCode(CMD_REQUEST_COMPLETED);
2865 msg.SetId(pRequest->GetId());
2866
2867 // Get alarm id and it's source object
2868 dwAlarmId = pRequest->GetVariableLong(VID_ALARM_ID);
2869 pObject = g_alarmMgr.GetAlarmSourceObject(dwAlarmId);
2870 if (pObject != NULL)
2871 {
2872 // User should have "acknowlege alarm" right to the object
2873 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_ACK_ALARMS))
2874 {
2875 g_alarmMgr.AckById(dwAlarmId, m_dwUserId);
2876 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2877 }
2878 else
2879 {
2880 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2881 }
2882 }
2883 else
2884 {
2885 // Normally, for existing alarms pObject will not be NULL,
2886 // so we assume that alarm id is invalid
2887 msg.SetVariable(VID_RCC, RCC_INVALID_ALARM_ID);
2888 }
2889
2890 // Send responce
2891 SendMessage(&msg);
2892}
c9363772
VK
2893
2894
ae3a55d9
VK
2895//
2896// Delete alarm
2897//
2898
2899void ClientSession::DeleteAlarm(CSCPMessage *pRequest)
2900{
2901 CSCPMessage msg;
2902 NetObj *pObject;
2903 DWORD dwAlarmId;
2904
2905 // Prepare responce message
2906 msg.SetCode(CMD_REQUEST_COMPLETED);
2907 msg.SetId(pRequest->GetId());
2908
2909 // Get alarm id and it's source object
2910 dwAlarmId = pRequest->GetVariableLong(VID_ALARM_ID);
2911 pObject = g_alarmMgr.GetAlarmSourceObject(dwAlarmId);
2912 if (pObject != NULL)
2913 {
2914 // User should have "acknowlege alarm" right to the object
2915 // and system right "delete alarms"
2916 if ((pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_ACK_ALARMS)) &&
2917 (m_dwSystemAccess & SYSTEM_ACCESS_DELETE_ALARMS))
2918 {
2919 g_alarmMgr.DeleteAlarm(dwAlarmId);
2920 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2921 }
2922 else
2923 {
2924 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2925 }
2926 }
2927 else
2928 {
2929 // Normally, for existing alarms pObject will not be NULL,
2930 // so we assume that alarm id is invalid
2931 msg.SetVariable(VID_RCC, RCC_INVALID_ALARM_ID);
2932 }
2933
2934 // Send responce
2935 SendMessage(&msg);
2936}
2937
2938
c9363772
VK
2939//
2940// Lock/unlock action configuration database
2941//
2942
2943void ClientSession::LockActionDB(DWORD dwRqId, BOOL bLock)
2944{
2945 CSCPMessage msg;
2946 char szBuffer[256];
2947
2948 // Prepare responce message
2949 msg.SetCode(CMD_REQUEST_COMPLETED);
2950 msg.SetId(dwRqId);
2951
2952 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS)
2953 {
2954 if (bLock)
2955 {
2956 if (!LockComponent(CID_ACTION_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
2957 {
2958 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
2959 msg.SetVariable(VID_LOCKED_BY, szBuffer);
2960 }
2961 else
2962 {
2963 m_dwFlags |= CSF_ACTION_DB_LOCKED;
2964 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2965 }
2966 }
2967 else
2968 {
2969 if (m_dwFlags & CSF_ACTION_DB_LOCKED)
2970 {
2971 UnlockComponent(CID_ACTION_DB);
2972 m_dwFlags &= ~CSF_ACTION_DB_LOCKED;
2973 }
2974 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2975 }
2976 }
2977 else
2978 {
2979 // Current user has no rights for action management
2980 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2981 }
2982
2983 // Send responce
2984 SendMessage(&msg);
2985}
2986
2987
2988//
2989// Create new action
2990//
2991
2992void ClientSession::CreateAction(CSCPMessage *pRequest)
2993{
2994 CSCPMessage msg;
2995
2996 // Prepare responce message
2997 msg.SetCode(CMD_REQUEST_COMPLETED);
2998 msg.SetId(pRequest->GetId());
2999
3000 // Check user rights
3001 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
3002 {
3003 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3004 }
3005 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
3006 {
3007 // Action database have to be locked before any
3008 // changes can be made
3009 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3010 }
3011 else
3012 {
3013 DWORD dwResult, dwActionId;
3014 char szActionName[MAX_USER_NAME];
3015
3016 pRequest->GetVariableStr(VID_ACTION_NAME, szActionName, MAX_OBJECT_NAME);
3017 if (IsValidObjectName(szActionName))
3018 {
3019 dwResult = CreateNewAction(szActionName, &dwActionId);
3020 msg.SetVariable(VID_RCC, dwResult);
3021 if (dwResult == RCC_SUCCESS)
3022 msg.SetVariable(VID_ACTION_ID, dwActionId); // Send id of new action to client
3023 }
3024 else
3025 {
3026 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
3027 }
3028 }
3029
3030 // Send responce
3031 SendMessage(&msg);
3032}
3033
3034
3035//
3036// Update existing action's data
3037//
3038
3039void ClientSession::UpdateAction(CSCPMessage *pRequest)
3040{
3041 CSCPMessage msg;
3042
3043 // Prepare responce message
3044 msg.SetCode(CMD_REQUEST_COMPLETED);
3045 msg.SetId(pRequest->GetId());
3046
3047 // Check user rights
3048 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
3049 {
3050 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3051 }
3052 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
3053 {
3054 // Action database have to be locked before any
3055 // changes can be made
3056 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3057 }
3058 else
3059 {
15b8d488 3060 msg.SetVariable(VID_RCC, ModifyActionFromMessage(pRequest));
c9363772
VK
3061 }
3062
3063 // Send responce
3064 SendMessage(&msg);
3065}
3066
3067
3068//
3069// Delete action
3070//
3071
3072void ClientSession::DeleteAction(CSCPMessage *pRequest)
3073{
3074 CSCPMessage msg;
3075 DWORD dwActionId;
3076
3077 // Prepare responce message
3078 msg.SetCode(CMD_REQUEST_COMPLETED);
3079 msg.SetId(pRequest->GetId());
3080
3081 // Check user rights
3082 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
3083 {
3084 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3085 }
3086 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
3087 {
3088 // Action database have to be locked before any
3089 // changes can be made
3090 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3091 }
3092 else
3093 {
3094 // Get Id of action to be deleted
3095 dwActionId = pRequest->GetVariableLong(VID_ACTION_ID);
15b8d488 3096 msg.SetVariable(VID_RCC, DeleteActionFromDB(dwActionId));
c9363772
VK
3097 }
3098
3099 // Send responce
3100 SendMessage(&msg);
3101}
3102
3103
3104//
3105// Process changes in actions
3106//
3107
3108void ClientSession::OnActionDBUpdate(DWORD dwCode, NXC_ACTION *pAction)
3109{
3110 UPDATE_INFO *pUpdate;
3111
cb7ec554 3112 if (IsAuthenticated())
c9363772
VK
3113 {
3114 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS)
3115 {
3116 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
3117 pUpdate->dwCategory = INFO_CAT_ACTION;
3118 pUpdate->dwCode = dwCode;
3119 pUpdate->pData = nx_memdup(pAction, sizeof(NXC_ACTION));
3120 m_pUpdateQueue->Put(pUpdate);
3121 }
3122 }
3123}
e91cb822
VK
3124
3125
3126//
3127// Send all actions to client
3128//
3129
3130void ClientSession::SendAllActions(DWORD dwRqId)
3131{
3132 CSCPMessage msg;
3133
3134 // Prepare responce message
3135 msg.SetCode(CMD_REQUEST_COMPLETED);
3136 msg.SetId(dwRqId);
3137
3138 // Check user rights
3139 if ((m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS) ||
3140 (m_dwSystemAccess & SYSTEM_ACCESS_EPP))
3141 {
3142 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3143 SendMessage(&msg);
3144 MutexLock(m_mutexSendActions, INFINITE);
3145 SendActionsToClient(this, dwRqId);
3146 MutexUnlock(m_mutexSendActions);
3147 }
3148 else
3149 {
3150 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3151 SendMessage(&msg);
3152 }
3153}
6849d9be
VK
3154
3155
3156//
3157// Send list of configured container categories to client
3158//
3159
3160void ClientSession::SendContainerCategories(DWORD dwRqId)
3161{
3162 CSCPMessage msg;
3163 DWORD i;
3164
3165 // Prepare responce message
3166 msg.SetCode(CMD_CONTAINER_CAT_DATA);
3167 msg.SetId(dwRqId);
3168
3169 for(i = 0; i < g_dwNumCategories; i++)
3170 {
3171 msg.SetVariable(VID_CATEGORY_ID, g_pContainerCatList[i].dwCatId);
3172 msg.SetVariable(VID_CATEGORY_NAME, g_pContainerCatList[i].szName);
3173 msg.SetVariable(VID_IMAGE_ID, g_pContainerCatList[i].dwImageId);
3174 msg.SetVariable(VID_DESCRIPTION, g_pContainerCatList[i].pszDescription);
3175 SendMessage(&msg);
3176 msg.DeleteAllVariables();
3177 }
3178
3179 // Send end-of-list indicator
3180 msg.SetVariable(VID_CATEGORY_ID, (DWORD)0);
3181 SendMessage(&msg);
3182}
0b89f5fb
VK
3183
3184
3185//
3186// Perform a forced node poll
3187//
3188
3189void ClientSession::ForcedNodePoll(CSCPMessage *pRequest)
3190{
eb8b1960 3191 CSCPMessage msg;
d966d18a 3192 POLLER_START_DATA *pData;
eb8b1960 3193 NetObj *pObject;
d966d18a
VK
3194
3195 pData = (POLLER_START_DATA *)malloc(sizeof(POLLER_START_DATA));
0ba90743 3196 pData->pSession = this;
d966d18a 3197 MutexLock(m_mutexPollerInit, INFINITE);
eb8b1960
VK
3198
3199 // Prepare responce message
d966d18a 3200 pData->dwRqId = pRequest->GetId();
eb8b1960 3201 msg.SetCode(CMD_POLLING_INFO);
d966d18a 3202 msg.SetId(pData->dwRqId);
eb8b1960
VK
3203
3204 // Get polling type
d966d18a 3205 pData->iPollType = pRequest->GetVariableShort(VID_POLL_TYPE);
eb8b1960
VK
3206
3207 // Find object to be deleted
3208 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3209 if (pObject != NULL)
3210 {
3211 // We can do polls only for node objects
3212 if ((pObject->Type() == OBJECT_NODE) &&
d966d18a 3213 ((pData->iPollType == POLL_STATUS) || (pData->iPollType == POLL_CONFIGURATION)))
eb8b1960
VK
3214 {
3215 // Check access rights
3216 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
3217 {
3218 ((Node *)pObject)->IncRefCount();
3219
d966d18a
VK
3220 pData->pNode = (Node *)pObject;
3221 ThreadCreate(PollerThreadStarter, 0, pData);
3222 msg.SetVariable(VID_RCC, RCC_OPERATION_IN_PROGRESS);
3223 msg.SetVariable(VID_POLLER_MESSAGE, _T("Poll request accepted\r\n"));
eb8b1960
VK
3224 }
3225 else
3226 {
3227 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3228 }
3229 }
3230 else
3231 {
3232 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3233 }
3234 }
3235 else
3236 {
3237 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3238 }
3239
3240 // Send responce
3241 SendMessage(&msg);
d966d18a 3242 MutexUnlock(m_mutexPollerInit);
eb8b1960
VK
3243}
3244
3245
3246//
3247// Send message fro poller to client
3248//
3249
d966d18a 3250void ClientSession::SendPollerMsg(DWORD dwRqId, TCHAR *pszMsg)
eb8b1960
VK
3251{
3252 CSCPMessage msg;
3253
3254 msg.SetCode(CMD_POLLING_INFO);
d966d18a 3255 msg.SetId(dwRqId);
eb8b1960
VK
3256 msg.SetVariable(VID_RCC, RCC_OPERATION_IN_PROGRESS);
3257 msg.SetVariable(VID_POLLER_MESSAGE, pszMsg);
3258 SendMessage(&msg);
0b89f5fb 3259}
d966d18a
VK
3260
3261
3262//
3263// Node poller thread
3264//
3265
3266void ClientSession::PollerThread(Node *pNode, int iPollType, DWORD dwRqId)
3267{
3268 CSCPMessage msg;
3269
3270 // Wait while parent thread finishes initialization
3271 MutexLock(m_mutexPollerInit, INFINITE);
3272 MutexUnlock(m_mutexPollerInit);
3273
0ba90743
VK
3274 switch(iPollType)
3275 {
3276 case POLL_STATUS:
3277 pNode->StatusPoll(this, dwRqId);
3278 break;
3279 case POLL_CONFIGURATION:
3280 pNode->ConfigurationPoll(this, dwRqId);
3281 break;
3282 default:
3283 SendPollerMsg(dwRqId, _T("Invalid poll type requested\r\n"));
3284 break;
3285 }
d966d18a
VK
3286 pNode->DecRefCount();
3287
3288 msg.SetCode(CMD_POLLING_INFO);
3289 msg.SetId(dwRqId);
3290 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3291 SendMessage(&msg);
3292}
b562fca8
VK
3293
3294
3295//
3296// Receive event from user
3297//
3298
3299void ClientSession::OnTrap(CSCPMessage *pRequest)
3300{
3301 CSCPMessage msg;
3302 DWORD dwObjectId, dwEventCode;
3303 int i, iNumArgs;
3304 NetObj *pObject;
3305 TCHAR *pszArgList[32];
3306 TCHAR szFormat[] = "ssssssssssssssssssssssssssssssss";
3307 BOOL bSuccess;
3308
3309 // Prepare responce message
3310 msg.SetCode(CMD_REQUEST_COMPLETED);
3311 msg.SetId(pRequest->GetId());
3312
3313 // Find event's source object
3314 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
3315 if (dwObjectId != 0)
3316 pObject = FindObjectById(dwObjectId); // Object is specified explicitely
3317 else
3318 pObject = FindNodeByIP(m_dwHostAddr); // Client is the source
3319 if (pObject != NULL)
3320 {
3321 // User should have SEND_EVENTS access right to object
3322 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_SEND_EVENTS))
3323 {
c19b2871 3324 dwEventCode = pRequest->GetVariableLong(VID_EVENT_CODE);
b562fca8
VK
3325 iNumArgs = pRequest->GetVariableShort(VID_NUM_ARGS);
3326 for(i = 0; i < iNumArgs; i++)
3327 pszArgList[i] = pRequest->GetVariableStr(VID_EVENT_ARG_BASE + i);
3328
3329 // Following call is not very good, but I'm too lazy now
3330 // to change PostEvent()
3331 szFormat[iNumArgs] = 0;
3332 bSuccess = PostEvent(dwEventCode, pObject->Id(), (iNumArgs > 0) ? szFormat : NULL,
3333 pszArgList[0], pszArgList[1], pszArgList[2], pszArgList[3],
3334 pszArgList[4], pszArgList[5], pszArgList[6], pszArgList[7],
3335 pszArgList[8], pszArgList[9], pszArgList[10], pszArgList[11],
3336 pszArgList[12], pszArgList[13], pszArgList[14], pszArgList[15],
3337 pszArgList[16], pszArgList[17], pszArgList[18], pszArgList[19],
3338 pszArgList[20], pszArgList[21], pszArgList[22], pszArgList[23],
3339 pszArgList[24], pszArgList[25], pszArgList[26], pszArgList[27],
6ed0d23d 3340 pszArgList[28], pszArgList[29], pszArgList[30], pszArgList[31]);
b562fca8
VK
3341
3342 // Cleanup
3343 for(i = 0; i < iNumArgs; i++)
3344 free(pszArgList[i]);
3345
3346 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_INVALID_EVENT_CODE);
3347 }
3348 else
3349 {
3350 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3351 }
3352 }
3353 else
3354 {
3355 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3356 }
3357
3358 // Send responce
3359 SendMessage(&msg);
3360}
ed1140dc
VK
3361
3362
3363//
3364// Wake up node
3365//
3366
3367void ClientSession::OnWakeUpNode(CSCPMessage *pRequest)
3368{
3369 NetObj *pObject;
3370 CSCPMessage msg;
3371
3372 // Prepare responce message
3373 msg.SetCode(CMD_REQUEST_COMPLETED);
3374 msg.SetId(pRequest->GetId());
3375
3376 // Find node or interface object
3377 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3378 if (pObject != NULL)
3379 {
3380 if ((pObject->Type() == OBJECT_NODE) ||
3381 (pObject->Type() == OBJECT_INTERFACE))
3382 {
3383 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
3384 {
3385 DWORD dwResult;
3386
3387 if (pObject->Type() == OBJECT_NODE)
3388 dwResult = ((Node *)pObject)->WakeUp();
3389 else
3390 dwResult = ((Interface *)pObject)->WakeUp();
3391 msg.SetVariable(VID_RCC, dwResult);
3392 }
3393 else
3394 {
3395 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3396 }
3397 }
3398 else
3399 {
80de4676
VK
3400 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3401 }
3402 }
3403 else
3404 {
3405 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3406 }
3407
3408 // Send responce
3409 SendMessage(&msg);
3410}
3411
3412
3413//
3414// Query specific parameter from node
3415//
3416
3417void ClientSession::QueryParameter(CSCPMessage *pRequest)
3418{
3419 NetObj *pObject;
3420 CSCPMessage msg;
3421
3422 // Prepare responce message
3423 msg.SetCode(CMD_REQUEST_COMPLETED);
3424 msg.SetId(pRequest->GetId());
3425
3426 // Find node object
3427 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3428 if (pObject != NULL)
3429 {
3430 if (pObject->Type() == OBJECT_NODE)
3431 {
3432 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
3433 {
3434 DWORD dwResult;
3435 TCHAR szBuffer[256], szName[MAX_PARAM_NAME];
3436
3437 pRequest->GetVariableStr(VID_NAME, szName, MAX_PARAM_NAME);
3438 dwResult = ((Node *)pObject)->GetItemForClient(pRequest->GetVariableShort(VID_DCI_SOURCE_TYPE),
3439 szName, szBuffer, 256);
3440 msg.SetVariable(VID_RCC, dwResult);
3441 if (dwResult == RCC_SUCCESS)
3442 msg.SetVariable(VID_VALUE, szBuffer);
3443 }
3444 else
3445 {
3446 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3447 }
3448 }
3449 else
3450 {
ed1140dc
VK
3451 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3452 }
3453 }
3454 else
3455 {
3456 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3457 }
3458
3459 // Send responce
3460 SendMessage(&msg);
3461}
b4895bbe
VK
3462
3463
3464//
693119d6 3465// Edit trap configuration record
b4895bbe
VK
3466//
3467
693119d6 3468void ClientSession::EditTrap(int iOperation, CSCPMessage *pRequest)
b4895bbe 3469{
106e7ae3 3470 CSCPMessage msg;
693119d6 3471 DWORD dwTrapId, dwResult;
106e7ae3
VK
3472
3473 // Prepare responce message
3474 msg.SetCode(CMD_REQUEST_COMPLETED);
3475 msg.SetId(pRequest->GetId());
3476
3477 // Check access rights
3478 if (m_dwSystemAccess & SYSTEM_ACCESS_CONFIGURE_TRAPS)
3479 {
3480 if (m_dwFlags & CSF_TRAP_CFG_LOCKED)
3481 {
693119d6
VK
3482 switch(iOperation)
3483 {
3484 case TRAP_CREATE:
3485 dwResult = CreateNewTrap(&dwTrapId);
3486 msg.SetVariable(VID_RCC, dwResult);
3487 if (dwResult == RCC_SUCCESS)
3488 msg.SetVariable(VID_TRAP_ID, dwTrapId); // Send id of new trap to client
3489 break;
3490 case TRAP_UPDATE:
3491 msg.SetVariable(VID_RCC, UpdateTrapFromMsg(pRequest));
3492 break;
3493 case TRAP_DELETE:
3494 dwTrapId = pRequest->GetVariableLong(VID_TRAP_ID);
3495 msg.SetVariable(VID_RCC, DeleteTrap(dwTrapId));
3496 break;
3497 default:
3498 msg.SetVariable(VID_RCC, RCC_SYSTEM_FAILURE);
3499 break;
3500 }
106e7ae3
VK
3501 }
3502 else
3503 {
3504 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3505 }
3506 }
3507 else
3508 {
3509 // Current user has no rights for trap management
3510 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3511 }
3512
3513 // Send responce
3514 SendMessage(&msg);
b4895bbe
VK
3515}
3516
3517
3518//
3519// Lock/unlock trap configuration
3520//
3521
3522void ClientSession::LockTrapCfg(DWORD dwRqId, BOOL bLock)
3523{
840eb902
VK
3524 CSCPMessage msg;
3525 char szBuffer[256];
3526
3527 // Prepare responce message
3528 msg.SetCode(CMD_REQUEST_COMPLETED);
3529 msg.SetId(dwRqId);
3530
3531 if (m_dwSystemAccess & SYSTEM_ACCESS_CONFIGURE_TRAPS)
3532 {
3533 if (bLock)
3534 {
3535 if (!LockComponent(CID_TRAP_CFG, m_dwIndex, m_szUserName, NULL, szBuffer))
3536 {
3537 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
3538 msg.SetVariable(VID_LOCKED_BY, szBuffer);
3539 }
3540 else
3541 {
3542 m_dwFlags |= CSF_TRAP_CFG_LOCKED;
3543 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3544 }
3545 }
3546 else
3547 {
3548 if (m_dwFlags & CSF_TRAP_CFG_LOCKED)
3549 {
3550 UnlockComponent(CID_TRAP_CFG);
3551 m_dwFlags &= ~CSF_TRAP_CFG_LOCKED;
3552 }
3553 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3554 }
3555 }
3556 else
3557 {
3558 // Current user has no rights for trap management
3559 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3560 }
3561
3562 // Send responce
3563 SendMessage(&msg);
b4895bbe
VK
3564}
3565
3566
3567//
3568// Send all trap configuration records to client
3569//
3570
3571void ClientSession::SendAllTraps(DWORD dwRqId)
3572{
840eb902
VK
3573 CSCPMessage msg;
3574 BOOL bSuccess = FALSE;
3575
3576 // Prepare responce message
3577 msg.SetCode(CMD_REQUEST_COMPLETED);
3578 msg.SetId(dwRqId);
3579
3580 if (m_dwSystemAccess & SYSTEM_ACCESS_CONFIGURE_TRAPS)
3581 {
3582 if (m_dwFlags & CSF_TRAP_CFG_LOCKED)
3583 {
3584 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3585 SendMessage(&msg);
3586 bSuccess = TRUE;
3587 SendTrapsToClient(this, dwRqId);
3588 }
3589 else
3590 {
3591 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3592 }
3593 }
3594 else
3595 {
3596 // Current user has no rights for trap management
3597 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3598 }
3599
3600 // Send responce
3601 if (!bSuccess)
3602 SendMessage(&msg);
b4895bbe 3603}
1c8b8363
VK
3604
3605
5be45ff2
VK
3606//
3607// Lock/unlock package database
3608//
3609
3610void ClientSession::LockPackageDB(DWORD dwRqId, BOOL bLock)
3611{
3612 CSCPMessage msg;
3613 char szBuffer[256];
3614
3615 // Prepare responce message
3616 msg.SetCode(CMD_REQUEST_COMPLETED);
3617 msg.SetId(dwRqId);
3618
3619 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_PACKAGES)
3620 {
3621 if (bLock)
3622 {
3623 if (!LockComponent(CID_PACKAGE_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
3624 {
3625 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
3626 msg.SetVariable(VID_LOCKED_BY, szBuffer);
3627 }
3628 else
3629 {
3630 m_dwFlags |= CSF_PACKAGE_DB_LOCKED;
3631 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3632 }
3633 }
3634 else
3635 {
3636 if (m_dwFlags & CSF_PACKAGE_DB_LOCKED)
3637 {
3638 UnlockComponent(CID_PACKAGE_DB);
3639 m_dwFlags &= ~CSF_PACKAGE_DB_LOCKED;
3640 }
3641 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3642 }
3643 }
3644 else
3645 {
3646 // Current user has no rights for trap management
3647 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3648 }
3649
3650 // Send responce
3651 SendMessage(&msg);
3652}
3653
3654
1c8b8363
VK
3655//
3656// Send list of all installed packages to client
3657//
3658
3659void ClientSession::SendAllPackages(DWORD dwRqId)
3660{
3661 CSCPMessage msg;
3662 DB_ASYNC_RESULT hResult;
3663 BOOL bSuccess = FALSE;
3664 TCHAR szBuffer[MAX_DB_STRING];
3665
3666 // Prepare responce message
3667 msg.SetCode(CMD_REQUEST_COMPLETED);
3668 msg.SetId(dwRqId);
3669
3670 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_PACKAGES)
3671 {
5be45ff2 3672 if (m_dwFlags & CSF_PACKAGE_DB_LOCKED)
1c8b8363 3673 {
257defd7 3674 hResult = DBAsyncSelect(g_hCoreDB, "SELECT pkg_id,version,platform,pkg_file,pkg_name,description FROM agent_pkg");
5be45ff2 3675 if (hResult != NULL)
1c8b8363 3676 {
5be45ff2 3677 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1c8b8363 3678 SendMessage(&msg);
5be45ff2
VK
3679 bSuccess = TRUE;
3680
3681 msg.SetCode(CMD_PACKAGE_INFO);
1c8b8363 3682 msg.DeleteAllVariables();
1c8b8363 3683
5be45ff2
VK
3684 while(DBFetch(hResult))
3685 {
3686 msg.SetVariable(VID_PACKAGE_ID, DBGetFieldAsyncULong(hResult, 0));
3687 msg.SetVariable(VID_PACKAGE_VERSION, DBGetFieldAsync(hResult, 1, szBuffer, MAX_DB_STRING));
3688 msg.SetVariable(VID_PLATFORM_NAME, DBGetFieldAsync(hResult, 2, szBuffer, MAX_DB_STRING));
3689 msg.SetVariable(VID_FILE_NAME, DBGetFieldAsync(hResult, 3, szBuffer, MAX_DB_STRING));
257defd7
VK
3690 msg.SetVariable(VID_PACKAGE_NAME, DBGetFieldAsync(hResult, 4, szBuffer, MAX_DB_STRING));
3691 DBGetFieldAsync(hResult, 5, szBuffer, MAX_DB_STRING);
3692 DecodeSQLString(szBuffer);
3693 msg.SetVariable(VID_DESCRIPTION, szBuffer);
5be45ff2
VK
3694 SendMessage(&msg);
3695 msg.DeleteAllVariables();
3696 }
1c8b8363 3697
5be45ff2
VK
3698 msg.SetVariable(VID_PACKAGE_ID, (DWORD)0);
3699 SendMessage(&msg);
3700
3701 DBFreeAsyncResult(hResult);
3702 }
3703 else
3704 {
3705 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
3706 }
1c8b8363
VK
3707 }
3708 else
3709 {
5be45ff2 3710 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1c8b8363
VK
3711 }
3712 }
3713 else
3714 {
3715 // Current user has no rights for package management
3716 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3717 }
3718
3719 // Send responce
3720 if (!bSuccess)
3721 SendMessage(&msg);
3722}
257defd7
VK
3723
3724
3725//
3726// Install package to server
3727//