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