- Changed to use new version of client library
[public/netxms.git] / src / libnxcl / comm.cpp
CommitLineData
05d9bba3
VK
1/*
2** NetXMS - Network Management System
3** Client Library
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**
22**/
23
24#include "libnxcl.h"
25
26
27//
55198bf4 28// Unique message ID
05d9bba3
VK
29//
30
55198bf4 31DWORD g_dwMsgId;
05d9bba3
VK
32
33
1dd9669b 34//
55198bf4 35// Static data
1dd9669b
VK
36//
37
55198bf4
VK
38static SOCKET m_hSocket = -1;
39static MsgWaitQueue m_msgWaitQueue;
1dd9669b
VK
40
41
05d9bba3
VK
42//
43// Send raw message
44//
45
46static BOOL SendRawMsg(CSCP_MESSAGE *pMsg)
47{
48 return send(m_hSocket, (char *)pMsg, ntohs(pMsg->wSize), 0) == (int)ntohs(pMsg->wSize);
49}
50
51
52//
53// Send message
54//
55
56BOOL SendMsg(CSCPMessage *pMsg)
57{
58 CSCP_MESSAGE *pRawMsg;
59 BOOL bResult;
55198bf4 60 char szBuffer[128];
05d9bba3 61
55198bf4 62 DebugPrintf("SendMsg(\"%s\", id:%ld)", CSCPMessageCodeName(pMsg->GetCode(), szBuffer), pMsg->GetId());
05d9bba3
VK
63 pRawMsg = pMsg->CreateMessage();
64 bResult = SendRawMsg(pRawMsg);
5b9ed9ac 65 MemFree(pRawMsg);
05d9bba3
VK
66 return bResult;
67}
68
69
70//
71// Network receiver thread
72//
73
74static void NetReceiver(void *pArg)
75{
76 CSCPMessage *pMsg;
77 CSCP_MESSAGE *pRawMsg;
78 CSCP_BUFFER *pMsgBuffer;
79 int iErr;
d8d6e1a4 80 BOOL bMsgNotNeeded;
55198bf4 81 char szBuffer[128];
05d9bba3
VK
82
83 // Initialize raw message receiving function
5b9ed9ac 84 pMsgBuffer = (CSCP_BUFFER *)MemAlloc(sizeof(CSCP_BUFFER));
05d9bba3
VK
85 RecvCSCPMessage(0, NULL, pMsgBuffer);
86
87 // Allocate space for raw message
5b9ed9ac 88 pRawMsg = (CSCP_MESSAGE *)MemAlloc(65536);
05d9bba3
VK
89
90 // Message receiving loop
91 while(1)
92 {
93 // Receive raw message
94 if ((iErr = RecvCSCPMessage(m_hSocket, pRawMsg, pMsgBuffer)) <= 0)
95 break;
96
97 // Check that actual received packet size is equal to encoded in packet
98 if (ntohs(pRawMsg->wSize) != iErr)
99 {
1dd9669b 100 DebugPrintf("RecvMsg: Bad packet length [wSize=%d ActualSize=%d]", ntohs(pRawMsg->wSize), iErr);
05d9bba3
VK
101 continue; // Bad packet, wait for next
102 }
103
104 // Create message object from raw message
f8e075ce
VK
105 if (IsBinaryMsg(pRawMsg))
106 {
107 // Convert numeric fields to host byte order
108 pRawMsg->wCode = ntohs(pRawMsg->wCode) & 0x0FFF; // Clear flag bits from code
109 pRawMsg->wSize = ntohs(pRawMsg->wSize);
110 pRawMsg->dwId = ntohl(pRawMsg->dwId);
111
55198bf4 112 DebugPrintf("RecvRawMsg(\"%s\", id:%ld)", CSCPMessageCodeName(pRawMsg->wCode, szBuffer), pRawMsg->dwId);
1dd9669b 113
f8e075ce
VK
114 // Process message
115 switch(pRawMsg->wCode)
116 {
117 case CMD_EVENT:
118 ProcessEvent(NULL, pRawMsg);
f8e075ce
VK
119 break;
120 default: // We ignore unknown raw messages
121 break;
122 }
123 }
124 else
05d9bba3 125 {
f8e075ce 126 pMsg = new CSCPMessage(pRawMsg);
d8d6e1a4 127 bMsgNotNeeded = TRUE;
55198bf4 128 DebugPrintf("RecvMsg(\"%s\", id:%ld)", CSCPMessageCodeName(pMsg->GetCode(), szBuffer), pMsg->GetId());
f8e075ce
VK
129
130 // Process message
131 switch(pMsg->GetCode())
132 {
133 case CMD_KEEPALIVE: // Keepalive message, ignore it
f8e075ce
VK
134 break;
135 case CMD_OBJECT: // Object information
824615ef 136 case CMD_OBJECT_UPDATE:
f8e075ce
VK
137 case CMD_OBJECT_LIST_END:
138 ProcessObjectUpdate(pMsg);
f8e075ce
VK
139 break;
140 case CMD_EVENT_LIST_END:
141 ProcessEvent(pMsg, NULL);
f8e075ce 142 break;
f160ff09
VK
143 case CMD_EVENT_DB_RECORD:
144 case CMD_EVENT_DB_EOF:
145 ProcessEventDBRecord(pMsg);
146 break;
bb68f467
VK
147 case CMD_USER_DATA:
148 case CMD_GROUP_DATA:
149 case CMD_USER_DB_EOF:
150 ProcessUserDBRecord(pMsg);
151 break;
f8e075ce
VK
152 default:
153 m_msgWaitQueue.Put(pMsg);
d8d6e1a4 154 bMsgNotNeeded = FALSE;
f8e075ce
VK
155 break;
156 }
d8d6e1a4
VK
157 if (bMsgNotNeeded)
158 delete pMsg;
05d9bba3
VK
159 }
160 }
161
162 ChangeState(STATE_DISCONNECTED);
5b9ed9ac
VK
163 MemFree(pRawMsg);
164 MemFree(pMsgBuffer);
05d9bba3
VK
165}
166
167
168//
169// Connect to server
170//
171
55198bf4 172BOOL LIBNXCL_EXPORTABLE NXCConnect(char *szServer, char *szLogin, char *szPassword)
05d9bba3
VK
173{
174 struct sockaddr_in servAddr;
175 CSCPMessage msg, *pResp;
55198bf4
VK
176 BOOL bSuccess = FALSE;
177 BYTE szPasswordHash[SHA_DIGEST_LENGTH];
05d9bba3 178
55198bf4 179 if (g_dwState == STATE_DISCONNECTED)
05d9bba3 180 {
55198bf4 181 ChangeState(STATE_CONNECTING);
05d9bba3 182
55198bf4
VK
183 // Reset unique message ID
184 g_dwMsgId = 1;
05d9bba3 185
55198bf4
VK
186 // Prepare address structure
187 memset(&servAddr, 0, sizeof(struct sockaddr_in));
188 servAddr.sin_family = AF_INET;
189 servAddr.sin_port = htons((WORD)SERVER_LISTEN_PORT);
190 servAddr.sin_addr.s_addr = inet_addr(szServer);
191 if (servAddr.sin_addr.s_addr == INADDR_NONE)
192 {
193 struct hostent *hs;
05d9bba3 194
55198bf4
VK
195 hs = gethostbyname(szServer);
196 if (hs != NULL)
197 memcpy(&servAddr.sin_addr, hs->h_addr, hs->h_length);
198 }
05d9bba3 199
55198bf4
VK
200 if (servAddr.sin_addr.s_addr != INADDR_NONE)
201 {
202 // Create socket
203 if ((m_hSocket = socket(AF_INET, SOCK_STREAM, 0)) != -1)
204 {
205 // Connect to target
206 if (connect(m_hSocket, (struct sockaddr *)&servAddr, sizeof(struct sockaddr_in)) == 0)
207 {
208 // Start receiver thread
209 ThreadCreate(NetReceiver, 0, NULL);
05d9bba3 210
55198bf4
VK
211 // Prepare login message
212 msg.SetId(g_dwMsgId++);
213 msg.SetCode(CMD_LOGIN);
214 msg.SetVariable(VID_LOGIN_NAME, szLogin);
215 CreateSHA1Hash(szPassword, szPasswordHash);
216 msg.SetVariable(VID_PASSWORD, szPasswordHash, SHA_DIGEST_LENGTH);
217
218 if (SendMsg(&msg))
219 {
220 // Receive responce message
221 pResp = m_msgWaitQueue.WaitForMessage(CMD_LOGIN_RESP, msg.GetId(), 2000);
222 if (pResp != NULL) // Connection is broken or timed out
223 {
224 bSuccess = pResp->GetVariableLong(VID_LOGIN_RESULT);
225 delete pResp;
226 }
227 }
228
229 shutdown(m_hSocket, 2);
230 }
231 closesocket(m_hSocket);
232 m_hSocket = -1;
233 }
234 }
235 CallEventHandler(NXC_EVENT_LOGIN_RESULT, bSuccess, NULL);
05d9bba3
VK
236 }
237
05d9bba3
VK
238 return bSuccess;
239}
240
241
05d9bba3
VK
242//
243// Disconnect from server
244//
245
8aeffdee 246void LIBNXCL_EXPORTABLE NXCDisconnect(void)
05d9bba3
VK
247{
248 // Close socket
249 shutdown(m_hSocket, 2);
250 closesocket(m_hSocket);
251
252 // Clear message wait queue
253 m_msgWaitQueue.Clear();
254}
d8d6e1a4
VK
255
256
257//
258// Wait for specific message
259//
260
261CSCPMessage *WaitForMessage(DWORD dwCode, DWORD dwId, DWORD dwTimeOut)
262{
263 return m_msgWaitQueue.WaitForMessage(dwCode, dwId, dwTimeOut);
264}