]> git.stg.codes - stg.git/blob - stglibs/srvconf.lib/netunit.cpp
Added special function to read/write all data (for TCP).
[stg.git] / stglibs / srvconf.lib / netunit.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
19  */
20
21  /*
22  $Revision: 1.6 $
23  $Date: 2009/02/06 10:25:54 $
24  $Author: faust $
25  */
26
27 //---------------------------------------------------------------------------
28 #include <netdb.h>
29 #include <arpa/inet.h>
30 #include <unistd.h>
31
32 #include <cstdio>
33 #include <cstring>
34
35 #include "stg/netunit.h"
36 #include "stg/common.h"
37
38 //---------------------------------------------------------------------------
39
40 #define SEND_DATA_ERROR             "Send data error!"
41 #define RECV_DATA_ANSWER_ERROR      "Recv data answer error!"
42 #define UNKNOWN_ERROR               "Unknown error!"
43 #define CONNECT_FAILED              "Connect failed!"
44 #define INCORRECT_LOGIN             "Incorrect login!"
45 #define INCORRECT_HEADER            "Incorrect header!"
46 #define SEND_LOGIN_ERROR            "Send login error!"
47 #define RECV_LOGIN_ANSWER_ERROR     "Recv login answer error!"
48 #define CREATE_SOCKET_ERROR         "Create socket failed!"
49 #define WSASTARTUP_FAILED           "WSAStartup failed!"
50 #define SEND_HEADER_ERROR           "Send header error!"
51 #define RECV_HEADER_ANSWER_ERROR    "Recv header answer error!"
52
53 //---------------------------------------------------------------------------
54 NETTRANSACT::NETTRANSACT()
55     : port(0),
56       outerSocket(-1),
57       RxCallBack(NULL),
58       dataRxCallBack(NULL)
59 {
60 }
61 //-----------------------------------------------------------------------------
62 void NETTRANSACT::EnDecryptInit(const char * passwd, int, BLOWFISH_CTX *ctx)
63 {
64 unsigned char * keyL = NULL;
65
66 keyL = new unsigned char[PASSWD_LEN];
67
68 memset(keyL, 0, PASSWD_LEN);
69
70 strncpy((char *)keyL, passwd, PASSWD_LEN);
71
72 Blowfish_Init(ctx, keyL, PASSWD_LEN);
73
74 delete[] keyL;
75 }
76 //-----------------------------------------------------------------------------
77 void NETTRANSACT::Encrypt(char * d, const char * s, BLOWFISH_CTX *ctx)
78 {
79 EncodeString(d, s, ctx);
80 }
81 //---------------------------------------------------------------------------
82 void NETTRANSACT::Decrypt(char * d, const char * s, BLOWFISH_CTX *ctx)
83 {
84 DecodeString(d, s, ctx);
85 }
86 //---------------------------------------------------------------------------
87 int NETTRANSACT::Connect()
88 {
89 int ret;
90
91 outerSocket = socket(PF_INET, SOCK_STREAM, 0);
92 if (outerSocket < 0)
93     {
94     errorMsg = CREATE_SOCKET_ERROR;
95     return st_conn_fail;
96     }
97
98 struct sockaddr_in outerAddr;
99 memset(&outerAddr, 0, sizeof(outerAddr));
100
101 struct hostent he;
102 struct hostent * phe;
103
104 unsigned long ip;
105 ip = inet_addr(server.c_str());
106
107 if (ip == INADDR_NONE)
108     {
109     phe = gethostbyname(server.c_str());
110     if (phe == NULL)
111         {
112         errorMsg = "DNS error.\nCan not reslove " + server;
113         return st_dns_err;
114         }
115
116     memcpy(&he, phe, sizeof(he));
117     ip = *((long*)he.h_addr_list[0]);
118     }
119 outerAddr.sin_family = AF_INET;
120 outerAddr.sin_port = htons(port);
121 outerAddr.sin_addr.s_addr = ip;
122
123 ret = connect(outerSocket, (struct sockaddr*)&outerAddr, sizeof(outerAddr));
124
125 if (ret < 0)
126     {
127     errorMsg = CONNECT_FAILED;
128     close(outerSocket);
129     return st_conn_fail;
130     }
131 return st_ok;
132 }
133 //---------------------------------------------------------------------------
134 int NETTRANSACT::Disconnect()
135 {
136 close(outerSocket);
137 return 0;
138 }
139 //---------------------------------------------------------------------------
140 int NETTRANSACT::Transact(const char * data)
141 {
142 int ret;
143 if ((ret = TxHeader()) != st_ok)
144     {
145     Disconnect();
146     return ret;
147     }
148
149 if ((ret = RxHeaderAnswer()) != st_ok)
150     {
151     Disconnect();
152     return ret;
153     }
154
155 if ((ret = TxLogin()) != st_ok)
156     {
157     Disconnect();
158     return ret;
159     }
160
161 if ((ret = RxLoginAnswer()) != st_ok)
162     {
163     Disconnect();
164     return ret;
165     }
166
167 if ((ret = TxLoginS()) != st_ok)
168     {
169     Disconnect();
170     return ret;
171     }
172
173 if ((ret = RxLoginSAnswer()) != st_ok)
174     {
175     Disconnect();
176     return ret;
177     }
178
179 if ((ret = TxData(data)) != st_ok)
180     {
181     Disconnect();
182     return ret;
183     }
184
185 if ((ret = RxDataAnswer()) != st_ok)
186     {
187     Disconnect();
188     return ret;
189     }
190
191 return st_ok;
192 }
193 //---------------------------------------------------------------------------
194 int NETTRANSACT::TxHeader()
195 {
196 int ret;
197 ret = send(outerSocket, STG_HEADER, strlen(STG_HEADER), 0);
198 if (ret <= 0)
199     {
200     errorMsg = SEND_HEADER_ERROR;
201     return st_send_fail;
202     }
203
204 return st_ok;
205 }
206 //---------------------------------------------------------------------------
207 int NETTRANSACT::RxHeaderAnswer()
208 {
209 char buffer[sizeof(STG_HEADER)+1];
210 int ret;
211
212 ret = recv(outerSocket, buffer, strlen(OK_HEADER), 0);
213 if (ret <= 0)
214     {
215     errorMsg = RECV_HEADER_ANSWER_ERROR;
216     return st_recv_fail;
217     }
218
219 if (strncmp(OK_HEADER, buffer, strlen(OK_HEADER)) == 0)
220     {
221     return st_ok;
222     }
223 else
224     {
225     if (strncmp(ERR_HEADER, buffer, strlen(ERR_HEADER)) == 0)
226         {
227         errorMsg = INCORRECT_HEADER;
228         return st_header_err;
229         }
230     else
231         {
232         errorMsg = UNKNOWN_ERROR;
233         return st_unknown_err;
234         }
235     }
236 }
237 //---------------------------------------------------------------------------
238 int NETTRANSACT::TxLogin()
239 {
240 char loginZ[ADM_LOGIN_LEN];
241 int ret;
242
243 memset(loginZ, 0, ADM_LOGIN_LEN);
244 strncpy(loginZ, login.c_str(), ADM_LOGIN_LEN);
245 ret = send(outerSocket, loginZ, ADM_LOGIN_LEN, 0);
246
247 if (ret <= 0)
248     {
249     errorMsg = SEND_LOGIN_ERROR;
250     return st_send_fail;
251     }
252
253 return st_ok;
254 }
255 //---------------------------------------------------------------------------
256 int NETTRANSACT::RxLoginAnswer()
257 {
258 char buffer[sizeof(OK_LOGIN)+1];
259 int ret;
260
261 ret = recv(outerSocket, buffer, strlen(OK_LOGIN), 0);
262 if (ret <= 0)
263     {
264     errorMsg = RECV_LOGIN_ANSWER_ERROR;
265     return st_recv_fail;
266     }
267
268 if (strncmp(OK_LOGIN, buffer, strlen(OK_LOGIN)) == 0)
269     {
270     return st_ok;
271     }
272 else
273     {
274     if (strncmp(ERR_LOGIN, buffer, strlen(ERR_LOGIN)) == 0)
275         {
276         errorMsg = INCORRECT_LOGIN;
277         return st_login_err;
278         }
279     else
280         {
281         errorMsg = UNKNOWN_ERROR;
282         return st_unknown_err;
283         }
284     }
285 }
286 //---------------------------------------------------------------------------
287 int NETTRANSACT::TxLoginS()
288 {
289 char loginZ[ADM_LOGIN_LEN];
290 char ct[ENC_MSG_LEN];
291 int ret;
292
293 memset(loginZ, 0, ADM_LOGIN_LEN);
294 BLOWFISH_CTX ctx;
295 InitContext(password.c_str(), PASSWD_LEN, &ctx);
296 EncryptString(loginZ, login.c_str(), std::min(login.length() + 1, ADM_LOGIN_LEN), &ctx);
297 if (send(outerSocket, loginZ, ADM_LOGIN_LEN, 0) <= 0)
298     {
299     errorMsg = SEND_LOGIN_ERROR;
300     return st_send_fail;
301     }
302 return st_ok;
303 }
304 //---------------------------------------------------------------------------
305 int NETTRANSACT::RxLoginSAnswer()
306 {
307 char buffer[sizeof(OK_LOGINS)+1];
308 int ret;
309
310 ret = recv(outerSocket, buffer, strlen(OK_LOGINS), 0);
311 if (ret <= 0)
312     {
313     errorMsg = RECV_LOGIN_ANSWER_ERROR;
314     return st_recv_fail;
315     }
316
317 if (strncmp(OK_LOGINS, buffer, strlen(OK_LOGINS)) == 0)
318     {
319     return st_ok;
320     }
321 else
322     {
323     if (strncmp(ERR_LOGINS, buffer, strlen(ERR_LOGINS)) == 0)
324         {
325         errorMsg = INCORRECT_LOGIN;
326         return st_logins_err;
327         }
328     else
329         {
330         errorMsg = UNKNOWN_ERROR;
331         return st_unknown_err;
332         }
333     }
334 }
335 //---------------------------------------------------------------------------
336 int NETTRANSACT::TxData(const char * text)
337 {
338 char textZ[ENC_MSG_LEN];
339 char ct[ENC_MSG_LEN];
340 int ret;
341 int j;
342
343 int n = strlen(text) / ENC_MSG_LEN;
344 int r = strlen(text) % ENC_MSG_LEN;
345
346 BLOWFISH_CTX ctx;
347 InitContext(password.c_str(), PASSWD_LEN, &ctx);
348 char buffer[text.length() + 9];
349 EncryptString(buffer, text.c_str(), text.length() + 1, &ctx);
350 if (send(outerSocket, buffer, sizeof(buffer), 0) <= 0)
351     {
352     errorMsg = SEND_DATA_ERROR;
353     return st_send_fail;
354     }
355 return st_ok;
356 }
357 //---------------------------------------------------------------------------
358 int NETTRANSACT::TxData(char * data)
359 {
360 char buff[ENC_MSG_LEN];
361 char buffS[ENC_MSG_LEN];
362 char passwd[ADM_PASSWD_LEN];
363
364 memset(passwd, 0, ADM_PASSWD_LEN);
365 strncpy(passwd, password.c_str(), ADM_PASSWD_LEN);
366 memset(buff, 0, ENC_MSG_LEN);
367
368 int l = strlen(data)/ENC_MSG_LEN;
369 if (strlen(data)%ENC_MSG_LEN)
370     l++;
371
372 BLOWFISH_CTX ctx;
373 InitContext(password.c_str(), PASSWD_LEN, &ctx);
374
375 for (int j = 0; j < l; j++)
376     {
377     strncpy(buff, &data[j*ENC_MSG_LEN], ENC_MSG_LEN);
378     Encrypt(buffS, buff, &ctx);
379     send(outerSocket, buffS, ENC_MSG_LEN, 0);
380     }
381
382 return 0;
383 }
384 //---------------------------------------------------------------------------
385 int NETTRANSACT::RxDataAnswer()
386 {
387 int n = 0;
388 int ret;
389 char bufferS[ENC_MSG_LEN];
390 char buffer[ENC_MSG_LEN + 1];
391
392 BLOWFISH_CTX ctx;
393 EnDecryptInit(password.c_str(), PASSWD_LEN, &ctx);
394
395 while (1)
396     {
397     ret = recv(outerSocket, &bufferS[n++], 1, 0);
398     if (ret <= 0)
399         {
400         close(outerSocket);
401         errorMsg = RECV_DATA_ANSWER_ERROR;
402         return st_recv_fail;
403         }
404
405     if (n == ENC_MSG_LEN)
406         {
407         n = 0;
408         Decrypt(buffer, bufferS, &ctx);
409         buffer[ENC_MSG_LEN] = 0;
410
411         answerList.push_back(buffer);
412
413         for (int j = 0; j < ENC_MSG_LEN; j++)
414             {
415             if (buffer[j] == 0)
416                 {
417                 if (RxCallBack)
418                     if (st_ok != RxCallBack(dataRxCallBack, &answerList))
419                         {
420                         return st_xml_parse_error;
421                         }
422                 return st_ok;
423                 }
424             }
425         }
426     }
427 }
428 //---------------------------------------------------------------------------
429 void NETTRANSACT::SetLogin(const char * l)
430 {
431 login = l;
432 }
433 //---------------------------------------------------------------------------
434 void NETTRANSACT::SetPassword(const char * p)
435 {
436 password = p;
437 }
438 //---------------------------------------------------------------------------
439 void NETTRANSACT::SetServer(const char * serverName)
440 {
441 server = serverName;
442 }
443 //---------------------------------------------------------------------------
444 void NETTRANSACT::SetServerPort(short unsigned p)
445 {
446 port = p;
447 }
448 //---------------------------------------------------------------------------
449 void NETTRANSACT::SetRxCallback(void * data, RxCallback_t cb)
450 {
451 RxCallBack = cb;
452 dataRxCallBack = data;
453 }
454 //---------------------------------------------------------------------------
455 const std::string & NETTRANSACT::GetError() const
456 {
457 return errorMsg;
458 }
459 //---------------------------------------------------------------------------
460 void NETTRANSACT::Reset()
461 {
462 answerList.clear();
463 }
464 //---------------------------------------------------------------------------