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