File comm.cpp was missing from previous commit
[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];
35static char m_szPassword[MAX_PASSWORD_LEN];
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);
60 LibUtilDestroyObject(pRawMsg);
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
77 pMsgBuffer = (CSCP_BUFFER *)malloc(sizeof(CSCP_BUFFER));
78 RecvCSCPMessage(0, NULL, pMsgBuffer);
79
80 // Allocate space for raw message
81 pRawMsg = (CSCP_MESSAGE *)malloc(65536);
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
98 pMsg = new CSCPMessage(pRawMsg);
99 DebugPrintf("RECV_MSG: Code=%d ID=%d", pMsg->GetCode(), pMsg->GetId());
100
101 // Process message
102 switch(pMsg->GetCode())
103 {
104 case CMD_KEEPALIVE: // Keepalive message, ignore it
105 delete pMsg;
106 break;
107 case CMD_OBJECT: // Object information
108 case CMD_OBJECT_LIST_END:
109 ProcessObjectUpdate(pMsg);
110 delete pMsg;
111 break;
112 default:
113 m_msgWaitQueue.Put(pMsg);
114 break;
115 }
116 }
117
118 ChangeState(STATE_DISCONNECTED);
119 free(pRawMsg);
120 free(pMsgBuffer);
121}
122
123
124//
125// Connect to server
126//
127
128BOOL Connect(void)
129{
130 struct sockaddr_in servAddr;
131 CSCPMessage msg, *pResp;
132 BOOL bSuccess;
133
134 ChangeState(STATE_CONNECTING);
135
136 // Reset unique message ID
137 m_dwMsgId = 1;
138
139 // Prepare address structure
140 memset(&servAddr, 0, sizeof(struct sockaddr_in));
141 servAddr.sin_family = AF_INET;
142 servAddr.sin_addr.s_addr = inet_addr(m_szServer);
143 if (servAddr.sin_addr.s_addr == INADDR_NONE)
144 {
145 struct hostent *hs;
146
147 hs = gethostbyname(m_szServer);
148 if (hs == NULL)
149 {
150 return FALSE; // Unable to resolve host name
151 }
152 else
153 {
154 memcpy(&servAddr.sin_addr, hs->h_addr, hs->h_length);
155 }
156 }
157 servAddr.sin_port = htons((WORD)SERVER_LISTEN_PORT);
158
159 // Create socket
160 if ((m_hSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
161 {
162 return FALSE;
163 }
164
165 // Connect to target
166 if (connect(m_hSocket, (struct sockaddr *)&servAddr, sizeof(struct sockaddr_in)) != 0)
167 {
168 closesocket(m_hSocket);
169 m_hSocket = -1;
170 return FALSE;
171 }
172
173 // Start receiver thread
174 ThreadCreate(NetReceiver, 0, NULL);
175
176 // Prepare login message
177 msg.SetId(m_dwMsgId++);
178 msg.SetCode(CMD_LOGIN);
179 msg.SetVariable("login", m_szLogin);
180 msg.SetVariable("password", m_szPassword);
181
182 if (!SendMsg(&msg))
183 {
184 // Message send failed, drop connection
185 shutdown(m_hSocket, 2);
186 closesocket(m_hSocket);
187 m_hSocket = -1;
188 return FALSE;
189 }
190
191 // Receive responce message
192 pResp = m_msgWaitQueue.WaitForMessage(CMD_LOGIN_RESP, msg.GetId(), 2000);
193 if (pResp == NULL) // Connection is broken or timed out
194 {
195 shutdown(m_hSocket, 2);
196 closesocket(m_hSocket);
197 m_hSocket = -1;
198 return FALSE;
199 }
200
201 bSuccess = pResp->GetVariableLong("result");
202 delete pResp;
203
204 CallEventHandler(NXC_EVENT_LOGIN_RESULT, bSuccess, NULL);
205 if (!bSuccess)
206 {
207 shutdown(m_hSocket, 2);
208 closesocket(m_hSocket);
209 m_hSocket = -1;
210 }
211 return bSuccess;
212}
213
214
215//
216// Initiate connection to server
217//
218
219BOOL EXPORTABLE NXCConnect(char *szServer, char *szLogin, char *szPassword)
220{
221 if (g_dwState != STATE_DISCONNECTED)
222 return FALSE;
223
224 strcpy(m_szServer, szServer);
225 strcpy(m_szLogin, szLogin);
226 strcpy(m_szPassword, szPassword);
227
228 CreateRequest(RQ_CONNECT, NULL, FALSE);
229
230 return TRUE;
231}
232
233
234//
235// Disconnect from server
236//
237
238void EXPORTABLE NXCDisconnect(void)
239{
240 // Close socket
241 shutdown(m_hSocket, 2);
242 closesocket(m_hSocket);
243
244 // Clear message wait queue
245 m_msgWaitQueue.Clear();
246}