Initial agent-side code for agent to server connections
[public/netxms.git] / src / libnetxms / nxcp.cpp
CommitLineData
9fa031cd 1/*
5039dede
AK
2** NetXMS - Network Management System
3** NetXMS Foundation Library
1a5ddd2a 4** Copyright (C) 2003-2015 Victor Kirhenshtein
5039dede
AK
5**
6** This program is free software; you can redistribute it and/or modify
68f384ea
VK
7** it under the terms of the GNU Lesser General Public License as published
8** by the Free Software Foundation; either version 3 of the License, or
5039dede
AK
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**
68f384ea 16** You should have received a copy of the GNU Lesser General Public License
5039dede
AK
17** along with this program; if not, write to the Free Software
18** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19**
20** File: nxcp.cpp
21**
22**/
23
24#include "libnetxms.h"
390271e0 25#include <nxstat.h>
5039dede 26
7b33ff5d
VK
27#ifdef _WIN32
28#define read _read
29#define close _close
30#endif
31
534e1b83
VK
32/**
33 * Get symbolic name for message code
34 */
b368969c 35TCHAR LIBNETXMS_EXPORTABLE *NXCPMessageCodeName(WORD code, TCHAR *pszBuffer)
5039dede
AK
36{
37 static const TCHAR *pszMsgNames[] =
38 {
39 _T("CMD_LOGIN"),
40 _T("CMD_LOGIN_RESP"),
41 _T("CMD_KEEPALIVE"),
3c35018e 42 _T("CMD_OPEN_HELPDESK_ISSUE"),
5039dede
AK
43 _T("CMD_GET_OBJECTS"),
44 _T("CMD_OBJECT"),
45 _T("CMD_DELETE_OBJECT"),
46 _T("CMD_MODIFY_OBJECT"),
47 _T("CMD_OBJECT_LIST_END"),
48 _T("CMD_OBJECT_UPDATE"),
49 _T("CMD_GET_EVENTS"),
50 _T("CMD_EVENTLOG_RECORDS"),
51 _T("CMD_GET_CONFIG_VARLIST"),
52 _T("CMD_SET_CONFIG_VARIABLE"),
53 _T("CMD_GET_OBJECT_TOOLS"),
54 _T("CMD_EXECUTE_ACTION"),
55 _T("CMD_DELETE_CONFIG_VARIABLE"),
56 _T("CMD_NOTIFY"),
57 _T("CMD_TRAP"),
58 _T("CMD_OPEN_EPP"),
59 _T("CMD_CLOSE_EPP"),
60 _T("CMD_SAVE_EPP"),
61 _T("CMD_EPP_RECORD"),
870d2546 62 _T("CMD_EVENT_DB_UPDATE"),
15edffbf 63 _T("CMD_TRAP_CFG_UPDATE"),
5039dede
AK
64 _T("CMD_SET_EVENT_INFO"),
65 _T("CMD_EVENT_DB_RECORD"),
66 _T("CMD_LOAD_EVENT_DB"),
67 _T("CMD_REQUEST_COMPLETED"),
68 _T("CMD_LOAD_USER_DB"),
69 _T("CMD_USER_DATA"),
70 _T("CMD_GROUP_DATA"),
71 _T("CMD_USER_DB_EOF"),
72 _T("CMD_UPDATE_USER"),
73 _T("CMD_DELETE_USER"),
74 _T("CMD_CREATE_USER"),
75 _T("CMD_LOCK_USER_DB"),
76 _T("CMD_UNLOCK_USER_DB"),
77 _T("CMD_USER_DB_UPDATE"),
78 _T("CMD_SET_PASSWORD"),
79 _T("CMD_GET_NODE_DCI_LIST"),
80 _T("CMD_NODE_DCI"),
f727d089 81 _T("CMD_GET_LOG_DATA"),
5039dede
AK
82 _T("CMD_DELETE_NODE_DCI"),
83 _T("CMD_MODIFY_NODE_DCI"),
84 _T("CMD_UNLOCK_NODE_DCI_LIST"),
85 _T("CMD_SET_OBJECT_MGMT_STATUS"),
86 _T("CMD_CREATE_NEW_DCI"),
87 _T("CMD_GET_DCI_DATA"),
88 _T("CMD_DCI_DATA"),
89 _T("CMD_GET_MIB_TIMESTAMP"),
90 _T("CMD_GET_MIB"),
6d738067 91 _T("CMD_TEST_DCI_TRANSFORMATION"),
ab621f39 92 _T("CMD_GET_JOB_LIST"),
5039dede
AK
93 _T("CMD_CREATE_OBJECT"),
94 _T("CMD_GET_EVENT_NAMES"),
95 _T("CMD_EVENT_NAME_LIST"),
96 _T("CMD_BIND_OBJECT"),
97 _T("CMD_UNBIND_OBJECT"),
93599cfd 98 _T("CMD_UNINSTALL_AGENT_POLICY"),
f727d089
VK
99 _T("CMD_OPEN_SERVER_LOG"),
100 _T("CMD_CLOSE_SERVER_LOG"),
101 _T("CMD_QUERY_LOG"),
5039dede
AK
102 _T("CMD_AUTHENTICATE"),
103 _T("CMD_GET_PARAMETER"),
104 _T("CMD_GET_LIST"),
105 _T("CMD_ACTION"),
d83dc1f0
VK
106 _T("CMD_GET_CURRENT_USER_ATTR"),
107 _T("CMD_SET_CURRENT_USER_ATTR"),
5039dede 108 _T("CMD_GET_ALL_ALARMS"),
4644eee7 109 _T("CMD_GET_ALARM_COMMENTS"),
5039dede
AK
110 _T("CMD_ACK_ALARM"),
111 _T("CMD_ALARM_UPDATE"),
112 _T("CMD_ALARM_DATA"),
113 _T("CMD_DELETE_ALARM"),
1da08bc6 114 _T("CMD_ADD_CLUSTER_NODE"),
1f385e47 115 _T("CMD_GET_POLICY_INVENTORY"),
5039dede
AK
116 _T("CMD_LOAD_ACTIONS"),
117 _T("CMD_ACTION_DB_UPDATE"),
118 _T("CMD_MODIFY_ACTION"),
119 _T("CMD_CREATE_ACTION"),
120 _T("CMD_DELETE_ACTION"),
121 _T("CMD_ACTION_DATA"),
842378a4 122 _T("CMD_SETUP_AGENT_TUNNEL"),
23464115
VK
123 _T("<unused>"),
124 _T("<unused>"),
125 _T("<unused>"),
126 _T("<unused>"),
5039dede
AK
127 _T("CMD_POLL_NODE"),
128 _T("CMD_POLLING_INFO"),
129 _T("CMD_COPY_DCI"),
130 _T("CMD_WAKEUP_NODE"),
131 _T("CMD_DELETE_EVENT_TEMPLATE"),
132 _T("CMD_GENERATE_EVENT_CODE"),
630e15d6 133 _T("CMD_FIND_NODE_CONNECTION"),
06a93345 134 _T("CMD_FIND_MAC_LOCATION"),
5039dede
AK
135 _T("CMD_CREATE_TRAP"),
136 _T("CMD_MODIFY_TRAP"),
137 _T("CMD_DELETE_TRAP"),
138 _T("CMD_LOAD_TRAP_CFG"),
139 _T("CMD_TRAP_CFG_RECORD"),
140 _T("CMD_QUERY_PARAMETER"),
141 _T("CMD_GET_SERVER_INFO"),
142 _T("CMD_SET_DCI_STATUS"),
143 _T("CMD_FILE_DATA"),
144 _T("CMD_TRANSFER_FILE"),
145 _T("CMD_UPGRADE_AGENT"),
146 _T("CMD_GET_PACKAGE_LIST"),
147 _T("CMD_PACKAGE_INFO"),
148 _T("CMD_REMOVE_PACKAGE"),
149 _T("CMD_INSTALL_PACKAGE"),
150 _T("CMD_LOCK_PACKAGE_DB"),
151 _T("CMD_UNLOCK_PACKAGE_DB"),
152 _T("CMD_ABORT_FILE_TRANSFER"),
153 _T("CMD_CHECK_NETWORK_SERVICE"),
154 _T("CMD_GET_AGENT_CONFIG"),
155 _T("CMD_UPDATE_AGENT_CONFIG"),
156 _T("CMD_GET_PARAMETER_LIST"),
157 _T("CMD_DEPLOY_PACKAGE"),
158 _T("CMD_INSTALLER_INFO"),
159 _T("CMD_GET_LAST_VALUES"),
160 _T("CMD_APPLY_TEMPLATE"),
161 _T("CMD_SET_USER_VARIABLE"),
162 _T("CMD_GET_USER_VARIABLE"),
163 _T("CMD_ENUM_USER_VARIABLES"),
164 _T("CMD_DELETE_USER_VARIABLE"),
165 _T("CMD_ADM_MESSAGE"),
166 _T("CMD_ADM_REQUEST"),
6d069676 167 _T("CMD_GET_NETWORK_PATH"),
5039dede
AK
168 _T("CMD_REQUEST_SESSION_KEY"),
169 _T("CMD_ENCRYPTED_MESSAGE"),
170 _T("CMD_SESSION_KEY"),
171 _T("CMD_REQUEST_ENCRYPTION"),
172 _T("CMD_GET_ROUTING_TABLE"),
173 _T("CMD_EXEC_TABLE_TOOL"),
174 _T("CMD_TABLE_DATA"),
f40831eb 175 _T("CMD_CANCEL_JOB"),
5039dede
AK
176 _T("CMD_CHANGE_SUBSCRIPTION"),
177 _T("CMD_GET_SYSLOG"),
178 _T("CMD_SYSLOG_RECORDS"),
ab621f39 179 _T("CMD_JOB_CHANGE_NOTIFICATION"),
fc61a868 180 _T("CMD_DEPLOY_AGENT_POLICY"),
f727d089 181 _T("CMD_LOG_DATA"),
5039dede 182 _T("CMD_GET_OBJECT_TOOL_DETAILS"),
f69c6203 183 _T("CMD_EXECUTE_SERVER_COMMAND"),
619e5c9b 184 _T("CMD_UPLOAD_FILE_TO_AGENT"),
5039dede
AK
185 _T("CMD_UPDATE_OBJECT_TOOL"),
186 _T("CMD_DELETE_OBJECT_TOOL"),
187 _T("CMD_SETUP_PROXY_CONNECTION"),
188 _T("CMD_GENERATE_OBJECT_TOOL_ID"),
189 _T("CMD_GET_SERVER_STATS"),
190 _T("CMD_GET_SCRIPT_LIST"),
191 _T("CMD_GET_SCRIPT"),
192 _T("CMD_UPDATE_SCRIPT"),
193 _T("CMD_DELETE_SCRIPT"),
194 _T("CMD_RENAME_SCRIPT"),
195 _T("CMD_GET_SESSION_LIST"),
196 _T("CMD_KILL_SESSION"),
197 _T("CMD_GET_TRAP_LOG"),
198 _T("CMD_TRAP_LOG_RECORDS"),
199 _T("CMD_START_SNMP_WALK"),
200 _T("CMD_SNMP_WALK_DATA"),
201 _T("CMD_GET_MAP_LIST"),
202 _T("CMD_LOAD_MAP"),
203 _T("CMD_SAVE_MAP"),
204 _T("CMD_DELETE_MAP"),
205 _T("CMD_RESOLVE_MAP_NAME"),
206 _T("CMD_SUBMAP_DATA"),
207 _T("CMD_UPLOAD_SUBMAP_BK_IMAGE"),
208 _T("CMD_GET_SUBMAP_BK_IMAGE"),
209 _T("CMD_GET_MODULE_LIST"),
210 _T("CMD_UPDATE_MODULE_INFO"),
211 _T("CMD_COPY_USER_VARIABLE"),
212 _T("CMD_RESOLVE_DCI_NAMES"),
213 _T("CMD_GET_MY_CONFIG"),
214 _T("CMD_GET_AGENT_CFG_LIST"),
215 _T("CMD_OPEN_AGENT_CONFIG"),
216 _T("CMD_SAVE_AGENT_CONFIG"),
217 _T("CMD_DELETE_AGENT_CONFIG"),
218 _T("CMD_SWAP_AGENT_CONFIGS"),
219 _T("CMD_TERMINATE_ALARM"),
220 _T("CMD_GET_NXCP_CAPS"),
221 _T("CMD_NXCP_CAPS"),
222 _T("CMD_GET_OBJECT_COMMENTS"),
223 _T("CMD_UPDATE_OBJECT_COMMENTS"),
224 _T("CMD_ENABLE_AGENT_TRAPS"),
225 _T("CMD_PUSH_DCI_DATA"),
226 _T("CMD_GET_ADDR_LIST"),
227 _T("CMD_SET_ADDR_LIST"),
228 _T("CMD_RESET_COMPONENT"),
229 _T("CMD_GET_DCI_EVENTS_LIST"),
a7ff20a5
VK
230 _T("CMD_EXPORT_CONFIGURATION"),
231 _T("CMD_IMPORT_CONFIGURATION"),
5039dede
AK
232 _T("CMD_GET_TRAP_CFG_RO"),
233 _T("CMD_SNMP_REQUEST"),
234 _T("CMD_GET_DCI_INFO"),
235 _T("CMD_GET_GRAPH_LIST"),
7a4c94ee 236 _T("CMD_SAVE_GRAPH"),
5039dede 237 _T("CMD_DELETE_GRAPH"),
74526d25 238 _T("CMD_GET_PERFTAB_DCI_LIST"),
5039dede
AK
239 _T("CMD_ADD_CA_CERTIFICATE"),
240 _T("CMD_DELETE_CERTIFICATE"),
241 _T("CMD_GET_CERT_LIST"),
242 _T("CMD_UPDATE_CERT_COMMENTS"),
243 _T("CMD_QUERY_L2_TOPOLOGY"),
244 _T("CMD_AUDIT_RECORD"),
245 _T("CMD_GET_AUDIT_LOG"),
246 _T("CMD_SEND_SMS"),
247 _T("CMD_GET_COMMUNITY_LIST"),
248 _T("CMD_UPDATE_COMMUNITY_LIST"),
249 _T("CMD_GET_SITUATION_LIST"),
250 _T("CMD_DELETE_SITUATION"),
251 _T("CMD_CREATE_SITUATION"),
252 _T("CMD_DEL_SITUATION_INSTANCE"),
253 _T("CMD_UPDATE_SITUATION"),
254 _T("CMD_SITUATION_DATA"),
255 _T("CMD_SITUATION_CHANGE"),
256 _T("CMD_CREATE_MAP"),
68f898c9
VK
257 _T("CMD_UPLOAD_FILE"),
258 _T("CMD_DELETE_FILE"),
3932fde6 259 _T("CMD_DELETE_REPORT_RESULTS"),
e12e1422 260 _T("CMD_RENDER_REPORT"),
8c5b6ed3
VK
261 _T("CMD_EXECUTE_REPORT"),
262 _T("CMD_GET_REPORT_RESULTS"),
5039dede
AK
263 _T("CMD_CONFIG_SET_CLOB"),
264 _T("CMD_CONFIG_GET_CLOB"),
265 _T("CMD_RENAME_MAP"),
266 _T("CMD_CLEAR_DCI_DATA"),
267 _T("CMD_GET_LICENSE"),
268 _T("CMD_CHECK_LICENSE"),
269 _T("CMD_RELEASE_LICENSE"),
270 _T("CMD_ISC_CONNECT_TO_SERVICE"),
271 _T("CMD_REGISTER_AGENT"),
272 _T("CMD_GET_SERVER_FILE"),
df8a4ca2
VK
273 _T("CMD_FORWARD_EVENT"),
274 _T("CMD_GET_USM_CREDENTIALS"),
071fd171 275 _T("CMD_UPDATE_USM_CREDENTIALS"),
1a5e0c22
VK
276 _T("CMD_GET_DCI_THRESHOLDS"),
277 _T("CMD_GET_IMAGE"),
278 _T("CMD_CREATE_IMAGE"),
279 _T("CMD_DELETE_IMAGE"),
280 _T("CMD_MODIFY_IMAGE"),
281 _T("CMD_LIST_IMAGES"),
810bd8c4 282 _T("CMD_LIST_SERVER_FILES"),
adac28be 283 _T("CMD_GET_TABLE"),
200d662d
VK
284 _T("CMD_QUERY_TABLE"),
285 _T("CMD_OPEN_CONSOLE"),
62768df3 286 _T("CMD_CLOSE_CONSOLE"),
7f632dfe 287 _T("CMD_GET_SELECTED_OBJECTS"),
509bb045
VK
288 _T("CMD_GET_VLANS"),
289 _T("CMD_HOLD_JOB"),
4c789f9e 290 _T("CMD_UNHOLD_JOB"),
6f16f12d
VK
291 _T("CMD_CHANGE_ZONE"),
292 _T("CMD_GET_AGENT_FILE"),
624f1165 293 _T("CMD_GET_FILE_DETAILS"),
8836184f 294 _T("CMD_IMAGE_LIBRARY_UPDATE"),
04f06779 295 _T("CMD_GET_NODE_COMPONENTS"),
4644eee7 296 _T("CMD_UPDATE_ALARM_COMMENT"),
b9a8e081 297 _T("CMD_GET_ALARM"),
92c51b1d 298 _T("CMD_GET_TABLE_LAST_VALUES"),
711e5e9a 299 _T("CMD_GET_TABLE_DCI_DATA"),
5f6bc78c 300 _T("CMD_GET_THRESHOLD_SUMMARY"),
534e1b83
VK
301 _T("CMD_RESOLVE_ALARM"),
302 _T("CMD_FIND_IP_LOCATION"),
303 _T("CMD_REPORT_DEVICE_STATUS"),
b1e9b6b3 304 _T("CMD_REPORT_DEVICE_INFO"),
0f506caa
VK
305 _T("CMD_GET_ALARM_EVENTS"),
306 _T("CMD_GET_ENUM_LIST"),
fdbee7f8
VK
307 _T("CMD_GET_TABLE_LIST"),
308 _T("CMD_GET_MAPPING_TABLE"),
309 _T("CMD_UPDATE_MAPPING_TABLE"),
310 _T("CMD_DELETE_MAPPING_TABLE"),
caa04e26 311 _T("CMD_LIST_MAPPING_TABLES"),
46ee6286 312 _T("CMD_GET_NODE_SOFTWARE"),
d5de1d1d 313 _T("CMD_GET_WINPERF_OBJECTS"),
b4c2a628
VK
314 _T("CMD_GET_WIRELESS_STATIONS"),
315 _T("CMD_GET_SUMMARY_TABLES"),
316 _T("CMD_MODIFY_SUMMARY_TABLE"),
317 _T("CMD_DELETE_SUMMARY_TABLE"),
318 _T("CMD_GET_SUMMARY_TABLE_DETAILS"),
f918b160 319 _T("CMD_QUERY_SUMMARY_TABLE"),
67ddc85e 320 _T("CMD_SHUTDOWN"),
ceb0fc8d 321 _T("CMD_SNMP_TRAP"),
9fa031cd 322 _T("CMD_GET_SUBNET_ADDRESS_MAP"),
323 _T("CMD_FILE_MONITORING"),
fce4295c 324 _T("CMD_CANCEL_FILE_MONITORING"),
9dd47420 325 _T("CMD_CHANGE_OBJECT_TOOL_STATUS"),
f82a8b5d 326 _T("CMD_SET_ALARM_STATUS_FLOW"),
4644eee7 327 _T("CMD_DELETE_ALARM_COMMENT"),
2ab9314f 328 _T("CMD_GET_EFFECTIVE_RIGHTS"),
6cedeb69 329 _T("CMD_GET_DCI_VALUES"),
1eb0b101 330 _T("CMD_GET_HELPDESK_URL"),
d9821bd7 331 _T("CMD_UNLINK_HELPDESK_ISSUE"),
7cf549ad 332 _T("CMD_GET_FOLDER_CONTENT"),
333 _T("CMD_FILEMGR_DELETE_FILE"),
334 _T("CMD_FILEMGR_RENAME_FILE"),
335 _T("CMD_FILEMGR_MOVE_FILE"),
c44cf458 336 _T("CMD_FILEMGR_UPLOAD"),
4899db4d 337 _T("CMD_GET_SWITCH_FDB"),
338 _T("CMD_COMMAND_OUTPUT"),
5944946e 339 _T("CMD_GET_LOC_HISTORY"),
529956a0 340 _T("CMD_TAKE_SCREENSHOT"),
341 _T("CMD_EXECUTE_SCRIPT"),
5de546a2 342 _T("CMD_EXECUTE_SCRIPT_UPDATE"),
5389f7b0 343 _T("CMD_FILEMGR_CREATE_FOLDER"),
32f372a5 344 _T("CMD_QUERY_ADHOC_SUMMARY_TABLE"),
ea3993c8 345 _T("CMD_GRAPH_UPDATE"),
1a5ddd2a 346 _T("CMD_SET_SERVER_CAPABILITIES"),
25a1e9d0 347 _T("CMD_FORCE_DCI_POLL"),
e9902466
VK
348 _T("CMD_GET_DCI_SCRIPT_LIST"),
349 _T("CMD_DATA_COLLECTION_CONFIG"),
c85c8ef2 350 _T("CMD_SET_SERVER_ID"),
2d8d8ea2 351 _T("CMD_GET_PUBLIC_CONFIG_VAR"),
352 _T("CMD_ENABLE_FILE_UPDATES"),
77a08c86 353 _T("CMD_DETACH_LDAP_USER"),
5f573844 354 _T("CMD_VALIDATE_PASSWORD"),
4b535d78 355 _T("CMD_COMPILE_SCRIPT"),
356 _T("CMD_CLEAN_AGENT_DCI_CONF"),
6b0abae2
Z
357 _T("CMD_RESYNC_AGENT_DCI_CONF"),
358 _T("CMD_LIST_SCHEDULE_CALLBACKS"),
359 _T("CMD_LIST_SCHEDULES"),
360 _T("CMD_ADD_SCHEDULE"),
361 _T("CMD_UPDATE_SCHEDULE"),
7e18667a
VK
362 _T("CMD_REMOVE_SCHEDULE"),
363 _T("CMD_ENTER_MAINT_MODE"),
5cf931e2 364 _T("CMD_LEAVE_MAINT_MODE"),
de12aebc 365 _T("CMD_JOIN_CLUSTER"),
badd6e08
VK
366 _T("CMD_CLUSTER_NOTIFY"),
367 _T("CMD_ZMQ_SUBSCRIBE_EVENT"),
368 _T("CMD_ZMQ_UNSUBSCRIBE_EVENT"),
369 _T("CMD_ZMQ_SUBSCRIBE_DATA"),
370 _T("CMD_ZMQ_UNSUBSCRIBE_DATA"),
371 _T("CMD_ZMQ_GET_EVT_SUBSCRIPTIONS"),
372 _T("CMD_ZMQ_GET_DATA_SUBSCRIPTIONS"),
373 _T("CMD_GET_REPOSITORIES"),
374 _T("CMD_ADD_REPOSITORY"),
375 _T("CMD_MODIFY_REPOSITORY"),
376 _T("CMD_DELETE_REPOSITORY")
5039dede
AK
377 };
378
badd6e08 379 if ((code >= CMD_LOGIN) && (code <= CMD_DELETE_REPOSITORY))
b368969c 380 _tcscpy(pszBuffer, pszMsgNames[code - CMD_LOGIN]);
5039dede 381 else
b368969c 382 _sntprintf(pszBuffer, 64, _T("CMD_0x%04X"), code);
5039dede
AK
383 return pszBuffer;
384}
385
534e1b83
VK
386/**
387 * Receive raw CSCP message from network
388 * If pMsg is NULL, temporary buffer will be re-initialized
389 * Returns message size on success or:
390 * 0 if connection is closed
391 * <0 on socket errors
392 * 1 if message is too large to fit in buffer (normal messages is at least 16
393 * bytes long, so we never get length of 1 for valid message)
394 * In this case, only message header will be copied into buffer
395 * 2 Message decryption failed
396 * 3 Receive timeout
397 */
b368969c
VK
398int LIBNETXMS_EXPORTABLE RecvNXCPMessageEx(SOCKET hSocket, NXCP_MESSAGE **msgBuffer,
399 NXCP_BUFFER *nxcpBuffer, UINT32 *bufferSize,
fce4295c 400 NXCPEncryptionContext **ppCtx,
967893bb
VK
401 BYTE **decryptionBuffer, UINT32 dwTimeout,
402 UINT32 maxMsgSize)
5039dede 403{
967893bb 404 UINT32 dwMsgSize = 0, dwBytesRead = 0, dwBytesToCopy;
5039dede
AK
405 int iErr;
406 BOOL bSkipMsg = FALSE;
407
408 // Initialize buffer if requested
b9b2b87b 409 if (msgBuffer == NULL)
5039dede 410 {
b368969c
VK
411 nxcpBuffer->bufferSize = 0;
412 nxcpBuffer->bufferPos = 0;
5039dede
AK
413 return 0;
414 }
415
416 // Check if we have something in buffer
b368969c 417 if (nxcpBuffer->bufferSize > 0)
5039dede
AK
418 {
419 // Handle the case when entire message header have not been read into the buffer
b368969c 420 if (nxcpBuffer->bufferSize < NXCP_HEADER_SIZE)
5039dede
AK
421 {
422 // Most likely we are at the buffer end, so move content
423 // to the beginning
b368969c
VK
424 memmove(nxcpBuffer->buffer, &nxcpBuffer->buffer[nxcpBuffer->bufferPos], nxcpBuffer->bufferSize);
425 nxcpBuffer->bufferPos = 0;
5039dede 426
fce4295c 427 // Receive new portion of data from the network
5039dede 428 // and append it to existing data in buffer
b368969c 429 iErr = RecvEx(hSocket, &nxcpBuffer->buffer[nxcpBuffer->bufferSize],
43a6f3ca 430 NXCP_TEMP_BUF_SIZE - nxcpBuffer->bufferSize, 0, dwTimeout);
5039dede
AK
431 if (iErr <= 0)
432 return (iErr == -2) ? 3 : iErr;
b368969c 433 nxcpBuffer->bufferSize += (UINT32)iErr;
5039dede
AK
434 }
435
fce4295c 436 // Get message size from message header and copy available
5039dede 437 // message bytes from buffer
b368969c 438 dwMsgSize = ntohl(((NXCP_MESSAGE *)(&nxcpBuffer->buffer[nxcpBuffer->bufferPos]))->size);
b9b2b87b 439 if (dwMsgSize > *bufferSize)
5039dede 440 {
b9b2b87b
VK
441 if ((*bufferSize >= maxMsgSize) || (dwMsgSize > maxMsgSize))
442 {
443 bSkipMsg = TRUE; // Message is too large, will skip it
b368969c 444 memcpy(*msgBuffer, &nxcpBuffer->buffer[nxcpBuffer->bufferPos], NXCP_HEADER_SIZE);
b9b2b87b
VK
445 }
446 else
447 {
448 // Increase buffer
449 *bufferSize = dwMsgSize;
b368969c 450 *msgBuffer = (NXCP_MESSAGE *)realloc(*msgBuffer, *bufferSize);
b9b2b87b
VK
451 if (decryptionBuffer != NULL)
452 *decryptionBuffer = (BYTE *)realloc(*decryptionBuffer, *bufferSize);
453 }
5039dede 454 }
b368969c 455 dwBytesRead = min(dwMsgSize, nxcpBuffer->bufferSize);
5039dede 456 if (!bSkipMsg)
b368969c
VK
457 memcpy(*msgBuffer, &nxcpBuffer->buffer[nxcpBuffer->bufferPos], dwBytesRead);
458 nxcpBuffer->bufferSize -= dwBytesRead;
459 nxcpBuffer->bufferPos = (nxcpBuffer->bufferSize > 0) ? (nxcpBuffer->bufferPos + dwBytesRead) : 0;
5039dede
AK
460 if (dwBytesRead == dwMsgSize)
461 goto decrypt_message;
462 }
463
464 // Receive rest of message from the network
4a64261c 465 // Buffer is empty now
b368969c
VK
466 nxcpBuffer->bufferSize = 0;
467 nxcpBuffer->bufferPos = 0;
5039dede
AK
468 do
469 {
b368969c 470 iErr = RecvEx(hSocket, &nxcpBuffer->buffer[nxcpBuffer->bufferSize],
43a6f3ca 471 NXCP_TEMP_BUF_SIZE - nxcpBuffer->bufferSize, 0, dwTimeout);
5039dede
AK
472 if (iErr <= 0)
473 return (iErr == -2) ? 3 : iErr;
474
4a64261c 475 if (dwBytesRead == 0) // New message?
5039dede 476 {
b368969c 477 if ((iErr + nxcpBuffer->bufferSize) < NXCP_HEADER_SIZE)
4a64261c
VK
478 {
479 // Header not received completely
b368969c 480 nxcpBuffer->bufferSize += iErr;
4a64261c
VK
481 continue;
482 }
b368969c
VK
483 iErr += nxcpBuffer->bufferSize;
484 nxcpBuffer->bufferSize = 0;
4a64261c 485
b368969c 486 dwMsgSize = ntohl(((NXCP_MESSAGE *)(nxcpBuffer->buffer))->size);
b9b2b87b 487 if (dwMsgSize > *bufferSize)
5039dede 488 {
b9b2b87b
VK
489 if ((*bufferSize >= maxMsgSize) || (dwMsgSize > maxMsgSize))
490 {
491 bSkipMsg = TRUE; // Message is too large, will skip it
b368969c 492 memcpy(*msgBuffer, nxcpBuffer->buffer, NXCP_HEADER_SIZE);
b9b2b87b
VK
493 }
494 else
495 {
496 // Increase buffer
497 *bufferSize = dwMsgSize;
b368969c 498 *msgBuffer = (NXCP_MESSAGE *)realloc(*msgBuffer, *bufferSize);
b9b2b87b
VK
499 if (decryptionBuffer != NULL)
500 *decryptionBuffer = (BYTE *)realloc(*decryptionBuffer, *bufferSize);
501 }
5039dede
AK
502 }
503 }
967893bb 504 dwBytesToCopy = min((UINT32)iErr, dwMsgSize - dwBytesRead);
5039dede 505 if (!bSkipMsg)
b368969c 506 memcpy(((char *)(*msgBuffer)) + dwBytesRead, nxcpBuffer->buffer, dwBytesToCopy);
5039dede
AK
507 dwBytesRead += dwBytesToCopy;
508 }
6be0a20b 509 while((dwBytesRead < dwMsgSize) || (dwBytesRead < NXCP_HEADER_SIZE));
fce4295c 510
5039dede 511 // Check if we have something left in buffer
967893bb 512 if (dwBytesToCopy < (UINT32)iErr)
5039dede 513 {
b368969c
VK
514 nxcpBuffer->bufferPos = dwBytesToCopy;
515 nxcpBuffer->bufferSize = (UINT32)iErr - dwBytesToCopy;
5039dede
AK
516 }
517
518 // Check for encrypted message
519decrypt_message:
b368969c 520 if ((!bSkipMsg) && (ntohs((*msgBuffer)->code) == CMD_ENCRYPTED_MESSAGE))
5039dede
AK
521 {
522 if ((*ppCtx != NULL) && (*ppCtx != PROXY_ENCRYPTION_CTX))
523 {
b368969c 524 if ((*ppCtx)->decryptMessage((NXCP_ENCRYPTED_MESSAGE *)(*msgBuffer), *decryptionBuffer))
5039dede 525 {
b368969c 526 dwMsgSize = ntohl((*msgBuffer)->size);
5039dede
AK
527 }
528 else
529 {
530 dwMsgSize = 2; // Decryption failed
531 }
532 }
533 else
534 {
535 if (*ppCtx != PROXY_ENCRYPTION_CTX)
536 dwMsgSize = 2;
537 }
538 }
539
540 return bSkipMsg ? 1 : (int)dwMsgSize;
541}
542
b368969c
VK
543int LIBNETXMS_EXPORTABLE RecvNXCPMessage(SOCKET hSocket, NXCP_MESSAGE *msgBuffer,
544 NXCP_BUFFER *nxcpBuffer, UINT32 bufferSize,
fce4295c 545 NXCPEncryptionContext **ppCtx,
967893bb 546 BYTE *decryptionBuffer, UINT32 dwTimeout)
b9b2b87b 547{
b368969c 548 NXCP_MESSAGE *mb = msgBuffer;
967893bb 549 UINT32 bs = bufferSize;
b9b2b87b
VK
550 BYTE *db = decryptionBuffer;
551 return RecvNXCPMessageEx(hSocket, (msgBuffer != NULL) ? &mb : NULL, nxcpBuffer, &bs, ppCtx,
552 (decryptionBuffer != NULL) ? &db : NULL, dwTimeout, bufferSize);
553}
554
390271e0
VK
555/**
556 * Create NXCP message with raw data (MF_BINARY flag)
557 * If pBuffer is NULL, new buffer is allocated with malloc()
6be0a20b 558 * Buffer should be of dwDataSize + NXCP_HEADER_SIZE + 8 bytes.
390271e0 559 */
b368969c 560NXCP_MESSAGE LIBNETXMS_EXPORTABLE *CreateRawNXCPMessage(WORD code, UINT32 id, WORD flags,
fce4295c 561 UINT32 dwDataSize, void *pData,
b368969c 562 NXCP_MESSAGE *pBuffer)
5039dede 563{
b368969c 564 NXCP_MESSAGE *pMsg;
967893bb 565 UINT32 dwPadding;
5039dede
AK
566
567 if (pBuffer == NULL)
b368969c 568 pMsg = (NXCP_MESSAGE *)malloc(dwDataSize + NXCP_HEADER_SIZE + 8);
5039dede
AK
569 else
570 pMsg = pBuffer;
571
572 // Message should be aligned to 8 bytes boundary
6be0a20b 573 dwPadding = (8 - ((dwDataSize + NXCP_HEADER_SIZE) % 8)) & 7;
5039dede 574
b368969c
VK
575 pMsg->code = htons(code);
576 pMsg->flags = htons(MF_BINARY | flags);
577 pMsg->id = htonl(id);
578 pMsg->size = htonl(dwDataSize + NXCP_HEADER_SIZE + dwPadding);
579 pMsg->numFields = htonl(dwDataSize); // numFields contains actual data size for binary message
580 memcpy(pMsg->fields, pData, dwDataSize);
5039dede
AK
581
582 return pMsg;
583}
584
bd8cc790
VK
585/**
586 * Send file over CSCP
587 */
b368969c 588BOOL LIBNETXMS_EXPORTABLE SendFileOverNXCP(SOCKET hSocket, UINT32 id, const TCHAR *pszFile,
cc022855 589 NXCPEncryptionContext *pCtx, long offset,
7b8b337e 590 void (* progressCallback)(INT64, void *), void *cbArg,
503da871 591 MUTEX mutex, NXCPCompressionMethod compressionMethod)
5039dede 592{
5039dede 593 int hFile, iBytes;
6173bea8 594 INT64 bytesTransferred = 0;
967893bb 595 UINT32 dwPadding;
5039dede 596 BOOL bResult = FALSE;
b368969c 597 NXCP_MESSAGE *pMsg;
6be0a20b 598 NXCP_ENCRYPTED_MESSAGE *pEnMsg;
5039dede 599
503da871
VK
600 StreamCompressor *compressor = (compressionMethod != NXCP_COMPRESSION_NONE) ? StreamCompressor::create(compressionMethod, true, FILE_BUFFER_SIZE) : NULL;
601 BYTE *compBuffer = (compressor != NULL) ? (BYTE *)malloc(FILE_BUFFER_SIZE) : NULL;
602
5039dede
AK
603 hFile = _topen(pszFile, O_RDONLY | O_BINARY);
604 if (hFile != -1)
c3a8e638 605 {
db05c2af
VK
606 NX_STAT_STRUCT st;
607 NX_FSTAT(hFile, &st);
608 long fileSize = (long)st.st_size;
cc022855 609 if (labs(offset) > fileSize)
610 offset = 0;
611 long bytesToRead = (offset < 0) ? (0 - offset) : (fileSize - offset);
db05c2af 612
cc022855 613 if (lseek(hFile, offset, (offset < 0) ? SEEK_END : SEEK_SET) != -1)
901a5a9b 614 {
901a5a9b 615 // Allocate message and prepare it's header
503da871 616 pMsg = (NXCP_MESSAGE *)malloc(NXCP_HEADER_SIZE + 8 + ((compressor != NULL) ? compressor->compressBufferSize(FILE_BUFFER_SIZE) + 4 : FILE_BUFFER_SIZE));
b368969c
VK
617 pMsg->id = htonl(id);
618 pMsg->code = htons(CMD_FILE_DATA);
503da871 619 pMsg->flags = htons(MF_BINARY | ((compressionMethod != NXCP_COMPRESSION_NONE) ? MF_COMPRESSED : 0));
901a5a9b
VK
620
621 while(1)
622 {
503da871
VK
623 if (compressor != NULL)
624 {
625 iBytes = read(hFile, compBuffer, min(FILE_BUFFER_SIZE, bytesToRead));
626 if (iBytes < 0)
627 break;
628 bytesToRead -= iBytes;
629 // Each compressed data block prepended with 4 bytes header
630 // First byte contains compression method, second is always 0,
631 // third and fourth contains uncompressed block size in network byte order
632 *((BYTE *)pMsg->fields) = (BYTE)compressionMethod;
633 *((BYTE *)pMsg->fields + 1) = 0;
634 *((UINT16 *)((BYTE *)pMsg->fields + 2)) = htons((UINT16)iBytes);
635 iBytes = (int)compressor->compress(compBuffer, iBytes, (BYTE *)pMsg->fields + 4, compressor->compressBufferSize(FILE_BUFFER_SIZE)) + 4;
636 }
637 else
638 {
639 iBytes = read(hFile, pMsg->fields, min(FILE_BUFFER_SIZE, bytesToRead));
640 if (iBytes < 0)
641 break;
642 bytesToRead -= iBytes;
643 }
5039dede 644
901a5a9b 645 // Message should be aligned to 8 bytes boundary
6be0a20b 646 dwPadding = (8 - (((UINT32)iBytes + NXCP_HEADER_SIZE) % 8)) & 7;
b368969c
VK
647 pMsg->size = htonl((UINT32)iBytes + NXCP_HEADER_SIZE + dwPadding);
648 pMsg->numFields = htonl((UINT32)iBytes); // numFields contains actual data size for binary message
db05c2af 649 if (bytesToRead <= 0)
b368969c 650 pMsg->flags |= htons(MF_END_OF_FILE);
901a5a9b
VK
651
652 if (pCtx != NULL)
5039dede 653 {
b368969c 654 pEnMsg = pCtx->encryptMessage(pMsg);
901a5a9b 655 if (pEnMsg != NULL)
c3a8e638 656 {
b368969c 657 SendEx(hSocket, (char *)pEnMsg, ntohl(pEnMsg->size), 0, mutex);
901a5a9b 658 free(pEnMsg);
c3a8e638 659 }
901a5a9b
VK
660 }
661 else
662 {
6be0a20b 663 if (SendEx(hSocket, (char *)pMsg, (UINT32)iBytes + NXCP_HEADER_SIZE + dwPadding, 0, mutex) <= 0)
901a5a9b
VK
664 break; // Send error
665 }
6173bea8
VK
666 if (progressCallback != NULL)
667 {
668 bytesTransferred += iBytes;
669 progressCallback(bytesTransferred, cbArg);
670 }
671
db05c2af 672 if (bytesToRead <= 0)
901a5a9b
VK
673 {
674 // End of file
675 bResult = TRUE;
676 break;
677 }
678 }
679
680 free(pMsg);
681 }
901a5a9b 682 close(hFile);
901a5a9b 683 }
5039dede 684
503da871
VK
685 safe_free(compBuffer);
686 delete compressor;
687
5039dede
AK
688 // If file upload failed, send CMD_ABORT_FILE_TRANSFER
689 if (!bResult)
690 {
b368969c 691 NXCP_MESSAGE msg;
5039dede 692
b368969c
VK
693 msg.id = htonl(id);
694 msg.code = htons(CMD_ABORT_FILE_TRANSFER);
695 msg.flags = htons(MF_BINARY);
696 msg.numFields = 0;
697 msg.size = htonl(NXCP_HEADER_SIZE);
5039dede
AK
698 if (pCtx != NULL)
699 {
b368969c 700 pEnMsg = pCtx->encryptMessage(&msg);
5039dede
AK
701 if (pEnMsg != NULL)
702 {
b368969c 703 SendEx(hSocket, (char *)pEnMsg, ntohl(pEnMsg->size), 0, mutex);
5039dede
AK
704 free(pEnMsg);
705 }
706 }
707 else
708 {
6be0a20b 709 SendEx(hSocket, (char *)&msg, NXCP_HEADER_SIZE, 0, mutex);
5039dede
AK
710 }
711 }
712
713 return bResult;
714}
715
bd8cc790
VK
716/**
717 * Get version of NXCP used by peer
718 */
7b8b337e 719BOOL LIBNETXMS_EXPORTABLE NXCPGetPeerProtocolVersion(SOCKET hSocket, int *pnVersion, MUTEX mutex)
5039dede 720{
b368969c 721 NXCP_MESSAGE msg;
98abc9f1 722 NXCPEncryptionContext *pDummyCtx = NULL;
b368969c 723 NXCP_BUFFER *pBuffer;
5039dede
AK
724 BOOL bRet = FALSE;
725 int nSize;
726
b368969c
VK
727 msg.id = 0;
728 msg.numFields = 0;
729 msg.size = htonl(NXCP_HEADER_SIZE);
730 msg.code = htons(CMD_GET_NXCP_CAPS);
731 msg.flags = htons(MF_CONTROL);
6be0a20b 732 if (SendEx(hSocket, &msg, NXCP_HEADER_SIZE, 0, mutex) == NXCP_HEADER_SIZE)
5039dede 733 {
b368969c 734 pBuffer = (NXCP_BUFFER *)malloc(sizeof(NXCP_BUFFER));
5039dede 735 RecvNXCPMessage(0, NULL, pBuffer, 0, NULL, NULL, 0);
6be0a20b
VK
736 nSize = RecvNXCPMessage(hSocket, &msg, pBuffer, NXCP_HEADER_SIZE, &pDummyCtx, NULL, 30000);
737 if ((nSize == NXCP_HEADER_SIZE) &&
b368969c
VK
738 (ntohs(msg.code) == CMD_NXCP_CAPS) &&
739 (ntohs(msg.flags) & MF_CONTROL))
5039dede
AK
740 {
741 bRet = TRUE;
b368969c 742 *pnVersion = ntohl(msg.numFields) >> 24;
5039dede 743 }
6be0a20b 744 else if ((nSize == 1) || (nSize == 3) || (nSize >= NXCP_HEADER_SIZE))
5039dede 745 {
fce4295c 746 // We don't receive any answer or receive invalid answer -
5039dede
AK
747 // assume that peer doesn't understand CMD_GET_NXCP_CAPS message
748 // and set version number to 1
749 bRet = TRUE;
750 *pnVersion = 1;
751 }
752 free(pBuffer);
753 }
754 return bRet;
755}