- nxevent fully working
[public/netxms.git] / src / server / core / session.cpp
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 #ifdef _WIN32
26 # include <direct.h>
27 #else
28 # include <dirent.h>
29 #endif
30
31
32 //
33 // Externals
34 //
35
36 void UnregisterSession(DWORD dwIndex);
37
38
39 //
40 // Node poller start data
41 //
42
43 typedef struct
44 {
45 ClientSession *pSession;
46 Node *pNode;
47 int iPollType;
48 DWORD dwRqId;
49 } POLLER_START_DATA;
50
51
52 //
53 // Fill CSCP message with user data
54 //
55
56 static void FillUserInfoMessage(CSCPMessage *pMsg, NMS_USER *pUser)
57 {
58 pMsg->SetVariable(VID_USER_ID, pUser->dwId);
59 pMsg->SetVariable(VID_USER_NAME, pUser->szName);
60 pMsg->SetVariable(VID_USER_FLAGS, pUser->wFlags);
61 pMsg->SetVariable(VID_USER_SYS_RIGHTS, pUser->wSystemRights);
62 pMsg->SetVariable(VID_USER_FULL_NAME, pUser->szFullName);
63 pMsg->SetVariable(VID_USER_DESCRIPTION, pUser->szDescription);
64 }
65
66
67 //
68 // Fill CSCP message with user group data
69 //
70
71 static void FillGroupInfoMessage(CSCPMessage *pMsg, NMS_USER_GROUP *pGroup)
72 {
73 DWORD i, dwId;
74
75 pMsg->SetVariable(VID_USER_ID, pGroup->dwId);
76 pMsg->SetVariable(VID_USER_NAME, pGroup->szName);
77 pMsg->SetVariable(VID_USER_FLAGS, pGroup->wFlags);
78 pMsg->SetVariable(VID_USER_SYS_RIGHTS, pGroup->wSystemRights);
79 pMsg->SetVariable(VID_USER_DESCRIPTION, pGroup->szDescription);
80 pMsg->SetVariable(VID_NUM_MEMBERS, pGroup->dwNumMembers);
81 for(i = 0, dwId = VID_GROUP_MEMBER_BASE; i < pGroup->dwNumMembers; i++, dwId++)
82 pMsg->SetVariable(dwId, pGroup->pMembers[i]);
83 }
84
85
86 //
87 // Client communication read thread starter
88 //
89
90 THREAD_RESULT THREAD_CALL ClientSession::ReadThreadStarter(void *pArg)
91 {
92 ((ClientSession *)pArg)->ReadThread();
93
94 // When ClientSession::ReadThread exits, all other session
95 // threads are already stopped, so we can safely destroy
96 // session object
97 UnregisterSession(((ClientSession *)pArg)->GetIndex());
98 delete (ClientSession *)pArg;
99 return THREAD_OK;
100 }
101
102
103 //
104 // Client communication write thread starter
105 //
106
107 THREAD_RESULT THREAD_CALL ClientSession::WriteThreadStarter(void *pArg)
108 {
109 ((ClientSession *)pArg)->WriteThread();
110 return THREAD_OK;
111 }
112
113
114 //
115 // Received message processing thread starter
116 //
117
118 THREAD_RESULT THREAD_CALL ClientSession::ProcessingThreadStarter(void *pArg)
119 {
120 ((ClientSession *)pArg)->ProcessingThread();
121 return THREAD_OK;
122 }
123
124
125 //
126 // Information update processing thread starter
127 //
128
129 THREAD_RESULT THREAD_CALL ClientSession::UpdateThreadStarter(void *pArg)
130 {
131 ((ClientSession *)pArg)->UpdateThread();
132 return THREAD_OK;
133 }
134
135
136 //
137 // Forced node poll thread starter
138 //
139
140 THREAD_RESULT THREAD_CALL ClientSession::PollerThreadStarter(void *pArg)
141 {
142 ((POLLER_START_DATA *)pArg)->pSession->PollerThread(
143 ((POLLER_START_DATA *)pArg)->pNode,
144 ((POLLER_START_DATA *)pArg)->iPollType,
145 ((POLLER_START_DATA *)pArg)->dwRqId);
146 free(pArg);
147 return THREAD_OK;
148 }
149
150
151 //
152 // Client session class constructor
153 //
154
155 ClientSession::ClientSession(SOCKET hSocket, DWORD dwHostAddr)
156 {
157 m_pSendQueue = new Queue;
158 m_pMessageQueue = new Queue;
159 m_pUpdateQueue = new Queue;
160 m_hSocket = hSocket;
161 m_dwIndex = INVALID_INDEX;
162 m_iState = STATE_CONNECTED;
163 m_pMsgBuffer = (CSCP_BUFFER *)malloc(sizeof(CSCP_BUFFER));
164 m_hWriteThread = INVALID_THREAD_HANDLE;
165 m_hProcessingThread = INVALID_THREAD_HANDLE;
166 m_hUpdateThread = INVALID_THREAD_HANDLE;
167 m_mutexSendEvents = MutexCreate();
168 m_mutexSendObjects = MutexCreate();
169 m_mutexSendAlarms = MutexCreate();
170 m_mutexSendActions = MutexCreate();
171 m_mutexPollerInit = MutexCreate();
172 m_dwFlags = 0;
173 m_dwHostAddr = dwHostAddr;
174 strcpy(m_szUserName, "<not logged in>");
175 m_dwUserId = INVALID_INDEX;
176 m_dwOpenDCIListSize = 0;
177 m_pOpenDCIList = NULL;
178 m_ppEPPRuleList = NULL;
179 }
180
181
182 //
183 // Destructor
184 //
185
186 ClientSession::~ClientSession()
187 {
188 shutdown(m_hSocket, 2);
189 closesocket(m_hSocket);
190 delete m_pSendQueue;
191 delete m_pMessageQueue;
192 delete m_pUpdateQueue;
193 safe_free(m_pMsgBuffer);
194 MutexDestroy(m_mutexSendEvents);
195 MutexDestroy(m_mutexSendObjects);
196 MutexDestroy(m_mutexSendAlarms);
197 MutexDestroy(m_mutexSendActions);
198 MutexDestroy(m_mutexPollerInit);
199 safe_free(m_pOpenDCIList);
200 if (m_ppEPPRuleList != NULL)
201 {
202 DWORD i;
203
204 if (m_dwFlags & CSF_EPP_UPLOAD) // Aborted in the middle of EPP transfer
205 for(i = 0; i < m_dwRecordsUploaded; i++)
206 delete m_ppEPPRuleList[i];
207 free(m_ppEPPRuleList);
208 }
209 }
210
211
212 //
213 // Start all threads
214 //
215
216 void ClientSession::Run(void)
217 {
218 m_hWriteThread = ThreadCreateEx(WriteThreadStarter, 0, this);
219 m_hProcessingThread = ThreadCreateEx(ProcessingThreadStarter, 0, this);
220 m_hUpdateThread = ThreadCreateEx(UpdateThreadStarter, 0, this);
221 ThreadCreate(ReadThreadStarter, 0, this);
222 }
223
224
225 //
226 // Print debug information
227 //
228
229 void ClientSession::DebugPrintf(char *szFormat, ...)
230 {
231 if ((g_dwFlags & AF_STANDALONE) && (g_dwFlags & AF_DEBUG_CSCP))
232 {
233 va_list args;
234
235 printf("*CSCP(%d)* ", m_dwIndex);
236 va_start(args, szFormat);
237 vprintf(szFormat, args);
238 va_end(args);
239 }
240 }
241
242
243 //
244 // ReadThread()
245 //
246
247 void ClientSession::ReadThread(void)
248 {
249 CSCP_MESSAGE *pRawMsg;
250 CSCPMessage *pMsg;
251 int iErr;
252 DWORD i;
253 NetObj *pObject;
254
255 // Initialize raw message receiving function
256 RecvCSCPMessage(0, NULL, m_pMsgBuffer, 0);
257
258 pRawMsg = (CSCP_MESSAGE *)malloc(65536);
259 while(1)
260 {
261 if ((iErr = RecvCSCPMessage(m_hSocket, pRawMsg, m_pMsgBuffer, 65536)) <= 0)
262 break;
263
264 // Check if message is too large
265 if (iErr == 1)
266 continue;
267
268 // Check that actual received packet size is equal to encoded in packet
269 if ((int)ntohl(pRawMsg->dwSize) != iErr)
270 {
271 DebugPrintf("Actual message size doesn't match wSize value (%d,%d)\n", iErr, ntohl(pRawMsg->dwSize));
272 continue; // Bad packet, wait for next
273 }
274
275 // Create message object from raw message
276 pMsg = new CSCPMessage(pRawMsg);
277 m_pMessageQueue->Put(pMsg);
278 }
279 if (iErr < 0)
280 WriteLog(MSG_SESSION_CLOSED, EVENTLOG_WARNING_TYPE, "e", WSAGetLastError());
281 free(pRawMsg);
282
283 // Notify other threads to exit
284 m_pSendQueue->Clear();
285 m_pSendQueue->Put(INVALID_POINTER_VALUE);
286 m_pMessageQueue->Clear();
287 m_pMessageQueue->Put(INVALID_POINTER_VALUE);
288 m_pUpdateQueue->Clear();
289 m_pUpdateQueue->Put(INVALID_POINTER_VALUE);
290
291 // Wait for other threads to finish
292 ThreadJoin(m_hWriteThread);
293 ThreadJoin(m_hProcessingThread);
294 ThreadJoin(m_hUpdateThread);
295
296 // Remove all locks created by this session
297 RemoveAllSessionLocks(m_dwIndex);
298 for(i = 0; i < m_dwOpenDCIListSize; i++)
299 {
300 pObject = FindObjectById(m_pOpenDCIList[i]);
301 if (pObject != NULL)
302 if (pObject->Type() == OBJECT_NODE)
303 ((Node *)pObject)->UnlockDCIList(m_dwIndex);
304 }
305
306 DebugPrintf("Session closed\n");
307 }
308
309
310 //
311 // WriteThread()
312 //
313
314 void ClientSession::WriteThread(void)
315 {
316 CSCP_MESSAGE *pMsg;
317 char szBuffer[128];
318
319 while(1)
320 {
321 pMsg = (CSCP_MESSAGE *)m_pSendQueue->GetOrBlock();
322 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
323 break;
324
325 DebugPrintf("Sending message %s\n", CSCPMessageCodeName(ntohs(pMsg->wCode), szBuffer));
326 if (send(m_hSocket, (const char *)pMsg, ntohl(pMsg->dwSize), 0) <= 0)
327 {
328 safe_free(pMsg);
329 break;
330 }
331 safe_free(pMsg);
332 }
333 }
334
335
336 //
337 // Update processing thread
338 //
339
340 void ClientSession::UpdateThread(void)
341 {
342 UPDATE_INFO *pUpdate;
343 CSCPMessage msg;
344
345 while(1)
346 {
347 pUpdate = (UPDATE_INFO *)m_pUpdateQueue->GetOrBlock();
348 if (pUpdate == INVALID_POINTER_VALUE) // Session termination indicator
349 break;
350
351 switch(pUpdate->dwCategory)
352 {
353 case INFO_CAT_EVENT:
354 MutexLock(m_mutexSendEvents, INFINITE);
355 m_pSendQueue->Put(CreateRawCSCPMessage(CMD_EVENT, 0, sizeof(NXC_EVENT), pUpdate->pData, NULL));
356 MutexUnlock(m_mutexSendEvents);
357 free(pUpdate->pData);
358 break;
359 case INFO_CAT_OBJECT_CHANGE:
360 MutexLock(m_mutexSendObjects, INFINITE);
361 msg.SetCode(CMD_OBJECT_UPDATE);
362 msg.SetId(0);
363 ((NetObj *)pUpdate->pData)->CreateMessage(&msg);
364 SendMessage(&msg);
365 MutexUnlock(m_mutexSendObjects);
366 msg.DeleteAllVariables();
367 ((NetObj *)pUpdate->pData)->DecRefCount();
368 break;
369 case INFO_CAT_ALARM:
370 MutexLock(m_mutexSendAlarms, INFINITE);
371 msg.SetCode(CMD_ALARM_UPDATE);
372 msg.SetId(0);
373 msg.SetVariable(VID_NOTIFICATION_CODE, pUpdate->dwCode);
374 FillAlarmInfoMessage(&msg, (NXC_ALARM *)pUpdate->pData);
375 SendMessage(&msg);
376 MutexUnlock(m_mutexSendAlarms);
377 msg.DeleteAllVariables();
378 free(pUpdate->pData);
379 break;
380 case INFO_CAT_ACTION:
381 MutexLock(m_mutexSendActions, INFINITE);
382 msg.SetCode(CMD_ACTION_DB_UPDATE);
383 msg.SetId(0);
384 msg.SetVariable(VID_NOTIFICATION_CODE, pUpdate->dwCode);
385 msg.SetVariable(VID_ACTION_ID, ((NXC_ACTION *)pUpdate->pData)->dwId);
386 if (pUpdate->dwCode != NX_NOTIFY_ACTION_DELETED)
387 FillActionInfoMessage(&msg, (NXC_ACTION *)pUpdate->pData);
388 SendMessage(&msg);
389 MutexUnlock(m_mutexSendActions);
390 msg.DeleteAllVariables();
391 free(pUpdate->pData);
392 break;
393 default:
394 break;
395 }
396
397 free(pUpdate);
398 }
399 }
400
401
402 //
403 // Message processing thread
404 //
405
406 void ClientSession::ProcessingThread(void)
407 {
408 CSCPMessage *pMsg;
409 char szBuffer[128];
410
411 while(1)
412 {
413 pMsg = (CSCPMessage *)m_pMessageQueue->GetOrBlock();
414 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
415 break;
416
417 DebugPrintf("Received message %s\n", CSCPMessageCodeName(pMsg->GetCode(), szBuffer));
418 if ((m_iState != STATE_AUTHENTICATED) && (pMsg->GetCode() != CMD_LOGIN))
419 {
420 delete pMsg;
421 continue;
422 }
423
424 switch(pMsg->GetCode())
425 {
426 case CMD_LOGIN:
427 Login(pMsg);
428 break;
429 case CMD_GET_OBJECTS:
430 SendAllObjects(pMsg->GetId());
431 break;
432 case CMD_GET_EVENTS:
433 SendAllEvents(pMsg->GetId());
434 break;
435 case CMD_GET_CONFIG_VARLIST:
436 SendAllConfigVars();
437 break;
438 case CMD_OPEN_EVENT_DB:
439 SendEventDB(pMsg->GetId());
440 break;
441 case CMD_CLOSE_EVENT_DB:
442 CloseEventDB(pMsg->GetId());
443 break;
444 case CMD_SET_EVENT_INFO:
445 SetEventInfo(pMsg);
446 break;
447 case CMD_MODIFY_OBJECT:
448 ModifyObject(pMsg);
449 break;
450 case CMD_SET_OBJECT_MGMT_STATUS:
451 ChangeObjectMgmtStatus(pMsg);
452 break;
453 case CMD_LOAD_USER_DB:
454 SendUserDB(pMsg->GetId());
455 break;
456 case CMD_CREATE_USER:
457 CreateUser(pMsg);
458 break;
459 case CMD_UPDATE_USER:
460 UpdateUser(pMsg);
461 break;
462 case CMD_DELETE_USER:
463 DeleteUser(pMsg);
464 break;
465 case CMD_LOCK_USER_DB:
466 LockUserDB(pMsg->GetId(), TRUE);
467 break;
468 case CMD_UNLOCK_USER_DB:
469 LockUserDB(pMsg->GetId(), FALSE);
470 break;
471 case CMD_SET_PASSWORD:
472 SetPassword(pMsg);
473 break;
474 case CMD_GET_NODE_DCI_LIST:
475 OpenNodeDCIList(pMsg);
476 break;
477 case CMD_UNLOCK_NODE_DCI_LIST:
478 CloseNodeDCIList(pMsg);
479 break;
480 case CMD_CREATE_NEW_DCI:
481 case CMD_MODIFY_NODE_DCI:
482 case CMD_DELETE_NODE_DCI:
483 ModifyNodeDCI(pMsg);
484 break;
485 case CMD_COPY_DCI:
486 CopyDCI(pMsg);
487 break;
488 case CMD_GET_DCI_DATA:
489 GetCollectedData(pMsg);
490 break;
491 case CMD_OPEN_EPP:
492 OpenEPP(pMsg->GetId());
493 break;
494 case CMD_CLOSE_EPP:
495 CloseEPP(pMsg->GetId());
496 break;
497 case CMD_SAVE_EPP:
498 SaveEPP(pMsg);
499 break;
500 case CMD_EPP_RECORD:
501 ProcessEPPRecord(pMsg);
502 break;
503 case CMD_GET_MIB_LIST:
504 SendMIBList(pMsg->GetId());
505 break;
506 case CMD_GET_MIB:
507 SendMIB(pMsg);
508 break;
509 case CMD_CREATE_OBJECT:
510 CreateObject(pMsg);
511 break;
512 case CMD_BIND_OBJECT:
513 ChangeObjectBinding(pMsg, TRUE);
514 break;
515 case CMD_UNBIND_OBJECT:
516 ChangeObjectBinding(pMsg, FALSE);
517 break;
518 case CMD_GET_EVENT_NAMES:
519 SendEventNames(pMsg->GetId());
520 break;
521 case CMD_GET_IMAGE_LIST:
522 SendImageCatalogue(this, pMsg->GetId(), pMsg->GetVariableShort(VID_IMAGE_FORMAT));
523 break;
524 case CMD_LOAD_IMAGE_FILE:
525 SendImageFile(this, pMsg->GetId(), pMsg->GetVariableLong(VID_IMAGE_ID),
526 pMsg->GetVariableShort(VID_IMAGE_FORMAT));
527 break;
528 case CMD_GET_DEFAULT_IMAGE_LIST:
529 SendDefaultImageList(this, pMsg->GetId());
530 break;
531 case CMD_GET_ALL_ALARMS:
532 SendAllAlarms(pMsg->GetId(), pMsg->GetVariableShort(VID_IS_ACK));
533 break;
534 case CMD_GET_ALARM:
535 break;
536 case CMD_ACK_ALARM:
537 AcknowlegeAlarm(pMsg);
538 break;
539 case CMD_DELETE_ALARM:
540 break;
541 case CMD_LOCK_ACTION_DB:
542 LockActionDB(pMsg->GetId(), TRUE);
543 break;
544 case CMD_UNLOCK_ACTION_DB:
545 LockActionDB(pMsg->GetId(), FALSE);
546 break;
547 case CMD_CREATE_ACTION:
548 CreateAction(pMsg);
549 break;
550 case CMD_MODIFY_ACTION:
551 UpdateAction(pMsg);
552 break;
553 case CMD_DELETE_ACTION:
554 DeleteAction(pMsg);
555 break;
556 case CMD_LOAD_ACTIONS:
557 SendAllActions(pMsg->GetId());
558 break;
559 case CMD_GET_CONTAINER_CAT_LIST:
560 SendContainerCategories(pMsg->GetId());
561 break;
562 case CMD_DELETE_OBJECT:
563 DeleteObject(pMsg);
564 break;
565 case CMD_POLL_NODE:
566 ForcedNodePoll(pMsg);
567 break;
568 case CMD_TRAP:
569 OnTrap(pMsg);
570 break;
571 default:
572 break;
573 }
574 delete pMsg;
575 }
576 }
577
578
579 //
580 // Authenticate client
581 //
582
583 void ClientSession::Login(CSCPMessage *pRequest)
584 {
585 CSCPMessage msg;
586 BYTE szPassword[SHA1_DIGEST_SIZE];
587 char szLogin[MAX_USER_NAME], szBuffer[32];
588
589 // Prepare responce message
590 msg.SetCode(CMD_LOGIN_RESP);
591 msg.SetId(pRequest->GetId());
592
593 if (m_iState != STATE_AUTHENTICATED)
594 {
595
596 pRequest->GetVariableStr(VID_LOGIN_NAME, szLogin, MAX_USER_NAME);
597 pRequest->GetVariableBinary(VID_PASSWORD, szPassword, SHA1_DIGEST_SIZE);
598
599 if (AuthenticateUser(szLogin, szPassword, &m_dwUserId, &m_dwSystemAccess))
600 {
601 m_iState = STATE_AUTHENTICATED;
602 sprintf(m_szUserName, "%s@%s", szLogin, IpToStr(m_dwHostAddr, szBuffer));
603 msg.SetVariable(VID_RCC, RCC_SUCCESS);
604 DebugPrintf("User %s authenticated\n", m_szUserName);
605 }
606 else
607 {
608 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
609 }
610 }
611 else
612 {
613 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
614 }
615
616 // Send responce
617 SendMessage(&msg);
618 }
619
620
621 //
622 // Send event configuration to client
623 //
624
625 void ClientSession::SendEventDB(DWORD dwRqId)
626 {
627 DB_ASYNC_RESULT hResult;
628 CSCPMessage msg;
629 char szBuffer[1024];
630
631 // Prepare responce message
632 msg.SetCode(CMD_REQUEST_COMPLETED);
633 msg.SetId(dwRqId);
634
635 if (!CheckSysAccessRights(SYSTEM_ACCESS_VIEW_EVENT_DB))
636 {
637 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
638 SendMessage(&msg);
639 }
640 else if (!LockComponent(CID_EVENT_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
641 {
642 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
643 msg.SetVariable(VID_LOCKED_BY, szBuffer);
644 SendMessage(&msg);
645 }
646 else
647 {
648 m_dwFlags |= CSF_EVENT_DB_LOCKED;
649 m_dwFlags &= ~CSF_EVENT_DB_MODIFIED;
650
651 msg.SetVariable(VID_RCC, RCC_SUCCESS);
652 SendMessage(&msg);
653 msg.DeleteAllVariables();
654
655 // Prepare data message
656 msg.SetCode(CMD_EVENT_DB_RECORD);
657 msg.SetId(dwRqId);
658
659 hResult = DBAsyncSelect(g_hCoreDB, "SELECT event_id,name,severity,flags,message,description FROM events");
660 if (hResult != NULL)
661 {
662 while(DBFetch(hResult))
663 {
664 msg.SetVariable(VID_EVENT_ID, DBGetFieldAsyncULong(hResult, 0));
665 msg.SetVariable(VID_NAME, DBGetFieldAsync(hResult, 1, szBuffer, 1024));
666 msg.SetVariable(VID_SEVERITY, DBGetFieldAsyncULong(hResult, 2));
667 msg.SetVariable(VID_FLAGS, DBGetFieldAsyncULong(hResult, 3));
668
669 DBGetFieldAsync(hResult, 4, szBuffer, 1024);
670 DecodeSQLString(szBuffer);
671 msg.SetVariable(VID_MESSAGE, szBuffer);
672
673 DBGetFieldAsync(hResult, 5, szBuffer, 1024);
674 DecodeSQLString(szBuffer);
675 msg.SetVariable(VID_DESCRIPTION, szBuffer);
676
677 SendMessage(&msg);
678 msg.DeleteAllVariables();
679 }
680 DBFreeAsyncResult(hResult);
681 }
682
683 // Send end-of-list indicator
684 msg.SetCode(CMD_EVENT_DB_EOF);
685 SendMessage(&msg);
686 }
687 }
688
689
690 //
691 // Close event configuration database
692 //
693
694 void ClientSession::CloseEventDB(DWORD dwRqId)
695 {
696 CSCPMessage msg;
697
698 msg.SetCode(CMD_REQUEST_COMPLETED);
699 msg.SetId(dwRqId);
700
701 if (m_dwFlags & CSF_EVENT_DB_LOCKED)
702 {
703 // Check if event configuration DB has been modified
704 if (m_dwFlags & CSF_EVENT_DB_MODIFIED)
705 {
706 ReloadEvents();
707
708 // Notify clients on event database change
709 EnumerateClientSessions(NotifyClient, (void *)NX_NOTIFY_EVENTDB_CHANGED);
710 }
711 UnlockComponent(CID_EVENT_DB);
712 m_dwFlags &= ~CSF_EVENT_DB_LOCKED;
713 msg.SetVariable(VID_RCC, RCC_SUCCESS);
714 }
715 else
716 {
717 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
718 }
719 SendMessage(&msg);
720 }
721
722
723 //
724 // Send all objects to client
725 //
726
727 void ClientSession::SendAllObjects(DWORD dwRqId)
728 {
729 DWORD i;
730 CSCPMessage msg;
731
732 // Send confirmation message
733 msg.SetCode(CMD_REQUEST_COMPLETED);
734 msg.SetId(dwRqId);
735 msg.SetVariable(VID_RCC, RCC_SUCCESS);
736 SendMessage(&msg);
737 msg.DeleteAllVariables();
738
739 MutexLock(m_mutexSendObjects, INFINITE);
740
741 // Prepare message
742 msg.SetCode(CMD_OBJECT);
743
744 // Send objects, one per message
745 ObjectsGlobalLock();
746 for(i = 0; i < g_dwIdIndexSize; i++)
747 if (g_pIndexById[i].pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
748 {
749 g_pIndexById[i].pObject->CreateMessage(&msg);
750 SendMessage(&msg);
751 msg.DeleteAllVariables();
752 }
753 ObjectsGlobalUnlock();
754
755 // Send end of list notification
756 msg.SetCode(CMD_OBJECT_LIST_END);
757 SendMessage(&msg);
758
759 MutexUnlock(m_mutexSendObjects);
760 }
761
762
763 //
764 // Send all events to client
765 //
766
767 void ClientSession::SendAllEvents(DWORD dwRqId)
768 {
769 CSCPMessage msg;
770 DB_ASYNC_RESULT hResult;
771 NXC_EVENT event;
772
773 // Send confirmation message
774 msg.SetCode(CMD_REQUEST_COMPLETED);
775 msg.SetId(dwRqId);
776 msg.SetVariable(VID_RCC, RCC_SUCCESS);
777 SendMessage(&msg);
778 msg.DeleteAllVariables();
779
780 MutexLock(m_mutexSendEvents, INFINITE);
781
782 // Retrieve events from database
783 hResult = DBAsyncSelect(g_hCoreDB, "SELECT event_id,event_timestamp,event_source,"
784 "event_severity,event_message FROM event_log "
785 "ORDER BY event_timestamp");
786 if (hResult != NULL)
787 {
788 // Send events, one per message
789 while(DBFetch(hResult))
790 {
791 event.dwEventId = htonl(DBGetFieldAsyncULong(hResult, 0));
792 event.dwTimeStamp = htonl(DBGetFieldAsyncULong(hResult, 1));
793 event.dwSourceId = htonl(DBGetFieldAsyncULong(hResult, 2));
794 event.dwSeverity = htonl(DBGetFieldAsyncULong(hResult, 3));
795 DBGetFieldAsync(hResult, 4, event.szMessage, MAX_EVENT_MSG_LENGTH);
796 DecodeSQLString(event.szMessage);
797 m_pSendQueue->Put(CreateRawCSCPMessage(CMD_EVENT, dwRqId, sizeof(NXC_EVENT), &event, NULL));
798 }
799 DBFreeAsyncResult(hResult);
800 }
801
802 // Send end of list notification
803 msg.SetCode(CMD_EVENT_LIST_END);
804 SendMessage(&msg);
805
806 MutexUnlock(m_mutexSendEvents);
807 }
808
809
810 //
811 // Send all configuration variables to client
812 //
813
814 void ClientSession::SendAllConfigVars(void)
815 {
816 DWORD i, dwNumRecords;
817 CSCPMessage msg;
818 DB_RESULT hResult;
819
820 // Check user rights
821 if ((m_dwUserId != 0) && ((m_dwSystemAccess & SYSTEM_ACCESS_VIEW_CONFIG) == 0))
822 {
823 // Access denied
824 msg.SetCode(CMD_CONFIG_VARLIST_END);
825 msg.SetVariable(VID_ERROR, (DWORD)1);
826 SendMessage(&msg);
827 }
828 else
829 {
830 // Prepare message
831 msg.SetCode(CMD_CONFIG_VARIABLE);
832
833 // Retrieve configuration variables from database
834 hResult = DBSelect(g_hCoreDB, "SELECT var_name,var_value FROM config");
835 if (hResult != NULL)
836 {
837 // Send events, one per message
838 dwNumRecords = DBGetNumRows(hResult);
839 for(i = 0; i < dwNumRecords; i++)
840 {
841 msg.SetVariable(VID_NAME, DBGetField(hResult, i, 0));
842 msg.SetVariable(VID_VALUE, DBGetField(hResult, i, 1));
843 SendMessage(&msg);
844 msg.DeleteAllVariables();
845 }
846 DBFreeResult(hResult);
847 }
848
849 // Send end of list notification
850 msg.SetCode(CMD_CONFIG_VARLIST_END);
851 msg.SetVariable(VID_ERROR, (DWORD)0);
852 SendMessage(&msg);
853 }
854 }
855
856
857 //
858 // Close session forcibly
859 //
860
861 void ClientSession::Kill(void)
862 {
863 // We shutdown socket connection, which will cause
864 // read thread to stop, and other threads will follow
865 shutdown(m_hSocket, 2);
866 }
867
868
869 //
870 // Handler for new events
871 //
872
873 void ClientSession::OnNewEvent(Event *pEvent)
874 {
875 UPDATE_INFO *pUpdate;
876
877 if (m_iState == STATE_AUTHENTICATED)
878 {
879 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
880 pUpdate->dwCategory = INFO_CAT_EVENT;
881 pUpdate->pData = malloc(sizeof(NXC_EVENT));
882 pEvent->PrepareMessage((NXC_EVENT *)pUpdate->pData);
883 m_pUpdateQueue->Put(pUpdate);
884 }
885 }
886
887
888 //
889 // Handler for object changes
890 //
891
892 void ClientSession::OnObjectChange(NetObj *pObject)
893 {
894 UPDATE_INFO *pUpdate;
895
896 if (m_iState == STATE_AUTHENTICATED)
897 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
898 {
899 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
900 pUpdate->dwCategory = INFO_CAT_OBJECT_CHANGE;
901 pUpdate->pData = pObject;
902 pObject->IncRefCount();
903 m_pUpdateQueue->Put(pUpdate);
904 }
905 }
906
907
908 //
909 // Send notification message to server
910 //
911
912 void ClientSession::Notify(DWORD dwCode, DWORD dwData)
913 {
914 CSCPMessage msg;
915
916 msg.SetCode(CMD_NOTIFY);
917 msg.SetVariable(VID_NOTIFICATION_CODE, dwCode);
918 msg.SetVariable(VID_NOTIFICATION_DATA, dwData);
919 SendMessage(&msg);
920 }
921
922
923 //
924 // Update event template
925 //
926
927 void ClientSession::SetEventInfo(CSCPMessage *pRequest)
928 {
929 CSCPMessage msg;
930
931 // Prepare reply message
932 msg.SetCode(CMD_REQUEST_COMPLETED);
933 msg.SetId(pRequest->GetId());
934
935 // Check if we have event configuration database opened
936 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
937 {
938 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
939 }
940 else
941 {
942 // Check access rights
943 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
944 {
945 char szQuery[4096], szName[MAX_EVENT_NAME];
946 DWORD dwEventId;
947 BOOL bEventExist = FALSE;
948 DB_RESULT hResult;
949
950 // Check if event with specific id exists
951 dwEventId = pRequest->GetVariableLong(VID_EVENT_ID);
952 sprintf(szQuery, "SELECT event_id FROM events WHERE event_id=%ld", dwEventId);
953 hResult = DBSelect(g_hCoreDB, szQuery);
954 if (hResult != NULL)
955 {
956 if (DBGetNumRows(hResult) > 0)
957 bEventExist = TRUE;
958 DBFreeResult(hResult);
959 }
960
961 // Prepare and execute SQL query
962 pRequest->GetVariableStr(VID_NAME, szName, MAX_EVENT_NAME);
963 if (IsValidObjectName(szName))
964 {
965 char szMessage[MAX_DB_STRING], *pszDescription, *pszEscMsg, *pszEscDescr;
966
967 pRequest->GetVariableStr(VID_MESSAGE, szMessage, MAX_DB_STRING);
968 pszEscMsg = EncodeSQLString(szMessage);
969
970 pszDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
971 pszEscDescr = EncodeSQLString(pszDescription);
972 safe_free(pszDescription);
973
974 if (bEventExist)
975 {
976 sprintf(szQuery, "UPDATE events SET name='%s',severity=%ld,flags=%ld,message='%s',description='%s' WHERE event_id=%ld",
977 szName, pRequest->GetVariableLong(VID_SEVERITY), pRequest->GetVariableLong(VID_FLAGS),
978 pszEscMsg, pszEscDescr, dwEventId);
979 }
980 else
981 {
982 sprintf(szQuery, "INSERT INTO events SET event_id,name,severity,flags,message,description VALUES (%ld,'%s',%ld,%ld,'%s','%s')",
983 dwEventId, szName, pRequest->GetVariableLong(VID_SEVERITY),
984 pRequest->GetVariableLong(VID_FLAGS), pszEscMsg, pszEscDescr);
985 }
986
987 free(pszEscMsg);
988 free(pszEscDescr);
989
990 if (DBQuery(g_hCoreDB, szQuery))
991 {
992 msg.SetVariable(VID_RCC, RCC_SUCCESS);
993 m_dwFlags |= CSF_EVENT_DB_MODIFIED;
994 }
995 else
996 {
997 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
998 }
999 }
1000 else
1001 {
1002 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
1003 }
1004 }
1005 else
1006 {
1007 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1008 }
1009 }
1010
1011 // Send responce
1012 SendMessage(&msg);
1013 }
1014
1015
1016 //
1017 // Modify object
1018 //
1019
1020 void ClientSession::ModifyObject(CSCPMessage *pRequest)
1021 {
1022 DWORD dwObjectId, dwResult = RCC_SUCCESS;
1023 NetObj *pObject;
1024 CSCPMessage msg;
1025
1026 // Prepare reply message
1027 msg.SetCode(CMD_REQUEST_COMPLETED);
1028 msg.SetId(pRequest->GetId());
1029
1030 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1031 pObject = FindObjectById(dwObjectId);
1032 if (pObject != NULL)
1033 {
1034 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1035 {
1036 // If user attempts to change object's ACL, check
1037 // if he has OBJECT_ACCESS_CONTROL permission
1038 if (pRequest->IsVariableExist(VID_ACL_SIZE))
1039 if (!pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CONTROL))
1040 dwResult = RCC_ACCESS_DENIED;
1041
1042 // If allowed, change object and set completion code
1043 if (dwResult != RCC_ACCESS_DENIED)
1044 dwResult = pObject->ModifyFromMessage(pRequest);
1045 msg.SetVariable(VID_RCC, dwResult);
1046 }
1047 else
1048 {
1049 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1050 }
1051 }
1052 else
1053 {
1054 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1055 }
1056
1057 // Send responce
1058 SendMessage(&msg);
1059 }
1060
1061
1062 //
1063 // Send users database to client
1064 //
1065
1066 void ClientSession::SendUserDB(DWORD dwRqId)
1067 {
1068 CSCPMessage msg;
1069 DWORD i;
1070
1071 // Prepare responce message
1072 msg.SetCode(CMD_REQUEST_COMPLETED);
1073 msg.SetId(dwRqId);
1074 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1075 SendMessage(&msg);
1076
1077 // Send users
1078 msg.SetCode(CMD_USER_DATA);
1079 for(i = 0; i < g_dwNumUsers; i++)
1080 {
1081 FillUserInfoMessage(&msg, &g_pUserList[i]);
1082 SendMessage(&msg);
1083 msg.DeleteAllVariables();
1084 }
1085
1086 // Send groups
1087 msg.SetCode(CMD_GROUP_DATA);
1088 for(i = 0; i < g_dwNumGroups; i++)
1089 {
1090 FillGroupInfoMessage(&msg, &g_pGroupList[i]);
1091 SendMessage(&msg);
1092 msg.DeleteAllVariables();
1093 }
1094
1095 // Send end-of-database notification
1096 msg.SetCode(CMD_USER_DB_EOF);
1097 SendMessage(&msg);
1098 }
1099
1100
1101 //
1102 // Create new user
1103 //
1104
1105 void ClientSession::CreateUser(CSCPMessage *pRequest)
1106 {
1107 CSCPMessage msg;
1108
1109 // Prepare responce message
1110 msg.SetCode(CMD_REQUEST_COMPLETED);
1111 msg.SetId(pRequest->GetId());
1112
1113 // Check user rights
1114 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
1115 {
1116 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1117 }
1118 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1119 {
1120 // User database have to be locked before any
1121 // changes to user database can be made
1122 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1123 }
1124 else
1125 {
1126 DWORD dwResult, dwUserId;
1127 BOOL bIsGroup;
1128 char szUserName[MAX_USER_NAME];
1129
1130 pRequest->GetVariableStr(VID_USER_NAME, szUserName, MAX_USER_NAME);
1131 if (IsValidObjectName(szUserName))
1132 {
1133 bIsGroup = pRequest->GetVariableShort(VID_IS_GROUP);
1134 dwResult = CreateNewUser(szUserName, bIsGroup, &dwUserId);
1135 msg.SetVariable(VID_RCC, dwResult);
1136 if (dwResult == RCC_SUCCESS)
1137 msg.SetVariable(VID_USER_ID, dwUserId); // Send id of new user to client
1138 }
1139 else
1140 {
1141 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
1142 }
1143 }
1144
1145 // Send responce
1146 SendMessage(&msg);
1147 }
1148
1149
1150 //
1151 // Update existing user's data
1152 //
1153
1154 void ClientSession::UpdateUser(CSCPMessage *pRequest)
1155 {
1156 CSCPMessage msg;
1157
1158 // Prepare responce message
1159 msg.SetCode(CMD_REQUEST_COMPLETED);
1160 msg.SetId(pRequest->GetId());
1161
1162 // Check user rights
1163 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
1164 {
1165 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1166 }
1167 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1168 {
1169 // User database have to be locked before any
1170 // changes to user database can be made
1171 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1172 }
1173 else
1174 {
1175 DWORD dwUserId, dwResult;
1176
1177 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1178 if (dwUserId & GROUP_FLAG)
1179 {
1180 NMS_USER_GROUP group;
1181 DWORD i, dwId;
1182
1183 group.dwId = dwUserId;
1184 pRequest->GetVariableStr(VID_USER_DESCRIPTION, group.szDescription, MAX_USER_DESCR);
1185 pRequest->GetVariableStr(VID_USER_NAME, group.szName, MAX_USER_NAME);
1186 group.wFlags = pRequest->GetVariableShort(VID_USER_FLAGS);
1187 group.wSystemRights = pRequest->GetVariableShort(VID_USER_SYS_RIGHTS);
1188 group.dwNumMembers = pRequest->GetVariableLong(VID_NUM_MEMBERS);
1189 group.pMembers = (DWORD *)malloc(sizeof(DWORD) * group.dwNumMembers);
1190 for(i = 0, dwId = VID_GROUP_MEMBER_BASE; i < group.dwNumMembers; i++, dwId++)
1191 group.pMembers[i] = pRequest->GetVariableLong(dwId);
1192 dwResult = ModifyGroup(&group);
1193 safe_free(group.pMembers);
1194 }
1195 else
1196 {
1197 NMS_USER user;
1198
1199 user.dwId = dwUserId;
1200 pRequest->GetVariableStr(VID_USER_DESCRIPTION, user.szDescription, MAX_USER_DESCR);
1201 pRequest->GetVariableStr(VID_USER_FULL_NAME, user.szFullName, MAX_USER_FULLNAME);
1202 pRequest->GetVariableStr(VID_USER_NAME, user.szName, MAX_USER_NAME);
1203 user.wFlags = pRequest->GetVariableShort(VID_USER_FLAGS);
1204 user.wSystemRights = pRequest->GetVariableShort(VID_USER_SYS_RIGHTS);
1205 dwResult = ModifyUser(&user);
1206 }
1207 msg.SetVariable(VID_RCC, dwResult);
1208 }
1209
1210 // Send responce
1211 SendMessage(&msg);
1212 }
1213
1214
1215 //
1216 // Delete user
1217 //
1218
1219 void ClientSession::DeleteUser(CSCPMessage *pRequest)
1220 {
1221 CSCPMessage msg;
1222 DWORD dwUserId;
1223
1224 // Prepare responce message
1225 msg.SetCode(CMD_REQUEST_COMPLETED);
1226 msg.SetId(pRequest->GetId());
1227
1228 // Check user rights
1229 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
1230 {
1231 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1232 }
1233 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1234 {
1235 // User database have to be locked before any
1236 // changes to user database can be made
1237 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1238 }
1239 else
1240 {
1241 // Get Id of user to be deleted
1242 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1243
1244 if (dwUserId != 0)
1245 {
1246 DWORD dwResult;
1247
1248 dwResult = DeleteUserFromDB(dwUserId);
1249 msg.SetVariable(VID_RCC, dwResult);
1250 }
1251 else
1252 {
1253 // Nobody can delete system administrator account
1254 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1255 }
1256 }
1257
1258 // Send responce
1259 SendMessage(&msg);
1260 }
1261
1262
1263 //
1264 // Lock/unlock user database
1265 //
1266
1267 void ClientSession::LockUserDB(DWORD dwRqId, BOOL bLock)
1268 {
1269 CSCPMessage msg;
1270 char szBuffer[256];
1271
1272 // Prepare responce message
1273 msg.SetCode(CMD_REQUEST_COMPLETED);
1274 msg.SetId(dwRqId);
1275
1276 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS)
1277 {
1278 if (bLock)
1279 {
1280 if (!LockComponent(CID_USER_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
1281 {
1282 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
1283 msg.SetVariable(VID_LOCKED_BY, szBuffer);
1284 }
1285 else
1286 {
1287 m_dwFlags |= CSF_USER_DB_LOCKED;
1288 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1289 }
1290 }
1291 else
1292 {
1293 if (m_dwFlags & CSF_USER_DB_LOCKED)
1294 {
1295 UnlockComponent(CID_USER_DB);
1296 m_dwFlags &= ~CSF_USER_DB_LOCKED;
1297 }
1298 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1299 }
1300 }
1301 else
1302 {
1303 // Current user has no rights for user account management
1304 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1305 }
1306
1307 // Send responce
1308 SendMessage(&msg);
1309 }
1310
1311
1312 //
1313 // Notify client on user database update
1314 //
1315
1316 void ClientSession::OnUserDBUpdate(int iCode, DWORD dwUserId, NMS_USER *pUser, NMS_USER_GROUP *pGroup)
1317 {
1318 CSCPMessage msg;
1319
1320 if (m_iState == STATE_AUTHENTICATED)
1321 {
1322 msg.SetCode(CMD_USER_DB_UPDATE);
1323 msg.SetId(0);
1324 msg.SetVariable(VID_UPDATE_TYPE, (WORD)iCode);
1325
1326 switch(iCode)
1327 {
1328 case USER_DB_CREATE:
1329 msg.SetVariable(VID_USER_ID, dwUserId);
1330 if (dwUserId & GROUP_FLAG)
1331 msg.SetVariable(VID_USER_NAME, pGroup->szName);
1332 else
1333 msg.SetVariable(VID_USER_NAME, pUser->szName);
1334 break;
1335 case USER_DB_MODIFY:
1336 if (dwUserId & GROUP_FLAG)
1337 FillGroupInfoMessage(&msg, pGroup);
1338 else
1339 FillUserInfoMessage(&msg, pUser);
1340 break;
1341 default:
1342 msg.SetVariable(VID_USER_ID, dwUserId);
1343 break;
1344 }
1345
1346 SendMessage(&msg);
1347 }
1348 }
1349
1350
1351 //
1352 // Change management status for the object
1353 //
1354
1355 void ClientSession::ChangeObjectMgmtStatus(CSCPMessage *pRequest)
1356 {
1357 CSCPMessage msg;
1358 DWORD dwObjectId;
1359 NetObj *pObject;
1360
1361 // Prepare responce message
1362 msg.SetCode(CMD_REQUEST_COMPLETED);
1363 msg.SetId(pRequest->GetId());
1364
1365 // Get object id and check access rights
1366 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1367 pObject = FindObjectById(dwObjectId);
1368 if (pObject != NULL)
1369 {
1370 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1371 {
1372 BOOL bIsManaged;
1373
1374 bIsManaged = (BOOL)pRequest->GetVariableShort(VID_MGMT_STATUS);
1375 pObject->SetMgmtStatus(bIsManaged);
1376 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1377 }
1378 else
1379 {
1380 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1381 }
1382 }
1383 else
1384 {
1385 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1386 }
1387
1388 // Send responce
1389 SendMessage(&msg);
1390 }
1391
1392
1393 //
1394 // Set user's password
1395 //
1396
1397 void ClientSession::SetPassword(CSCPMessage *pRequest)
1398 {
1399 CSCPMessage msg;
1400 DWORD dwUserId;
1401
1402 // Prepare responce message
1403 msg.SetCode(CMD_REQUEST_COMPLETED);
1404 msg.SetId(pRequest->GetId());
1405
1406 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1407
1408 if (((m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS) &&
1409 !((dwUserId == 0) && (m_dwUserId != 0))) || // Only administrator can change password for UID 0
1410 (dwUserId == m_dwUserId)) // User can change password for itself
1411 {
1412 DWORD dwResult;
1413 BYTE szPassword[SHA1_DIGEST_SIZE];
1414
1415 pRequest->GetVariableBinary(VID_PASSWORD, szPassword, SHA1_DIGEST_SIZE);
1416 dwResult = SetUserPassword(dwUserId, szPassword);
1417 msg.SetVariable(VID_RCC, dwResult);
1418 }
1419 else
1420 {
1421 // Current user has no rights to change password for specific user
1422 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1423 }
1424
1425 // Send responce
1426 SendMessage(&msg);
1427 }
1428
1429
1430 //
1431 // Send node's DCIs to client and lock data collection settings
1432 //
1433
1434 void ClientSession::OpenNodeDCIList(CSCPMessage *pRequest)
1435 {
1436 CSCPMessage msg;
1437 DWORD dwObjectId;
1438 NetObj *pObject;
1439 BOOL bSuccess = FALSE;
1440
1441 // Prepare responce message
1442 msg.SetCode(CMD_REQUEST_COMPLETED);
1443 msg.SetId(pRequest->GetId());
1444
1445 // Get node id and check object class and access rights
1446 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1447 pObject = FindObjectById(dwObjectId);
1448 if (pObject != NULL)
1449 {
1450 if ((pObject->Type() == OBJECT_NODE) ||
1451 (pObject->Type() == OBJECT_TEMPLATE))
1452 {
1453 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1454 {
1455 // Try to lock DCI list
1456 bSuccess = ((Template *)pObject)->LockDCIList(m_dwIndex);
1457 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_COMPONENT_LOCKED);
1458
1459 // Modify list of open nodes DCI lists
1460 if (bSuccess)
1461 {
1462 m_pOpenDCIList = (DWORD *)realloc(m_pOpenDCIList, sizeof(DWORD) * (m_dwOpenDCIListSize + 1));
1463 m_pOpenDCIList[m_dwOpenDCIListSize] = dwObjectId;
1464 m_dwOpenDCIListSize++;
1465 }
1466 }
1467 else
1468 {
1469 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1470 }
1471 }
1472 else
1473 {
1474 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1475 }
1476 }
1477 else
1478 {
1479 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1480 }
1481
1482 // Send responce
1483 SendMessage(&msg);
1484
1485 // If DCI list was successfully locked, send it to client
1486 if (bSuccess)
1487 ((Template *)pObject)->SendItemsToClient(this, pRequest->GetId());
1488 }
1489
1490
1491 //
1492 // Unlock node's data collection settings
1493 //
1494
1495 void ClientSession::CloseNodeDCIList(CSCPMessage *pRequest)
1496 {
1497 CSCPMessage msg;
1498 DWORD dwObjectId;
1499 NetObj *pObject;
1500
1501 // Prepare responce message
1502 msg.SetCode(CMD_REQUEST_COMPLETED);
1503 msg.SetId(pRequest->GetId());
1504
1505 // Get node id and check object class and access rights
1506 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1507 pObject = FindObjectById(dwObjectId);
1508 if (pObject != NULL)
1509 {
1510 if ((pObject->Type() == OBJECT_NODE) ||
1511 (pObject->Type() == OBJECT_TEMPLATE))
1512 {
1513 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1514 {
1515 BOOL bSuccess;
1516
1517 // Try to unlock DCI list
1518 bSuccess = ((Template *)pObject)->UnlockDCIList(m_dwIndex);
1519 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_OUT_OF_STATE_REQUEST);
1520
1521 // Modify list of open nodes DCI lists
1522 if (bSuccess)
1523 {
1524 DWORD i;
1525
1526 for(i = 0; i < m_dwOpenDCIListSize; i++)
1527 if (m_pOpenDCIList[i] == dwObjectId)
1528 {
1529 m_dwOpenDCIListSize--;
1530 memmove(&m_pOpenDCIList[i], &m_pOpenDCIList[i + 1],
1531 sizeof(DWORD) * (m_dwOpenDCIListSize - i));
1532 break;
1533 }
1534 }
1535 }
1536 else
1537 {
1538 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1539 }
1540 }
1541 else
1542 {
1543 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1544 }
1545 }
1546 else
1547 {
1548 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1549 }
1550
1551 // Send responce
1552 SendMessage(&msg);
1553 }
1554
1555
1556 //
1557 // Create, modify, or delete data collection item for node
1558 //
1559
1560 void ClientSession::ModifyNodeDCI(CSCPMessage *pRequest)
1561 {
1562 CSCPMessage msg;
1563 DWORD dwObjectId;
1564 NetObj *pObject;
1565
1566 // Prepare responce message
1567 msg.SetCode(CMD_REQUEST_COMPLETED);
1568 msg.SetId(pRequest->GetId());
1569
1570 // Get node id and check object class and access rights
1571 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1572 pObject = FindObjectById(dwObjectId);
1573 if (pObject != NULL)
1574 {
1575 if ((pObject->Type() == OBJECT_NODE) ||
1576 (pObject->Type() == OBJECT_TEMPLATE))
1577 {
1578 if (((Template *)pObject)->IsLockedBySession(m_dwIndex))
1579 {
1580 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1581 {
1582 DWORD i, dwItemId, dwNumMaps, *pdwMapId, *pdwMapIndex;
1583 DCItem *pItem;
1584 BOOL bSuccess;
1585
1586 switch(pRequest->GetCode())
1587 {
1588 case CMD_CREATE_NEW_DCI:
1589 // Create dummy DCI
1590 pItem = new DCItem(CreateUniqueId(IDG_ITEM), "no name", DS_INTERNAL,
1591 DCI_DT_INT, 60, 30, (Node *)pObject);
1592 pItem->SetStatus(ITEM_STATUS_DISABLED);
1593 if (((Template *)pObject)->AddItem(pItem))
1594 {
1595 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1596 // Return new item id to client
1597 msg.SetVariable(VID_DCI_ID, pItem->Id());
1598 }
1599 else // Unable to add item to node
1600 {
1601 delete pItem;
1602 msg.SetVariable(VID_RCC, RCC_DUPLICATE_DCI);
1603 }
1604 break;
1605 case CMD_MODIFY_NODE_DCI:
1606 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
1607 bSuccess = ((Template *)pObject)->UpdateItem(dwItemId, pRequest, &dwNumMaps,
1608 &pdwMapIndex, &pdwMapId);
1609 if (bSuccess)
1610 {
1611 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1612
1613 // Send index to id mapping for newly created thresholds to client
1614 msg.SetVariable(VID_DCI_NUM_MAPS, dwNumMaps);
1615 for(i = 0; i < dwNumMaps; i++)
1616 {
1617 pdwMapId[i] = htonl(pdwMapId[i]);
1618 pdwMapIndex[i] = htonl(pdwMapIndex[i]);
1619 }
1620 msg.SetVariable(VID_DCI_MAP_IDS, (BYTE *)pdwMapId, sizeof(DWORD) * dwNumMaps);
1621 msg.SetVariable(VID_DCI_MAP_INDEXES, (BYTE *)pdwMapIndex, sizeof(DWORD) * dwNumMaps);
1622 safe_free(pdwMapId);
1623 safe_free(pdwMapIndex);
1624 }
1625 else
1626 {
1627 msg.SetVariable(VID_RCC, RCC_INVALID_DCI_ID);
1628 }
1629 break;
1630 case CMD_DELETE_NODE_DCI:
1631 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
1632 bSuccess = ((Template *)pObject)->DeleteItem(dwItemId);
1633 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_INVALID_DCI_ID);
1634 break;
1635 }
1636 if (bSuccess)
1637 ((Template *)pObject)->SetDCIModificationFlag();
1638 }
1639 else // User doesn't have MODIFY rights on object
1640 {
1641 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1642 }
1643 }
1644 else // Nodes DCI list not locked by this session
1645 {
1646 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1647 }
1648 }
1649 else // Object is not a node
1650 {
1651 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1652 }
1653 }
1654 else // No object with given ID
1655 {
1656 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1657 }
1658
1659 // Send responce
1660 SendMessage(&msg);
1661 }
1662
1663
1664 //
1665 // Copy DCI from one node or template to another
1666 //
1667
1668 void ClientSession::CopyDCI(CSCPMessage *pRequest)
1669 {
1670 CSCPMessage msg;
1671 NetObj *pSource, *pDestination;
1672
1673 // Prepare responce message
1674 msg.SetCode(CMD_REQUEST_COMPLETED);
1675 msg.SetId(pRequest->GetId());
1676
1677 // Get source and destination
1678 pSource = FindObjectById(pRequest->GetVariableLong(VID_SOURCE_OBJECT_ID));
1679 pDestination = FindObjectById(pRequest->GetVariableLong(VID_DESTINATION_OBJECT_ID));
1680 if ((pSource != NULL) && (pDestination != NULL))
1681 {
1682 // Check object types
1683 if (((pSource->Type() == OBJECT_NODE) || (pSource->Type() == OBJECT_TEMPLATE)) &&
1684 (pDestination->Type() == OBJECT_NODE))
1685 {
1686 if (((Template *)pSource)->IsLockedBySession(m_dwIndex))
1687 {
1688 // Check access rights
1689 if ((pSource->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ)) &&
1690 (pDestination->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)))
1691 {
1692 // Attempt to lock destination's DCI list
1693 if (((Template *)pDestination)->LockDCIList(m_dwIndex))
1694 {
1695 DWORD i, *pdwItemList, dwNumItems;
1696 const DCItem *pSrcItem;
1697 DCItem *pDstItem;
1698 int iErrors = 0;
1699
1700 // Get list of items to be copied
1701 dwNumItems = pRequest->GetVariableLong(VID_NUM_ITEMS);
1702 pdwItemList = (DWORD *)malloc(sizeof(DWORD) * dwNumItems);
1703 pRequest->GetVariableInt32Array(VID_ITEM_LIST, dwNumItems, pdwItemList);
1704
1705 // Copy items
1706 for(i = 0; i < dwNumItems; i++)
1707 {
1708 pSrcItem = ((Template *)pSource)->GetItemById(pdwItemList[i]);
1709 if (pSrcItem != NULL)
1710 {
1711 pDstItem = new DCItem(pSrcItem);
1712 pDstItem->SetId(CreateUniqueId(IDG_ITEM));
1713 pDstItem->SetStatus(ITEM_STATUS_ACTIVE);
1714 pDstItem->BindToNode((Template *)pDestination);
1715 if (!((Template *)pDestination)->AddItem(pDstItem))
1716 {
1717 delete pDstItem;
1718 iErrors++;
1719 }
1720 }
1721 else
1722 {
1723 iErrors++;
1724 }
1725 }
1726
1727 // Cleanup
1728 free(pdwItemList);
1729 ((Template *)pDestination)->UnlockDCIList(m_dwIndex);
1730 msg.SetVariable(VID_RCC, (iErrors == 0) ? RCC_SUCCESS : RCC_DCI_COPY_ERRORS);
1731 }
1732 else // Destination's DCI list already locked by someone else
1733 {
1734 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
1735 }
1736 }
1737 else // User doesn't have enough rights on object(s)
1738 {
1739 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1740 }
1741 }
1742 else // Source node DCI list not locked by this session
1743 {
1744 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1745 }
1746 }
1747 else // Object(s) is not a node
1748 {
1749 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1750 }
1751 }
1752 else // No object(s) with given ID
1753 {
1754 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1755 }
1756
1757 // Send responce
1758 SendMessage(&msg);
1759 }
1760
1761
1762 //
1763 // Get collected data
1764 //
1765
1766 void ClientSession::GetCollectedData(CSCPMessage *pRequest)
1767 {
1768 CSCPMessage msg;
1769 DWORD dwObjectId;
1770 NetObj *pObject;
1771 BOOL bSuccess = FALSE;
1772 static DWORD m_dwRowSize[] = { 8, 8, 12, 12, 260, 12 };
1773
1774 // Prepare responce message
1775 msg.SetCode(CMD_REQUEST_COMPLETED);
1776 msg.SetId(pRequest->GetId());
1777
1778 // Get node id and check object class and access rights
1779 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1780 pObject = FindObjectById(dwObjectId);
1781 if (pObject != NULL)
1782 {
1783 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1784 {
1785 DB_ASYNC_RESULT hResult;
1786 DWORD dwItemId, dwMaxRows, dwTimeFrom, dwTimeTo;
1787 DWORD dwAllocatedRows = 100, dwNumRows = 0;
1788 char szQuery[512], szCond[256];
1789 int iPos = 0, iType;
1790 DCI_DATA_HEADER *pData = NULL;
1791 DCI_DATA_ROW *pCurr;
1792
1793 // Send CMD_REQUEST_COMPLETED message
1794 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1795 SendMessage(&msg);
1796
1797 // Get request parameters
1798 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
1799 dwMaxRows = pRequest->GetVariableLong(VID_MAX_ROWS);
1800 dwTimeFrom = pRequest->GetVariableLong(VID_TIME_FROM);
1801 dwTimeTo = pRequest->GetVariableLong(VID_TIME_TO);
1802
1803 szCond[0] = 0;
1804 if (dwTimeFrom != 0)
1805 {
1806 sprintf(szCond, " AND idata_timestamp>=%d", dwTimeFrom);
1807 iPos = strlen(szCond);
1808 }
1809 if (dwTimeTo != 0)
1810 {
1811 sprintf(&szCond[iPos], " AND idata_timestamp<=%d", dwTimeTo);
1812 }
1813
1814 sprintf(szQuery, "SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC",
1815 dwObjectId, dwItemId, szCond);
1816 hResult = DBAsyncSelect(g_hCoreDB, szQuery);
1817 if (hResult != NULL)
1818 {
1819 // Get item's data type to determine actual row size
1820 iType = ((Node *)pObject)->GetItemType(dwItemId);
1821
1822 // Allocate initial memory block and prepare data header
1823 pData = (DCI_DATA_HEADER *)malloc(dwAllocatedRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER));
1824 pData->dwDataType = htonl((DWORD)iType);
1825 pData->dwItemId = htonl(dwItemId);
1826
1827 // Fill memory block with records
1828 pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER));
1829 while(DBFetch(hResult))
1830 {
1831 if ((dwMaxRows > 0) && (dwNumRows >= dwMaxRows))
1832 break;
1833
1834 // Extend buffer if we are at the end
1835 if (dwNumRows == dwAllocatedRows)
1836 {
1837 dwAllocatedRows += 50;
1838 pData = (DCI_DATA_HEADER *)realloc(pData,
1839 dwAllocatedRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER));
1840 pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER) + m_dwRowSize[iType] * dwNumRows);
1841 }
1842
1843 dwNumRows++;
1844
1845 pCurr->dwTimeStamp = htonl(DBGetFieldAsyncULong(hResult, 0));
1846 switch(iType)
1847 {
1848 case DCI_DT_INT:
1849 case DCI_DT_UINT:
1850 pCurr->value.dwInteger = htonl(DBGetFieldAsyncULong(hResult, 1));
1851 break;
1852 case DCI_DT_INT64:
1853 case DCI_DT_UINT64:
1854 pCurr->value.qwInt64 = htonq(DBGetFieldAsyncUQuad(hResult, 1));
1855 break;
1856 case DCI_DT_FLOAT:
1857 pCurr->value.dFloat = htond(DBGetFieldAsyncDouble(hResult, 1));
1858 break;
1859 case DCI_DT_STRING:
1860 DBGetFieldAsync(hResult, 1, pCurr->value.szString, MAX_DCI_STRING_VALUE);
1861 break;
1862 }
1863 pCurr = (DCI_DATA_ROW *)(((char *)pCurr) + m_dwRowSize[iType]);
1864 }
1865 DBFreeAsyncResult(hResult);
1866 pData->dwNumRows = htonl(dwNumRows);
1867
1868 // Prepare and send raw message with fetched data
1869 m_pSendQueue->Put(
1870 CreateRawCSCPMessage(CMD_DCI_DATA, pRequest->GetId(),
1871 dwNumRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER),
1872 pData, NULL));
1873 free(pData);
1874 bSuccess = TRUE;
1875 }
1876 else
1877 {
1878 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
1879 }
1880 }
1881 else
1882 {
1883 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1884 }
1885 }
1886 else // No object with given ID
1887 {
1888 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1889 }
1890
1891 // Send responce
1892 if (!bSuccess)
1893 SendMessage(&msg);
1894 }
1895
1896
1897 //
1898 // Open event processing policy
1899 //
1900
1901 void ClientSession::OpenEPP(DWORD dwRqId)
1902 {
1903 CSCPMessage msg;
1904 char szBuffer[256];
1905 BOOL bSuccess = FALSE;
1906
1907 // Prepare responce message
1908 msg.SetCode(CMD_REQUEST_COMPLETED);
1909 msg.SetId(dwRqId);
1910
1911 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
1912 {
1913 if (!LockComponent(CID_EPP, m_dwIndex, m_szUserName, NULL, szBuffer))
1914 {
1915 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
1916 msg.SetVariable(VID_LOCKED_BY, szBuffer);
1917 }
1918 else
1919 {
1920 m_dwFlags |= CSF_EPP_LOCKED;
1921 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1922 msg.SetVariable(VID_NUM_RULES, g_pEventPolicy->NumRules());
1923 bSuccess = TRUE;
1924 }
1925 }
1926 else
1927 {
1928 // Current user has no rights for event policy management
1929 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1930 }
1931
1932 // Send responce
1933 SendMessage(&msg);
1934
1935 // Send policy to client
1936 if (bSuccess)
1937 g_pEventPolicy->SendToClient(this, dwRqId);
1938 }
1939
1940
1941 //
1942 // Close event processing policy
1943 //
1944
1945 void ClientSession::CloseEPP(DWORD dwRqId)
1946 {
1947 CSCPMessage msg;
1948
1949 // Prepare responce message
1950 msg.SetCode(CMD_REQUEST_COMPLETED);
1951 msg.SetId(dwRqId);
1952
1953 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
1954 {
1955 if (m_dwFlags & CSF_EPP_LOCKED)
1956 {
1957 UnlockComponent(CID_EPP);
1958 m_dwFlags &= ~CSF_EPP_LOCKED;
1959 }
1960 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1961 }
1962 else
1963 {
1964 // Current user has no rights for event policy management
1965 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1966 }
1967
1968 // Send responce
1969 SendMessage(&msg);
1970 }
1971
1972
1973 //
1974 // Save event processing policy
1975 //
1976
1977 void ClientSession::SaveEPP(CSCPMessage *pRequest)
1978 {
1979 CSCPMessage msg;
1980
1981 // Prepare responce message
1982 msg.SetCode(CMD_REQUEST_COMPLETED);
1983 msg.SetId(pRequest->GetId());
1984
1985 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
1986 {
1987 if (m_dwFlags & CSF_EPP_LOCKED)
1988 {
1989 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1990 m_dwNumRecordsToUpload = pRequest->GetVariableLong(VID_NUM_RULES);
1991 m_dwRecordsUploaded = 0;
1992 if (m_dwNumRecordsToUpload == 0)
1993 {
1994 g_pEventPolicy->ReplacePolicy(0, NULL);
1995 g_pEventPolicy->SaveToDB();
1996 }
1997 else
1998 {
1999 m_dwFlags |= CSF_EPP_UPLOAD;
2000 m_ppEPPRuleList = (EPRule **)malloc(sizeof(EPRule *) * m_dwNumRecordsToUpload);
2001 memset(m_ppEPPRuleList, 0, sizeof(EPRule *) * m_dwNumRecordsToUpload);
2002 }
2003 DebugPrintf("Accepted EPP upload request for %d rules\n", m_dwNumRecordsToUpload);
2004 }
2005 else
2006 {
2007 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2008 }
2009 }
2010 else
2011 {
2012 // Current user has no rights for event policy management
2013 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2014 }
2015
2016 // Send responce
2017 SendMessage(&msg);
2018 }
2019
2020
2021 //
2022 // Process EPP rule received from client
2023 //
2024
2025 void ClientSession::ProcessEPPRecord(CSCPMessage *pRequest)
2026 {
2027 if (!(m_dwFlags & CSF_EPP_LOCKED))
2028 {
2029 CSCPMessage msg;
2030
2031 msg.SetCode(CMD_REQUEST_COMPLETED);
2032 msg.SetId(pRequest->GetId());
2033 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2034 SendMessage(&msg);
2035 }
2036 else
2037 {
2038 if (m_dwRecordsUploaded < m_dwNumRecordsToUpload)
2039 {
2040 m_ppEPPRuleList[m_dwRecordsUploaded] = new EPRule(pRequest);
2041 m_dwRecordsUploaded++;
2042 if (m_dwRecordsUploaded == m_dwNumRecordsToUpload)
2043 {
2044 CSCPMessage msg;
2045
2046 // All records received, replace event policy...
2047 DebugPrintf("Replacing event processing policy with a new one at %p (%d rules)\n",
2048 m_ppEPPRuleList, m_dwNumRecordsToUpload);
2049 g_pEventPolicy->ReplacePolicy(m_dwNumRecordsToUpload, m_ppEPPRuleList);
2050 g_pEventPolicy->SaveToDB();
2051 m_ppEPPRuleList = NULL;
2052
2053 // ... and send final confirmation
2054 msg.SetCode(CMD_REQUEST_COMPLETED);
2055 msg.SetId(pRequest->GetId());
2056 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2057 SendMessage(&msg);
2058
2059 m_dwFlags &= ~CSF_EPP_UPLOAD;
2060 }
2061 }
2062 }
2063 }
2064
2065
2066 //
2067 // Send list of available MIB files to client
2068 //
2069
2070 void ClientSession::SendMIBList(DWORD dwRqId)
2071 {
2072 CSCPMessage msg;
2073 DWORD dwId1, dwId2, dwNumFiles;
2074 DIR *dir;
2075 int iBufPos;
2076 #ifdef _WIN32
2077 struct direct *dptr;
2078 #else
2079 struct dirent *dptr;
2080 #endif
2081 char szBuffer[MAX_PATH];
2082 BYTE md5Hash[MD5_DIGEST_SIZE];
2083
2084 // Prepare responce message
2085 msg.SetCode(CMD_MIB_LIST);
2086 msg.SetId(dwRqId);
2087
2088 // Read directory
2089 dwNumFiles = 0;
2090 strcpy(szBuffer, g_szDataDir);
2091 strcat(szBuffer, DDIR_MIBS);
2092 dir = opendir(szBuffer);
2093 if (dir != NULL)
2094 {
2095 strcat(szBuffer, FS_PATH_SEPARATOR);
2096 iBufPos = strlen(szBuffer);
2097 dwId1 = VID_MIB_NAME_BASE;
2098 dwId2 = VID_MIB_HASH_BASE;
2099 while((dptr = readdir(dir)) != NULL)
2100 {
2101 if (dptr->d_name[0] == '.')
2102 continue;
2103
2104 strcpy(&szBuffer[iBufPos], dptr->d_name);
2105 if (CalculateFileMD5Hash(szBuffer, md5Hash))
2106 {
2107 msg.SetVariable(dwId1++, dptr->d_name);
2108 msg.SetVariable(dwId2++, md5Hash, MD5_DIGEST_SIZE);
2109 dwNumFiles++;
2110 }
2111 }
2112 closedir(dir);
2113 }
2114
2115 msg.SetVariable(VID_NUM_MIBS, dwNumFiles);
2116
2117 // Send responce
2118 SendMessage(&msg);
2119 }
2120
2121
2122 //
2123 // Send requested MIB file to client
2124 //
2125
2126 void ClientSession::SendMIB(CSCPMessage *pRequest)
2127 {
2128 CSCPMessage msg;
2129 BYTE *pFile;
2130 DWORD dwFileSize;
2131 char szBuffer[MAX_PATH], szMIB[MAX_PATH];
2132
2133 // Prepare responce message
2134 msg.SetCode(CMD_MIB);
2135 msg.SetId(pRequest->GetId());
2136
2137 // Get name of the requested file
2138 pRequest->GetVariableStr(VID_MIB_NAME, szMIB, MAX_PATH);
2139
2140 // Load file into memory
2141 strcpy(szBuffer, g_szDataDir);
2142 strcat(szBuffer, DDIR_MIBS);
2143 #ifdef _WIN32
2144 strcat(szBuffer, "\\");
2145 #else
2146 strcat(szBuffer, "/");
2147 #endif
2148 strcat(szBuffer, szMIB);
2149 pFile = LoadFile(szBuffer, &dwFileSize);
2150 if (pFile != NULL)
2151 {
2152 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2153 msg.SetVariable(VID_MIB_FILE_SIZE, dwFileSize);
2154 msg.SetVariable(VID_MIB_FILE, pFile, dwFileSize);
2155 free(pFile);
2156 }
2157 else
2158 {
2159 msg.SetVariable(VID_RCC, RCC_SYSTEM_FAILURE);
2160 }
2161
2162 // Send responce
2163 SendMessage(&msg);
2164 }
2165
2166
2167 //
2168 // Send list of event name/identifier pairs
2169 //
2170
2171 void ClientSession::SendEventNames(DWORD dwRqId)
2172 {
2173 CSCPMessage msg;
2174 DB_RESULT hResult;
2175
2176 msg.SetCode(CMD_EVENT_NAME_LIST);
2177 msg.SetId(dwRqId);
2178 hResult = DBSelect(g_hCoreDB, "SELECT event_id,name,severity FROM events");
2179 if (hResult != NULL)
2180 {
2181 DWORD i, dwNumEvents;
2182 NXC_EVENT_NAME *pList;
2183
2184 dwNumEvents = DBGetNumRows(hResult);
2185 msg.SetVariable(VID_NUM_EVENTS, dwNumEvents);
2186 if (dwNumEvents > 0)
2187 {
2188 pList = (NXC_EVENT_NAME *)malloc(sizeof(NXC_EVENT_NAME) * dwNumEvents);
2189 for(i = 0; i < dwNumEvents; i++)
2190 {
2191 pList[i].dwEventId = htonl(DBGetFieldULong(hResult, i, 0));
2192 pList[i].dwSeverity = htonl(DBGetFieldLong(hResult, i, 2));
2193 strcpy(pList[i].szName, DBGetField(hResult, i, 1));
2194 }
2195 msg.SetVariable(VID_EVENT_NAME_TABLE, (BYTE *)pList, sizeof(NXC_EVENT_NAME) * dwNumEvents);
2196 free(pList);
2197 }
2198 DBFreeResult(hResult);
2199 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2200 }
2201 else
2202 {
2203 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
2204 }
2205 SendMessage(&msg);
2206 }
2207
2208
2209 //
2210 // Create new object
2211 //
2212
2213 void ClientSession::CreateObject(CSCPMessage *pRequest)
2214 {
2215 CSCPMessage msg;
2216 NetObj *pObject, *pParent;
2217 int iClass;
2218 char *pDescription, szObjectName[MAX_OBJECT_NAME];
2219 DWORD dwIpAddr;
2220 BOOL bParentAlwaysValid = FALSE;
2221
2222 // Prepare responce message
2223 msg.SetCode(CMD_REQUEST_COMPLETED);
2224 msg.SetId(pRequest->GetId());
2225
2226 iClass = pRequest->GetVariableShort(VID_OBJECT_CLASS);
2227
2228 // Find parent object
2229 pParent = FindObjectById(pRequest->GetVariableLong(VID_PARENT_ID));
2230 if ((pParent == NULL) && (iClass == OBJECT_NODE))
2231 {
2232 dwIpAddr = pRequest->GetVariableLong(VID_IP_ADDRESS);
2233 pParent = FindSubnetForNode(dwIpAddr);
2234 bParentAlwaysValid = TRUE;
2235 }
2236 if ((pParent != NULL) || (iClass == OBJECT_NODE))
2237 {
2238 // User should have create access to parent object
2239 if ((pParent != NULL) ?
2240 pParent->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CREATE) :
2241 g_pEntireNet->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CREATE))
2242 {
2243 // Parent object should be of valid type
2244 if (bParentAlwaysValid || IsValidParentClass(iClass, (pParent != NULL) ? pParent->Type() : -1))
2245 {
2246 pRequest->GetVariableStr(VID_OBJECT_NAME, szObjectName, MAX_OBJECT_NAME);
2247 if (IsValidObjectName(szObjectName))
2248 {
2249 // Create new object
2250 switch(iClass)
2251 {
2252 case OBJECT_NODE:
2253 pObject = PollNewNode(dwIpAddr, pRequest->GetVariableLong(VID_IP_NETMASK),
2254 DF_DEFAULT, szObjectName);
2255 break;
2256 case OBJECT_CONTAINER:
2257 pDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
2258 pObject = new Container(szObjectName,
2259 pRequest->GetVariableLong(VID_CATEGORY),
2260 pDescription);
2261 safe_free(pDescription);
2262 NetObjInsert(pObject, TRUE);
2263 break;
2264 case OBJECT_TEMPLATEGROUP:
2265 pDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
2266 pObject = new TemplateGroup(szObjectName, pDescription);
2267 safe_free(pDescription);
2268 NetObjInsert(pObject, TRUE);
2269 break;
2270 case OBJECT_TEMPLATE:
2271 pObject = new Template;
2272 pObject->SetName(szObjectName);
2273 NetObjInsert(pObject, TRUE);
2274 break;
2275 }
2276
2277 // If creation was successful do binding
2278 if (pObject != NULL)
2279 {
2280 pParent->AddChild(pObject);
2281 pObject->AddParent(pParent);
2282 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2283 msg.SetVariable(VID_OBJECT_ID, pObject->Id());
2284 }
2285 else
2286 {
2287 msg.SetVariable(VID_RCC, RCC_OBJECT_CREATION_FAILED);
2288 }
2289 }
2290 else
2291 {
2292 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
2293 }
2294 }
2295 else
2296 {
2297 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2298 }
2299 }
2300 else
2301 {
2302 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2303 }
2304 }
2305 else
2306 {
2307 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2308 }
2309
2310 // Send responce
2311 SendMessage(&msg);
2312 }
2313
2314
2315 //
2316 // Bind/unbind object
2317 //
2318
2319 void ClientSession::ChangeObjectBinding(CSCPMessage *pRequest, BOOL bBind)
2320 {
2321 CSCPMessage msg;
2322 NetObj *pParent, *pChild;
2323
2324 // Prepare responce message
2325 msg.SetCode(CMD_REQUEST_COMPLETED);
2326 msg.SetId(pRequest->GetId());
2327
2328 // Get parent and child objects
2329 pParent = FindObjectById(pRequest->GetVariableLong(VID_PARENT_ID));
2330 pChild = FindObjectById(pRequest->GetVariableLong(VID_CHILD_ID));
2331
2332 // Check access rights and change binding
2333 if ((pParent != NULL) && (pChild != NULL))
2334 {
2335 // User should have modify access to both objects
2336 if ((pParent->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)) &&
2337 (pChild->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)))
2338 {
2339 // Parent object should be container or service root
2340 if ((pParent->Type() == OBJECT_CONTAINER) ||
2341 (pParent->Type() == OBJECT_SERVICEROOT))
2342 {
2343 if (bBind)
2344 {
2345 // Prevent loops
2346 if (!pChild->IsChild(pParent->Id()))
2347 {
2348 pParent->AddChild(pChild);
2349 pChild->AddParent(pParent);
2350 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2351 }
2352 else
2353 {
2354 msg.SetVariable(VID_RCC, RCC_OBJECT_LOOP);
2355 }
2356 }
2357 else
2358 {
2359 pParent->DeleteChild(pChild);
2360 pChild->DeleteParent(pParent);
2361 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2362 }
2363 }
2364 else
2365 {
2366 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2367 }
2368 }
2369 else
2370 {
2371 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2372 }
2373 }
2374 else
2375 {
2376 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2377 }
2378
2379 // Send responce
2380 SendMessage(&msg);
2381 }
2382
2383
2384 //
2385 // Delete object
2386 //
2387
2388 void ClientSession::DeleteObject(CSCPMessage *pRequest)
2389 {
2390 CSCPMessage msg;
2391 NetObj *pObject;
2392
2393 // Prepare responce message
2394 msg.SetCode(CMD_REQUEST_COMPLETED);
2395 msg.SetId(pRequest->GetId());
2396
2397 // Find object to be deleted
2398 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
2399 if (pObject != NULL)
2400 {
2401 // Check if it is a built-in object, like "Entire Network"
2402 if (pObject->Id() >= 10)
2403 {
2404 // Check access rights
2405 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_DELETE))
2406 {
2407 pObject->Delete();
2408 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2409 }
2410 else
2411 {
2412 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2413 }
2414 }
2415 else
2416 {
2417 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2418 }
2419 }
2420 else
2421 {
2422 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2423 }
2424
2425 // Send responce
2426 SendMessage(&msg);
2427 }
2428
2429
2430 //
2431 // Process changes in alarms
2432 //
2433
2434 void ClientSession::OnAlarmUpdate(DWORD dwCode, NXC_ALARM *pAlarm)
2435 {
2436 UPDATE_INFO *pUpdate;
2437 NetObj *pObject;
2438
2439 if (m_iState == STATE_AUTHENTICATED)
2440 {
2441 pObject = FindObjectById(pAlarm->dwSourceObject);
2442 if (pObject != NULL)
2443 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ_ALARMS))
2444 {
2445 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
2446 pUpdate->dwCategory = INFO_CAT_ALARM;
2447 pUpdate->dwCode = dwCode;
2448 pUpdate->pData = nx_memdup(pAlarm, sizeof(NXC_ALARM));
2449 m_pUpdateQueue->Put(pUpdate);
2450 }
2451 }
2452 }
2453
2454
2455 //
2456 // Send all alarms to client
2457 //
2458
2459 void ClientSession::SendAllAlarms(DWORD dwRqId, BOOL bIncludeAck)
2460 {
2461 MutexLock(m_mutexSendAlarms, INFINITE);
2462 g_alarmMgr.SendAlarmsToClient(dwRqId, bIncludeAck, this);
2463 MutexUnlock(m_mutexSendAlarms);
2464 }
2465
2466
2467 //
2468 // Acknowlege alarm
2469 //
2470
2471 void ClientSession::AcknowlegeAlarm(CSCPMessage *pRequest)
2472 {
2473 CSCPMessage msg;
2474 NetObj *pObject;
2475 DWORD dwAlarmId;
2476
2477 // Prepare responce message
2478 msg.SetCode(CMD_REQUEST_COMPLETED);
2479 msg.SetId(pRequest->GetId());
2480
2481 // Get alarm id and it's source object
2482 dwAlarmId = pRequest->GetVariableLong(VID_ALARM_ID);
2483 pObject = g_alarmMgr.GetAlarmSourceObject(dwAlarmId);
2484 if (pObject != NULL)
2485 {
2486 // User should have "acknowlege alarm" right to the object
2487 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_ACK_ALARMS))
2488 {
2489 g_alarmMgr.AckById(dwAlarmId, m_dwUserId);
2490 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2491 }
2492 else
2493 {
2494 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2495 }
2496 }
2497 else
2498 {
2499 // Normally, for existing alarms pObject will not be NULL,
2500 // so we assume that alarm id is invalid
2501 msg.SetVariable(VID_RCC, RCC_INVALID_ALARM_ID);
2502 }
2503
2504 // Send responce
2505 SendMessage(&msg);
2506 }
2507
2508
2509 //
2510 // Lock/unlock action configuration database
2511 //
2512
2513 void ClientSession::LockActionDB(DWORD dwRqId, BOOL bLock)
2514 {
2515 CSCPMessage msg;
2516 char szBuffer[256];
2517
2518 // Prepare responce message
2519 msg.SetCode(CMD_REQUEST_COMPLETED);
2520 msg.SetId(dwRqId);
2521
2522 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS)
2523 {
2524 if (bLock)
2525 {
2526 if (!LockComponent(CID_ACTION_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
2527 {
2528 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
2529 msg.SetVariable(VID_LOCKED_BY, szBuffer);
2530 }
2531 else
2532 {
2533 m_dwFlags |= CSF_ACTION_DB_LOCKED;
2534 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2535 }
2536 }
2537 else
2538 {
2539 if (m_dwFlags & CSF_ACTION_DB_LOCKED)
2540 {
2541 UnlockComponent(CID_ACTION_DB);
2542 m_dwFlags &= ~CSF_ACTION_DB_LOCKED;
2543 }
2544 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2545 }
2546 }
2547 else
2548 {
2549 // Current user has no rights for action management
2550 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2551 }
2552
2553 // Send responce
2554 SendMessage(&msg);
2555 }
2556
2557
2558 //
2559 // Create new action
2560 //
2561
2562 void ClientSession::CreateAction(CSCPMessage *pRequest)
2563 {
2564 CSCPMessage msg;
2565
2566 // Prepare responce message
2567 msg.SetCode(CMD_REQUEST_COMPLETED);
2568 msg.SetId(pRequest->GetId());
2569
2570 // Check user rights
2571 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
2572 {
2573 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2574 }
2575 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
2576 {
2577 // Action database have to be locked before any
2578 // changes can be made
2579 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2580 }
2581 else
2582 {
2583 DWORD dwResult, dwActionId;
2584 char szActionName[MAX_USER_NAME];
2585
2586 pRequest->GetVariableStr(VID_ACTION_NAME, szActionName, MAX_OBJECT_NAME);
2587 if (IsValidObjectName(szActionName))
2588 {
2589 dwResult = CreateNewAction(szActionName, &dwActionId);
2590 msg.SetVariable(VID_RCC, dwResult);
2591 if (dwResult == RCC_SUCCESS)
2592 msg.SetVariable(VID_ACTION_ID, dwActionId); // Send id of new action to client
2593 }
2594 else
2595 {
2596 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
2597 }
2598 }
2599
2600 // Send responce
2601 SendMessage(&msg);
2602 }
2603
2604
2605 //
2606 // Update existing action's data
2607 //
2608
2609 void ClientSession::UpdateAction(CSCPMessage *pRequest)
2610 {
2611 CSCPMessage msg;
2612
2613 // Prepare responce message
2614 msg.SetCode(CMD_REQUEST_COMPLETED);
2615 msg.SetId(pRequest->GetId());
2616
2617 // Check user rights
2618 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
2619 {
2620 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2621 }
2622 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
2623 {
2624 // Action database have to be locked before any
2625 // changes can be made
2626 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2627 }
2628 else
2629 {
2630 msg.SetVariable(VID_RCC, ModifyActionFromMessage(pRequest));
2631 }
2632
2633 // Send responce
2634 SendMessage(&msg);
2635 }
2636
2637
2638 //
2639 // Delete action
2640 //
2641
2642 void ClientSession::DeleteAction(CSCPMessage *pRequest)
2643 {
2644 CSCPMessage msg;
2645 DWORD dwActionId;
2646
2647 // Prepare responce message
2648 msg.SetCode(CMD_REQUEST_COMPLETED);
2649 msg.SetId(pRequest->GetId());
2650
2651 // Check user rights
2652 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
2653 {
2654 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2655 }
2656 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
2657 {
2658 // Action database have to be locked before any
2659 // changes can be made
2660 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2661 }
2662 else
2663 {
2664 // Get Id of action to be deleted
2665 dwActionId = pRequest->GetVariableLong(VID_ACTION_ID);
2666 msg.SetVariable(VID_RCC, DeleteActionFromDB(dwActionId));
2667 }
2668
2669 // Send responce
2670 SendMessage(&msg);
2671 }
2672
2673
2674 //
2675 // Process changes in actions
2676 //
2677
2678 void ClientSession::OnActionDBUpdate(DWORD dwCode, NXC_ACTION *pAction)
2679 {
2680 UPDATE_INFO *pUpdate;
2681
2682 if (m_iState == STATE_AUTHENTICATED)
2683 {
2684 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS)
2685 {
2686 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
2687 pUpdate->dwCategory = INFO_CAT_ACTION;
2688 pUpdate->dwCode = dwCode;
2689 pUpdate->pData = nx_memdup(pAction, sizeof(NXC_ACTION));
2690 m_pUpdateQueue->Put(pUpdate);
2691 }
2692 }
2693 }
2694
2695
2696 //
2697 // Send all actions to client
2698 //
2699
2700 void ClientSession::SendAllActions(DWORD dwRqId)
2701 {
2702 CSCPMessage msg;
2703
2704 // Prepare responce message
2705 msg.SetCode(CMD_REQUEST_COMPLETED);
2706 msg.SetId(dwRqId);
2707
2708 // Check user rights
2709 if ((m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS) ||
2710 (m_dwSystemAccess & SYSTEM_ACCESS_EPP))
2711 {
2712 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2713 SendMessage(&msg);
2714 MutexLock(m_mutexSendActions, INFINITE);
2715 SendActionsToClient(this, dwRqId);
2716 MutexUnlock(m_mutexSendActions);
2717 }
2718 else
2719 {
2720 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2721 SendMessage(&msg);
2722 }
2723 }
2724
2725
2726 //
2727 // Send list of configured container categories to client
2728 //
2729
2730 void ClientSession::SendContainerCategories(DWORD dwRqId)
2731 {
2732 CSCPMessage msg;
2733 DWORD i;
2734
2735 // Prepare responce message
2736 msg.SetCode(CMD_CONTAINER_CAT_DATA);
2737 msg.SetId(dwRqId);
2738
2739 for(i = 0; i < g_dwNumCategories; i++)
2740 {
2741 msg.SetVariable(VID_CATEGORY_ID, g_pContainerCatList[i].dwCatId);
2742 msg.SetVariable(VID_CATEGORY_NAME, g_pContainerCatList[i].szName);
2743 msg.SetVariable(VID_IMAGE_ID, g_pContainerCatList[i].dwImageId);
2744 msg.SetVariable(VID_DESCRIPTION, g_pContainerCatList[i].pszDescription);
2745 SendMessage(&msg);
2746 msg.DeleteAllVariables();
2747 }
2748
2749 // Send end-of-list indicator
2750 msg.SetVariable(VID_CATEGORY_ID, (DWORD)0);
2751 SendMessage(&msg);
2752 }
2753
2754
2755 //
2756 // Perform a forced node poll
2757 //
2758
2759 void ClientSession::ForcedNodePoll(CSCPMessage *pRequest)
2760 {
2761 CSCPMessage msg;
2762 POLLER_START_DATA *pData;
2763 NetObj *pObject;
2764
2765 pData = (POLLER_START_DATA *)malloc(sizeof(POLLER_START_DATA));
2766 pData->pSession = this;
2767 MutexLock(m_mutexPollerInit, INFINITE);
2768
2769 // Prepare responce message
2770 pData->dwRqId = pRequest->GetId();
2771 msg.SetCode(CMD_POLLING_INFO);
2772 msg.SetId(pData->dwRqId);
2773
2774 // Get polling type
2775 pData->iPollType = pRequest->GetVariableShort(VID_POLL_TYPE);
2776
2777 // Find object to be deleted
2778 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
2779 if (pObject != NULL)
2780 {
2781 // We can do polls only for node objects
2782 if ((pObject->Type() == OBJECT_NODE) &&
2783 ((pData->iPollType == POLL_STATUS) || (pData->iPollType == POLL_CONFIGURATION)))
2784 {
2785 // Check access rights
2786 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
2787 {
2788 ((Node *)pObject)->IncRefCount();
2789
2790 pData->pNode = (Node *)pObject;
2791 ThreadCreate(PollerThreadStarter, 0, pData);
2792 msg.SetVariable(VID_RCC, RCC_OPERATION_IN_PROGRESS);
2793 msg.SetVariable(VID_POLLER_MESSAGE, _T("Poll request accepted\r\n"));
2794 }
2795 else
2796 {
2797 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2798 }
2799 }
2800 else
2801 {
2802 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2803 }
2804 }
2805 else
2806 {
2807 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2808 }
2809
2810 // Send responce
2811 SendMessage(&msg);
2812 MutexUnlock(m_mutexPollerInit);
2813 }
2814
2815
2816 //
2817 // Send message fro poller to client
2818 //
2819
2820 void ClientSession::SendPollerMsg(DWORD dwRqId, TCHAR *pszMsg)
2821 {
2822 CSCPMessage msg;
2823
2824 msg.SetCode(CMD_POLLING_INFO);
2825 msg.SetId(dwRqId);
2826 msg.SetVariable(VID_RCC, RCC_OPERATION_IN_PROGRESS);
2827 msg.SetVariable(VID_POLLER_MESSAGE, pszMsg);
2828 SendMessage(&msg);
2829 }
2830
2831
2832 //
2833 // Node poller thread
2834 //
2835
2836 void ClientSession::PollerThread(Node *pNode, int iPollType, DWORD dwRqId)
2837 {
2838 CSCPMessage msg;
2839
2840 // Wait while parent thread finishes initialization
2841 MutexLock(m_mutexPollerInit, INFINITE);
2842 MutexUnlock(m_mutexPollerInit);
2843
2844 switch(iPollType)
2845 {
2846 case POLL_STATUS:
2847 pNode->StatusPoll(this, dwRqId);
2848 break;
2849 case POLL_CONFIGURATION:
2850 pNode->ConfigurationPoll(this, dwRqId);
2851 break;
2852 default:
2853 SendPollerMsg(dwRqId, _T("Invalid poll type requested\r\n"));
2854 break;
2855 }
2856 pNode->DecRefCount();
2857
2858 msg.SetCode(CMD_POLLING_INFO);
2859 msg.SetId(dwRqId);
2860 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2861 SendMessage(&msg);
2862 }
2863
2864
2865 //
2866 // Receive event from user
2867 //
2868
2869 void ClientSession::OnTrap(CSCPMessage *pRequest)
2870 {
2871 CSCPMessage msg;
2872 DWORD dwObjectId, dwEventCode;
2873 int i, iNumArgs;
2874 NetObj *pObject;
2875 TCHAR *pszArgList[32];
2876 TCHAR szFormat[] = "ssssssssssssssssssssssssssssssss";
2877 BOOL bSuccess;
2878
2879 // Prepare responce message
2880 msg.SetCode(CMD_REQUEST_COMPLETED);
2881 msg.SetId(pRequest->GetId());
2882
2883 // Find event's source object
2884 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
2885 if (dwObjectId != 0)
2886 pObject = FindObjectById(dwObjectId); // Object is specified explicitely
2887 else
2888 pObject = FindNodeByIP(m_dwHostAddr); // Client is the source
2889 if (pObject != NULL)
2890 {
2891 // User should have SEND_EVENTS access right to object
2892 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_SEND_EVENTS))
2893 {
2894 dwEventCode = pRequest->GetVariableLong(VID_EVENT_ID);
2895 iNumArgs = pRequest->GetVariableShort(VID_NUM_ARGS);
2896 for(i = 0; i < iNumArgs; i++)
2897 pszArgList[i] = pRequest->GetVariableStr(VID_EVENT_ARG_BASE + i);
2898
2899 // Following call is not very good, but I'm too lazy now
2900 // to change PostEvent()
2901 szFormat[iNumArgs] = 0;
2902 bSuccess = PostEvent(dwEventCode, pObject->Id(), (iNumArgs > 0) ? szFormat : NULL,
2903 pszArgList[0], pszArgList[1], pszArgList[2], pszArgList[3],
2904 pszArgList[4], pszArgList[5], pszArgList[6], pszArgList[7],
2905 pszArgList[8], pszArgList[9], pszArgList[10], pszArgList[11],
2906 pszArgList[12], pszArgList[13], pszArgList[14], pszArgList[15],
2907 pszArgList[16], pszArgList[17], pszArgList[18], pszArgList[19],
2908 pszArgList[20], pszArgList[21], pszArgList[22], pszArgList[23],
2909 pszArgList[24], pszArgList[25], pszArgList[26], pszArgList[27],
2910 pszArgList[30], pszArgList[31], pszArgList[32], pszArgList[33]);
2911
2912 // Cleanup
2913 for(i = 0; i < iNumArgs; i++)
2914 free(pszArgList[i]);
2915
2916 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_INVALID_EVENT_CODE);
2917 }
2918 else
2919 {
2920 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2921 }
2922 }
2923 else
2924 {
2925 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2926 }
2927
2928 // Send responce
2929 SendMessage(&msg);
2930 }