Implemented object caching on client side
[public/netxms.git] / src / console / win32 / comm.cpp
CommitLineData
f7a7f8e4
VK
1/*
2** NetXMS - Network Management System
3** Windows Console
4** Copyright (C) 2004 Victor Kirhenshtein
5**
6** This program is free software; you can redistribute it and/or modify
7** it under the terms of the GNU General Public License as published by
8** the Free Software Foundation; either version 2 of the License, or
9** (at your option) any later version.
10**
11** This program is distributed in the hope that it will be useful,
12** but WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14** GNU General Public License for more details.
15**
16** You should have received a copy of the GNU General Public License
17** along with this program; if not, write to the Free Software
18** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19**
20** $module: comm.cpp
21** Background communication functions
22**
23**/
24
25#include "stdafx.h"
26#include "nxcon.h"
27
28
fadbdf37
VK
29//
30// Constants
31//
32
33#define UI_THREAD_WAIT_TIME 300
34
35
f7a7f8e4
VK
36//
37// Set status text in wait window
38//
39
40inline void SetInfoText(HWND hWnd, char *pszText)
41{
42 SendMessage(hWnd, WM_SET_INFO_TEXT, 0, (LPARAM)pszText);
43}
44
45
34870fc0
VK
46//
47// Check if MIB file is exist and up-to-date
48//
49
50static DWORD CheckMIBFile(char *pszName, BYTE *pHash)
51{
52 char szFileName[MAX_PATH];
53 BYTE currHash[MD5_DIGEST_SIZE];
54 BOOL bNeedUpdate = TRUE;
55 DWORD dwResult = RCC_SUCCESS;
56
57 // Build full file name
58 strcpy(szFileName, g_szWorkDir);
59 strcat(szFileName, WORKDIR_MIBCACHE);
60 strcat(szFileName, "\\");
61 strcat(szFileName, pszName);
62
63 // Check file hash
64 if (CalculateFileMD5Hash(szFileName, currHash))
65 bNeedUpdate = memcmp(currHash, pHash, MD5_DIGEST_SIZE);
66
67 // Download file from server if needed
68 if (bNeedUpdate)
69 {
70 strcpy(szFileName, g_szWorkDir);
71 strcat(szFileName, WORKDIR_MIBCACHE);
babb8280 72 dwResult = NXCDownloadMIBFile(g_hSession, pszName, szFileName);
34870fc0
VK
73 }
74 return dwResult;
75}
76
77
babb8280
VK
78//
79// Wrapper for client library event handler
80//
81
82static void ClientEventHandler(NXC_SESSION hSession, DWORD dwEvent, DWORD dwCode, void *pArg)
83{
84 theApp.EventHandler(dwEvent, dwCode, pArg);
85}
86
87
f7a7f8e4
VK
88//
89// Login thread
90//
91
92static DWORD WINAPI LoginThread(void *pArg)
93{
94 HWND hWnd = *((HWND *)pArg); // Handle to status window
95 DWORD dwResult;
96
babb8280 97 dwResult = NXCConnect(g_szServer, g_szLogin, g_szPassword, &g_hSession);
6849d9be
VK
98
99 // If successful, load container objects' categories
100 if (dwResult == RCC_SUCCESS)
101 {
890ae660 102 theApp.GetMainWnd()->PostMessage(WM_STATE_CHANGE, TRUE, 0);
babb8280
VK
103 NXCSetEventHandler(g_hSession, ClientEventHandler);
104
6849d9be 105 SetInfoText(hWnd, "Loading container categories...");
babb8280 106 dwResult = NXCLoadCCList(g_hSession, &g_pCCList);
6849d9be
VK
107 }
108
109 // Synchronize objects
f7a7f8e4
VK
110 if (dwResult == RCC_SUCCESS)
111 {
bfa29136
VK
112 TCHAR szCacheFile[MAX_PATH];
113
f7a7f8e4 114 SetInfoText(hWnd, "Synchronizing objects...");
bfa29136
VK
115 _tcscpy(szCacheFile, g_szWorkDir);
116 _tcscat(szCacheFile, WORKFILE_OBJECTCACHE);
117 dwResult = NXCSyncObjectsEx(g_hSession, szCacheFile);
34870fc0
VK
118 }
119
120 if (dwResult == RCC_SUCCESS)
121 {
122 SetInfoText(hWnd, "Loading user database...");
babb8280 123 dwResult = NXCLoadUserDB(g_hSession);
34870fc0 124 }
f7a7f8e4 125
c7863da1
VK
126 if (dwResult == RCC_SUCCESS)
127 {
128 SetInfoText(hWnd, "Loading action configuration...");
babb8280 129 dwResult = NXCLoadActions(g_hSession, &g_dwNumActions, &g_pActionList);
22c38feb
VK
130 if (dwResult == RCC_ACCESS_DENIED)
131 dwResult = RCC_SUCCESS; // User may not have rights to see actions, it's ok here
c7863da1
VK
132 }
133
34870fc0
VK
134 if (dwResult == RCC_SUCCESS)
135 {
136 NXC_MIB_LIST *pMibList;
137 DWORD i;
138
139 SetInfoText(hWnd, "Loading and initializing MIB files...");
babb8280 140 dwResult = NXCGetMIBList(g_hSession, &pMibList);
f7a7f8e4
VK
141 if (dwResult == RCC_SUCCESS)
142 {
34870fc0
VK
143 for(i = 0; i < pMibList->dwNumFiles; i++)
144 if ((dwResult = CheckMIBFile(pMibList->ppszName[i], pMibList->ppHash[i])) != RCC_SUCCESS)
145 break;
146 NXCDestroyMIBList(pMibList);
147 if (dwResult == RCC_SUCCESS)
148 CreateMIBTree();
f7a7f8e4 149 }
f7a7f8e4
VK
150 }
151
3421c063
VK
152 if (dwResult == RCC_SUCCESS)
153 {
154 SetInfoText(hWnd, "Loading event information...");
babb8280 155 dwResult = NXCLoadEventDB(g_hSession);
3421c063
VK
156 }
157
51bd5a10 158 // Synchronize images
f70fc197
VK
159 if (dwResult == RCC_SUCCESS)
160 {
161 char szCacheDir[MAX_PATH];
162
163 SetInfoText(hWnd, "Synchronizing images...");
164 strcpy(szCacheDir, g_szWorkDir);
165 strcat(szCacheDir, WORKDIR_IMAGECACHE);
babb8280 166 dwResult = NXCSyncImages(g_hSession, &g_pSrvImageList, szCacheDir, IMAGE_FORMAT_ICO);
cea97623
VK
167 if (dwResult == RCC_SUCCESS)
168 CreateObjectImageList();
f70fc197
VK
169 }
170
51bd5a10
VK
171 // Load default image list
172 if (dwResult == RCC_SUCCESS)
173 {
174 DWORD i, *pdwClassId, *pdwImageId;
175
176 SetInfoText(hWnd, "Loading default image list...");
babb8280 177 dwResult = NXCLoadDefaultImageList(g_hSession, &g_dwDefImgListSize, &pdwClassId, &pdwImageId);
51bd5a10
VK
178 if (dwResult == RCC_SUCCESS)
179 {
180 g_pDefImgList = (DEF_IMG *)realloc(g_pDefImgList, sizeof(DEF_IMG) * g_dwDefImgListSize);
181 for(i = 0; i < g_dwDefImgListSize; i++)
182 {
183 g_pDefImgList[i].dwObjectClass = pdwClassId[i];
184 g_pDefImgList[i].dwImageId = pdwImageId[i];
2d6e6388 185 g_pDefImgList[i].iImageIndex = ImageIdToIndex(pdwImageId[i]);
51bd5a10 186 }
9d72bde1
VK
187 safe_free(pdwClassId);
188 safe_free(pdwImageId);
51bd5a10
VK
189 }
190 }
191
34870fc0
VK
192 // Disconnect if some of post-login operations was failed
193 if (dwResult != RCC_SUCCESS)
a1cb335b 194 {
890ae660 195 theApp.GetMainWnd()->PostMessage(WM_STATE_CHANGE, FALSE, 0);
babb8280 196 NXCDisconnect(g_hSession);
a1cb335b
VK
197 g_hSession = NULL;
198 }
34870fc0 199
f7a7f8e4
VK
200 PostMessage(hWnd, WM_REQUEST_COMPLETED, 0, dwResult);
201 return dwResult;
202}
203
204
205//
206// Perform login
207//
208
209DWORD DoLogin(void)
210{
211 HANDLE hThread;
212 HWND hWnd = NULL;
213 DWORD dwThreadId, dwResult;
214
215 hThread = CreateThread(NULL, 0, LoginThread, &hWnd, CREATE_SUSPENDED, &dwThreadId);
216 if (hThread != NULL)
217 {
218 CRequestProcessingDlg wndWaitDlg;
219
220 wndWaitDlg.m_phWnd = &hWnd;
221 wndWaitDlg.m_hThread = hThread;
222 wndWaitDlg.m_strInfoText = "Connecting to server...";
223 dwResult = (DWORD)wndWaitDlg.DoModal();
224 CloseHandle(hThread);
225 }
226 else
227 {
228 dwResult = RCC_SYSTEM_FAILURE;
229 }
230
231 return dwResult;
232}
233
234
235//
eb8b1960 236// Request processing thread
f7a7f8e4
VK
237//
238
239static DWORD WINAPI RequestThread(void *pArg)
240{
241 RqData *pData = (RqData *)pArg;
242 DWORD dwResult;
243
244 switch(pData->dwNumParams)
245 {
246 case 0:
247 dwResult = pData->pFunc();
248 break;
249 case 1:
250 dwResult = pData->pFunc(pData->pArg1);
251 break;
fadbdf37
VK
252 case 2:
253 dwResult = pData->pFunc(pData->pArg1, pData->pArg2);
254 break;
255 case 3:
256 dwResult = pData->pFunc(pData->pArg1, pData->pArg2, pData->pArg3);
257 break;
933aee5c
VK
258 case 4:
259 dwResult = pData->pFunc(pData->pArg1, pData->pArg2, pData->pArg3, pData->pArg4);
260 break;
22c38feb
VK
261 case 5:
262 dwResult = pData->pFunc(pData->pArg1, pData->pArg2, pData->pArg3,
263 pData->pArg4, pData->pArg5);
264 break;
9f20696e 265 case 6:
933aee5c
VK
266 dwResult = pData->pFunc(pData->pArg1, pData->pArg2, pData->pArg3,
267 pData->pArg4, pData->pArg5, pData->pArg6);
9f20696e 268 break;
babb8280
VK
269 case 7:
270 dwResult = pData->pFunc(pData->pArg1, pData->pArg2, pData->pArg3,
271 pData->pArg4, pData->pArg5, pData->pArg6,
272 pData->pArg7);
273 break;
f7a7f8e4
VK
274 }
275 if (pData->hWnd != NULL)
276 PostMessage(pData->hWnd, WM_REQUEST_COMPLETED, 0, dwResult);
277 return dwResult;
278}
279
280
281//
fadbdf37 282// Perform request (common code)
f7a7f8e4
VK
283//
284
fadbdf37 285static DWORD ExecuteRequest(RqData *pData, char *pszInfoText)
f7a7f8e4
VK
286{
287 HANDLE hThread;
f7a7f8e4
VK
288 DWORD dwThreadId, dwResult;
289
fadbdf37 290 hThread = CreateThread(NULL, 0, RequestThread, pData, 0, &dwThreadId);
f7a7f8e4
VK
291 if (hThread != NULL)
292 {
293 CRequestProcessingDlg wndWaitDlg;
294
fadbdf37
VK
295 // Wait for request completion
296 if (WaitForSingleObject(hThread, UI_THREAD_WAIT_TIME) == WAIT_TIMEOUT)
f7a7f8e4
VK
297 {
298 // Thread still not finished, open status window
299 SuspendThread(hThread);
fadbdf37 300 wndWaitDlg.m_phWnd = &pData->hWnd;
f7a7f8e4
VK
301 wndWaitDlg.m_hThread = hThread;
302 wndWaitDlg.m_strInfoText = pszInfoText;
303 dwResult = (DWORD)wndWaitDlg.DoModal();
304 }
305 else
306 {
307 // Thread is finished, get it's exit code
308 if (!GetExitCodeThread(hThread, &dwResult))
309 dwResult = RCC_SYSTEM_FAILURE;
310 }
311 CloseHandle(hThread);
312 }
313 else
314 {
315 dwResult = RCC_SYSTEM_FAILURE;
316 }
317
318 return dwResult;
319}
320
321
fadbdf37
VK
322//
323// Perform generic request without parameters
324//
325
326DWORD DoRequest(DWORD (* pFunc)(void), char *pszInfoText)
327{
328 RqData rqData;
329
330 rqData.hWnd = NULL;
331 rqData.dwNumParams = 0;
332 rqData.pFunc = (DWORD (*)(...))pFunc;
333 return ExecuteRequest(&rqData, pszInfoText);
334}
335
336
f7a7f8e4
VK
337//
338// Perform request with 1 parameter
339//
340
341DWORD DoRequestArg1(void *pFunc, void *pArg1, char *pszInfoText)
342{
f7a7f8e4 343 RqData rqData;
f7a7f8e4
VK
344
345 rqData.hWnd = NULL;
346 rqData.dwNumParams = 1;
347 rqData.pArg1 = pArg1;
348 rqData.pFunc = (DWORD (*)(...))pFunc;
fadbdf37
VK
349 return ExecuteRequest(&rqData, pszInfoText);
350}
f7a7f8e4 351
f7a7f8e4 352
4925a756
VK
353//
354// Perform request with 2 parameters
355//
356
357DWORD DoRequestArg2(void *pFunc, void *pArg1, void *pArg2, char *pszInfoText)
358{
359 RqData rqData;
360
361 rqData.hWnd = NULL;
362 rqData.dwNumParams = 2;
363 rqData.pArg1 = pArg1;
364 rqData.pArg2 = pArg2;
365 rqData.pFunc = (DWORD (*)(...))pFunc;
366 return ExecuteRequest(&rqData, pszInfoText);
367}
368
369
fadbdf37
VK
370//
371// Perform request with 3 parameter
372//
373
374DWORD DoRequestArg3(void *pFunc, void *pArg1, void *pArg2, void *pArg3, char *pszInfoText)
375{
376 RqData rqData;
377
378 rqData.hWnd = NULL;
379 rqData.dwNumParams = 3;
380 rqData.pArg1 = pArg1;
381 rqData.pArg2 = pArg2;
382 rqData.pArg3 = pArg3;
383 rqData.pFunc = (DWORD (*)(...))pFunc;
384 return ExecuteRequest(&rqData, pszInfoText);
f7a7f8e4 385}
9f20696e
VK
386
387
933aee5c
VK
388//
389// Perform request with 4 parameter
390//
391
392DWORD DoRequestArg4(void *pFunc, void *pArg1, void *pArg2, void *pArg3,
393 void *pArg4, char *pszInfoText)
394{
395 RqData rqData;
396
397 rqData.hWnd = NULL;
398 rqData.dwNumParams = 4;
399 rqData.pArg1 = pArg1;
400 rqData.pArg2 = pArg2;
401 rqData.pArg3 = pArg3;
402 rqData.pArg4 = pArg4;
403 rqData.pFunc = (DWORD (*)(...))pFunc;
404 return ExecuteRequest(&rqData, pszInfoText);
405}
406
407
22c38feb
VK
408//
409// Perform request with 5 parameter
410//
411
412DWORD DoRequestArg5(void *pFunc, void *pArg1, void *pArg2, void *pArg3, void *pArg4,
413 void *pArg5, char *pszInfoText)
414{
415 RqData rqData;
416
417 rqData.hWnd = NULL;
418 rqData.dwNumParams = 5;
419 rqData.pArg1 = pArg1;
420 rqData.pArg2 = pArg2;
421 rqData.pArg3 = pArg3;
422 rqData.pArg4 = pArg4;
423 rqData.pArg5 = pArg5;
424 rqData.pFunc = (DWORD (*)(...))pFunc;
425 return ExecuteRequest(&rqData, pszInfoText);
426}
427
428
9f20696e
VK
429//
430// Perform request with 6 parameter
431//
432
433DWORD DoRequestArg6(void *pFunc, void *pArg1, void *pArg2, void *pArg3, void *pArg4,
434 void *pArg5, void *pArg6, char *pszInfoText)
435{
436 RqData rqData;
437
438 rqData.hWnd = NULL;
439 rqData.dwNumParams = 6;
440 rqData.pArg1 = pArg1;
441 rqData.pArg2 = pArg2;
442 rqData.pArg3 = pArg3;
443 rqData.pArg4 = pArg4;
444 rqData.pArg5 = pArg5;
445 rqData.pArg6 = pArg6;
446 rqData.pFunc = (DWORD (*)(...))pFunc;
447 return ExecuteRequest(&rqData, pszInfoText);
448}
eb8b1960
VK
449
450
babb8280
VK
451//
452// Perform request with 7 parameter
453//
454
455DWORD DoRequestArg7(void *pFunc, void *pArg1, void *pArg2, void *pArg3, void *pArg4,
456 void *pArg5, void *pArg6, void *pArg7, char *pszInfoText)
457{
458 RqData rqData;
459
460 rqData.hWnd = NULL;
461 rqData.dwNumParams = 7;
462 rqData.pArg1 = pArg1;
463 rqData.pArg2 = pArg2;
464 rqData.pArg3 = pArg3;
465 rqData.pArg4 = pArg4;
466 rqData.pArg5 = pArg5;
467 rqData.pArg6 = pArg6;
468 rqData.pArg7 = pArg7;
469 rqData.pFunc = (DWORD (*)(...))pFunc;
470 return ExecuteRequest(&rqData, pszInfoText);
471}
472
473
eb8b1960
VK
474//
475// Callback function for node poller
476//
477
478static void PollerCallback(TCHAR *pszMsg, void *pArg)
479{
480 if (((RqData *)pArg)->hWnd != NULL)
481 PostMessage(((RqData *)pArg)->hWnd, WM_POLLER_MESSAGE, 0, (LPARAM)_tcsdup(pszMsg));
482}
483
484
485//
486// Poller thread
487//
488
bbf5bbcf 489DWORD WINAPI PollerThread(void *pArg)
eb8b1960
VK
490{
491 RqData *pData = (RqData *)pArg;
492 DWORD dwResult;
493
babb8280
VK
494 dwResult = NXCPollNode(g_hSession, (DWORD)pData->pArg1, (int)pData->pArg2,
495 PollerCallback, pArg);
eb8b1960
VK
496 if (pData->hWnd != NULL)
497 PostMessage(pData->hWnd, WM_REQUEST_COMPLETED, 0, dwResult);
498 return dwResult;
499}