Added new object class "ServiceRoot"
[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
23#include "nms_core.h"
24
06e7be2f 25#ifdef _WIN32
c9ccd685
AK
26# include <direct.h>
27#else
28# include <dirent.h>
06e7be2f
VK
29#endif
30
21e4b6f0 31
2d5c8ac8
VK
32//
33// Fill CSCP message with user data
34//
35
36static void FillUserInfoMessage(CSCPMessage *pMsg, NMS_USER *pUser)
37{
38 pMsg->SetVariable(VID_USER_ID, pUser->dwId);
39 pMsg->SetVariable(VID_USER_NAME, pUser->szName);
40 pMsg->SetVariable(VID_USER_FLAGS, pUser->wFlags);
41 pMsg->SetVariable(VID_USER_SYS_RIGHTS, pUser->wSystemRights);
42 pMsg->SetVariable(VID_USER_FULL_NAME, pUser->szFullName);
43 pMsg->SetVariable(VID_USER_DESCRIPTION, pUser->szDescription);
44}
45
46
47//
48// Fill CSCP message with user group data
49//
50
51static void FillGroupInfoMessage(CSCPMessage *pMsg, NMS_USER_GROUP *pGroup)
52{
53 DWORD i, dwId;
54
55 pMsg->SetVariable(VID_USER_ID, pGroup->dwId);
56 pMsg->SetVariable(VID_USER_NAME, pGroup->szName);
57 pMsg->SetVariable(VID_USER_FLAGS, pGroup->wFlags);
58 pMsg->SetVariable(VID_USER_SYS_RIGHTS, pGroup->wSystemRights);
59 pMsg->SetVariable(VID_USER_DESCRIPTION, pGroup->szDescription);
60 pMsg->SetVariable(VID_NUM_MEMBERS, pGroup->dwNumMembers);
61 for(i = 0, dwId = VID_GROUP_MEMBER_BASE; i < pGroup->dwNumMembers; i++, dwId++)
62 pMsg->SetVariable(dwId, pGroup->pMembers[i]);
63}
64
65
21e4b6f0
VK
66//
67// Client session class constructor
68//
69
b54b2b11 70ClientSession::ClientSession(SOCKET hSocket, DWORD dwHostAddr)
21e4b6f0
VK
71{
72 m_pSendQueue = new Queue;
73 m_pMessageQueue = new Queue;
62f5857f 74 m_pUpdateQueue = new Queue;
21e4b6f0
VK
75 m_hSocket = hSocket;
76 m_dwIndex = INVALID_INDEX;
77 m_iState = STATE_CONNECTED;
78 m_pMsgBuffer = (CSCP_BUFFER *)malloc(sizeof(CSCP_BUFFER));
d16cf8a5
AK
79 m_hCondWriteThreadStopped = ConditionCreate(FALSE);
80 m_hCondProcessingThreadStopped = ConditionCreate(FALSE);
81 m_hCondUpdateThreadStopped = ConditionCreate(FALSE);
62f5857f 82 m_hMutexSendEvents = MutexCreate();
53512272 83 m_hMutexSendObjects = MutexCreate();
b54b2b11
VK
84 m_dwFlags = 0;
85 m_dwHostAddr = dwHostAddr;
86 strcpy(m_szUserName, "<not logged in>");
984542f8 87 m_dwUserId = INVALID_INDEX;
338493a0
VK
88 m_dwOpenDCIListSize = 0;
89 m_pOpenDCIList = NULL;
21e4b6f0
VK
90}
91
92
93//
94// Destructor
95//
96
97ClientSession::~ClientSession()
98{
99 shutdown(m_hSocket, 2);
100 closesocket(m_hSocket);
101 delete m_pSendQueue;
102 delete m_pMessageQueue;
62f5857f 103 delete m_pUpdateQueue;
338493a0 104 safe_free(m_pMsgBuffer);
ecb7e1ee
VK
105 ConditionDestroy(m_hCondWriteThreadStopped);
106 ConditionDestroy(m_hCondProcessingThreadStopped);
62f5857f
VK
107 ConditionDestroy(m_hCondUpdateThreadStopped);
108 MutexDestroy(m_hMutexSendEvents);
53512272 109 MutexDestroy(m_hMutexSendObjects);
338493a0 110 safe_free(m_pOpenDCIList);
21e4b6f0
VK
111}
112
113
114//
115// Print debug information
116//
117
118void ClientSession::DebugPrintf(char *szFormat, ...)
119{
120 if ((g_dwFlags & AF_STANDALONE) && (g_dwFlags & AF_DEBUG_CSCP))
121 {
122 va_list args;
123
124 printf("*CSCP(%d)* ", m_dwIndex);
125 va_start(args, szFormat);
126 vprintf(szFormat, args);
127 va_end(args);
128 }
129}
130
131
21e4b6f0
VK
132//
133// ReadThread()
134//
135
136void ClientSession::ReadThread(void)
137{
138 CSCP_MESSAGE *pRawMsg;
139 CSCPMessage *pMsg;
140 int iErr;
338493a0
VK
141 DWORD i;
142 NetObj *pObject;
21e4b6f0
VK
143
144 // Initialize raw message receiving function
a933a2bf 145 RecvCSCPMessage(0, NULL, m_pMsgBuffer, 0);
21e4b6f0
VK
146
147 pRawMsg = (CSCP_MESSAGE *)malloc(65536);
148 while(1)
149 {
a933a2bf 150 if ((iErr = RecvCSCPMessage(m_hSocket, pRawMsg, m_pMsgBuffer, 65536)) <= 0)
21e4b6f0
VK
151 break;
152
a933a2bf
VK
153 // Check if message is too large
154 if (iErr == 1)
155 continue;
156
21e4b6f0 157 // Check that actual received packet size is equal to encoded in packet
6159a875 158 if ((int)ntohl(pRawMsg->dwSize) != iErr)
21e4b6f0 159 {
6159a875 160 DebugPrintf("Actual message size doesn't match wSize value (%d,%d)\n", iErr, ntohl(pRawMsg->dwSize));
21e4b6f0
VK
161 continue; // Bad packet, wait for next
162 }
163
164 // Create message object from raw message
165 pMsg = new CSCPMessage(pRawMsg);
166 m_pMessageQueue->Put(pMsg);
167 }
168 if (iErr < 0)
169 WriteLog(MSG_SESSION_CLOSED, EVENTLOG_WARNING_TYPE, "e", WSAGetLastError());
170 free(pRawMsg);
171
172 // Notify other threads to exit
ecb7e1ee
VK
173 m_pSendQueue->Put(INVALID_POINTER_VALUE);
174 m_pMessageQueue->Put(INVALID_POINTER_VALUE);
175
176 // Wait for other threads to finish
177 ConditionWait(m_hCondWriteThreadStopped, INFINITE);
178 ConditionWait(m_hCondProcessingThreadStopped, INFINITE);
54abbe0e
VK
179
180 // Remove all locks created by this session
181 RemoveAllSessionLocks(m_dwIndex);
338493a0
VK
182 for(i = 0; i < m_dwOpenDCIListSize; i++)
183 {
184 pObject = FindObjectById(m_pOpenDCIList[i]);
185 if (pObject != NULL)
186 if (pObject->Type() == OBJECT_NODE)
187 ((Node *)pObject)->UnlockDCIList(m_dwIndex);
188 }
21e4b6f0
VK
189}
190
191
192//
193// WriteThread()
194//
195
196void ClientSession::WriteThread(void)
197{
198 CSCP_MESSAGE *pMsg;
7ac0c0a8 199 char szBuffer[128];
21e4b6f0
VK
200
201 while(1)
202 {
203 pMsg = (CSCP_MESSAGE *)m_pSendQueue->GetOrBlock();
ecb7e1ee 204 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
21e4b6f0
VK
205 break;
206
6159a875
VK
207 DebugPrintf("Sending message %s\n", CSCPMessageCodeName(ntohs(pMsg->wCode), szBuffer));
208 if (send(m_hSocket, (const char *)pMsg, ntohl(pMsg->dwSize), 0) <= 0)
21e4b6f0 209 {
7968a52d 210 MemFree(pMsg);
21e4b6f0
VK
211 break;
212 }
7968a52d 213 MemFree(pMsg);
21e4b6f0 214 }
ecb7e1ee 215 ConditionSet(m_hCondWriteThreadStopped);
21e4b6f0
VK
216}
217
218
219//
220// Message processing thread
221//
222
223void ClientSession::ProcessingThread(void)
224{
3421c063 225 CSCPMessage *pMsg;
74a5aa17 226 char szBuffer[128];
21e4b6f0
VK
227
228 while(1)
229 {
230 pMsg = (CSCPMessage *)m_pMessageQueue->GetOrBlock();
ecb7e1ee 231 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
21e4b6f0
VK
232 break;
233
74a5aa17 234 DebugPrintf("Received message %s\n", CSCPMessageCodeName(pMsg->GetCode(), szBuffer));
21e4b6f0
VK
235 if ((m_iState != STATE_AUTHENTICATED) && (pMsg->GetCode() != CMD_LOGIN))
236 {
237 delete pMsg;
238 continue;
239 }
240
241 switch(pMsg->GetCode())
242 {
243 case CMD_LOGIN:
e100f091 244 Login(pMsg);
21e4b6f0
VK
245 break;
246 case CMD_GET_OBJECTS:
e100f091 247 SendAllObjects(pMsg->GetId());
21e4b6f0
VK
248 break;
249 case CMD_GET_EVENTS:
74a5aa17 250 SendAllEvents(pMsg->GetId());
21e4b6f0
VK
251 break;
252 case CMD_GET_CONFIG_VARLIST:
253 SendAllConfigVars();
254 break;
b54b2b11
VK
255 case CMD_OPEN_EVENT_DB:
256 SendEventDB(pMsg->GetId());
257 break;
258 case CMD_CLOSE_EVENT_DB:
3421c063 259 CloseEventDB(pMsg->GetId());
b54b2b11 260 break;
605d2931
VK
261 case CMD_SET_EVENT_INFO:
262 SetEventInfo(pMsg);
263 break;
24156e90
VK
264 case CMD_MODIFY_OBJECT:
265 ModifyObject(pMsg);
266 break;
c1c39152
VK
267 case CMD_SET_OBJECT_MGMT_STATUS:
268 ChangeObjectMgmtStatus(pMsg);
269 break;
23a32988
VK
270 case CMD_LOAD_USER_DB:
271 SendUserDB(pMsg->GetId());
272 break;
ff550544
VK
273 case CMD_CREATE_USER:
274 CreateUser(pMsg);
275 break;
276 case CMD_UPDATE_USER:
277 UpdateUser(pMsg);
278 break;
279 case CMD_DELETE_USER:
280 DeleteUser(pMsg);
281 break;
282 case CMD_LOCK_USER_DB:
283 LockUserDB(pMsg->GetId(), TRUE);
284 break;
285 case CMD_UNLOCK_USER_DB:
286 LockUserDB(pMsg->GetId(), FALSE);
287 break;
017e1e13
VK
288 case CMD_SET_PASSWORD:
289 SetPassword(pMsg);
290 break;
7257eb7d
VK
291 case CMD_GET_NODE_DCI_LIST:
292 OpenNodeDCIList(pMsg);
293 break;
294 case CMD_UNLOCK_NODE_DCI_LIST:
295 CloseNodeDCIList(pMsg);
296 break;
9ed4eaff
VK
297 case CMD_CREATE_NEW_DCI:
298 case CMD_MODIFY_NODE_DCI:
299 case CMD_DELETE_NODE_DCI:
300 ModifyNodeDCI(pMsg);
301 break;
ebebc8ea
VK
302 case CMD_GET_DCI_DATA:
303 GetCollectedData(pMsg);
304 break;
06e7be2f
VK
305 case CMD_OPEN_EPP:
306 OpenEPP(pMsg->GetId());
307 break;
308 case CMD_CLOSE_EPP:
309 CloseEPP(pMsg->GetId());
310 break;
311 case CMD_SAVE_EPP:
312 SaveEPP(pMsg);
313 break;
314 case CMD_INSTALL_EPP:
315 InstallEPP(pMsg->GetId());
316 break;
317 case CMD_GET_MIB_LIST:
318 SendMIBList(pMsg->GetId());
319 break;
320 case CMD_GET_MIB:
321 SendMIB(pMsg);
322 break;
ef44d5ea
VK
323 case CMD_CREATE_OBJECT:
324 CreateObject(pMsg);
325 break;
3421c063
VK
326 case CMD_GET_EVENT_NAMES:
327 SendEventNames(pMsg->GetId());
328 break;
21e4b6f0
VK
329 default:
330 break;
331 }
332 delete pMsg;
333 }
ecb7e1ee 334 ConditionSet(m_hCondProcessingThreadStopped);
21e4b6f0
VK
335}
336
337
e100f091
VK
338//
339// Authenticate client
340//
341
342void ClientSession::Login(CSCPMessage *pRequest)
343{
344 CSCPMessage msg;
345 BYTE szPassword[SHA_DIGEST_LENGTH];
346 char szLogin[MAX_USER_NAME], szBuffer[32];
347
348 // Prepare responce message
349 msg.SetCode(CMD_LOGIN_RESP);
350 msg.SetId(pRequest->GetId());
351
352 if (m_iState != STATE_AUTHENTICATED)
353 {
354
355 pRequest->GetVariableStr(VID_LOGIN_NAME, szLogin, MAX_USER_NAME);
356 pRequest->GetVariableBinary(VID_PASSWORD, szPassword, SHA_DIGEST_LENGTH);
357
358 if (AuthenticateUser(szLogin, szPassword, &m_dwUserId, &m_dwSystemAccess))
359 {
360 m_iState = STATE_AUTHENTICATED;
361 sprintf(m_szUserName, "%s@%s", szLogin, IpToStr(m_dwHostAddr, szBuffer));
362 msg.SetVariable(VID_RCC, RCC_SUCCESS);
363 DebugPrintf("User %s authenticated\n", m_szUserName);
364 }
365 else
366 {
367 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
368 }
369 }
370 else
371 {
372 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
373 }
374
375 // Send responce
376 SendMessage(&msg);
377}
378
379
b54b2b11
VK
380//
381// Send event configuration to client
382//
383
384void ClientSession::SendEventDB(DWORD dwRqId)
385{
386 DB_ASYNC_RESULT hResult;
387 CSCPMessage msg;
388 char szBuffer[1024];
389
390 // Prepare responce message
3a5042fd 391 msg.SetCode(CMD_REQUEST_COMPLETED);
b54b2b11
VK
392 msg.SetId(dwRqId);
393
b8bad201
VK
394 if (!CheckSysAccessRights(SYSTEM_ACCESS_VIEW_EVENT_DB))
395 {
396 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
397 SendMessage(&msg);
398 }
399 else if (!LockComponent(CID_EVENT_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
b54b2b11
VK
400 {
401 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
402 msg.SetVariable(VID_LOCKED_BY, szBuffer);
403 SendMessage(&msg);
404 }
405 else
406 {
407 m_dwFlags |= CSF_EVENT_DB_LOCKED;
b8bad201 408 m_dwFlags &= ~CSF_EVENT_DB_MODIFIED;
b54b2b11
VK
409
410 msg.SetVariable(VID_RCC, RCC_SUCCESS);
411 SendMessage(&msg);
412 msg.DeleteAllVariables();
413
414 // Prepare data message
415 msg.SetCode(CMD_EVENT_DB_RECORD);
416 msg.SetId(dwRqId);
417
eafa21c7 418 hResult = DBAsyncSelect(g_hCoreDB, "SELECT event_id,name,severity,flags,message,description FROM events");
ebebc8ea 419 if (hResult != NULL)
b54b2b11 420 {
ebebc8ea
VK
421 while(DBFetch(hResult))
422 {
423 msg.SetVariable(VID_EVENT_ID, DBGetFieldAsyncULong(hResult, 0));
424 msg.SetVariable(VID_NAME, DBGetFieldAsync(hResult, 1, szBuffer, 1024));
425 msg.SetVariable(VID_SEVERITY, DBGetFieldAsyncULong(hResult, 2));
426 msg.SetVariable(VID_FLAGS, DBGetFieldAsyncULong(hResult, 3));
427 msg.SetVariable(VID_MESSAGE, DBGetFieldAsync(hResult, 4, szBuffer, 1024));
428 msg.SetVariable(VID_DESCRIPTION, DBGetFieldAsync(hResult, 5, szBuffer, 1024));
429 SendMessage(&msg);
430 msg.DeleteAllVariables();
431 }
432 DBFreeAsyncResult(hResult);
b54b2b11 433 }
3a5042fd
VK
434
435 // Send end-of-list indicator
436 msg.SetCode(CMD_EVENT_DB_EOF);
437 SendMessage(&msg);
b54b2b11
VK
438 }
439}
440
441
3421c063
VK
442//
443// Close event configuration database
444//
445
446void ClientSession::CloseEventDB(DWORD dwRqId)
447{
448 CSCPMessage msg;
449
450 msg.SetCode(CMD_REQUEST_COMPLETED);
451 msg.SetId(dwRqId);
452
453 if (m_dwFlags & CSF_EVENT_DB_LOCKED)
454 {
455 // Check if event configuration DB has been modified
456 if (m_dwFlags & CSF_EVENT_DB_MODIFIED)
457 {
458 ReloadEvents();
459
460 // Notify clients on event database change
461 EnumerateClientSessions(NotifyClient, (void *)NX_NOTIFY_EVENTDB_CHANGED);
462 }
463 UnlockComponent(CID_EVENT_DB);
464 m_dwFlags &= ~CSF_EVENT_DB_LOCKED;
465 msg.SetVariable(VID_RCC, RCC_SUCCESS);
466 }
467 else
468 {
469 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
470 }
471 SendMessage(&msg);
472}
473
474
21e4b6f0
VK
475//
476// Send all objects to client
477//
478
e100f091 479void ClientSession::SendAllObjects(DWORD dwRqId)
21e4b6f0
VK
480{
481 DWORD i;
482 CSCPMessage msg;
483
e100f091
VK
484 // Send confirmation message
485 msg.SetCode(CMD_REQUEST_COMPLETED);
486 msg.SetId(dwRqId);
487 msg.SetVariable(VID_RCC, RCC_SUCCESS);
488 SendMessage(&msg);
489 msg.DeleteAllVariables();
490
53512272
VK
491 MutexLock(m_hMutexSendObjects, INFINITE);
492
21e4b6f0
VK
493 // Prepare message
494 msg.SetCode(CMD_OBJECT);
495
496 // Send objects, one per message
497 ObjectsGlobalLock();
498 for(i = 0; i < g_dwIdIndexSize; i++)
24156e90
VK
499 if (g_pIndexById[i].pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
500 {
501 g_pIndexById[i].pObject->CreateMessage(&msg);
502 SendMessage(&msg);
503 msg.DeleteAllVariables();
504 }
21e4b6f0
VK
505 ObjectsGlobalUnlock();
506
507 // Send end of list notification
508 msg.SetCode(CMD_OBJECT_LIST_END);
509 SendMessage(&msg);
53512272
VK
510
511 MutexUnlock(m_hMutexSendObjects);
21e4b6f0
VK
512}
513
514
515//
516// Send all events to client
517//
518
74a5aa17 519void ClientSession::SendAllEvents(DWORD dwRqId)
21e4b6f0 520{
21e4b6f0 521 CSCPMessage msg;
20177e8e 522 DB_ASYNC_RESULT hResult;
9c36ef66 523 NXC_EVENT event;
21e4b6f0 524
74a5aa17
VK
525 // Send confirmation message
526 msg.SetCode(CMD_REQUEST_COMPLETED);
527 msg.SetId(dwRqId);
528 msg.SetVariable(VID_RCC, RCC_SUCCESS);
529 SendMessage(&msg);
530 msg.DeleteAllVariables();
531
62f5857f
VK
532 MutexLock(m_hMutexSendEvents, INFINITE);
533
21e4b6f0 534 // Retrieve events from database
fa1d3757 535 hResult = DBAsyncSelect(g_hCoreDB, "SELECT event_id,timestamp,source,severity,message FROM event_log ORDER BY timestamp");
21e4b6f0
VK
536 if (hResult != NULL)
537 {
538 // Send events, one per message
20177e8e 539 while(DBFetch(hResult))
21e4b6f0 540 {
20177e8e
VK
541 event.dwEventId = htonl(DBGetFieldAsyncULong(hResult, 0));
542 event.dwTimeStamp = htonl(DBGetFieldAsyncULong(hResult, 1));
543 event.dwSourceId = htonl(DBGetFieldAsyncULong(hResult, 2));
544 event.dwSeverity = htonl(DBGetFieldAsyncULong(hResult, 3));
545 DBGetFieldAsync(hResult, 4, event.szMessage, MAX_EVENT_MSG_LENGTH);
74a5aa17 546 m_pSendQueue->Put(CreateRawCSCPMessage(CMD_EVENT, dwRqId, sizeof(NXC_EVENT), &event, NULL));
9c36ef66 547 }
20177e8e 548 DBFreeAsyncResult(hResult);
21e4b6f0
VK
549 }
550
551 // Send end of list notification
552 msg.SetCode(CMD_EVENT_LIST_END);
553 SendMessage(&msg);
62f5857f
VK
554
555 MutexUnlock(m_hMutexSendEvents);
21e4b6f0
VK
556}
557
558
559//
560// Send all configuration variables to client
561//
562
563void ClientSession::SendAllConfigVars(void)
564{
565 DWORD i, dwNumRecords;
566 CSCPMessage msg;
567 DB_RESULT hResult;
568
569 // Check user rights
570 if ((m_dwUserId != 0) && ((m_dwSystemAccess & SYSTEM_ACCESS_VIEW_CONFIG) == 0))
571 {
572 // Access denied
573 msg.SetCode(CMD_CONFIG_VARLIST_END);
a5f8dbb8 574 msg.SetVariable(VID_ERROR, (DWORD)1);
21e4b6f0
VK
575 SendMessage(&msg);
576 }
577 else
578 {
579 // Prepare message
580 msg.SetCode(CMD_CONFIG_VARIABLE);
581
582 // Retrieve configuration variables from database
583 hResult = DBSelect(g_hCoreDB, "SELECT name,value FROM config");
584 if (hResult != NULL)
585 {
586 // Send events, one per message
587 dwNumRecords = DBGetNumRows(hResult);
588 for(i = 0; i < dwNumRecords; i++)
589 {
a5f8dbb8
VK
590 msg.SetVariable(VID_NAME, DBGetField(hResult, i, 0));
591 msg.SetVariable(VID_VALUE, DBGetField(hResult, i, 1));
21e4b6f0
VK
592 SendMessage(&msg);
593 msg.DeleteAllVariables();
594 }
20177e8e 595 DBFreeResult(hResult);
21e4b6f0
VK
596 }
597
598 // Send end of list notification
599 msg.SetCode(CMD_CONFIG_VARLIST_END);
a5f8dbb8 600 msg.SetVariable(VID_ERROR, (DWORD)0);
21e4b6f0
VK
601 SendMessage(&msg);
602 }
603}
20177e8e
VK
604
605
606//
607// Close session forcibly
608//
609
610void ClientSession::Kill(void)
611{
612 // We shutdown socket connection, which will cause
613 // read thread to stop, and other threads will follow
614 shutdown(m_hSocket, 2);
615}
62f5857f
VK
616
617
618//
619// Handler for new events
620//
621
622void ClientSession::OnNewEvent(Event *pEvent)
623{
624 UPDATE_INFO *pUpdate;
625
984542f8
VK
626 if (m_iState == STATE_AUTHENTICATED)
627 {
628 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
629 pUpdate->dwCategory = INFO_CAT_EVENT;
630 pUpdate->pData = malloc(sizeof(NXC_EVENT));
631 pEvent->PrepareMessage((NXC_EVENT *)pUpdate->pData);
632 m_pUpdateQueue->Put(pUpdate);
633 }
62f5857f
VK
634}
635
636
637//
638// Handler for object changes
639//
640
53512272 641void ClientSession::OnObjectChange(NetObj *pObject)
62f5857f 642{
53512272
VK
643 UPDATE_INFO *pUpdate;
644
984542f8
VK
645 if (m_iState == STATE_AUTHENTICATED)
646 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
647 {
648 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
649 pUpdate->dwCategory = INFO_CAT_OBJECT_CHANGE;
650 pUpdate->pData = pObject;
651 m_pUpdateQueue->Put(pUpdate);
652 pObject->IncRefCount();
653 }
62f5857f
VK
654}
655
656
657//
658// Update processing thread
659//
660
661void ClientSession::UpdateThread(void)
662{
663 UPDATE_INFO *pUpdate;
53512272 664 CSCPMessage msg;
62f5857f
VK
665
666 while(1)
667 {
668 pUpdate = (UPDATE_INFO *)m_pUpdateQueue->GetOrBlock();
669 if (pUpdate == INVALID_POINTER_VALUE) // Session termination indicator
670 break;
671
672 switch(pUpdate->dwCategory)
673 {
674 case INFO_CAT_EVENT:
675 MutexLock(m_hMutexSendEvents, INFINITE);
676 m_pSendQueue->Put(CreateRawCSCPMessage(CMD_EVENT, 0, sizeof(NXC_EVENT), pUpdate->pData, NULL));
677 MutexUnlock(m_hMutexSendEvents);
678 free(pUpdate->pData);
679 break;
53512272
VK
680 case INFO_CAT_OBJECT_CHANGE:
681 MutexLock(m_hMutexSendObjects, INFINITE);
682 msg.SetId(0);
683 msg.SetCode(CMD_OBJECT_UPDATE);
684 ((NetObj *)pUpdate->pData)->CreateMessage(&msg);
685 SendMessage(&msg);
686 MutexUnlock(m_hMutexSendObjects);
687 msg.DeleteAllVariables();
688 ((NetObj *)pUpdate->pData)->DecRefCount();
689 break;
62f5857f
VK
690 default:
691 break;
692 }
693
694 free(pUpdate);
695 }
696 ConditionSet(m_hCondUpdateThreadStopped);
697}
83f0529c
VK
698
699
700//
701// Send notification message to server
702//
703
704void ClientSession::Notify(DWORD dwCode)
705{
706 CSCPMessage msg;
707
708 msg.SetCode(CMD_NOTIFY);
709 msg.SetVariable(VID_NOTIFICATION_CODE, dwCode);
710 SendMessage(&msg);
711}
605d2931
VK
712
713
714//
715// Update event template
716//
717
718void ClientSession::SetEventInfo(CSCPMessage *pRequest)
719{
720 CSCPMessage msg;
721
722 // Prepare reply message
723 msg.SetCode(CMD_REQUEST_COMPLETED);
724 msg.SetId(pRequest->GetId());
725
726 // Check if we have event configuration database opened
727 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
728 {
729 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
730 }
731 else
732 {
733 // Check access rights
734 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
735 {
736 char szQuery[4096], *pszName, *pszMessage, *pszDescription;
737 DWORD dwEventId;
738 BOOL bEventExist = FALSE;
739 DB_RESULT hResult;
740
741 // Check if event with specific id exists
742 dwEventId = pRequest->GetVariableLong(VID_EVENT_ID);
743 sprintf(szQuery, "SELECT event_id FROM events WHERE event_id=%ld", dwEventId);
744 hResult = DBSelect(g_hCoreDB, szQuery);
745 if (hResult != NULL)
746 {
747 if (DBGetNumRows(hResult) > 0)
748 bEventExist = TRUE;
749 DBFreeResult(hResult);
750 }
751
b8bad201 752 // Prepare and execute SQL query
eafa21c7
VK
753 pszName = pRequest->GetVariableStr(VID_NAME);
754 pszMessage = pRequest->GetVariableStr(VID_MESSAGE);
755 pszDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
605d2931
VK
756 if (bEventExist)
757 sprintf(szQuery, "UPDATE events SET name='%s',severity=%ld,flags=%ld,message='%s',description='%s' WHERE event_id=%ld",
eafa21c7 758 pszName, pRequest->GetVariableLong(VID_SEVERITY), pRequest->GetVariableLong(VID_FLAGS),
b8bad201 759 pszMessage, pszDescription, dwEventId);
605d2931 760 else
b8bad201 761 sprintf(szQuery, "INSERT INTO events SET event_id,name,severity,flags,message,description VALUES (%ld,'%s',%ld,%ld,'%s','%s')",
eafa21c7
VK
762 dwEventId, pszName, pRequest->GetVariableLong(VID_SEVERITY),
763 pRequest->GetVariableLong(VID_FLAGS), pszMessage, pszDescription);
605d2931 764 if (DBQuery(g_hCoreDB, szQuery))
b8bad201 765 {
605d2931 766 msg.SetVariable(VID_RCC, RCC_SUCCESS);
b8bad201
VK
767 m_dwFlags |= CSF_EVENT_DB_MODIFIED;
768 }
605d2931 769 else
b8bad201 770 {
605d2931 771 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
b8bad201 772 }
605d2931
VK
773
774 MemFree(pszName);
775 MemFree(pszMessage);
776 MemFree(pszDescription);
777 }
778 else
779 {
780 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
781 }
782 }
783
784 // Send responce
785 SendMessage(&msg);
786}
24156e90
VK
787
788
789//
790// Modify object
791//
792
793void ClientSession::ModifyObject(CSCPMessage *pRequest)
794{
ff550544 795 DWORD dwObjectId, dwResult = RCC_SUCCESS;
24156e90
VK
796 NetObj *pObject;
797 CSCPMessage msg;
798
799 // Prepare reply message
800 msg.SetCode(CMD_REQUEST_COMPLETED);
801 msg.SetId(pRequest->GetId());
802
803 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
804 pObject = FindObjectById(dwObjectId);
805 if (pObject != NULL)
806 {
807 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
808 {
ff550544
VK
809 // If user attempts to change object's ACL, check
810 // if he has OBJECT_ACCESS_CONTROL permission
811 if (pRequest->IsVariableExist(VID_ACL_SIZE))
812 if (!pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CONTROL))
813 dwResult = RCC_ACCESS_DENIED;
814
815 // If allowed, change object and set completion code
816 if (dwResult != RCC_ACCESS_DENIED)
817 dwResult = pObject->ModifyFromMessage(pRequest);
24156e90
VK
818 msg.SetVariable(VID_RCC, dwResult);
819 }
820 else
821 {
822 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
823 }
824 }
825 else
826 {
827 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
828 }
829
830 // Send responce
831 SendMessage(&msg);
832}
23a32988
VK
833
834
835//
836// Send users database to client
837//
838
839void ClientSession::SendUserDB(DWORD dwRqId)
840{
841 CSCPMessage msg;
2d5c8ac8 842 DWORD i;
23a32988
VK
843
844 // Prepare responce message
845 msg.SetCode(CMD_REQUEST_COMPLETED);
846 msg.SetId(dwRqId);
847 msg.SetVariable(VID_RCC, RCC_SUCCESS);
848 SendMessage(&msg);
849
850 // Send users
851 msg.SetCode(CMD_USER_DATA);
852 for(i = 0; i < g_dwNumUsers; i++)
853 {
2d5c8ac8 854 FillUserInfoMessage(&msg, &g_pUserList[i]);
23a32988
VK
855 SendMessage(&msg);
856 msg.DeleteAllVariables();
857 }
858
859 // Send groups
860 msg.SetCode(CMD_GROUP_DATA);
861 for(i = 0; i < g_dwNumGroups; i++)
862 {
2d5c8ac8 863 FillGroupInfoMessage(&msg, &g_pGroupList[i]);
23a32988
VK
864 SendMessage(&msg);
865 msg.DeleteAllVariables();
866 }
867
868 // Send end-of-database notification
869 msg.SetCode(CMD_USER_DB_EOF);
870 SendMessage(&msg);
871}
ff550544
VK
872
873
874//
875// Create new user
876//
877
878void ClientSession::CreateUser(CSCPMessage *pRequest)
879{
880 CSCPMessage msg;
881
882 // Prepare responce message
883 msg.SetCode(CMD_REQUEST_COMPLETED);
884 msg.SetId(pRequest->GetId());
885
886 // Check user rights
887 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
888 {
889 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
890 }
891 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
892 {
893 // User database have to be locked before any
894 // changes to user database can be made
895 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
896 }
897 else
898 {
984542f8 899 DWORD dwResult, dwUserId;
ff550544
VK
900 BOOL bIsGroup;
901 char szUserName[MAX_USER_NAME];
902
903 pRequest->GetVariableStr(VID_USER_NAME, szUserName, MAX_USER_NAME);
904 bIsGroup = pRequest->GetVariableShort(VID_IS_GROUP);
984542f8 905 dwResult = CreateNewUser(szUserName, bIsGroup, &dwUserId);
ff550544 906 msg.SetVariable(VID_RCC, dwResult);
984542f8
VK
907 if (dwResult == RCC_SUCCESS)
908 msg.SetVariable(VID_USER_ID, dwUserId); // Send id of new user to client
ff550544
VK
909 }
910
911 // Send responce
912 SendMessage(&msg);
913}
914
915
916//
917// Update existing user's data
918//
919
920void ClientSession::UpdateUser(CSCPMessage *pRequest)
921{
612d43dc
VK
922 CSCPMessage msg;
923
924 // Prepare responce message
925 msg.SetCode(CMD_REQUEST_COMPLETED);
926 msg.SetId(pRequest->GetId());
927
928 // Check user rights
929 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
930 {
931 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
932 }
933 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
934 {
935 // User database have to be locked before any
936 // changes to user database can be made
937 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
938 }
939 else
940 {
86f31e8f 941 DWORD dwUserId, dwResult;
612d43dc
VK
942
943 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
944 if (dwUserId & GROUP_FLAG)
945 {
946 NMS_USER_GROUP group;
2d5c8ac8 947 DWORD i, dwId;
86f31e8f
VK
948
949 group.dwId = dwUserId;
2d5c8ac8
VK
950 pRequest->GetVariableStr(VID_USER_DESCRIPTION, group.szDescription, MAX_USER_DESCR);
951 pRequest->GetVariableStr(VID_USER_NAME, group.szName, MAX_USER_NAME);
952 group.wFlags = pRequest->GetVariableShort(VID_USER_FLAGS);
953 group.wSystemRights = pRequest->GetVariableShort(VID_USER_SYS_RIGHTS);
954 group.dwNumMembers = pRequest->GetVariableLong(VID_NUM_MEMBERS);
955 group.pMembers = (DWORD *)malloc(sizeof(DWORD) * group.dwNumMembers);
956 for(i = 0, dwId = VID_GROUP_MEMBER_BASE; i < group.dwNumMembers; i++, dwId++)
957 group.pMembers[i] = pRequest->GetVariableLong(dwId);
86f31e8f 958 dwResult = ModifyGroup(&group);
2d5c8ac8 959 safe_free(group.pMembers);
612d43dc
VK
960 }
961 else
962 {
963 NMS_USER user;
964
965 user.dwId = dwUserId;
966 pRequest->GetVariableStr(VID_USER_DESCRIPTION, user.szDescription, MAX_USER_DESCR);
967 pRequest->GetVariableStr(VID_USER_FULL_NAME, user.szFullName, MAX_USER_FULLNAME);
968 pRequest->GetVariableStr(VID_USER_NAME, user.szName, MAX_USER_NAME);
969 user.wFlags = pRequest->GetVariableShort(VID_USER_FLAGS);
86f31e8f
VK
970 user.wSystemRights = pRequest->GetVariableShort(VID_USER_SYS_RIGHTS);
971 dwResult = ModifyUser(&user);
612d43dc 972 }
86f31e8f 973 msg.SetVariable(VID_RCC, dwResult);
612d43dc
VK
974 }
975
976 // Send responce
977 SendMessage(&msg);
ff550544
VK
978}
979
980
981//
982// Delete user
983//
984
985void ClientSession::DeleteUser(CSCPMessage *pRequest)
986{
987 CSCPMessage msg;
988 DWORD dwUserId;
989
990 // Prepare responce message
991 msg.SetCode(CMD_REQUEST_COMPLETED);
992 msg.SetId(pRequest->GetId());
993
612d43dc
VK
994 // Check user rights
995 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
ff550544 996 {
612d43dc
VK
997 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
998 }
999 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1000 {
1001 // User database have to be locked before any
1002 // changes to user database can be made
1003 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1004 }
1005 else
1006 {
1007 // Get Id of user to be deleted
1008 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1009
1010 if (dwUserId != 0)
ff550544 1011 {
612d43dc
VK
1012 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
1013 {
1014 // Current user has no rights for user account management
1015 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1016 }
1017 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1018 {
1019 // User database have to be locked before any
1020 // changes to user database can be made
1021 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1022 }
1023 else
1024 {
1025 DWORD dwResult;
1026
1027 dwResult = DeleteUserFromDB(dwUserId);
1028 msg.SetVariable(VID_RCC, dwResult);
1029 }
ff550544
VK
1030 }
1031 else
1032 {
612d43dc
VK
1033 // Nobody can delete system administrator account
1034 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
ff550544
VK
1035 }
1036 }
ff550544
VK
1037
1038 // Send responce
1039 SendMessage(&msg);
1040}
1041
1042
1043//
1044// Lock/unlock user database
1045//
1046
1047void ClientSession::LockUserDB(DWORD dwRqId, BOOL bLock)
1048{
1049 CSCPMessage msg;
1050 char szBuffer[256];
1051
1052 // Prepare responce message
1053 msg.SetCode(CMD_REQUEST_COMPLETED);
1054 msg.SetId(dwRqId);
1055
1056 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS)
1057 {
1058 if (bLock)
1059 {
1060 if (!LockComponent(CID_USER_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
1061 {
1062 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
1063 msg.SetVariable(VID_LOCKED_BY, szBuffer);
1064 }
1065 else
1066 {
1067 m_dwFlags |= CSF_USER_DB_LOCKED;
1068 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1069 }
1070 }
1071 else
1072 {
1073 if (m_dwFlags & CSF_USER_DB_LOCKED)
1074 {
1075 UnlockComponent(CID_USER_DB);
1076 m_dwFlags &= ~CSF_USER_DB_LOCKED;
1077 }
1078 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1079 }
1080 }
1081 else
1082 {
1083 // Current user has no rights for user account management
1084 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1085 }
1086
1087 // Send responce
1088 SendMessage(&msg);
1089}
984542f8
VK
1090
1091
1092//
1093// Notify client on user database update
1094//
1095
1096void ClientSession::OnUserDBUpdate(int iCode, DWORD dwUserId, NMS_USER *pUser, NMS_USER_GROUP *pGroup)
1097{
1098 CSCPMessage msg;
1099
1100 if (m_iState == STATE_AUTHENTICATED)
1101 {
1102 msg.SetCode(CMD_USER_DB_UPDATE);
1103 msg.SetId(0);
1104 msg.SetVariable(VID_UPDATE_TYPE, (WORD)iCode);
984542f8
VK
1105
1106 switch(iCode)
1107 {
1108 case USER_DB_CREATE:
2d5c8ac8 1109 msg.SetVariable(VID_USER_ID, dwUserId);
984542f8 1110 if (dwUserId & GROUP_FLAG)
984542f8 1111 msg.SetVariable(VID_USER_NAME, pGroup->szName);
984542f8 1112 else
984542f8 1113 msg.SetVariable(VID_USER_NAME, pUser->szName);
2d5c8ac8
VK
1114 break;
1115 case USER_DB_MODIFY:
1116 if (dwUserId & GROUP_FLAG)
1117 FillGroupInfoMessage(&msg, pGroup);
1118 else
1119 FillUserInfoMessage(&msg, pUser);
984542f8
VK
1120 break;
1121 default:
2d5c8ac8 1122 msg.SetVariable(VID_USER_ID, dwUserId);
984542f8
VK
1123 break;
1124 }
1125
1126 SendMessage(&msg);
1127 }
1128}
017e1e13
VK
1129
1130
9ed4eaff
VK
1131//
1132// Change management status for the object
1133//
1134
1135void ClientSession::ChangeObjectMgmtStatus(CSCPMessage *pRequest)
1136{
1137 CSCPMessage msg;
1138 DWORD dwObjectId;
1139 NetObj *pObject;
1140
1141 // Prepare responce message
1142 msg.SetCode(CMD_REQUEST_COMPLETED);
1143 msg.SetId(pRequest->GetId());
1144
1145 // Get object id and check access rights
1146 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1147 pObject = FindObjectById(dwObjectId);
1148 if (pObject != NULL)
1149 {
1150 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1151 {
1152 BOOL bIsManaged;
1153
1154 bIsManaged = (BOOL)pRequest->GetVariableShort(VID_MGMT_STATUS);
1155 pObject->SetMgmtStatus(bIsManaged);
1156 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1157 }
1158 else
1159 {
1160 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1161 }
1162 }
1163 else
1164 {
1165 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1166 }
1167
1168 // Send responce
1169 SendMessage(&msg);
1170}
1171
1172
017e1e13
VK
1173//
1174// Set user's password
1175//
1176
1177void ClientSession::SetPassword(CSCPMessage *pRequest)
1178{
1179 CSCPMessage msg;
1180 DWORD dwUserId;
1181
1182 // Prepare responce message
1183 msg.SetCode(CMD_REQUEST_COMPLETED);
1184 msg.SetId(pRequest->GetId());
1185
1186 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1187
1188 if (((m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS) &&
1189 !((dwUserId == 0) && (m_dwUserId != 0))) || // Only administrator can change password for UID 0
1190 (dwUserId == m_dwUserId)) // User can change password for itself
1191 {
1192 DWORD dwResult;
1193 BYTE szPassword[SHA_DIGEST_LENGTH];
1194
1195 pRequest->GetVariableBinary(VID_PASSWORD, szPassword, SHA_DIGEST_LENGTH);
1196 dwResult = SetUserPassword(dwUserId, szPassword);
1197 msg.SetVariable(VID_RCC, dwResult);
1198 }
1199 else
1200 {
1201 // Current user has no rights to change password for specific user
1202 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1203 }
1204
1205 // Send responce
1206 SendMessage(&msg);
1207}
7257eb7d
VK
1208
1209
1210//
1211// Send node's DCIs to client and lock data collection settings
1212//
1213
1214void ClientSession::OpenNodeDCIList(CSCPMessage *pRequest)
1215{
1216 CSCPMessage msg;
3c55b85d
VK
1217 DWORD dwObjectId;
1218 NetObj *pObject;
1219 BOOL bSuccess = FALSE;
7257eb7d
VK
1220
1221 // Prepare responce message
1222 msg.SetCode(CMD_REQUEST_COMPLETED);
1223 msg.SetId(pRequest->GetId());
1224
3c55b85d
VK
1225 // Get node id and check object class and access rights
1226 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1227 pObject = FindObjectById(dwObjectId);
1228 if (pObject != NULL)
1229 {
1230 if (pObject->Type() == OBJECT_NODE)
1231 {
1232 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1233 {
1234 // Try to lock DCI list
1235 bSuccess = ((Node *)pObject)->LockDCIList(m_dwIndex);
1236 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_COMPONENT_LOCKED);
338493a0
VK
1237
1238 // Modify list of open nodes DCI lists
1239 if (bSuccess)
1240 {
1241 m_pOpenDCIList = (DWORD *)realloc(m_pOpenDCIList, sizeof(DWORD) * (m_dwOpenDCIListSize + 1));
1242 m_pOpenDCIList[m_dwOpenDCIListSize] = dwObjectId;
1243 m_dwOpenDCIListSize++;
1244 }
3c55b85d
VK
1245 }
1246 else
1247 {
1248 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1249 }
1250 }
1251 else
1252 {
1253 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1254 }
1255 }
1256 else
1257 {
1258 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1259 }
7257eb7d
VK
1260
1261 // Send responce
1262 SendMessage(&msg);
3c55b85d
VK
1263
1264 // If DCI list was successfully locked, send it to client
1265 if (bSuccess)
1266 ((Node *)pObject)->SendItemsToClient(this, pRequest->GetId());
7257eb7d
VK
1267}
1268
1269
1270//
1271// Unlock node's data collection settings
1272//
1273
1274void ClientSession::CloseNodeDCIList(CSCPMessage *pRequest)
1275{
1276 CSCPMessage msg;
3c55b85d
VK
1277 DWORD dwObjectId;
1278 NetObj *pObject;
7257eb7d
VK
1279
1280 // Prepare responce message
1281 msg.SetCode(CMD_REQUEST_COMPLETED);
1282 msg.SetId(pRequest->GetId());
1283
3c55b85d
VK
1284 // Get node id and check object class and access rights
1285 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1286 pObject = FindObjectById(dwObjectId);
1287 if (pObject != NULL)
1288 {
1289 if (pObject->Type() == OBJECT_NODE)
1290 {
1291 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1292 {
1293 BOOL bSuccess;
1294
1295 // Try to unlock DCI list
1296 bSuccess = ((Node *)pObject)->UnlockDCIList(m_dwIndex);
1297 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_OUT_OF_STATE_REQUEST);
338493a0
VK
1298
1299 // Modify list of open nodes DCI lists
1300 if (bSuccess)
1301 {
1302 DWORD i;
1303
1304 for(i = 0; i < m_dwOpenDCIListSize; i++)
1305 if (m_pOpenDCIList[i] == dwObjectId)
1306 {
1307 m_dwOpenDCIListSize--;
1308 memmove(&m_pOpenDCIList[i], &m_pOpenDCIList[i + 1],
1309 sizeof(DWORD) * (m_dwOpenDCIListSize - i));
1310 break;
1311 }
1312 }
3c55b85d
VK
1313 }
1314 else
1315 {
1316 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1317 }
1318 }
1319 else
1320 {
1321 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1322 }
1323 }
1324 else
1325 {
1326 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1327 }
1328
7257eb7d
VK
1329 // Send responce
1330 SendMessage(&msg);
1331}
c1c39152
VK
1332
1333
1334//
9ed4eaff 1335// Create, modify, or delete data collection item for node
c1c39152
VK
1336//
1337
9ed4eaff 1338void ClientSession::ModifyNodeDCI(CSCPMessage *pRequest)
c1c39152
VK
1339{
1340 CSCPMessage msg;
1341 DWORD dwObjectId;
1342 NetObj *pObject;
1343
1344 // Prepare responce message
1345 msg.SetCode(CMD_REQUEST_COMPLETED);
1346 msg.SetId(pRequest->GetId());
1347
9ed4eaff 1348 // Get node id and check object class and access rights
c1c39152
VK
1349 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1350 pObject = FindObjectById(dwObjectId);
1351 if (pObject != NULL)
1352 {
9ed4eaff 1353 if (pObject->Type() == OBJECT_NODE)
c1c39152 1354 {
9ed4eaff
VK
1355 if (((Node *)pObject)->IsLockedBySession(m_dwIndex))
1356 {
1357 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1358 {
07a45e04 1359 DWORD i, dwItemId, dwNumMaps, *pdwMapId, *pdwMapIndex;
9ed4eaff
VK
1360 DCItem *pItem;
1361 BOOL bSuccess;
1362
1363 switch(pRequest->GetCode())
1364 {
1365 case CMD_CREATE_NEW_DCI:
1366 // Create dummy DCI
1367 pItem = new DCItem(CreateUniqueId(IDG_ITEM), "no name", DS_INTERNAL,
1368 DTYPE_INTEGER, 60, 30, (Node *)pObject);
1369 pItem->SetStatus(ITEM_STATUS_DISABLED);
1370 if (((Node *)pObject)->AddItem(pItem))
1371 {
1372 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1373 // Return new item id to client
1374 msg.SetVariable(VID_DCI_ID, pItem->Id());
1375 }
1376 else // Unable to add item to node
1377 {
1378 delete pItem;
1379 msg.SetVariable(VID_RCC, RCC_DUPLICATE_DCI);
1380 }
1381 break;
1382 case CMD_MODIFY_NODE_DCI:
1383 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
07a45e04
VK
1384 bSuccess = ((Node *)pObject)->UpdateItem(dwItemId, pRequest, &dwNumMaps,
1385 &pdwMapIndex, &pdwMapId);
1386 if (bSuccess)
1387 {
1388 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1389
1390 // Send index to id mapping for newly created thresholds to client
1391 msg.SetVariable(VID_DCI_NUM_MAPS, dwNumMaps);
1392 for(i = 0; i < dwNumMaps; i++)
1393 {
1394 pdwMapId[i] = htonl(pdwMapId[i]);
1395 pdwMapIndex[i] = htonl(pdwMapIndex[i]);
1396 }
1397 msg.SetVariable(VID_DCI_MAP_IDS, (BYTE *)pdwMapId, sizeof(DWORD) * dwNumMaps);
1398 msg.SetVariable(VID_DCI_MAP_INDEXES, (BYTE *)pdwMapIndex, sizeof(DWORD) * dwNumMaps);
7247842d
VK
1399 safe_free(pdwMapId);
1400 safe_free(pdwMapIndex);
07a45e04
VK
1401 }
1402 else
1403 {
1404 msg.SetVariable(VID_RCC, RCC_INVALID_DCI_ID);
1405 }
9ed4eaff
VK
1406 break;
1407 case CMD_DELETE_NODE_DCI:
1408 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
1409 bSuccess = ((Node *)pObject)->DeleteItem(dwItemId);
1410 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_INVALID_DCI_ID);
1411 break;
1412 }
1413 }
1414 else // User doesn't have MODIFY rights on object
1415 {
1416 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1417 }
1418 }
1419 else // Nodes DCI list not locked by this session
1420 {
1421 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1422 }
c1c39152 1423 }
9ed4eaff 1424 else // Object is not a node
c1c39152 1425 {
9ed4eaff 1426 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
c1c39152
VK
1427 }
1428 }
9ed4eaff 1429 else // No object with given ID
c1c39152
VK
1430 {
1431 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1432 }
1433
1434 // Send responce
1435 SendMessage(&msg);
1436}
ebebc8ea
VK
1437
1438
1439//
1440// Get collected data
1441//
1442
1443void ClientSession::GetCollectedData(CSCPMessage *pRequest)
1444{
1445 CSCPMessage msg;
1446 DWORD dwObjectId;
1447 NetObj *pObject;
6159a875
VK
1448 BOOL bSuccess = FALSE;
1449 static DWORD m_dwRowSize[] = { 8, 12, 260, 12 };
ebebc8ea
VK
1450
1451 // Prepare responce message
1452 msg.SetCode(CMD_REQUEST_COMPLETED);
1453 msg.SetId(pRequest->GetId());
1454
1455 // Get node id and check object class and access rights
1456 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1457 pObject = FindObjectById(dwObjectId);
1458 if (pObject != NULL)
1459 {
1460 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1461 {
1462 DB_ASYNC_RESULT hResult;
1463 DWORD dwItemId, dwMaxRows, dwTimeFrom, dwTimeTo;
6159a875 1464 DWORD dwAllocatedRows = 100, dwNumRows = 0;
bdce7422
VK
1465 char szQuery[512], szCond[256];
1466 int iPos = 0, iType;
1467 DCI_DATA_HEADER *pData = NULL;
6159a875 1468 DCI_DATA_ROW *pCurr;
bdce7422
VK
1469
1470 // Send CMD_REQUEST_COMPLETED message
1471 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1472 SendMessage(&msg);
ebebc8ea
VK
1473
1474 // Get request parameters
1475 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
1476 dwMaxRows = pRequest->GetVariableLong(VID_MAX_ROWS);
1477 dwTimeFrom = pRequest->GetVariableLong(VID_TIME_FROM);
1478 dwTimeTo = pRequest->GetVariableLong(VID_TIME_TO);
1479
9f20696e 1480 szCond[0] = 0;
bdce7422
VK
1481 if (dwTimeFrom != 0)
1482 {
1483 sprintf(szCond, " AND timestamp>=%d", dwTimeFrom);
1484 iPos = strlen(szCond);
1485 }
1486 if (dwTimeTo != 0)
1487 {
1488 sprintf(&szCond[iPos], " AND timestamp<=%d", dwTimeTo);
1489 }
1490
1491 sprintf(szQuery, "SELECT timestamp,value FROM idata_%d WHERE item_id=%d%s ORDER BY timestamp DESC",
1492 dwObjectId, dwItemId, szCond);
ebebc8ea
VK
1493 hResult = DBAsyncSelect(g_hCoreDB, szQuery);
1494 if (hResult != NULL)
1495 {
6159a875 1496 // Get item's data type to determine actual row size
bdce7422
VK
1497 iType = ((Node *)pObject)->GetItemType(dwItemId);
1498
6159a875
VK
1499 // Allocate initial memory block and prepare data header
1500 pData = (DCI_DATA_HEADER *)malloc(dwAllocatedRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER));
1501 pData->dwDataType = htonl((DWORD)iType);
1502 pData->dwItemId = htonl(dwItemId);
1503
1504 // Fill memory block with records
1505 pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER));
ebebc8ea
VK
1506 while(DBFetch(hResult))
1507 {
6159a875 1508 if ((dwMaxRows > 0) && (dwNumRows >= dwMaxRows))
bdce7422 1509 break;
6159a875
VK
1510
1511 // Extend buffer if we are at the end
1512 if (dwNumRows == dwAllocatedRows)
1513 {
1514 dwAllocatedRows += 50;
1515 pData = (DCI_DATA_HEADER *)realloc(pData,
1516 dwAllocatedRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER));
1517 pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER) + m_dwRowSize[iType] * dwNumRows);
1518 }
1519
1520 dwNumRows++;
1521
1522 pCurr->dwTimeStamp = htonl(DBGetFieldAsyncULong(hResult, 0));
1523 switch(iType)
1524 {
1525 case DTYPE_INTEGER:
9f20696e
VK
1526 pCurr->value.dwInteger = htonl(DBGetFieldAsyncULong(hResult, 1));
1527 break;
1528 case DTYPE_FLOAT:
1529 pCurr->value.dFloat = htond(DBGetFieldAsyncDouble(hResult, 1));
6159a875
VK
1530 break;
1531 case DTYPE_STRING:
1532 DBGetFieldAsync(hResult, 1, pCurr->value.szString, MAX_DCI_STRING_VALUE);
1533 break;
1534 }
1535 pCurr = (DCI_DATA_ROW *)(((char *)pCurr) + m_dwRowSize[iType]);
ebebc8ea
VK
1536 }
1537 DBFreeAsyncResult(hResult);
9f20696e 1538 pData->dwNumRows = htonl(dwNumRows);
6159a875
VK
1539
1540 // Prepare and send raw message with fetched data
1541 m_pSendQueue->Put(
1542 CreateRawCSCPMessage(CMD_DCI_DATA, pRequest->GetId(),
1543 dwNumRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER),
1544 pData, NULL));
1545 free(pData);
1546 bSuccess = TRUE;
ebebc8ea
VK
1547 }
1548 }
1549 else
1550 {
1551 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1552 }
1553 }
1554 else // No object with given ID
1555 {
1556 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1557 }
1558
1559 // Send responce
6159a875
VK
1560 if (!bSuccess)
1561 SendMessage(&msg);
ebebc8ea 1562}
06e7be2f
VK
1563
1564
1565//
1566// Open event processing policy
1567//
1568
1569void ClientSession::OpenEPP(DWORD dwRqId)
1570{
1571 CSCPMessage msg;
1572 char szBuffer[256];
1573 BOOL bSuccess = FALSE;
1574
1575 // Prepare responce message
1576 msg.SetCode(CMD_REQUEST_COMPLETED);
1577 msg.SetId(dwRqId);
1578
1579 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
1580 {
1581 if (!LockComponent(CID_EPP, m_dwIndex, m_szUserName, NULL, szBuffer))
1582 {
1583 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
1584 msg.SetVariable(VID_LOCKED_BY, szBuffer);
1585 }
1586 else
1587 {
1588 m_dwFlags |= CSF_EPP_LOCKED;
1589 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1590 msg.SetVariable(VID_NUM_RULES, g_pEventPolicy->NumRules());
1591 bSuccess = TRUE;
1592 }
1593 }
1594 else
1595 {
1596 // Current user has no rights for event policy management
1597 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1598 }
1599
1600 // Send responce
1601 SendMessage(&msg);
1602
1603 // Send policy to client
1604 if (bSuccess)
1605 g_pEventPolicy->SendToClient(this, dwRqId);
1606}
1607
1608
1609//
1610// Close event processing policy
1611//
1612
1613void ClientSession::CloseEPP(DWORD dwRqId)
1614{
1615 CSCPMessage msg;
1616
1617 // Prepare responce message
1618 msg.SetCode(CMD_REQUEST_COMPLETED);
1619 msg.SetId(dwRqId);
1620
1621 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
1622 {
1623 if (m_dwFlags & CSF_EPP_LOCKED)
1624 {
1625 UnlockComponent(CID_EPP);
1626 m_dwFlags &= ~CSF_EPP_LOCKED;
1627 }
1628 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1629 }
1630 else
1631 {
1632 // Current user has no rights for event policy management
1633 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1634 }
1635
1636 // Send responce
1637 SendMessage(&msg);
1638}
1639
1640
1641//
1642// Save event processing policy
1643//
1644
1645void ClientSession::SaveEPP(CSCPMessage *pMsg)
1646{
1647}
1648
1649
1650//
1651// Install event processing policy
1652//
1653
1654void ClientSession::InstallEPP(DWORD dwRqId)
1655{
1656}
1657
1658
1659//
1660// Send list of available MIB files to client
1661//
1662
1663void ClientSession::SendMIBList(DWORD dwRqId)
1664{
1665 CSCPMessage msg;
1666 DWORD dwId1, dwId2, dwNumFiles;
1667 DIR *dir;
1668 int iBufPos;
c9ccd685 1669#ifdef _WIN32
06e7be2f 1670 struct direct *dptr;
c9ccd685
AK
1671#else
1672 struct dirent *dptr;
1673#endif
06e7be2f
VK
1674 char szBuffer[MAX_PATH];
1675 BYTE md5Hash[MD5_DIGEST_SIZE];
1676
1677 // Prepare responce message
1678 msg.SetCode(CMD_MIB_LIST);
1679 msg.SetId(dwRqId);
1680
1681 // Read directory
1682 dwNumFiles = 0;
1683 strcpy(szBuffer, g_szDataDir);
1684 strcat(szBuffer, DDIR_MIBS);
1685 dir = opendir(szBuffer);
1686 if (dir != NULL)
1687 {
1688#ifdef _WIN32
1689 strcat(szBuffer, "\\");
1690#else
1691 strcat(szBuffer, "/");
1692#endif
1693 iBufPos = strlen(szBuffer);
1694 dwId1 = VID_MIB_NAME_BASE;
1695 dwId2 = VID_MIB_HASH_BASE;
1696 while((dptr = readdir(dir)) != NULL)
1697 {
1698 strcpy(&szBuffer[iBufPos], dptr->d_name);
1699 if (CalculateFileMD5Hash(szBuffer, md5Hash))
1700 {
1701 msg.SetVariable(dwId1++, dptr->d_name);
1702 msg.SetVariable(dwId2++, md5Hash, MD5_DIGEST_SIZE);
1703 dwNumFiles++;
1704 }
1705 }
1706 closedir(dir);
1707 }
1708
1709 msg.SetVariable(VID_NUM_MIBS, dwNumFiles);
1710
1711 // Send responce
1712 SendMessage(&msg);
1713}
1714
1715
1716//
1717// Send requested MIB file to client
1718//
1719
1720void ClientSession::SendMIB(CSCPMessage *pRequest)
1721{
1722 CSCPMessage msg;
1723 BYTE *pFile;
1724 DWORD dwFileSize;
1725 char szBuffer[MAX_PATH], szMIB[MAX_PATH];
1726
1727 // Prepare responce message
1728 msg.SetCode(CMD_MIB);
1729 msg.SetId(pRequest->GetId());
1730
1731 // Get name of the requested file
1732 pRequest->GetVariableStr(VID_MIB_NAME, szMIB, MAX_PATH);
1733
1734 // Load file into memory
1735 strcpy(szBuffer, g_szDataDir);
1736 strcat(szBuffer, DDIR_MIBS);
1737#ifdef _WIN32
1738 strcat(szBuffer, "\\");
1739#else
1740 strcat(szBuffer, "/");
1741#endif
1742 strcat(szBuffer, szMIB);
1743 pFile = LoadFile(szBuffer, &dwFileSize);
1744 if (pFile != NULL)
1745 {
1746 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1747 msg.SetVariable(VID_MIB_FILE_SIZE, dwFileSize);
1748 msg.SetVariable(VID_MIB_FILE, pFile, dwFileSize);
1749 free(pFile);
1750 }
1751 else
1752 {
1753 msg.SetVariable(VID_RCC, RCC_SYSTEM_FAILURE);
1754 }
1755
1756 // Send responce
1757 SendMessage(&msg);
1758}
ef44d5ea
VK
1759
1760
3421c063
VK
1761//
1762// Send list of event name/identifier pairs
1763//
1764
1765void ClientSession::SendEventNames(DWORD dwRqId)
1766{
1767 CSCPMessage msg;
1768 DB_RESULT hResult;
1769
1770 msg.SetCode(CMD_EVENT_NAME_LIST);
1771 msg.SetId(dwRqId);
1772 hResult = DBSelect(g_hCoreDB, "SELECT event_id,name FROM events");
1773 if (hResult != NULL)
1774 {
1775 DWORD i, dwNumEvents;
1776 NXC_EVENT_NAME *pList;
1777
1778 dwNumEvents = DBGetNumRows(hResult);
1779 msg.SetVariable(VID_NUM_EVENTS, dwNumEvents);
1780 if (dwNumEvents > 0)
1781 {
1782 pList = (NXC_EVENT_NAME *)malloc(sizeof(NXC_EVENT_NAME) * dwNumEvents);
1783 for(i = 0; i < dwNumEvents; i++)
1784 {
1785 pList[i].dwEventId = htonl(DBGetFieldULong(hResult, i, 0));
1786 strcpy(pList[i].szName, DBGetField(hResult, i, 1));
1787 }
1788 msg.SetVariable(VID_EVENT_NAME_TABLE, (BYTE *)pList, sizeof(NXC_EVENT_NAME) * dwNumEvents);
1789 free(pList);
1790 }
1791 DBFreeResult(hResult);
1792 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1793 }
1794 else
1795 {
1796 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
1797 }
1798 SendMessage(&msg);
1799}
1800
1801
ef44d5ea
VK
1802//
1803// Create new object
1804//
1805
1806void ClientSession::CreateObject(CSCPMessage *pRequest)
1807{
1808}