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